diff --git a/Makefile b/Makefile index acde00a8..5084c408 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,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 := $(ALL_ARCHES) +BUILD_ARCHES_jessie := amd64 powerpc armel BUILD_ARCHES_stretch := arm64 amd64 # Build available architectures by default. diff --git a/builds/any/installer/installer.sh.in b/builds/any/installer/installer.sh.in index 470bc882..c5e33f3b 100644 --- a/builds/any/installer/installer.sh.in +++ b/builds/any/installer/installer.sh.in @@ -141,6 +141,9 @@ if has_boot_env onl_installer_debug; then installer_debug=1; fi if test "$installer_debug"; then echo "Debug mode" set -x + installer_wait=30 +else + installer_wait=3 fi # Pickup ONIE defines for this machine. @@ -254,7 +257,7 @@ if test "${onie_platform}"; then installer_umount - if installer_reboot; then + if installer_reboot $installer_wait; then : else sync @@ -587,7 +590,7 @@ trap - 0 1 installer_umount if test "${onie_platform}"; then - installer_reboot + installer_reboot $installer_wait fi exit diff --git a/docs/SupportedHardware.md b/docs/SupportedHardware.md index 658ee98b..020036d7 100644 --- a/docs/SupportedHardware.md +++ b/docs/SupportedHardware.md @@ -1,114 +1,139 @@ Hardware Support ================ +Last Updated Thu 03 May 2018 10:03:20 AM PDT Accton/Edge-Core ------ -Device Ports CPU Forwarding In Lab -Accton AS4600-54T 48x1G + 4x10G FreeScale P2020 Broadcom BCM56540 (Apollo2) Yes -Accton AS4610-54P 48x1G + 4x10G + 2x20G Dual-core ARM Cortex A9 Broadcom BCM56340 (Helix4) Yes -Accton AS5512-54X 48x10G + 6x40G Intel C2538 MediaTek/Nephos MT3258 Yes -Accton AS5610-52X 48x10G + 4x40G FreeScale P2020 Broadcom BCM56846 (Trident+) Yes -Accton AS5710-54X 48x10G + 6x40G FreeScale P2041 Broadcom BCM56854 (Trident2) Yes -Accton AS5712-54X 48x10G + 6x40G Intel C2538 Broadcom BCM56854 (Trident2) Yes -Accton AS5812-54T 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes -Accton AS5812-54X 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes -Accton AS5822-32X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes -Accton AS5912-54X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes -Accton AS5912-54XK 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes -Accton AS5916-54XM 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) No -Accton AS5916-54X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) No -Accton AS6700-32X 32x40G FreeScale P2041 Broadcom BCM56850 (Trident2) Yes -Accton AS6712-32X 32x40G Intel C2538 Broadcom BCM56850 (Trident2) Yes -Accton AS6812-32X 32x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes -Accton AS7312-54X 48x25G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes -Accton AS7712-32X 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes -Accton AS7716-32X 32x100G Intel Xeon D-1518 Broadcom BCM56960 (Tomahawk) Yes -Accton AS7816-64X 64x100 Intel C2558 Broadcom BCM56970 (Tomahawk II) Yes -Accton Wedge-16X 16x40G Intel C2550 Broadcom BCM56864 (Trident2+) Yes -Accton Wedge 100-32X 32x100G Intel E3845 Broadcom BCM56960 (Tomahawk) Yes -Accton Wedge 100S-32X 32x100G Intel D1508 Broadcom BCM56960 (Tomahawk) Yes -Alpha Networks ---- -Device Ports CPU Forwarding In Lab -SNX-60A0-486F 48x10G + 6x40G Intel C2558 Broadcom BCM56850 (Trident2) Yes - -Celestica ---- -Device Ports CPU Forwarding In Lab -Redstone-XP 48x10G + 6x40G Intel C2558 Broadcom BCM56854 (Trident2) Yes -Seastone 32x100G Intel C2558 Broadcom BCM56960 (Tomahawk) No - -DNI/Agema ---- -Device Ports CPU Forwarding In Lab -AG-7448CU 48x10G + 4x40G FreeScale P2020 Broadcom BCM56845 (Trident) Yes -AG-5648 48x25G + 6x100G Intel D1548 Broadcom BCM56960 (Tomahawk) No -AG-5648v1 48x25G + 6x100G Intel D1548 Broadcom BCM56963 (Tomahawk+) No -AG-7648 48x10G + 6x40G Intel D1548 Broadcom BCM56854 (Trident2) Yes -AG-9032v1 32x100G Intel D1548 Broadcom BCM56960 (Tomahawk) Yes -AG-9032v2 32x100G Intel D1548 Broadcom BCM56963 (Tomahawk+) No -AG-9064 64x100G Intel D1547 Broadcom BCM56970 (Tomahawk II) No -AGC-5648S 48x25G + 6x100G Intel D1548 Broadcom BCM88680 (Jericho+) No -AGC-7648A 48x10G + 6x100G Intel D1548 Broadcom BCM88370 (Qumran MX) No -WB-2448 48x1GT + 4x10G Intel E3805 Broadcom BCM56150 (Hurricane2) No -AG-6248C 48x1GT + 2x10G ARM A9 1GHz Broadcom BCM56340 (Helix4) Yes - -Dell ---- -Device Ports CPU Forwarding In Lab -S4000-ON 48x10G + 6x40G Intel C2338 Broadcom BCM56854 (Trident2) Yes -S4810-ON 48x10G + 4x40G FreeScale P2020 Broadcom BCM56845 (Trident) Yes -S4048-ON 48x10G + 6x40G Intel C2338 Broadcom BCM56854 (Trident2) Yes -S6000-ON 32x40G Intel S1220 Broadcom BCM56850 (Trident2) Yes -S6010-ON 32x40G Intel S1220 Broadcom BCM56850 (Trident2) Yes -S6100-ON 64x50G/128x25G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes -Z9100-ON 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes - -HPE ---- -Device Ports CPU Forwarding In Lab -Altoline 6921 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes -Altoline 6921T 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes -Altoline 6941 32x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes -Altoline 6960 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes - -Ingrasys ---- -Device Ports CPU Forwarding In Lab -S9100-32X 32x100G Intel Broadcom BCM56960 (Tomahawk) No - -Inventec ---- -Device Ports CPU Forwarding In Lab -D7032Q28B 32x100G Intel No - -Mellanox ---- -Device Ports CPU Forwarding In Lab -SN2100 16x100G Intel C2558 Mellanox Spectrum Yes -SN2100B 16x40G Intel C2558 Mellanox Spectrum No -SN2410 48x25G + 8x100G Intel 1047UE Mellanox Spectrum Yes -SN2410B 48x10G + 8x100G Intel 1047UE Mellanox Spectrum No -SN2700 32x100G Intel 1047UE Mellanox Spectrum Yes -SN2700B 32x40G Intel 1047UE Mellanox Spectrum No - -Netberg ---- -Device Ports CPU Forwarding In Lab -Aurora 620 32x100G Intel C2558 Broadcom BCM56960 (Tomahawk) Yes -Aurora 720 48x10/25G + 6x40/100G Intel C2558 Broadcom BCM56960 (Tomahawk) Yes +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|AS4600-54T|48x1G + 4x10G|FreeScale P2020|BCM56540 (Apollo2)|YES| +|AS4610-54P|48x1G + 4x10G + 2x20G|ARM A9 1GHz|BCM56340 (Helix4)|YES| +|AS5610-52X|48x10G + 4x40G|FreeScale P2020|BCM56846 (Trident+)|YES| +|AS5710-54X|48x10G + 6x40G|FreeScale P2040|BCM56854 (Trident2)|YES| +|AS5712-54X|48x10G + 6x40G|Intel C2538|BCM56854 (Trident2)|YES| +|AS6700-32X|32x40G|FreeScale P2041|BCM56850 (Trident2)|YES| +|AS5512-54X|48x10G + 6x40G|Intel C2538|Nephos MT32582|YES| +|AS6712-32X|32x40G|Intel C2538|BCM56850 (Trident2)|YES| +|AS5812-54T|48x10G + 6x40G|Intel C2538|BCM56864 (Trident2+)|YES| +|AS5812-54X|48x10G + 6x40G|Intel C2538|BCM56864 (Trident2+)|YES| +|AS6812-32X|32x40G|Intel C2538|BCM56864 (Trident2+)|YES| +|AS7712-32X|32x100G|Intel C2538|BCM56960 (Tomahawk)|YES| +|AS7716-32X|32x100G|Intel D-1518|BCM56960 (Tomahawk)|YES| +|Wedge-16X|16x40G|Intel C2550|BCM56864 (Trident2+)|YES| +|Wedge 100-32X|32x100G|Intel E3845|BCM56960 (Tomahawk)|YES| +|AS5912-54X|48x10G + 6x100G|Intel C2558|BCM88375 (Qumran)|YES| +|AS5912-54XK|48x10G + 6x100G|Intel C2558|BCM88375 (Qumran)|YES| +|AS5916-54XM|48x10G + 6x100G|Intel C2558|BCM88375 (Qumran)|NO| +|AS5916-54X|48x10G + 6x100G|Intel C2558|BCM88375 (Qumran)|NO| +|AS5822-32X|48x10G + 6x100G|Intel C2558|BCM88375 (Qumran)|YES| +|AS7816-64X|64x100|Intel C2558|BCM56970 (Tomahawk II)|YES| +|AS7312-54X|48x25G + 6x100G|Intel C2558|BCM88375 (Qumran)|YES| +|Wedge 100S-32X|32x100G|Intel D1508|BCM56960 (Tomahawk)|YES| +|Wedge 100BF-32x|32x100G|Intel D1517|Tofino-3.3Tb/s|NO| +|Wedge 100BF-65x|65x100G|Intel D1517|Tofino-6.5Tb/s|NO| Quanta ------ -Device Ports CPU Forwarding In Lab -QuantaMesh T1048-LB9 48x1G + 4x10G FreeScale P2020 Broadcom BCM56534 (Firebolt3) Yes -QuantaMesh T3048-LY2 48x10G + 4x40G FreeScale P2020 Broadcom BCM56846 (Trident+) Yes -QuantaMesh T5032-LY6 32x40G Intel C2758 Broadcom BCM56850 (Trident2) Yes -QuantaMesh T3048-LY7 48x10G + 4x100G Intel C2558 Broadcom BCM56768 (Maverick) Yes -QuantaMesh T3048-LY8 48x10G + 6x40G Intel C2758 Broadcom BCM56854 (Trident2) Yes -QuantaMesh T3048-LY9 48x10GT + 6x40G Intel C2758 Broadcom BCM56850 (Trident2) Yes -QuantaMesh T7032-IX1 32x100G Intel C2758 Broadcom BCM56960 (Tomahawk) Yes -QuantaMesh T7032-IX1B 32x100G Intel C2758 Broadcom BCM56960 (Tomahawk) Yes -QuantaMesh T4048-IX2 48xSFP28 + 8xQSFP28 Intel C2758 Broadcom BCM56960 (Tomahawk) Yes -QuantaMesh T4048-IX8 48x10G + 8x100G Intel Broadcom BCM56870 (Trident 3) Yes + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|QuantaMesh T1048-LY4R|48x1G + 4x10G|Intel C2338|2x BCM56150 (Hurricane2)|YES| +|QuantaMesh T3048-LY2|48x10G + 4x40G|FreeScale P2020|BCM56846 (Trident+)|YES| +|QuantaMesh T3048-LY8|48x10G + 6x40G|Intel C2758|BCM56854 (Trident2)|YES| +|QuantaMesh T5032-LY6|32x40G|Intel C2758|BCM56850 (Trident2)|YES| +|QuantaMesh T3048-LY9|48x10GT + 6x40G|Intel C2758|BCM56854 (Trident2)|YES| +|QuantaMesh T7032-IX1|32x100G|Intel C2558|BCM56960 (Tomahawk)|YES| +|QuantaMesh T4048-IX2|48xSFP28 + 8xQSFP28|Intel C2558|BCM56962 (Tomahawk)|YES| +|QuantaMesh T7032-IX1B|32x100G|Intel C2558|BCM56960 (Tomahawk)|YES| +|QuantaMesh T4048-IX8|48x10G + 8x100G|Intel C2558|BCM56873 (Trident 3)|YES| +|QuantaMesh T3048-LY7|48x10G + 4x100G|Intel C2558|BCM56760 (Maverick)|YES| +|QuantaMesh T1048-LB9|48x1G + 4x10G|FreeScale P2020|BCM56534 (Firebolt3)|YES| + +Dell +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|S4810-ON|48x10G + 4x40G|FreeScale P2020|BCM56845 (Trident2)|YES| +|S4048-ON|48x10G + 6x40G|Intel C2338|BCM56854 (Trident2)|YES| +|S6000-ON|32x40G|Intel S1220|BCM56850 (Trident2)|YES| +|Z9100-ON|32x100G|Intel C2538|BCM56960 (Tomahawk)|YES| +|S4000-ON|48x10G + 6x40G|Intel C2338|BCM56854 (Trident2)|YES| +|S6010-ON|32x40G|Intel S1220|BCM56850 (Trident2)|YES| +|S6100-ON|64x50G/128x25G|Intel C2538|BCM56960 (Tomahawk)|YES| + +Mellanox +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|SN2100|16x100G|Intel C2558|Mellanox Spectrum|YES| +|SN2100B|16x40G|Intel C2558|Mellanox Spectrum|NO| +|SN2410|48x25G + 8x100G|Intel 1047UE|Mellanox Spectrum|YES| +|SN2410B|48x10G + 8x100G|Intel 1047UE|Mellanox Spectrum|NO| +|SN2700|32x100G|Intel 1047UE|Mellanox Spectrum|YES| +|SN2700B|32x40G|Intel 1047UE|Mellanox Spectrum|NO| + +Netberg +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|Aurora 720|32x100G|Intel C2558|BCM56960 (Tomahawk)|YES| +|Aurora 620|48x10/25G + 6x40/100G|Intel C2558|BCM56960 (Tomahawk)|YES| + +Inventec +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|D7032Q28B|32x100G|Intel|on|NO| + +Celestica +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|Redstone-XP|48x10G + 6x40G|Intel C2558|BCM56854 (Trident2)|YES| +|Seastone|32x100G|Intel C2558|BCM56960 (Tomahawk)|NO| + +HPE +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|Altoline 6921|48x10G + 6x40G|Intel C2538|BCM56864 (Trident2+)|YES| +|Altoline 6921T|48x10G + 6x40G|Intel C2538|BCM56864 (Trident2+)|YES| +|Altoline 6941|32x40G|Intel C2538|BCM56864 (Trident2+)|YES| +|Altoline 6960|32x100G|Intel C2538|BCM56960 (Tomahawk)|YES| + +DNI +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|AG5648|48x25G + 6x100G|Intel D1548|BCM56960 (Tomahawk)|NO| +|AG5648v1|48x25G + 6x100G|Intel D1548|BCM56963 (Tomahawk+)|NO| +|AG7648|48x10G + 6x40G|Intel D1548|BCM56854 (Trident2)|YES| +|AG9032v1|32x100G|Intel D1548|BCM56960 (Tomahawk)|YES| +|AG9032v2|32x100G|Intel D1548|BCM56963 (Tomahawk+)|NO| +|AG9064|64x100G|Intel D1547|BCM56970 (Tomahawk II)|NO| +|AGC5648S|48x25G + 6x100G|Intel D1548|BCM88680 (Jericho+)|NO| +|AGC7648A|48x10G + 6x100G|Intel D1548|BCM88370 (Qumran MX)|NO| +|WB2448|48x1GT + 4x10G|Intel E3805|BCM56150 (Hurricane2)|NO| +|AG6248C|48x1GT + 2x10G|ARM A9 1GHz|BCM56340 (Helix4)|YES| + +Ingrasys +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|S9100-32X|32x100|Intel|BCM56960 (Tomahawk)|NO| + +Alpha Networks +------ + +|Device |Ports |CPU |Forwarding |In Lab| +|-------------|:--------------|:-------------|:------------|:-----------| +|SNX-60A0-486F|48x10G + 6x40G|Intel C2558|BCM56854 (Trident2)|NO| diff --git a/packages/base/all/initrds/loader-initrd-files/src/bin/switchroot b/packages/base/all/initrds/loader-initrd-files/src/bin/switchroot index 2eb8ead6..16529007 100644 --- a/packages/base/all/initrds/loader-initrd-files/src/bin/switchroot +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/switchroot @@ -54,6 +54,7 @@ if [ -d /sys/firmware/efi/efivars ]; then fi mount --move /sys /newroot/sys if [ -d /newroot/sys/firmware/efi/efivars ]; then + modprobe efivarfs || : mount -t efivarfs efivarfs /newroot/sys/firmware/efi/efivars fi mount --move /dev /newroot/dev 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 910b3fcf..9d869beb 100755 --- a/packages/base/all/initrds/loader-initrd-files/src/bin/sysinit +++ b/packages/base/all/initrds/loader-initrd-files/src/bin/sysinit @@ -36,6 +36,7 @@ trap "restoreconsole; reboot -f" EXIT mount -t proc proc /proc mount -t sysfs sysfs /sys if [ -d /sys/firmware/efi/efivars ]; then + modprobe efivarfs || : mount -t efivarfs efivarfs /sys/firmware/efi/efivars fi mount -o remount,size=1M /dev diff --git a/packages/base/all/vendor-config-onl/src/lib/install/lib.sh b/packages/base/all/vendor-config-onl/src/lib/install/lib.sh index d684cf15..bb6730c3 100644 --- a/packages/base/all/vendor-config-onl/src/lib/install/lib.sh +++ b/packages/base/all/vendor-config-onl/src/lib/install/lib.sh @@ -114,6 +114,7 @@ installer_mkchroot() { fi mount -t devpts devpts "${rootdir}/dev/pts" if test -d "${rootdir}/sys/firmware/efi/efivars"; then + modprobe efivarfs || : mount -t efivarfs efivarfs "${rootdir}/sys/firmware/efi/efivars" fi diff --git a/packages/base/all/vendor-config-onl/src/python/onl/install/BaseInstall.py b/packages/base/all/vendor-config-onl/src/python/onl/install/BaseInstall.py index 3290ec34..7416c20b 100755 --- a/packages/base/all/vendor-config-onl/src/python/onl/install/BaseInstall.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/install/BaseInstall.py @@ -726,6 +726,9 @@ class GrubInstaller(SubprocessMixin, Base): ctx['boot_loading_name'] = sysconfig.installer.os_name if self.isUEFI: + if not self.espFsUuid: + self.log.error("cannnot find ESP UUID") + return 1 ctx['onie_boot_uuid'] = self.espFsUuid else: ctx['onie_boot_uuid'] = "" @@ -846,6 +849,16 @@ class GrubInstaller(SubprocessMixin, Base): self.blkidParts = BlkidParser(log=self.log.getChild("blkid")) + code = self.findGpt() + if code: return code + + if self.isUEFI: + code = self.findEsp() + if code: return code + self.im.grubEnv.__dict__['espPart'] = self.espDevice + else: + self.im.grubEnv.__dict__['espPart'] = None + code = self.installGrubCfg() if code: return code diff --git a/packages/base/all/vendor-config-onl/src/python/onl/install/InstallUtils.py b/packages/base/all/vendor-config-onl/src/python/onl/install/InstallUtils.py index 85fe2c01..834eeaac 100644 --- a/packages/base/all/vendor-config-onl/src/python/onl/install/InstallUtils.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/install/InstallUtils.py @@ -1059,6 +1059,16 @@ class InitrdContext(SubprocessMixin): cmd = ('mount', '-t', 'sysfs', 'sysfs', dst,) self.check_call(cmd, vmode=self.V1) + # Hurr, the efivarfs module may not be loaded + with open("/proc/filesystems") as fd: + buf = fd.read() + if "efivarfs" not in buf: + cmd = ('modprobe', 'efivarfs',) + try: + self.check_call(cmd, vmode=self.V1) + except subprocess.CalledProcessError: + pass + dst = os.path.join(self.dir, "sys/firmware/efi/efivars") if os.path.exists(dst): cmd = ('mount', '-t', 'efivarfs', 'efivarfs', dst,) diff --git a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py index a2d00feb..46a6ccb7 100755 --- a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py @@ -528,3 +528,7 @@ class OnlPlatformPortConfig_8x1_8x10(object): class OnlPlatformPortConfig_48x10_6x100(object): PORT_COUNT=54 PORT_CONFIG="48x10 + 6x100" + +class OnlPlatformPortConfig_12x10_3x100(object): + PORT_COUNT=15 + PORT_CONFIG="12x10 + 3x100" diff --git a/packages/base/all/vendor-config-onl/src/python/onl/upgrade/loader.py b/packages/base/all/vendor-config-onl/src/python/onl/upgrade/loader.py index 9ebec5b5..bf3bbe51 100755 --- a/packages/base/all/vendor-config-onl/src/python/onl/upgrade/loader.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/upgrade/loader.py @@ -89,6 +89,8 @@ class LoaderUpgrade_Fit(LoaderUpgradeBase): path = os.path.join(octx.initrdDir, "etc/machine.conf") if os.path.exists(path): machineConf = ConfUtils.MachineConf(path=path) + else: + machineConf = ConfUtils.MachineConf(path='/dev/null') installerConf = ConfUtils.InstallerConf(path="/dev/null") # start with an empty installerConf, fill it in piece by piece @@ -171,41 +173,54 @@ class LoaderUpgrade_x86_64(LoaderUpgradeBase, InstallUtils.SubprocessMixin): onlPlatform = onl.platform.current.OnlPlatform() - with OnieBootContext(log=self.logger) as octx: + with OnieBootContext(log=self.log) as octx: + + octx.ictx.attach() + octx.ictx.unmount() + octx.ictx.detach() + # XXX roth -- here, detach the initrd mounts + + octx.detach() + # hold on to the ONIE boot context for grub access + + if os.path.exists("/usr/bin/onie-shell"): + machineConf = OnieSysinfo(log=self.logger.getChild("onie-sysinfo")) + else: path = os.path.join(octx.initrdDir, "etc/machine.conf") - machineConf = ConfUtils.MachineConf(path=path) + if os.path.exists(path): + machineConf = ConfUtils.MachineConf(path=path) + else: + machineConf = ConfUtils.MachineConf(path='/dev/null') - # hold on to the ONIE boot context for grub access + installerConf = ConfUtils.InstallerConf(path="/dev/null") - installerConf = ConfUtils.InstallerConf(path="/dev/null") + # XXX fill in installerConf fields + installerConf.installer_platform = onlPlatform.platform() + installerConf.installer_arch = machineConf.onie_arch + installerConf.installer_platform_dir = os.path.join("/lib/platform-config", + onlPlatform.platform()) - # XXX fill in installerConf fields - installerConf.installer_platform = onlPlatform.platform() - installerConf.installer_arch = machineConf.onie_arch - installerConf.installer_platform_dir = os.path.join("/lib/platform-config", - onlPlatform.platform()) + mfPath = os.path.join(sysconfig.upgrade.loader.package.dir, "manifest.json") + mf = onl.versions.OnlVersionManifest(mfPath) + installerConf.onl_version = mf.RELEASE_ID - mfPath = os.path.join(sysconfig.upgrade.loader.package.dir, "manifest.json") - mf = onl.versions.OnlVersionManifest(mfPath) - installerConf.onl_version = mf.RELEASE_ID + grubEnv = ConfUtils.ChrootGrubEnv(octx.initrdDir, + bootDir=octx.onieDir, + path="/grub/grubenv", + log=self.logger.getChild("grub")) - grubEnv = ConfUtils.ChrootGrubEnv(octx.initrdDir, - bootDir=octx.onieDir, - path="/grub/grubenv", - log=self.logger.getChild("grub")) + ubootEnv = None - ubootEnv = None + installer = self.installer_klass(machineConf=machineConf, + installerConf=installerConf, + platformConf=onlPlatform.platform_config, + grubEnv=grubEnv, + ubootEnv=ubootEnv, + force=True, + log=self.logger) - installer = self.installer_klass(machineConf=machineConf, - installerConf=installerConf, - platformConf=onlPlatform.platform_config, - grubEnv=grubEnv, - ubootEnv=ubootEnv, - force=True, - log=self.logger) - - installer.upgradeBootLoader() - installer.shutdown() + installer.upgradeBootLoader() + installer.shutdown() self.reboot() diff --git a/packages/base/any/kernels/modules/optoe.c b/packages/base/any/kernels/modules/optoe.c new file mode 100644 index 00000000..b3064f02 --- /dev/null +++ b/packages/base/any/kernels/modules/optoe.c @@ -0,0 +1,1146 @@ +/* + * 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/base/any/onlp/src/sff/module/auto/sff.yml b/packages/base/any/onlp/src/sff/module/auto/sff.yml index 038eb41f..69ef9e50 100644 --- a/packages/base/any/onlp/src/sff/module/auto/sff.yml +++ b/packages/base/any/onlp/src/sff/module/auto/sff.yml @@ -77,6 +77,10 @@ sff_module_types: &sff_module_types desc: "25GBASE-CR" - 25G_BASE_SR: desc: "25GBASE-SR" +- 25G_BASE_LR: + desc: "25GBASE-LR" +- 25G_BASE_AOC: + desc: "25GBASE-AOC" - 10G_BASE_SR: desc: "10GBASE-SR" - 10G_BASE_LR: diff --git a/packages/base/any/onlp/src/sff/module/inc/sff/8472.h b/packages/base/any/onlp/src/sff/module/inc/sff/8472.h index 20b52d70..0e2f73d0 100644 --- a/packages/base/any/onlp/src/sff/module/inc/sff/8472.h +++ b/packages/base/any/onlp/src/sff/module/inc/sff/8472.h @@ -149,6 +149,9 @@ #define SFF8472_CC36_XGE_UNALLOCATED 0x01 #define SFF8472_CC36_UNALLOCATED1 0xF7 #define SFF8472_CC36_100G_25G_SR 0x02 +#define SFF8472_CC36_100G_25G_LR 0x03 +#define SFF8472_CC36_100G_25G_AOC_1 0x01 +#define SFF8472_CC36_100G_25G_AOC_2 0x18 #define SFF8471_CC60_FC_PI_4_LIMITING 0x08 #define SFF8471_CC60_SFF8431_LIMITING 0x04 @@ -986,4 +989,30 @@ _sff8472_media_sfp28_sr(const uint8_t* idprom) return 0; } +static inline int +_sff8472_media_sfp28_lr(const uint8_t* idprom) +{ + /* module should be sfp */ + if (!SFF8472_MODULE_SFP(idprom)) return 0; + + if (idprom[12] != 0xFF) return 0; + if (idprom[36] == SFF8472_CC36_100G_25G_LR) return 1; + + return 0; +} + +static inline int +_sff8472_media_sfp28_aoc(const uint8_t* idprom) +{ + /* module should be sfp */ + if (!SFF8472_MODULE_SFP(idprom)) return 0; + + if (idprom[12] != 0xFF) return 0; + if ((idprom[36] == SFF8472_CC36_100G_25G_AOC_1) || + (idprom[36] == SFF8472_CC36_100G_25G_AOC_2)) { + return 1; + } + + return 0; +} #endif diff --git a/packages/base/any/onlp/src/sff/module/inc/sff/sff.h b/packages/base/any/onlp/src/sff/module/inc/sff/sff.h index ce580cf4..8971a36d 100644 --- a/packages/base/any/onlp/src/sff/module/inc/sff/sff.h +++ b/packages/base/any/onlp/src/sff/module/inc/sff/sff.h @@ -114,6 +114,8 @@ typedef enum sff_module_type_e { SFF_MODULE_TYPE_40G_BASE_ER4, SFF_MODULE_TYPE_25G_BASE_CR, SFF_MODULE_TYPE_25G_BASE_SR, + SFF_MODULE_TYPE_25G_BASE_LR, + SFF_MODULE_TYPE_25G_BASE_AOC, SFF_MODULE_TYPE_10G_BASE_SR, SFF_MODULE_TYPE_10G_BASE_LR, SFF_MODULE_TYPE_10G_BASE_LRM, @@ -155,6 +157,8 @@ typedef enum sff_module_type_e { "40G_BASE_ER4", \ "25G_BASE_CR", \ "25G_BASE_SR", \ + "25G_BASE_LR", \ + "25G_BASE_AOC", \ "10G_BASE_SR", \ "10G_BASE_LR", \ "10G_BASE_LRM", \ diff --git a/packages/base/any/onlp/src/sff/module/inc/sff/sff.x b/packages/base/any/onlp/src/sff/module/inc/sff/sff.x index 82ec6c09..40499305 100644 --- a/packages/base/any/onlp/src/sff/module/inc/sff/sff.x +++ b/packages/base/any/onlp/src/sff/module/inc/sff/sff.x @@ -24,6 +24,8 @@ SFF_MEDIA_TYPE_ENTRY(40G_BASE_SM4, 40GBASE-SM4) SFF_MEDIA_TYPE_ENTRY(40G_BASE_ER4, 40GBASE-ER4) SFF_MEDIA_TYPE_ENTRY(25G_BASE_CR, 25GBASE-CR) SFF_MEDIA_TYPE_ENTRY(25G_BASE_SR, 25GBASE-SR) +SFF_MEDIA_TYPE_ENTRY(25G_BASE_LR, 25GBASE-LR) +SFF_MEDIA_TYPE_ENTRY(25G_BASE_AOC, 25GBASE-AOC) SFF_MEDIA_TYPE_ENTRY(10G_BASE_SR, 10GBASE-SR) SFF_MEDIA_TYPE_ENTRY(10G_BASE_LR, 10GBASE-LR) SFF_MEDIA_TYPE_ENTRY(10G_BASE_LRM, 10GBASE-LRM) @@ -71,6 +73,8 @@ SFF_MODULE_TYPE_ENTRY(40G_BASE_SM4, 40GBASE-SM4) SFF_MODULE_TYPE_ENTRY(40G_BASE_ER4, 40GBASE-ER4) SFF_MODULE_TYPE_ENTRY(25G_BASE_CR, 25GBASE-CR) SFF_MODULE_TYPE_ENTRY(25G_BASE_SR, 25GBASE-SR) +SFF_MODULE_TYPE_ENTRY(25G_BASE_LR, 25GBASE-LR) +SFF_MODULE_TYPE_ENTRY(25G_BASE_AOC, 25GBASE-AOC) SFF_MODULE_TYPE_ENTRY(10G_BASE_SR, 10GBASE-SR) SFF_MODULE_TYPE_ENTRY(10G_BASE_LR, 10GBASE-LR) SFF_MODULE_TYPE_ENTRY(10G_BASE_LRM, 10GBASE-LRM) diff --git a/packages/base/any/onlp/src/sff/module/python/onlp/sff/enums.py b/packages/base/any/onlp/src/sff/module/python/onlp/sff/enums.py index 747c7090..31ddcda5 100644 --- a/packages/base/any/onlp/src/sff/module/python/onlp/sff/enums.py +++ b/packages/base/any/onlp/src/sff/module/python/onlp/sff/enums.py @@ -44,22 +44,24 @@ class SFF_MODULE_TYPE(Enumeration): _40G_BASE_ER4 = 14 _25G_BASE_CR = 15 _25G_BASE_SR = 16 - _10G_BASE_SR = 17 - _10G_BASE_LR = 18 - _10G_BASE_LRM = 19 - _10G_BASE_ER = 20 - _10G_BASE_CR = 21 - _10G_BASE_SX = 22 - _10G_BASE_LX = 23 - _10G_BASE_ZR = 24 - _10G_BASE_SRL = 25 - _1G_BASE_SX = 26 - _1G_BASE_LX = 27 - _1G_BASE_CX = 28 - _1G_BASE_T = 29 - _100_BASE_LX = 30 - _100_BASE_FX = 31 - _4X_MUX = 32 + _25G_BASE_LR = 17 + _25G_BASE_AOC = 18 + _10G_BASE_SR = 19 + _10G_BASE_LR = 20 + _10G_BASE_LRM = 21 + _10G_BASE_ER = 22 + _10G_BASE_CR = 23 + _10G_BASE_SX = 24 + _10G_BASE_LX = 25 + _10G_BASE_ZR = 26 + _10G_BASE_SRL = 27 + _1G_BASE_SX = 28 + _1G_BASE_LX = 29 + _1G_BASE_CX = 30 + _1G_BASE_T = 31 + _100_BASE_LX = 32 + _100_BASE_FX = 33 + _4X_MUX = 34 class SFF_SFP_TYPE(Enumeration): diff --git a/packages/base/any/onlp/src/sff/module/src/sff.c b/packages/base/any/onlp/src/sff/module/src/sff.c index 281c4450..b21ace8f 100644 --- a/packages/base/any/onlp/src/sff/module/src/sff.c +++ b/packages/base/any/onlp/src/sff/module/src/sff.c @@ -153,6 +153,16 @@ sff_module_type_get(const uint8_t* eeprom) return SFF_MODULE_TYPE_25G_BASE_SR; } + if (SFF8472_MODULE_SFP(eeprom) + && _sff8472_media_sfp28_lr(eeprom)) { + return SFF_MODULE_TYPE_25G_BASE_LR; + } + + if (SFF8472_MODULE_SFP(eeprom) + && _sff8472_media_sfp28_aoc(eeprom)) { + return SFF_MODULE_TYPE_25G_BASE_AOC; + } + if (SFF8472_MODULE_SFP(eeprom) && SFF8472_MEDIA_XGE_SR(eeprom) && !_sff8472_media_gbe_sx_fc_hack(eeprom)) @@ -261,6 +271,8 @@ sff_media_type_get(sff_module_type_t mt) case SFF_MODULE_TYPE_40G_BASE_SM4: case SFF_MODULE_TYPE_40G_BASE_ER4: case SFF_MODULE_TYPE_25G_BASE_SR: + case SFF_MODULE_TYPE_25G_BASE_LR: + case SFF_MODULE_TYPE_25G_BASE_AOC: case SFF_MODULE_TYPE_10G_BASE_SR: case SFF_MODULE_TYPE_10G_BASE_LR: case SFF_MODULE_TYPE_10G_BASE_LRM: @@ -317,6 +329,7 @@ sff_module_caps_get(sff_module_type_t mt, uint32_t *caps) case SFF_MODULE_TYPE_25G_BASE_CR: case SFF_MODULE_TYPE_25G_BASE_SR: + case SFF_MODULE_TYPE_25G_BASE_AOC: *caps |= SFF_MODULE_CAPS_F_25G; return 0; @@ -490,6 +503,7 @@ sff_eeprom_parse_standard__(sff_eeprom_t* se, uint8_t* eeprom) break; case SFF_SFP_TYPE_QSFP_PLUS: case SFF_SFP_TYPE_SFP: + case SFF_SFP_TYPE_SFP28: aoc_length = _sff8436_qsfp_40g_aoc_length(se->eeprom); if (aoc_length < 0) aoc_length = _sff8472_sfp_10g_aoc_length(se->eeprom); @@ -740,6 +754,8 @@ sff_info_init(sff_info_t* info, sff_module_type_t mt, break; case SFF_MODULE_TYPE_25G_BASE_SR: + case SFF_MODULE_TYPE_25G_BASE_LR: + case SFF_MODULE_TYPE_25G_BASE_AOC: info->sfp_type = SFF_SFP_TYPE_SFP28; info->media_type = SFF_MEDIA_TYPE_FIBER; info->caps = SFF_MODULE_CAPS_F_25G; diff --git a/packages/base/any/onlp/src/sff/module/src/sff_enums.c b/packages/base/any/onlp/src/sff/module/src/sff_enums.c index 8d8e62b9..d499582c 100644 --- a/packages/base/any/onlp/src/sff/module/src/sff_enums.c +++ b/packages/base/any/onlp/src/sff/module/src/sff_enums.c @@ -148,6 +148,8 @@ aim_map_si_t sff_module_type_map[] = { "40G_BASE_ER4", SFF_MODULE_TYPE_40G_BASE_ER4 }, { "25G_BASE_CR", SFF_MODULE_TYPE_25G_BASE_CR }, { "25G_BASE_SR", SFF_MODULE_TYPE_25G_BASE_SR }, + { "25G_BASE_LR", SFF_MODULE_TYPE_25G_BASE_LR }, + { "25G_BASE_AOC", SFF_MODULE_TYPE_25G_BASE_AOC }, { "10G_BASE_SR", SFF_MODULE_TYPE_10G_BASE_SR }, { "10G_BASE_LR", SFF_MODULE_TYPE_10G_BASE_LR }, { "10G_BASE_LRM", SFF_MODULE_TYPE_10G_BASE_LRM }, @@ -186,6 +188,8 @@ aim_map_si_t sff_module_type_desc_map[] = { "40GBASE-ER4", SFF_MODULE_TYPE_40G_BASE_ER4 }, { "25GBASE-CR", SFF_MODULE_TYPE_25G_BASE_CR }, { "25GBASE-SR", SFF_MODULE_TYPE_25G_BASE_SR }, + { "25GBASE-LR", SFF_MODULE_TYPE_25G_BASE_LR }, + { "25GBASE-AOC", SFF_MODULE_TYPE_25G_BASE_AOC }, { "10GBASE-SR", SFF_MODULE_TYPE_10G_BASE_SR }, { "10GBASE-LR", SFF_MODULE_TYPE_10G_BASE_LR }, { "10GBASE-LRM", SFF_MODULE_TYPE_10G_BASE_LRM }, diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-sfp.c deleted file mode 100644 index 8202b39e..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-sfp.c +++ /dev/null @@ -1,1882 +0,0 @@ -/* - * SFP driver for accton as5712_54x sfp - * - * Copyright (C) Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "as5712_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 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8472_DIAG_MON_TYPE_ADDR 92 -#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -#define MULTIPAGE_SUPPORT 1 - -#if (MULTIPAGE_SUPPORT == 1) -/* fundamental unit of addressing for SFF_8472/SFF_8436 */ -#define SFF_8436_PAGE_SIZE 128 -/* - * The current 8436 (QSFP) spec provides for only 4 supported - * pages (pages 0-3). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8436_SPECED_PAGES 4 -#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) -/* - * The current 8472 (SFP) spec provides for only 3 supported - * pages (pages 0-2). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8472_SPECED_PAGES 3 -#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define SFF_8436_PAGE_SELECT_REG 0x7F -#define SFF_8436_PAGEABLE_REG 0x02 -#define SFF_8436_NOT_PAGEABLE (1<<2) -#define SFF_8472_PAGEABLE_REG 0x40 -#define SFF_8472_PAGEABLE (1<<4) - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = SFF_8436_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; - -typedef enum qsfp_opcode { - QSFP_READ_OP = 0, - QSFP_WRITE_OP = 1 -} qsfp_opcode_e; -#endif - -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 as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -enum 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_rx_loss, 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_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_loss.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_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); -static struct attribute *sfp_msa_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - NULL -}; - -/* Platform dependent +++ */ -/* The table maps active port to cpld port. - * Array index 0 is for active port 1, - * index 1 for active port 2, and so on. - * The array content implies cpld port index. - */ -static const u8 cpld_to_front_port_table[] = -{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 52, 50, 53, 51, 54}; -#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port]) - -enum port_numbers { -as5712_54x_port1, as5712_54x_port2, as5712_54x_port3, as5712_54x_port4, -as5712_54x_port5, as5712_54x_port6, as5712_54x_port7, as5712_54x_port8, -as5712_54x_port9, as5712_54x_port10, as5712_54x_port11, as5712_54x_port12, -as5712_54x_port13, as5712_54x_port14, as5712_54x_port15, as5712_54x_port16, -as5712_54x_port17, as5712_54x_port18, as5712_54x_port19, as5712_54x_port20, -as5712_54x_port21, as5712_54x_port22, as5712_54x_port23, as5712_54x_port24, -as5712_54x_port25, as5712_54x_port26, as5712_54x_port27, as5712_54x_port28, -as5712_54x_port29, as5712_54x_port30, as5712_54x_port31, as5712_54x_port32, -as5712_54x_port33, as5712_54x_port34, as5712_54x_port35, as5712_54x_port36, -as5712_54x_port37, as5712_54x_port38, as5712_54x_port39, as5712_54x_port40, -as5712_54x_port41, as5712_54x_port42, as5712_54x_port43, as5712_54x_port44, -as5712_54x_port45, as5712_54x_port46, as5712_54x_port47, as5712_54x_port48, -as5712_54x_port49, as5712_54x_port52, as5712_54x_port50, as5712_54x_port53, -as5712_54x_port51, as5712_54x_port54 -}; - -#define I2C_DEV_ID(x) { #x, x} - -static const struct i2c_device_id sfp_device_id[] = { -I2C_DEV_ID(as5712_54x_port1), -I2C_DEV_ID(as5712_54x_port2), -I2C_DEV_ID(as5712_54x_port3), -I2C_DEV_ID(as5712_54x_port4), -I2C_DEV_ID(as5712_54x_port5), -I2C_DEV_ID(as5712_54x_port6), -I2C_DEV_ID(as5712_54x_port7), -I2C_DEV_ID(as5712_54x_port8), -I2C_DEV_ID(as5712_54x_port9), -I2C_DEV_ID(as5712_54x_port10), -I2C_DEV_ID(as5712_54x_port11), -I2C_DEV_ID(as5712_54x_port12), -I2C_DEV_ID(as5712_54x_port13), -I2C_DEV_ID(as5712_54x_port14), -I2C_DEV_ID(as5712_54x_port15), -I2C_DEV_ID(as5712_54x_port16), -I2C_DEV_ID(as5712_54x_port17), -I2C_DEV_ID(as5712_54x_port18), -I2C_DEV_ID(as5712_54x_port19), -I2C_DEV_ID(as5712_54x_port20), -I2C_DEV_ID(as5712_54x_port21), -I2C_DEV_ID(as5712_54x_port22), -I2C_DEV_ID(as5712_54x_port23), -I2C_DEV_ID(as5712_54x_port24), -I2C_DEV_ID(as5712_54x_port25), -I2C_DEV_ID(as5712_54x_port26), -I2C_DEV_ID(as5712_54x_port27), -I2C_DEV_ID(as5712_54x_port28), -I2C_DEV_ID(as5712_54x_port29), -I2C_DEV_ID(as5712_54x_port30), -I2C_DEV_ID(as5712_54x_port31), -I2C_DEV_ID(as5712_54x_port32), -I2C_DEV_ID(as5712_54x_port33), -I2C_DEV_ID(as5712_54x_port34), -I2C_DEV_ID(as5712_54x_port35), -I2C_DEV_ID(as5712_54x_port36), -I2C_DEV_ID(as5712_54x_port37), -I2C_DEV_ID(as5712_54x_port38), -I2C_DEV_ID(as5712_54x_port39), -I2C_DEV_ID(as5712_54x_port40), -I2C_DEV_ID(as5712_54x_port41), -I2C_DEV_ID(as5712_54x_port42), -I2C_DEV_ID(as5712_54x_port43), -I2C_DEV_ID(as5712_54x_port44), -I2C_DEV_ID(as5712_54x_port45), -I2C_DEV_ID(as5712_54x_port46), -I2C_DEV_ID(as5712_54x_port47), -I2C_DEV_ID(as5712_54x_port48), -I2C_DEV_ID(as5712_54x_port49), -I2C_DEV_ID(as5712_54x_port50), -I2C_DEV_ID(as5712_54x_port51), -I2C_DEV_ID(as5712_54x_port52), -I2C_DEV_ID(as5712_54x_port53), -I2C_DEV_ID(as5712_54x_port54), -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); -/* Platform dependent --- */ - -enum driver_type_e { - DRIVER_TYPE_SFP_MSA, - DRIVER_TYPE_QSFP -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct sfp_msa_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u64 status[6]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss - 3 => device id - 4 => 10G Ethernet Compliance Codes - to distinguish SFP or SFP+ - 5 => DIAGNOSTIC MONITORING TYPE */ - struct eeprom_data eeprom; -#if (MULTIPAGE_SUPPORT == 1) - struct i2c_client *ddm_client; /* dummy client instance for 0xA2 */ -#endif -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct sfp_msa_data *msa; - struct qsfp_data *qsfp; - - struct i2c_client *client; -#if (MULTIPAGE_SUPPORT == 1) - int use_smbus; - u8 *writebuf; - unsigned write_max; -#endif -}; - -#if (MULTIPAGE_SUPPORT == 1) -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); -#endif -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - int i = 0, j = 0, status = -1; - u8 reg; - unsigned short cpld_addr; - struct sfp_port_data *data = i2c_get_clientdata(client); - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - data->present = 0; - - /* Read present status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - cpld_addr = 0x61+i; - reg = 0x6+j; - status = as5712_54x_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-54(QSFP port) */ - cpld_addr = 0x62; - reg = 0x14; - status = as5712_54x_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 << 48; - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0, j = 0; - int status = -1; - - if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { - return data; - } - - DEBUG_PRINT("Starting as5712_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 = as5712_54x_i2c_cpld_read(cpld_addr, reg); - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - - data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); - } - } - - data->msa->valid = 1; - data->msa->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - unsigned short cpld_addr = 0; - u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; - long disable; - int error; - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_set_tx_disable(dev, da, buf, count); - } - - error = kstrtol(buf, 10, &disable); - if (error) { - return error; - } - - mutex_lock(&data->update_lock); - - if(data->port < 24) { - cpld_addr = 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 = as5712_54x_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; - } - - as5712_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); - mutex_unlock(&data->update_lock); - return count; -} -/* Platform dependent --- */ - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ -} - -/* Platform dependent +++ */ -static ssize_t show_present(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - - if (PRESENT_ALL == attr->index) { - int i; - u8 values[7] = {0}; - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = ~(u8)(data->present >> (i * 8)); - } - - /* Return values 1 -> 54 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5], - values[6] & 0x3F); - } - else { - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - /* PRESENT */ - return sprintf(buf, "%d", 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 sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_show_tx_rx_status(dev, da, buf); - } - - data = sfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - if(attr->index == RX_LOS_ALL) { - int i = 0; - u8 values[6] = {0}; - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = (u8)(data->msa->status[2] >> (i * 8)); - } - - /** Return values 1 -> 48 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5]); - } - - switch (attr->index) { - case TX_FAULT: - index = 0; - break; - case TX_DISABLE: - index = 1; - break; - case RX_LOS: - index = 2; - break; - default: - return 0; - } - - val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; - return sprintf(buf, "%d", val); -} -/* Platform dependent --- */ - -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -#if (MULTIPAGE_SUPPORT == 0) -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} -#endif - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); -#else - return sfp_port_write(data, buf, off, count); -#endif -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both SFP and QSFP. - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ -static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = port_data->client; - - /* if SFP style, offset > 255, shift to i2c addr 0x51 */ - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - if (*offset > 255) { - /* like QSFP, but shifted to client[1] */ - *client = port_data->msa->ddm_client; - *offset -= 256; - } - } - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < SFF_8436_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, - struct i2c_client *client, - char *buf, unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, - struct i2c_client *client, - const char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > port_data->write_max) - count = port_data->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = port_data->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, - char *buf, loff_t off, - size_t count, qsfp_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - u8 page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = sff_8436_translate_offset(port_data, &phy_offset, &client); - - dev_dbg(&client->dev, - "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == QSFP_READ_OP) { - status = sff_8436_eeprom_read(port_data, client, - buf, phy_offset, count); - } else { - status = sff_8436_eeprom_write(port_data, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - return retval; -} - - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return -EINVAL - */ -static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, - loff_t off, size_t len) -{ - struct i2c_client *client = port_data->client; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - /* SFP case */ - if ((off + len) <= 256) return len; - /* if no pages needed, we're good */ - //if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; - - /* Check if ddm is supported */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF8472_DIAG_MON_TYPE_ADDR, 1); - if (status < 0) return status; /* error out (no module?) */ - if (!(regval & SFF8472_DIAG_MON_TYPE_DDM_MASK)) { - if (off >= 256) return -EINVAL; - maxlen = 256 - off; - } - else { - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8472_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8472_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8472_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - if (off >= SFF_8472_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; - } - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } - else if (port_data->driver_type == DRIVER_TYPE_QSFP) { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8436_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8436_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - if (off >= SFF_8436_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8436_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - else { - return -EINVAL; - } - return len; -} - - -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) -{ - struct i2c_client *client = port_data->client; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&port_data->update_lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - len = sff_8436_page_legal(port_data, off, len); - if (len < 0) { - status = len; - goto err; - } - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - SFF_8436_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ - } else { - chunk_offset = chunk_start_offset; - if (pending_len > SFF_8436_PAGE_SIZE) - chunk_len = SFF_8436_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = sff_8436_eeprom_update_client(port_data, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - goto err; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&port_data->update_lock); - - return retval; - -err: - mutex_unlock(&port_data->update_lock); - - return status; -} - -#else -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} -#endif - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); -#else - return sfp_port_read(data, buf, off, count); -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) -#else -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -#endif -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; -#if (MULTIPAGE_SUPPORT == 1) - eeprom->size = size; -#else - eeprom->size = EEPROM_SIZE; -#endif - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - - -#if (MULTIPAGE_SUPPORT == 0) -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} -#endif - -static const struct attribute_group sfp_msa_group = { - .attrs = sfp_msa_attributes, -}; - -static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_msa_data **data) -{ - int status; - struct sfp_msa_data *msa; - -#if (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); - if (!msa) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - -#if (MULTIPAGE_SUPPORT == 1) - msa->ddm_client = i2c_new_dummy(client->adapter, client->addr + 1); - if (!msa->ddm_client) { - dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + 1); - status = -EADDRINUSE; - goto exit_eeprom; - } -#endif - - *data = msa; - dev_info(&client->dev, "sfp msa '%s'\n", client->name); - - return 0; - -exit_eeprom: - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &msa->eeprom.bin); -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -exit_free: - kfree(msa); -exit: - - return status; -} - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - -#if (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - - /* Bring QSFPs out of reset */ - as5712_54x_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; -} - -/* Platform dependent +++ */ -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int ret = 0; - struct sfp_port_data *data = NULL; - - if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { - return -ENODEV; - } - - if (dev_id->driver_data < as5712_54x_port1 || dev_id->driver_data > as5712_54x_port54) { - return -ENXIO; - } - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - -#if (MULTIPAGE_SUPPORT == 1) - data->use_smbus = 0; - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - data->use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - data->use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - ret = -EPFNOSUPPORT; - goto exit_kfree; - } - } - - if (!data->use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned write_max = 1; - - if (write_max > io_limit) - write_max = io_limit; - if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - data->write_max = write_max; - - /* buffer (data + address at the beginning) */ - data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!data->writebuf) { - ret = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - if (data->use_smbus == I2C_SMBUS_WORD_DATA || - data->use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", data->use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } -#endif - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - - if (dev_id->driver_data >= as5712_54x_port1 && dev_id->driver_data <= as5712_54x_port48) { - data->driver_type = DRIVER_TYPE_SFP_MSA; - ret = sfp_msa_probe(client, dev_id, &data->msa); - } - else { /* as5712_54x_portsfp49 ~ as5712_54x_portsfp54 */ - data->driver_type = DRIVER_TYPE_QSFP; - ret = qsfp_probe(client, dev_id, &data->qsfp); - } - - if (ret < 0) { - goto exit_kfree_buf; - } - - - return ret; - -exit_kfree_buf: -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) kfree(data->writebuf); -#endif - -exit_kfree: - kfree(data); - return ret; -} -/* Platform dependent --- */ - -static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); -#if (MULTIPAGE_SUPPORT == 1) - i2c_unregister_device(data->ddm_client); -#endif - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); - kfree(data); - return 0; -} - -static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - int ret = 0; - struct sfp_port_data *data = i2c_get_clientdata(client); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - return sfp_msa_remove(client, data->msa); - case DRIVER_TYPE_QSFP: - return qfp_remove(client, data->qsfp); - } - -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) - kfree(data->writebuf); -#endif - kfree(data); - return ret; -} - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as5712_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-as5812-54t/modules/builds/x86-64-accton-as5812-54t-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54t/modules/builds/x86-64-accton-as5812-54t-sfp.c deleted file mode 100644 index 0f1b7aac..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54t/modules/builds/x86-64-accton-as5812-54t-sfp.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * SFP driver for accton as5812_54t 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 "as5812_54t_sfp" - -#define DEBUG_MODE 0 - -#if (DEBUG_MODE == 1) - #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#else - #define DEBUG_PRINT(fmt, args...) -#endif - -#define NUM_OF_SFP_PORT 32 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -#define MULTIPAGE_SUPPORT 1 - -#if (MULTIPAGE_SUPPORT == 1) -/* fundamental unit of addressing for SFF_8472/SFF_8436 */ -#define SFF_8436_PAGE_SIZE 128 -/* - * The current 8436 (QSFP) spec provides for only 4 supported - * pages (pages 0-3). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8436_SPECED_PAGES 4 -#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) -/* - * The current 8472 (SFP) spec provides for only 3 supported - * pages (pages 0-2). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8472_SPECED_PAGES 3 -#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define SFF_8436_PAGE_SELECT_REG 0x7F -#define SFF_8436_PAGEABLE_REG 0x02 -#define SFF_8436_NOT_PAGEABLE (1<<2) -#define SFF_8472_PAGEABLE_REG 0x40 -#define SFF_8472_PAGEABLE (1<<4) - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = SFF_8436_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; - -typedef enum qsfp_opcode { - QSFP_READ_OP = 0, - QSFP_WRITE_OP = 1 -} qsfp_opcode_e; -#endif - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; -static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int accton_i2c_cpld_read(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_is_present, S_IRUGO, show_present, NULL, PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT); - -/* QSFP attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -static struct attribute *qsfp_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, - NULL -}; - -/* Platform dependent +++ */ -#define CPLD_PORT_TO_FRONT_PORT(port) (port+49) - -enum port_numbers { -as5812_54t_port49, -as5812_54t_port50, -as5812_54t_port51, -as5812_54t_port52, -as5812_54t_port53, -as5812_54t_port54 -}; - -#define I2C_DEV_ID(x) { #x, x} - -static const struct i2c_device_id sfp_device_id[] = { -I2C_DEV_ID(as5812_54t_port49), -I2C_DEV_ID(as5812_54t_port50), -I2C_DEV_ID(as5812_54t_port51), -I2C_DEV_ID(as5812_54t_port52), -I2C_DEV_ID(as5812_54t_port53), -I2C_DEV_ID(as5812_54t_port54), -{ /* 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 -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct qsfp_data *qsfp; - - struct i2c_client *client; -#if (MULTIPAGE_SUPPORT == 1) - int use_smbus; - u8 *writebuf; - unsigned write_max; -#endif -}; - -#if (MULTIPAGE_SUPPORT == 1) -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); -#endif - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - int status = -1; - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - - /* Read present status of port 49~54 */ - data->present = 0; - - status = accton_i2c_cpld_read(0x60, 0x22); - if (status < 0) { - DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); - goto exit; - } - - data->present |= (u64)status; - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -/* Platform dependent --- */ - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ -} - -/* Platform dependent +++ */ -static ssize_t show_present(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - - if (PRESENT_ALL == attr->index) { - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - /* Return values 49 -> 54 in order */ - return sprintf(buf, "%.2x\n", (unsigned int)~data->present); - } - 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", present); - } -} -/* Platform dependent --- */ - -static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i, status = -1; - u8 buf = 0; - u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; - - if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { - return data; - } - - DEBUG_PRINT("Starting sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->qsfp->valid = 0; - memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); - - /* Notify device to update tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - } - msleep(200); - - /* Read actual tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - - DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); - data->qsfp->status[i] = (buf & 0xF); - } - - data->qsfp->valid = 1; - data->qsfp->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int present; - u8 val = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - present = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENXIO; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - switch (attr->index) { - case TX_FAULT: - val = !!(data->qsfp->status[2] & 0xF); - break; - case TX_FAULT1: - case TX_FAULT2: - case TX_FAULT3: - case TX_FAULT4: - val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); - break; - case TX_DISABLE: - val = data->qsfp->status[1] & 0xF; - break; - case TX_DISABLE1: - case TX_DISABLE2: - case TX_DISABLE3: - case TX_DISABLE4: - val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); - break; - case RX_LOS: - val = !!(data->qsfp->status[0] & 0xF); - break; - case RX_LOS1: - case RX_LOS2: - case RX_LOS3: - case RX_LOS4: - val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); - break; - default: - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - long disable; - int status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (!status) { - /* port is not present */ - return -ENXIO; - } - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - mutex_lock(&data->update_lock); - - if (attr->index == TX_DISABLE) { - if (disable) { - data->qsfp->status[1] |= 0xF; - } - else { - data->qsfp->status[1] &= ~0xF; - } - } - else {/* TX_DISABLE1 ~ TX_DISABLE4*/ - if (disable) { - data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); - } - else { - data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); - } - } - - DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); - status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); - if (unlikely(status < 0)) { - count = status; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -#if (MULTIPAGE_SUPPORT == 0) -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} -#endif - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); -#else - return sfp_port_write(data, buf, off, count); -#endif -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both SFP and QSFP. - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ -static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = port_data->client; - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < SFF_8436_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, - struct i2c_client *client, - char *buf, unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, - struct i2c_client *client, - const char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > port_data->write_max) - count = port_data->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = port_data->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, - char *buf, loff_t off, - size_t count, qsfp_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - u8 page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = sff_8436_translate_offset(port_data, &phy_offset, &client); - - dev_dbg(&client->dev, - "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == QSFP_READ_OP) { - status = sff_8436_eeprom_read(port_data, client, - buf, phy_offset, count); - } else { - status = sff_8436_eeprom_write(port_data, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - return retval; -} - - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return -EINVAL - */ -static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, - loff_t off, size_t len) -{ - struct i2c_client *client = port_data->client; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - /* SFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8472_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8472_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8472_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } - else if (port_data->driver_type == DRIVER_TYPE_QSFP) { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8436_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8436_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8436_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - else { - return -EINVAL; - } - return len; -} - - -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) -{ - struct i2c_client *client = port_data->client; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&port_data->update_lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - len = sff_8436_page_legal(port_data, off, len); - if (len < 0) { - status = len; - goto err; - } - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - SFF_8436_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ - } else { - chunk_offset = chunk_start_offset; - if (pending_len > SFF_8436_PAGE_SIZE) - chunk_len = SFF_8436_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = sff_8436_eeprom_update_client(port_data, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - goto err; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&port_data->update_lock); - - return retval; - -err: - mutex_unlock(&port_data->update_lock); - - return status; -} - -#else -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} -#endif - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); -#else - return sfp_port_read(data, buf, off, count); -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) -#else -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -#endif -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; -#if (MULTIPAGE_SUPPORT == 1) - eeprom->size = size; -#else - eeprom->size = EEPROM_SIZE; -#endif - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - - -#if (MULTIPAGE_SUPPORT == 0) -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} -#endif - - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - -#if (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - - /* - * Bring QSFPs out of reset, - * This is a temporary fix until the QSFP+_MOD_RST register - * can be exposed through the driver. - */ - accton_i2c_cpld_write(0x60, 0x23, 0x3F); - - *data = qsfp; - dev_info(&client->dev, "qsfp '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &qsfp_group); -exit_free: - kfree(qsfp); -exit: - - return status; -} - -/* Platform dependent +++ */ -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int ret = 0; - struct sfp_port_data *data = NULL; - - if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { - return -ENODEV; - } - - if (dev_id->driver_data < as5812_54t_port49 || dev_id->driver_data > as5812_54t_port54) { - return -ENXIO; - } - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - -#if (MULTIPAGE_SUPPORT == 1) - data->use_smbus = 0; - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - data->use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - data->use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - ret = -EPFNOSUPPORT; - goto exit_kfree; - } - } - - if (!data->use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned write_max = 1; - - if (write_max > io_limit) - write_max = io_limit; - if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - data->write_max = write_max; - - /* buffer (data + address at the beginning) */ - data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!data->writebuf) { - ret = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - if (data->use_smbus == I2C_SMBUS_WORD_DATA || - data->use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", data->use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } -#endif - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - data->driver_type = DRIVER_TYPE_QSFP; - - ret = qsfp_probe(client, dev_id, &data->qsfp); - if (ret < 0) { - goto exit_kfree_buf; - } - - return ret; - -exit_kfree_buf: -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) kfree(data->writebuf); -#endif - -exit_kfree: - kfree(data); - return ret; -} -/* Platform dependent --- */ - -static int qsfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - int ret = 0; - struct sfp_port_data *data = i2c_get_clientdata(client); -#if (MULTIPAGE_SUPPORT == 1) - kfree(data->writebuf); -#endif - - if (data->driver_type == DRIVER_TYPE_QSFP) { - ret = qsfp_remove(client, data->qsfp); - } - - kfree(data); - return ret; -} - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as5812_54t_sfp driver"); -MODULE_LICENSE("GPL"); - -module_init(sfp_init); -module_exit(sfp_exit); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/modules/builds/x86-64-accton-as5812-54x-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/modules/builds/x86-64-accton-as5812-54x-sfp.c deleted file mode 100644 index 44727e22..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5812-54x/modules/builds/x86-64-accton-as5812-54x-sfp.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * An hwmon driver for accton as5812_54x sfp - * - * Copyright (C) 2015 Accton Technology Corporation. - * Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NUM_OF_SFP_PORT 54 -#define BIT_INDEX(i) (1ULL << (i)) - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; - -/* Each client has this additional data - */ -struct as5812_54x_sfp_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - int port; /* Front port index */ - char eeprom[256]; /* eeprom data */ - u64 status[4]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => is_present - 1 => tx_fail - 2 => tx_disable - 3 => rx_loss */ -}; - -/* The table maps active port to cpld port. - * Array index 0 is for active port 1, - * index 1 for active port 2, and so on. - * The array content implies cpld port index. - */ -static const u8 cpld_to_front_port_table[] = -{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 52, 50, 53, 51, 54}; - -#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port]) - -static struct as5812_54x_sfp_data *as5812_54x_sfp_update_device(struct device *dev, int update_eeprom); -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count); -extern int as5812_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int as5812_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -enum as5812_54x_sfp_sysfs_attributes { - SFP_IS_PRESENT, - SFP_TX_FAULT, - SFP_TX_DISABLE, - SFP_RX_LOSS, - SFP_PORT_NUMBER, - SFP_EEPROM, - SFP_RX_LOS_ALL, - SFP_IS_PRESENT_ALL, -}; - -/* sysfs attributes for hwmon - */ -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, show_status, NULL, SFP_TX_FAULT); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, show_status, set_tx_disable, SFP_TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_rx_loss, S_IRUGO, show_status,NULL, SFP_RX_LOSS); -static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); -static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); -static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, show_status,NULL, SFP_RX_LOS_ALL); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL); - -static struct attribute *as5812_54x_sfp_attributes[] = { - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_eeprom.dev_attr.attr, - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - NULL -}; - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); - - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -static ssize_t show_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct as5812_54x_sfp_data *data; - u8 val; - int values[7]; - - /* Error-check the CPLD read results. */ -#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ - do { \ - _rv = (_read_expr); \ - if(_rv < 0) { \ - return sprintf(_buf, "READ ERROR\n"); \ - } \ - if(_invert) { \ - _rv = ~_rv; \ - } \ - _rv &= 0xFF; \ - } while(0) - - if(attr->index == SFP_RX_LOS_ALL) { - /* - * Report the RX_LOS status for all ports. - * This does not depend on the currently active SFP selector. - */ - - /* RX_LOS Ports 1-8 */ - VALIDATED_READ(buf, values[0], as5812_54x_i2c_cpld_read(0x61, 0x0F), 0); - /* RX_LOS Ports 9-16 */ - VALIDATED_READ(buf, values[1], as5812_54x_i2c_cpld_read(0x61, 0x10), 0); - /* RX_LOS Ports 17-24 */ - VALIDATED_READ(buf, values[2], as5812_54x_i2c_cpld_read(0x61, 0x11), 0); - /* RX_LOS Ports 25-32 */ - VALIDATED_READ(buf, values[3], as5812_54x_i2c_cpld_read(0x62, 0x0F), 0); - /* RX_LOS Ports 33-40 */ - VALIDATED_READ(buf, values[4], as5812_54x_i2c_cpld_read(0x62, 0x10), 0); - /* RX_LOS Ports 41-48 */ - VALIDATED_READ(buf, values[5], as5812_54x_i2c_cpld_read(0x62, 0x11), 0); - - /** Return values 1 -> 48 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5]); - } - - if(attr->index == SFP_IS_PRESENT_ALL) { - /* - * Report the SFP_PRESENCE status for all ports. - * This does not depend on the currently active SFP selector. - */ - - /* SFP_PRESENT Ports 1-8 */ - VALIDATED_READ(buf, values[0], as5812_54x_i2c_cpld_read(0x61, 0x6), 1); - /* SFP_PRESENT Ports 9-16 */ - VALIDATED_READ(buf, values[1], as5812_54x_i2c_cpld_read(0x61, 0x7), 1); - /* SFP_PRESENT Ports 17-24 */ - VALIDATED_READ(buf, values[2], as5812_54x_i2c_cpld_read(0x61, 0x8), 1); - /* SFP_PRESENT Ports 25-32 */ - VALIDATED_READ(buf, values[3], as5812_54x_i2c_cpld_read(0x62, 0x6), 1); - /* SFP_PRESENT Ports 33-40 */ - VALIDATED_READ(buf, values[4], as5812_54x_i2c_cpld_read(0x62, 0x7), 1); - /* SFP_PRESENT Ports 41-48 */ - VALIDATED_READ(buf, values[5], as5812_54x_i2c_cpld_read(0x62, 0x8), 1); - /* QSFP_PRESENT Ports 49-54 */ - VALIDATED_READ(buf, values[6], as5812_54x_i2c_cpld_read(0x62, 0x14), 1); - - /* Return values 1 -> 54 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5], - values[6] & 0x3F); - } - /* - * The remaining attributes are gathered on a per-selected-sfp basis. - */ - data = as5812_54x_sfp_update_device(dev, 0); - if (attr->index == SFP_IS_PRESENT) { - val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 0 : 1; - } - else { - val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 1 : 0; - } - - return sprintf(buf, "%d", val); -} - -static ssize_t 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 as5812_54x_sfp_data *data = i2c_get_clientdata(client); - unsigned short cpld_addr = 0; - u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; - long disable; - int error; - - /* Tx disable is not supported for QSFP ports(49-54) */ - if (data->port >= 48) { - return -EINVAL; - } - - 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 { - cpld_addr = 0x62; - cpld_reg = 0xC + (data->port - 24) / 8; - cpld_bit = 1 << (data->port % 8); - } - - cpld_val = as5812_54x_i2c_cpld_read(cpld_addr, cpld_reg); - - /* Update tx_disable status */ - if (disable) { - data->status[SFP_TX_DISABLE] |= BIT_INDEX(data->port); - cpld_val |= cpld_bit; - } - else { - data->status[SFP_TX_DISABLE] &= ~BIT_INDEX(data->port); - cpld_val &= ~cpld_bit; - } - - as5812_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct as5812_54x_sfp_data *data = as5812_54x_sfp_update_device(dev, 1); - - if (!data->valid) { - return 0; - } - - if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) != 0) { - return 0; - } - - memcpy(buf, data->eeprom, sizeof(data->eeprom)); - - return sizeof(data->eeprom); -} - -static const struct attribute_group as5812_54x_sfp_group = { - .attrs = as5812_54x_sfp_attributes, -}; - -static int as5812_54x_sfp_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct as5812_54x_sfp_data *data; - int status; - - extern int platform_accton_as5812_54x(void); - if(!platform_accton_as5812_54x()) { - return -ENODEV; - } - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - status = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct as5812_54x_sfp_data), GFP_KERNEL); - if (!data) { - status = -ENOMEM; - goto exit; - } - - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - i2c_set_clientdata(client, data); - - dev_info(&client->dev, "chip found\n"); - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &as5812_54x_sfp_group); - if (status) { - goto exit_free; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "%s: sfp '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &as5812_54x_sfp_group); -exit_free: - kfree(data); -exit: - - return status; -} - -static int as5812_54x_sfp_remove(struct i2c_client *client) -{ - struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &as5812_54x_sfp_group); - kfree(data); - - return 0; -} - -enum port_numbers { -as5812_54x_sfp1, as5812_54x_sfp2, as5812_54x_sfp3, as5812_54x_sfp4, -as5812_54x_sfp5, as5812_54x_sfp6, as5812_54x_sfp7, as5812_54x_sfp8, -as5812_54x_sfp9, as5812_54x_sfp10, as5812_54x_sfp11,as5812_54x_sfp12, -as5812_54x_sfp13, as5812_54x_sfp14, as5812_54x_sfp15,as5812_54x_sfp16, -as5812_54x_sfp17, as5812_54x_sfp18, as5812_54x_sfp19,as5812_54x_sfp20, -as5812_54x_sfp21, as5812_54x_sfp22, as5812_54x_sfp23,as5812_54x_sfp24, -as5812_54x_sfp25, as5812_54x_sfp26, as5812_54x_sfp27,as5812_54x_sfp28, -as5812_54x_sfp29, as5812_54x_sfp30, as5812_54x_sfp31,as5812_54x_sfp32, -as5812_54x_sfp33, as5812_54x_sfp34, as5812_54x_sfp35,as5812_54x_sfp36, -as5812_54x_sfp37, as5812_54x_sfp38, as5812_54x_sfp39,as5812_54x_sfp40, -as5812_54x_sfp41, as5812_54x_sfp42, as5812_54x_sfp43,as5812_54x_sfp44, -as5812_54x_sfp45, as5812_54x_sfp46, as5812_54x_sfp47,as5812_54x_sfp48, -as5812_54x_sfp49, as5812_54x_sfp52, as5812_54x_sfp50,as5812_54x_sfp53, -as5812_54x_sfp51, as5812_54x_sfp54 -}; - -static const struct i2c_device_id as5812_54x_sfp_id[] = { -{ "as5812_54x_sfp1", as5812_54x_sfp1 }, { "as5812_54x_sfp2", as5812_54x_sfp2 }, -{ "as5812_54x_sfp3", as5812_54x_sfp3 }, { "as5812_54x_sfp4", as5812_54x_sfp4 }, -{ "as5812_54x_sfp5", as5812_54x_sfp5 }, { "as5812_54x_sfp6", as5812_54x_sfp6 }, -{ "as5812_54x_sfp7", as5812_54x_sfp7 }, { "as5812_54x_sfp8", as5812_54x_sfp8 }, -{ "as5812_54x_sfp9", as5812_54x_sfp9 }, { "as5812_54x_sfp10", as5812_54x_sfp10 }, -{ "as5812_54x_sfp11", as5812_54x_sfp11 }, { "as5812_54x_sfp12", as5812_54x_sfp12 }, -{ "as5812_54x_sfp13", as5812_54x_sfp13 }, { "as5812_54x_sfp14", as5812_54x_sfp14 }, -{ "as5812_54x_sfp15", as5812_54x_sfp15 }, { "as5812_54x_sfp16", as5812_54x_sfp16 }, -{ "as5812_54x_sfp17", as5812_54x_sfp17 }, { "as5812_54x_sfp18", as5812_54x_sfp18 }, -{ "as5812_54x_sfp19", as5812_54x_sfp19 }, { "as5812_54x_sfp20", as5812_54x_sfp20 }, -{ "as5812_54x_sfp21", as5812_54x_sfp21 }, { "as5812_54x_sfp22", as5812_54x_sfp22 }, -{ "as5812_54x_sfp23", as5812_54x_sfp23 }, { "as5812_54x_sfp24", as5812_54x_sfp24 }, -{ "as5812_54x_sfp25", as5812_54x_sfp25 }, { "as5812_54x_sfp26", as5812_54x_sfp26 }, -{ "as5812_54x_sfp27", as5812_54x_sfp27 }, { "as5812_54x_sfp28", as5812_54x_sfp28 }, -{ "as5812_54x_sfp29", as5812_54x_sfp29 }, { "as5812_54x_sfp30", as5812_54x_sfp30 }, -{ "as5812_54x_sfp31", as5812_54x_sfp31 }, { "as5812_54x_sfp32", as5812_54x_sfp32 }, -{ "as5812_54x_sfp33", as5812_54x_sfp33 }, { "as5812_54x_sfp34", as5812_54x_sfp34 }, -{ "as5812_54x_sfp35", as5812_54x_sfp35 }, { "as5812_54x_sfp36", as5812_54x_sfp36 }, -{ "as5812_54x_sfp37", as5812_54x_sfp37 }, { "as5812_54x_sfp38", as5812_54x_sfp38 }, -{ "as5812_54x_sfp39", as5812_54x_sfp39 }, { "as5812_54x_sfp40", as5812_54x_sfp40 }, -{ "as5812_54x_sfp41", as5812_54x_sfp41 }, { "as5812_54x_sfp42", as5812_54x_sfp42 }, -{ "as5812_54x_sfp43", as5812_54x_sfp43 }, { "as5812_54x_sfp44", as5812_54x_sfp44 }, -{ "as5812_54x_sfp45", as5812_54x_sfp45 }, { "as5812_54x_sfp46", as5812_54x_sfp46 }, -{ "as5812_54x_sfp47", as5812_54x_sfp47 }, { "as5812_54x_sfp48", as5812_54x_sfp48 }, -{ "as5812_54x_sfp49", as5812_54x_sfp49 }, { "as5812_54x_sfp50", as5812_54x_sfp50 }, -{ "as5812_54x_sfp51", as5812_54x_sfp51 }, { "as5812_54x_sfp52", as5812_54x_sfp52 }, -{ "as5812_54x_sfp53", as5812_54x_sfp53 }, { "as5812_54x_sfp54", as5812_54x_sfp54 }, - -{} -}; -MODULE_DEVICE_TABLE(i2c, as5812_54x_sfp_id); - -static struct i2c_driver as5812_54x_sfp_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "as5812_54x_sfp", - }, - .probe = as5812_54x_sfp_probe, - .remove = as5812_54x_sfp_remove, - .id_table = as5812_54x_sfp_id, - .address_list = normal_i2c, -}; - -static int as5812_54x_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data) -{ - int result = i2c_smbus_read_byte_data(client, command); - - if (unlikely(result < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); - goto abort; - } - - *data = (u8)result; - result = 0; - -abort: - return result; -} - -#define ALWAYS_UPDATE_DEVICE 1 - -static struct as5812_54x_sfp_data *as5812_54x_sfp_update_device(struct device *dev, int update_eeprom) -{ - struct i2c_client *client = to_i2c_client(dev); - struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (ALWAYS_UPDATE_DEVICE || time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int status = -1; - int i = 0, j = 0; - - data->valid = 0; - //dev_dbg(&client->dev, "Starting as5812_54x sfp status update\n"); - memset(data->status, 0, sizeof(data->status)); - - /* Read status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 12; j++) { - status = as5812_54x_i2c_cpld_read(0x61+i, 0x6+j); - - if (status < 0) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", 0x61+i, 0x6+j, status); - goto exit; - } - - data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); - } - } - - /* - * Bring QSFPs out of reset, - * This is a temporary fix until the QSFP+_MOD_RST register - * can be exposed through the driver. - */ - as5812_54x_i2c_cpld_write(0x62, 0x15, 0x3F); - - /* Read present status of port 49-54(QSFP port) */ - status = as5812_54x_i2c_cpld_read(0x62, 0x14); - - if (status < 0) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", 0x61+i, 0x6+j, status); - } - else { - data->status[SFP_IS_PRESENT] |= (u64)status << 48; - } - - if (update_eeprom) { - /* Read eeprom data based on port number */ - memset(data->eeprom, 0, sizeof(data->eeprom)); - - /* Check if the port is present */ - if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { - /* read eeprom */ - for (i = 0; i < sizeof(data->eeprom); i++) { - status = as5812_54x_sfp_read_byte(client, i, data->eeprom + i); - - if (status < 0) { - dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", - CPLD_PORT_TO_FRONT_PORT(data->port)); - goto exit; - } - } - } - } - - data->valid = 1; - data->last_updated = jiffies; - } - -exit: - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(as5812_54x_sfp_driver); - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as5812_54x_sfp driver"); -MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as6812-32x/modules/builds/x86-64-accton-as6812-32x-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as6812-32x/modules/builds/x86-64-accton-as6812-32x-sfp.c deleted file mode 100644 index 362d87db..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as6812-32x/modules/builds/x86-64-accton-as6812-32x-sfp.c +++ /dev/null @@ -1,1532 +0,0 @@ -/* - * SFP driver for accton as6812_32x sfp - * - * Copyright (C) Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "as6812_32x_sfp" - -#define DEBUG_MODE 0 - -#if (DEBUG_MODE == 1) - #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#else - #define DEBUG_PRINT(fmt, args...) -#endif - -#define NUM_OF_SFP_PORT 32 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -#define MULTIPAGE_SUPPORT 1 - -#if (MULTIPAGE_SUPPORT == 1) -/* fundamental unit of addressing for SFF_8472/SFF_8436 */ -#define SFF_8436_PAGE_SIZE 128 -/* - * The current 8436 (QSFP) spec provides for only 4 supported - * pages (pages 0-3). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8436_SPECED_PAGES 4 -#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) -/* - * The current 8472 (SFP) spec provides for only 3 supported - * pages (pages 0-2). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8472_SPECED_PAGES 3 -#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define SFF_8436_PAGE_SELECT_REG 0x7F -#define SFF_8436_PAGEABLE_REG 0x02 -#define SFF_8436_NOT_PAGEABLE (1<<2) -#define SFF_8472_PAGEABLE_REG 0x40 -#define SFF_8472_PAGEABLE (1<<4) - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = SFF_8436_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; - -typedef enum qsfp_opcode { - QSFP_READ_OP = 0, - QSFP_WRITE_OP = 1 -} qsfp_opcode_e; -#endif - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; -static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int as6812_32x_i2c_cpld_read (unsigned short cpld_addr, u8 reg); - -enum sfp_sysfs_attributes { - PRESENT, - PRESENT_ALL, - PORT_NUMBER, - PORT_TYPE, - DDM_IMPLEMENTED, - TX_FAULT, - TX_FAULT1, - TX_FAULT2, - TX_FAULT3, - TX_FAULT4, - TX_DISABLE, - TX_DISABLE1, - TX_DISABLE2, - TX_DISABLE3, - TX_DISABLE4, - RX_LOS, - RX_LOS1, - RX_LOS2, - RX_LOS3, - RX_LOS4, - RX_LOS_ALL -}; - -/* SFP/QSFP common attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT); - -/* QSFP attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -static struct attribute *qsfp_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, - NULL -}; - -/* Platform dependent +++ */ -#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) - -enum port_numbers { -as6812_32x_port1, as6812_32x_port2, as6812_32x_port3, as6812_32x_port4, as6812_32x_port5, as6812_32x_port6, as6812_32x_port7, as6812_32x_port8, -as6812_32x_port9, as6812_32x_port10, as6812_32x_port11, as6812_32x_port12, as6812_32x_port13, as6812_32x_port14, as6812_32x_port15, as6812_32x_port16, -as6812_32x_port17, as6812_32x_port18, as6812_32x_port19, as6812_32x_port20, as6812_32x_port21, as6812_32x_port22, as6812_32x_port23, as6812_32x_port24, -as6812_32x_port25, as6812_32x_port26, as6812_32x_port27, as6812_32x_port28, as6812_32x_port29, as6812_32x_port30, as6812_32x_port31, as6812_32x_port32 -}; - -#define I2C_DEV_ID(x) { #x, x} - -static const struct i2c_device_id sfp_device_id[] = { -I2C_DEV_ID(as6812_32x_port1), -I2C_DEV_ID(as6812_32x_port2), -I2C_DEV_ID(as6812_32x_port3), -I2C_DEV_ID(as6812_32x_port4), -I2C_DEV_ID(as6812_32x_port5), -I2C_DEV_ID(as6812_32x_port6), -I2C_DEV_ID(as6812_32x_port7), -I2C_DEV_ID(as6812_32x_port8), -I2C_DEV_ID(as6812_32x_port9), -I2C_DEV_ID(as6812_32x_port10), -I2C_DEV_ID(as6812_32x_port11), -I2C_DEV_ID(as6812_32x_port12), -I2C_DEV_ID(as6812_32x_port13), -I2C_DEV_ID(as6812_32x_port14), -I2C_DEV_ID(as6812_32x_port15), -I2C_DEV_ID(as6812_32x_port16), -I2C_DEV_ID(as6812_32x_port17), -I2C_DEV_ID(as6812_32x_port18), -I2C_DEV_ID(as6812_32x_port19), -I2C_DEV_ID(as6812_32x_port20), -I2C_DEV_ID(as6812_32x_port21), -I2C_DEV_ID(as6812_32x_port22), -I2C_DEV_ID(as6812_32x_port23), -I2C_DEV_ID(as6812_32x_port24), -I2C_DEV_ID(as6812_32x_port25), -I2C_DEV_ID(as6812_32x_port26), -I2C_DEV_ID(as6812_32x_port27), -I2C_DEV_ID(as6812_32x_port28), -I2C_DEV_ID(as6812_32x_port29), -I2C_DEV_ID(as6812_32x_port30), -I2C_DEV_ID(as6812_32x_port31), -I2C_DEV_ID(as6812_32x_port32), -{ /* 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 -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct qsfp_data *qsfp; - - struct i2c_client *client; -#if (MULTIPAGE_SUPPORT == 1) - int use_smbus; - u8 *writebuf; - unsigned write_max; -#endif -}; - -#if (MULTIPAGE_SUPPORT == 1) -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); -#endif -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0, j = 0; - int status = -1; - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - - /* Read present status of port 1~32 */ - data->present = 0; - - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - status = as6812_32x_i2c_cpld_read(0x62+i*2, 0xA+j); - - if (status < 0) { - DEBUG_PRINT("cpld(0x%x) reg(0x%x) err %d", 0x62+i*2, 0xA+j, status); - goto exit; - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); - data->present |= (u64)status << ((i*16) + (j*8)); - } - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -/* Platform dependent --- */ - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ -} - -/* Platform dependent +++ */ -static ssize_t show_present(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - - if (PRESENT_ALL == attr->index) { - int i; - u8 values[4] = {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 -> 32 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3]); - } - 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", present); - } -} -/* Platform dependent --- */ - -static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i, status = -1; - u8 buf = 0; - u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; - - if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { - return data; - } - - DEBUG_PRINT("Starting sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->qsfp->valid = 0; - memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); - - /* Notify device to update tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - } - msleep(200); - - /* Read actual tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - - DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); - data->qsfp->status[i] = (buf & 0xF); - } - - data->qsfp->valid = 1; - data->qsfp->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int present; - u8 val = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - present = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENXIO; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - switch (attr->index) { - case TX_FAULT: - val = !!(data->qsfp->status[2] & 0xF); - break; - case TX_FAULT1: - case TX_FAULT2: - case TX_FAULT3: - case TX_FAULT4: - val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); - break; - case TX_DISABLE: - val = data->qsfp->status[1] & 0xF; - break; - case TX_DISABLE1: - case TX_DISABLE2: - case TX_DISABLE3: - case TX_DISABLE4: - val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); - break; - case RX_LOS: - val = !!(data->qsfp->status[0] & 0xF); - break; - case RX_LOS1: - case RX_LOS2: - case RX_LOS3: - case RX_LOS4: - val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); - break; - default: - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - long disable; - int status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (!status) { - /* port is not present */ - return -ENXIO; - } - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - mutex_lock(&data->update_lock); - - if (attr->index == TX_DISABLE) { - if (disable) { - data->qsfp->status[1] |= 0xF; - } - else { - data->qsfp->status[1] &= ~0xF; - } - } - else {/* TX_DISABLE1 ~ TX_DISABLE4*/ - if (disable) { - data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); - } - else { - data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); - } - } - - DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); - status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); - if (unlikely(status < 0)) { - count = status; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -#if (MULTIPAGE_SUPPORT == 0) -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} -#endif - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); -#else - return sfp_port_write(data, buf, off, count); -#endif -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both SFP and QSFP. - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ -static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = port_data->client; - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < SFF_8436_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, - struct i2c_client *client, - char *buf, unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, - struct i2c_client *client, - const char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > port_data->write_max) - count = port_data->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = port_data->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, - char *buf, loff_t off, - size_t count, qsfp_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - u8 page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = sff_8436_translate_offset(port_data, &phy_offset, &client); - - dev_dbg(&client->dev, - "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == QSFP_READ_OP) { - status = sff_8436_eeprom_read(port_data, client, - buf, phy_offset, count); - } else { - status = sff_8436_eeprom_write(port_data, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - return retval; -} - - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return -EINVAL - */ -static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, - loff_t off, size_t len) -{ - struct i2c_client *client = port_data->client; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - /* SFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8472_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8472_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8472_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } - else if (port_data->driver_type == DRIVER_TYPE_QSFP) { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8436_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8436_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8436_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - else { - return -EINVAL; - } - return len; -} - - -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) -{ - struct i2c_client *client = port_data->client; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&port_data->update_lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - len = sff_8436_page_legal(port_data, off, len); - if (len < 0) { - status = len; - goto err; - } - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - SFF_8436_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ - } else { - chunk_offset = chunk_start_offset; - if (pending_len > SFF_8436_PAGE_SIZE) - chunk_len = SFF_8436_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = sff_8436_eeprom_update_client(port_data, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - goto err; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&port_data->update_lock); - - return retval; - -err: - mutex_unlock(&port_data->update_lock); - - return status; -} - -#else -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} -#endif - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); -#else - return sfp_port_read(data, buf, off, count); -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) -#else -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -#endif -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; -#if (MULTIPAGE_SUPPORT == 1) - eeprom->size = size; -#else - eeprom->size = EEPROM_SIZE; -#endif - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - - -#if (MULTIPAGE_SUPPORT == 0) -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} -#endif - - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - -#if (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - - *data = qsfp; - dev_info(&client->dev, "qsfp '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &qsfp_group); -exit_free: - kfree(qsfp); -exit: - - return status; -} - -/* Platform dependent +++ */ -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int ret = 0; - struct sfp_port_data *data = NULL; - - if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { - return -ENODEV; - } - - if (dev_id->driver_data < as6812_32x_port1 || dev_id->driver_data > as6812_32x_port32) { - return -ENXIO; - } - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - -#if (MULTIPAGE_SUPPORT == 1) - data->use_smbus = 0; - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - data->use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - data->use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - ret = -EPFNOSUPPORT; - goto exit_kfree; - } - } - - if (!data->use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned write_max = 1; - - if (write_max > io_limit) - write_max = io_limit; - if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - data->write_max = write_max; - - /* buffer (data + address at the beginning) */ - data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!data->writebuf) { - ret = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - if (data->use_smbus == I2C_SMBUS_WORD_DATA || - data->use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", data->use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } -#endif - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - data->driver_type = DRIVER_TYPE_QSFP; - - ret = qsfp_probe(client, dev_id, &data->qsfp); - if (ret < 0) { - goto exit_kfree_buf; - } - - return ret; - -exit_kfree_buf: -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) kfree(data->writebuf); -#endif - -exit_kfree: - kfree(data); - return ret; -} -/* Platform dependent --- */ - -static int qsfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - int ret = 0; - struct sfp_port_data *data = i2c_get_clientdata(client); -#if (MULTIPAGE_SUPPORT == 1) - kfree(data->writebuf); -#endif - - if (data->driver_type == DRIVER_TYPE_QSFP) { - ret = qsfp_remove(client, data->qsfp); - } - - kfree(data); - return ret; -} - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as6812_32x_sfp driver"); -MODULE_LICENSE("GPL"); - -module_init(sfp_init); -module_exit(sfp_exit); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/.gitignore new file mode 100755 index 00000000..f8bc5a4d --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/.gitignore @@ -0,0 +1,3 @@ +*x86*64*accton*as7312*54x*.mk +onlpdump.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml new file mode 100755 index 00000000..3f59762e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-csp9250 ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/.gitignore new file mode 100755 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/Makefile new file mode 100755 index 00000000..1f3ab737 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-csp9250 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-cpld.c new file mode 100755 index 00000000..a3021334 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-cpld.c @@ -0,0 +1,251 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct dmi_system_id csp9250_dmi_table[] = { + { + .ident = "Accton csp9250", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "csp9250"), + }, + } +}; + +int platform_accton_csp9250(void) +{ + return dmi_check_system(csp9250_dmi_table); +} +EXPORT_SYMBOL(platform_accton_csp9250); + + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x62, 0x64, I2C_CLIENT_END }; + + +//#define DRIVER_CLASS_SWC_NAME "swc" +//static ssize_t accton_i2c_drv_version_get(struct device *dev, struct device_attribute *attr, char *buf); +//static SENSOR_DEVICE_ATTR(version, S_IRUGO, accton_i2c_drv_version_get, NULL, 0); +//static struct attribute *accton_attributes[] = { +// &sensor_dev_attr_version.dev_attr.attr, +// NULL, +//}; +//static struct attribute_group accton_attributes_group = { +// .attrs = accton_attributes, +//}; + +//struct accton_device { +// struct device *dev; + //struct kobject *kobject_version; +// int id; +// const char *name; + +//}; +//static struct class sysfs_class_swc = { +// .name = DRIVER_CLASS_SWC_NAME, + // .owner = THIS_MODULE, +//}; +//static struct accton_device accton_data; + +//#define DRIVER_VERSION "0.0.0.2" +/* +static ssize_t accton_i2c_drv_version_get(struct device *dev, struct device_attribute *attr, char *buf) +{ + int status = 0; + + status = snprintf(buf, PAGE_SIZE - 1, "\r%s\n", DRIVER_VERSION); + + return status; +} + +*/ + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + accton_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + accton_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "accton_i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int csp9250_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(csp9250_i2c_cpld_read); + +int csp9250_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(csp9250_i2c_cpld_write); + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-fan.c new file mode 100755 index 00000000..9fee803a --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-fan.c @@ -0,0 +1,488 @@ +/* + * A hwmon driver for the Accton as7312 54x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "csp9250_fan" + +static struct csp9250_fan_data *csp9250_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 csp9250_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int csp9250_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct csp9250_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 *csp9250_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 csp9250_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int csp9250_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 csp9250_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; + + csp9250_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + csp9250_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 csp9250_fan_data *data = csp9250_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 csp9250_fan_group = { + .attrs = csp9250_fan_attributes, +}; + +static struct csp9250_fan_data *csp9250_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct csp9250_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 csp9250_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = csp9250_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 csp9250_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct csp9250_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct csp9250_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, &csp9250_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, &csp9250_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int csp9250_fan_remove(struct i2c_client *client) +{ + struct csp9250_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &csp9250_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id csp9250_fan_id[] = { + { "csp9250_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, csp9250_fan_id); + +static struct i2c_driver csp9250_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = csp9250_fan_probe, + .remove = csp9250_fan_remove, + .id_table = csp9250_fan_id, + .address_list = normal_i2c, +}; + +static int __init csp9250_fan_init(void) +{ + + + return i2c_add_driver(&csp9250_fan_driver); +} + +static void __exit csp9250_fan_exit(void) +{ + i2c_del_driver(&csp9250_fan_driver); +} + +module_init(csp9250_fan_init); +module_exit(csp9250_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("csp9250_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c new file mode 100755 index 00000000..f3a2f878 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c @@ -0,0 +1,438 @@ +/* + * A LED driver for the accton_csp9250_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 csp9250_i2c_cpld_read (unsigned short cpld_addr, u8 reg); +extern int csp9250_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_csp9250_led" + +struct accton_csp9250_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_csp9250_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_csp9250_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_csp9250_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_csp9250_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_csp9250_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_csp9250_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_csp9250_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_csp9250_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_csp9250_led_diag_get(struct led_classdev *cdev) +{ + accton_csp9250_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_csp9250_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_csp9250_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_csp9250_led_loc_get(struct led_classdev *cdev) +{ + accton_csp9250_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_csp9250_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_csp9250_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_csp9250_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_csp9250_led::diag", + .default_trigger = "unused", + .brightness_set = accton_csp9250_led_diag_set, + .brightness_get = accton_csp9250_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_csp9250_led::loc", + .default_trigger = "unused", + .brightness_set = accton_csp9250_led_loc_set, + .brightness_get = accton_csp9250_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_csp9250_led::fan", + .default_trigger = "unused", + .brightness_set = accton_csp9250_led_auto_set, + .brightness_get = accton_csp9250_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_csp9250_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_csp9250_led_auto_set, + .brightness_get = accton_csp9250_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_csp9250_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_csp9250_led_auto_set, + .brightness_get = accton_csp9250_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_csp9250_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_csp9250_leds); i++) { + led_classdev_suspend(&accton_csp9250_leds[i]); + } + + return 0; +} + +static int accton_csp9250_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_csp9250_leds); i++) { + led_classdev_resume(&accton_csp9250_leds[i]); + } + + return 0; +} + +static int accton_csp9250_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_csp9250_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_csp9250_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_csp9250_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_csp9250_leds[i]); + } + } + + return ret; +} + +static int accton_csp9250_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_csp9250_leds); i++) { + led_classdev_unregister(&accton_csp9250_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_csp9250_led_driver = { + .probe = accton_csp9250_led_probe, + .remove = accton_csp9250_led_remove, + .suspend = accton_csp9250_led_suspend, + .resume = accton_csp9250_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_csp9250_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_csp9250_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_csp9250_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_csp9250_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_csp9250_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_csp9250_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_csp9250_led_driver); + kfree(ledctl); +} + +module_init(accton_csp9250_led_init); +module_exit(accton_csp9250_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_csp9250_led driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-psu.c new file mode 100755 index 00000000..659b151a --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-psu.c @@ -0,0 +1,293 @@ +/* + * An hwmon driver for accton csp9250 Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int csp9250_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int csp9250_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct csp9250_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 csp9250_psu_data *csp9250_psu_update_device(struct device *dev); + +enum csp9250_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 *csp9250_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 csp9250_psu_data *data = csp9250_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct csp9250_psu_data *data = csp9250_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group csp9250_psu_group = { + .attrs = csp9250_psu_attributes, +}; + +static int csp9250_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct csp9250_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct csp9250_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, &csp9250_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, &csp9250_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int csp9250_psu_remove(struct i2c_client *client) +{ + struct csp9250_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &csp9250_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + csp9250_psu1, + csp9250_psu2 +}; + +static const struct i2c_device_id csp9250_psu_id[] = { + { "csp9250_psu1", csp9250_psu1 }, + { "csp9250_psu2", csp9250_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, csp9250_psu_id); + +static struct i2c_driver csp9250_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "csp9250_psu", + }, + .probe = csp9250_psu_probe, + .remove = csp9250_psu_remove, + .id_table = csp9250_psu_id, + .address_list = normal_i2c, +}; + +static int csp9250_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 csp9250_psu_data *csp9250_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct csp9250_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 csp9250 update\n"); + + /* Read psu status */ + status = csp9250_i2c_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = csp9250_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init csp9250_psu_init(void) +{ + extern int platform_accton_csp9250(void); + if (!platform_accton_csp9250()) { + return -ENODEV; + } + + return i2c_add_driver(&csp9250_psu_driver); +} + +static void __exit csp9250_psu_exit(void) +{ + i2c_del_driver(&csp9250_psu_driver); +} + +module_init(csp9250_psu_init); +module_exit(csp9250_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("csp9250_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c new file mode 100755 index 00000000..d13bf7c9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c @@ -0,0 +1,1354 @@ +/* + * SFP driver for accton csp9250 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 "csp9250_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 +#define I2C_ADDR_CPLD3 0x64 +/* 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 csp9250_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int csp9250_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 { + csp9250_sfp1, csp9250_sfp2, csp9250_sfp3, csp9250_sfp4, csp9250_sfp5, csp9250_sfp6, csp9250_sfp7, csp9250_sfp8, + csp9250_sfp9, csp9250_sfp10, csp9250_sfp11, csp9250_sfp12, csp9250_sfp13, csp9250_sfp14, csp9250_sfp15, csp9250_sfp16, + csp9250_sfp17, csp9250_sfp18, csp9250_sfp19, csp9250_sfp20, csp9250_sfp21, csp9250_sfp22, csp9250_sfp23, csp9250_sfp24, + csp9250_sfp25, csp9250_sfp26, csp9250_sfp27, csp9250_sfp28, csp9250_sfp29, csp9250_sfp30, csp9250_sfp31, csp9250_sfp32, + csp9250_sfp33, csp9250_sfp34, csp9250_sfp35, csp9250_sfp36, csp9250_sfp37, csp9250_sfp38, csp9250_sfp39, csp9250_sfp40, + csp9250_sfp41, csp9250_sfp42, csp9250_sfp43, csp9250_sfp44, csp9250_sfp45, csp9250_sfp46, csp9250_sfp47, csp9250_sfp48, + csp9250_sfp49, csp9250_sfp50, csp9250_sfp51, csp9250_sfp52, csp9250_sfp53, csp9250_sfp54 +}; +#define DEV_NAME_ID(x) {#x, x} +static const struct i2c_device_id csp9250_sfp_id[] = { +#if 1 + DEV_NAME_ID(csp9250_sfp1), DEV_NAME_ID(csp9250_sfp2), + DEV_NAME_ID(csp9250_sfp3), DEV_NAME_ID(csp9250_sfp4), + DEV_NAME_ID(csp9250_sfp5), DEV_NAME_ID(csp9250_sfp6), + DEV_NAME_ID(csp9250_sfp7), DEV_NAME_ID(csp9250_sfp8), + DEV_NAME_ID(csp9250_sfp9), DEV_NAME_ID(csp9250_sfp10), + DEV_NAME_ID(csp9250_sfp11), DEV_NAME_ID(csp9250_sfp12), + DEV_NAME_ID(csp9250_sfp13), DEV_NAME_ID(csp9250_sfp14), + DEV_NAME_ID(csp9250_sfp15), DEV_NAME_ID(csp9250_sfp16), + DEV_NAME_ID(csp9250_sfp17), DEV_NAME_ID(csp9250_sfp18), + DEV_NAME_ID(csp9250_sfp19), DEV_NAME_ID(csp9250_sfp20), + DEV_NAME_ID(csp9250_sfp21), DEV_NAME_ID(csp9250_sfp22), + DEV_NAME_ID(csp9250_sfp23), DEV_NAME_ID(csp9250_sfp24), + DEV_NAME_ID(csp9250_sfp25), DEV_NAME_ID(csp9250_sfp26), + DEV_NAME_ID(csp9250_sfp27), DEV_NAME_ID(csp9250_sfp28), + DEV_NAME_ID(csp9250_sfp29), DEV_NAME_ID(csp9250_sfp30), + DEV_NAME_ID(csp9250_sfp31), DEV_NAME_ID(csp9250_sfp32), + DEV_NAME_ID(csp9250_sfp33), DEV_NAME_ID(csp9250_sfp34), + DEV_NAME_ID(csp9250_sfp35), DEV_NAME_ID(csp9250_sfp36), + DEV_NAME_ID(csp9250_sfp37), DEV_NAME_ID(csp9250_sfp38), + DEV_NAME_ID(csp9250_sfp39), DEV_NAME_ID(csp9250_sfp40), + DEV_NAME_ID(csp9250_sfp41), DEV_NAME_ID(csp9250_sfp42), + DEV_NAME_ID(csp9250_sfp43), DEV_NAME_ID(csp9250_sfp44), + DEV_NAME_ID(csp9250_sfp45), DEV_NAME_ID(csp9250_sfp46), + DEV_NAME_ID(csp9250_sfp47), DEV_NAME_ID(csp9250_sfp48), + DEV_NAME_ID(csp9250_sfp49), DEV_NAME_ID(csp9250_sfp50), + DEV_NAME_ID(csp9250_sfp51), DEV_NAME_ID(csp9250_sfp52), + DEV_NAME_ID(csp9250_sfp53), DEV_NAME_ID(csp9250_sfp54), +#else + { "csp9250_sfp1", csp9250_sfp1 }, { "csp9250_sfp2", csp9250_sfp2 }, { "csp9250_sfp3", csp9250_sfp3 }, { "csp9250_sfp4", csp9250_sfp4 }, + { "csp9250_sfp5", csp9250_sfp5 }, { "csp9250_sfp6", csp9250_sfp6 }, { "csp9250_sfp7", csp9250_sfp7 }, { "csp9250_sfp8", csp9250_sfp8 }, + { "csp9250_sfp9", csp9250_sfp9 }, { "csp9250_sfp10", csp9250_sfp10 }, { "csp9250_sfp11", csp9250_sfp11 }, { "csp9250_sfp12", csp9250_sfp12 }, + { "csp9250_sfp13", csp9250_sfp13 }, { "csp9250_sfp14", csp9250_sfp14 }, { "csp9250_sfp15", csp9250_sfp15 }, { "csp9250_sfp16", csp9250_sfp16 }, + { "csp9250_sfp17", csp9250_sfp17 }, { "csp9250_sfp18", csp9250_sfp18 }, { "csp9250_sfp19", csp9250_sfp19 }, { "csp9250_sfp20", csp9250_sfp20 }, + { "csp9250_sfp21", csp9250_sfp21 }, { "csp9250_sfp22", csp9250_sfp22 }, { "csp9250_sfp23", csp9250_sfp23 }, { "csp9250_sfp24", csp9250_sfp24 }, + { "csp9250_sfp25", csp9250_sfp25 }, { "csp9250_sfp26", csp9250_sfp26 }, { "csp9250_sfp27", csp9250_sfp27 }, { "csp9250_sfp28", csp9250_sfp28 }, + { "csp9250_sfp29", csp9250_sfp29 }, { "csp9250_sfp30", csp9250_sfp30 }, { "csp9250_sfp31", csp9250_sfp31 }, { "csp9250_sfp32", csp9250_sfp32 }, + { "csp9250_sfp33", csp9250_sfp33 }, { "csp9250_sfp34", csp9250_sfp34 }, { "csp9250_sfp35", csp9250_sfp35 }, { "csp9250_sfp36", csp9250_sfp36 }, + { "csp9250_sfp37", csp9250_sfp37 }, { "csp9250_sfp38", csp9250_sfp38 }, { "csp9250_sfp39", csp9250_sfp39 }, { "csp9250_sfp40", csp9250_sfp40 }, + { "csp9250_sfp41", csp9250_sfp41 }, { "csp9250_sfp42", csp9250_sfp42 }, { "csp9250_sfp43", csp9250_sfp43 }, { "csp9250_sfp44", csp9250_sfp44 }, + { "csp9250_sfp45", csp9250_sfp45 }, { "csp9250_sfp46", csp9250_sfp46 }, { "csp9250_sfp47", csp9250_sfp47 }, { "csp9250_sfp48", csp9250_sfp48 }, + { "csp9250_sfp49", csp9250_sfp49 }, { "csp9250_sfp50", csp9250_sfp50 }, { "csp9250_sfp51", csp9250_sfp51 }, { "csp9250_sfp52", csp9250_sfp52 }, + { "csp9250_sfp53", csp9250_sfp53 }, { "csp9250_sfp54", csp9250_sfp54 }, +#endif + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, csp9250_sfp_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_CPLD2 + i*2; + reg = 0x9+j; + status = csp9250_i2c_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + data->present |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-52(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD2; + reg = 0x18; + status = csp9250_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0xF) << 48; + } + + /* Read present status of port 53-54(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD3; + reg = 0x18; + status = csp9250_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0x3) << 52; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting csp9250 sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 9; j++) { + u8 reg; + unsigned short cpld_addr; + reg = 0xc+j; + cpld_addr = I2C_ADDR_CPLD2 + i*2; + + status = csp9250_i2c_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xF + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { /* port 24 ~ 48 */ + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xF + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + /* Read current status */ + cpld_val = csp9250_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; + } + + csp9250_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); + } +} + +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 -ENODEV; + } + + 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) ? 1 : 0; + break; + 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_DISABLE: + val = (data->qsfp->status[1] & 0xF) ? 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_LOS: + val = (data->qsfp->status[0] & 0xF) ? 1 : 0; + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)) ? 1 : 0; + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int 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 (attr->index == TX_DISABLE) { + if (disable) { + data->qsfp->status[1] |= 0xF; + } + else { + data->qsfp->status[1] &= ~0xF; + } + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_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) ? 1 : 0); +} + +/* 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 != data_len)) { + status = -EIO; + + goto abort; + } + +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; + printk("acc trace %s:%d\n", __FUNCTION__, __LINE__); + if (unlikely(!count)) { + printk("acc trace %s:%d\n", __FUNCTION__, __LINE__); + 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); + printk("acc trace %s:%d, off=0x%x,data->client->addr=0x%x\n", __FUNCTION__, __LINE__, off,data->client->addr); + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + printk("acc trace %s:%d\n", __FUNCTION__, __LINE__); + 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)); + printk("acc trace %s:%d, data->port=%d\n", __FUNCTION__, __LINE__, data->port); + printk("offset = (%d), count = (%d)", off, count); + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + printk("Acc trace %s:%d, present=%d\n", __FUNCTION__, __LINE__, 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; +} + +static int csp9250_sfp_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 >= csp9250_sfp1 && dev_id->driver_data <= csp9250_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 { /* csp9250_sfp49 ~ csp9250_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 csp9250_sfp_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 = csp9250_sfp_probe, + .remove = csp9250_sfp_remove, + .id_table = csp9250_sfp_id, + .address_list = normal_i2c, +}; + +static int __init csp9250_sfp_init(void) +{ + //extern int platform_accton_csp9250(void); + //if(!platform_accton_csp9250()) { + // return -ENODEV; + //} + printk("Acc trace %s\n", __FUNCTION__); + return i2c_add_driver(&sfp_driver); +} + +static void __exit csp9250_sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton csp9250_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(csp9250_sfp_init); +module_exit(csp9250_sfp_exit); + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/PKG.yml new file mode 100755 index 00000000..20233ecb --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-csp9250 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/lib/Makefile new file mode 100755 index 00000000..bdf072c1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_csp9250 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-csp9250.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-csp9250/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..78e0ca0a --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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_csp9250 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-csp9250/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/.module new file mode 100755 index 00000000..e0797bf3 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_csp9250 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/Makefile new file mode 100755 index 00000000..5d0c54b2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_accton_csp9250 +AUTOMODULE := x86_64_accton_csp9250 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/README new file mode 100755 index 00000000..9a62ecfc --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_csp9250 README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/auto/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/auto/make.mk new file mode 100755 index 00000000..f349d340 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_csp9250 Autogeneration +# +############################################################################### +x86_64_accton_csp9250_AUTO_DEFS := module/auto/x86_64_accton_csp9250.yml +x86_64_accton_csp9250_AUTO_DIRS := module/inc/x86_64_accton_csp9250 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/auto/x86_64_accton_csp9250.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/auto/x86_64_accton_csp9250.yml new file mode 100755 index 00000000..227f3670 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/auto/x86_64_accton_csp9250.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_csp9250 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_accton_csp9250_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_accton_csp9250_CONFIG_PORTING_STDLIB +- x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_accton_csp9250_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_csp9250_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_csp9250_config + + portingmacro: + x86_64_accton_csp9250: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250.x b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250.x new file mode 100755 index 00000000..9efed291 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250.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-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_config.h b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_config.h new file mode 100755 index 00000000..142f9e22 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_csp9250 Configuration Header + * + * @addtogroup x86_64_accton_csp9250-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_csp9250_CONFIG_H__ +#define __x86_64_accton_csp9250_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_accton_csp9250_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING +#define x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT +#define x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_accton_csp9250_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_PORTING_STDLIB +#define x86_64_accton_csp9250_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_accton_as5512_54x_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI +#define x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_csp9250_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_csp9250_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_csp9250_config_settings table. */ +extern x86_64_accton_csp9250_config_settings_t x86_64_accton_csp9250_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_csp9250_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_csp9250_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_csp9250_porting.h" + +#endif /* __x86_64_accton_csp9250_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_dox.h new file mode 100755 index 00000000..72bb34c9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_csp9250 Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_csp9250_DOX_H__ +#define __x86_64_accton_csp9250_DOX_H__ + +/** + * @defgroup x86_64_accton_csp9250 x86_64_accton_csp9250 - x86_64_accton_csp9250 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_csp9250-x86_64_accton_csp9250 Public Interface + * @defgroup x86_64_accton_csp9250-config Compile Time Configuration + * @defgroup x86_64_accton_csp9250-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_accton_csp9250_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_porting.h new file mode 100755 index 00000000..c5ecbb13 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/inc/x86_64_accton_csp9250/x86_64_accton_csp9250_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_csp9250 Porting Macros. + * + * @addtogroup x86_64_accton_csp9250-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_csp9250_PORTING_H__ +#define __x86_64_accton_csp9250_PORTING_H__ + + +/* */ +#if x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_accton_csp9250_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_accton_csp9250_MALLOC GLOBAL_MALLOC + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_MALLOC malloc + #else + #error The macro x86_64_accton_csp9250_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_FREE + #if defined(GLOBAL_FREE) + #define x86_64_accton_csp9250_FREE GLOBAL_FREE + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_FREE free + #else + #error The macro x86_64_accton_csp9250_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_accton_csp9250_MEMSET GLOBAL_MEMSET + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_MEMSET memset + #else + #error The macro x86_64_accton_csp9250_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_accton_csp9250_MEMCPY GLOBAL_MEMCPY + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_MEMCPY memcpy + #else + #error The macro x86_64_accton_csp9250_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_accton_csp9250_STRNCPY GLOBAL_STRNCPY + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_STRNCPY strncpy + #else + #error The macro x86_64_accton_csp9250_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_accton_csp9250_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_VSNPRINTF vsnprintf + #else + #error The macro x86_64_accton_csp9250_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_accton_csp9250_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_SNPRINTF snprintf + #else + #error The macro x86_64_accton_csp9250_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_csp9250_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_accton_csp9250_STRLEN GLOBAL_STRLEN + #elif x86_64_accton_csp9250_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_csp9250_STRLEN strlen + #else + #error The macro x86_64_accton_csp9250_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_accton_csp9250_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..b7da4aa9 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_csp9250_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_csp9250_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_csp9250_DEPENDMODULE_ENTRIES := init:x86_64_accton_csp9250 ucli:x86_64_accton_csp9250 + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/Makefile new file mode 100755 index 00000000..d4010caa --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_csp9250.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/debug.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/debug.c new file mode 100755 index 00000000..2c01a6b3 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_accton_csp9250_int.h" + +#if x86_64_accton_csp9250_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_accton_csp9250_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-csp9250/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..3b667e52 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/fani.c @@ -0,0 +1,423 @@ +/************************************************************ + * + * + * 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 MAX_FAN_1_SPEED 21500 +#define MAX_FAN_2_SPEED 18000 + +#define MAX_PSU_FAN_SPEED 25500 + +#define FAN_MAX_LENGTH 256 +#define FAN_LEAVE_NUM 2 + +#define FAN_IPMI_TMP_FILE_RM_RPM "rm -f /tmp/fan_bmc_info_rpm > /dev/null 2>&1" +#define FAN_IPMI_TMP_FILE_RM_PERCENT "rm -f /tmp/fan_bmc_info_rpm_percent > /dev/null 2>&1" + +#define FAN_IPMI_TMP_FILE_RPM "/tmp/fan_bmc_info_rpm" +#define FAN_IPMI_TMP_FILE_PERCENT "/tmp/fan_bmc_info_percent" + +#define FAN_IPMI_TMP_FILE_FIND_NO_READ "No Reading" +#define FAN_IPMI_TMP_FILE_FIND "RPM" +#define FAN_IPMI_TMP_FILE_FIND_PERCENT "02" + +#define FAN_IPMI_SDR_CMD "ipmitool sdr list" +#define FAN_IPMI_PWM_SET "ipmitool raw 0x34 0xaa 0x5a 0x54 0x40 0x04 0x01 0xff" +#define FAN_IPMI_PWM_GET "ipmitool raw 0x34 0xaa 0x5a 0x54 0x40 0x04 0x02 0x01" +#define FAN_IPMI_SDR_FILE "/usr/bin/fan_bmc_sdr" +#define FAN_IPMI_SDR_FILE_RM "rm -f /usr/bin/fan_bmc_sdr > /dev/null 2>&1" +#define FAN_CHECK_TIME "/usr/bin/fan_check_time" +#define FAN_IPMI_PWM_FILE "/usr/bin/fan_bmc_pwm" +#define FAN_IPMI_PWM_FILE_RM "rm -f /usr/bin/fan_bmc_pwm > /dev/null 2>&1" + +#define FAN_CAN_SET_IPMI_TIME 5 + +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 CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "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) +}; + + + +typedef struct onlp_fan_dev_s +{ + int fan_id; + char *tag[FAN_LEAVE_NUM]; + +}onlp_fan_dev_t; + + +onlp_fan_dev_t fan_sensor_table[]= +{ + {0, {NULL, NULL}}, + {FAN_1_ON_FAN_BOARD, {"Fan1_1", "Fan1_2"}}, + {FAN_2_ON_FAN_BOARD, {"Fan2_1", "Fan2_2"}}, + {FAN_3_ON_FAN_BOARD, {"Fan3_1", "Fan3_2"}}, + {FAN_4_ON_FAN_BOARD, {"Fan4_1", "Fan4_2"}}, + {FAN_5_ON_FAN_BOARD, {"Fan5_1", "Fan5_2"}}, +}; + + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + +static int +fani_time_exist(void) +{ + struct stat file_info; + if(stat(FAN_CHECK_TIME ,&file_info)==0) + { + if(file_info.st_size==0) + return 0; + return 1; + } + else + return 1; +} +static int +fani_sdr_file_exist(void) +{ + struct stat file_info; + if(stat(FAN_IPMI_SDR_FILE ,&file_info)==0) + { + if(file_info.st_size==0) + return 0; + return 1; + } + else + return 0; +} + + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int i, size; + char *tag, *p; + char cmd[FAN_MAX_LENGTH/2]={0}; + char fan_val_str[6]={0}; + int fan_val_int=0; + uint8_t data[FAN_MAX_LENGTH] = {0}; + struct timeval new_tv; + long last_time; + int get_data_by_ipmi=0; + + if(fid > FAN_5_ON_FAN_BOARD) + return ONLP_STATUS_E_INTERNAL; + + if(fani_time_exist()) + { + if(onlp_file_read(data, FAN_MAX_LENGTH, &size, FAN_CHECK_TIME)!=ONLP_STATUS_OK) + { + last_time=0; + } + else + last_time = atol((char*)data); + } + else + last_time=0; + + gettimeofday(&new_tv,NULL); + + if(last_time==0) /* first time */ + { + get_data_by_ipmi=1; + } + else + { + if(new_tv.tv_sec > last_time) + { + if((new_tv.tv_sec - last_time) > FAN_CAN_SET_IPMI_TIME) + { + get_data_by_ipmi=1; + } + else + get_data_by_ipmi=0; + } + else if(new_tv.tv_sec == last_time) + get_data_by_ipmi=0; + else + get_data_by_ipmi=1; + + } + memset(data ,0x0, FAN_MAX_LENGTH); + snprintf((char*)data, FAN_MAX_LENGTH-1, "%ld", new_tv.tv_sec); + if(onlp_file_write_str((char*)data, FAN_CHECK_TIME)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + + if(get_data_by_ipmi || !fani_sdr_file_exist()) /* Set ipmitool cmd to get all data and save to file*/ + { + /* set ipmi sdr cmd to get rpm */ + snprintf(cmd, (FAN_MAX_LENGTH/2) -1, "%s > %s ", FAN_IPMI_SDR_CMD, FAN_IPMI_SDR_FILE); + system(cmd); + /* set ipmi cmd to get pwm */ + snprintf(cmd, (FAN_MAX_LENGTH/2) -1, "%s > %s ", FAN_IPMI_PWM_GET, FAN_IPMI_PWM_FILE); + system(cmd); + fflush(stdout); + } + for(i=0; i %s", FAN_IPMI_SDR_FILE, tag, FAN_IPMI_TMP_FILE_RPM); + system(cmd); + + if(onlp_file_read(data, FAN_MAX_LENGTH, &size, FAN_IPMI_TMP_FILE_RPM)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + p=strstr((char*)data, FAN_IPMI_TMP_FILE_FIND); + if(p==NULL) + { + return ONLP_STATUS_E_INTERNAL; + } + if(((uint8_t*)p-data) < sizeof(fan_val_str)/sizeof(char)) + { + return ONLP_STATUS_E_INTERNAL; + } + fan_val_str[0]=(data[(uint8_t*)p-data-6]=='|' || data[(uint8_t*)p-data-6]==' ')?'0':data[(uint8_t*)p-data-6]; + fan_val_str[1]=(data[(uint8_t*)p-data-5]=='|' || data[(uint8_t*)p-data-5]==' ')?'0':data[(uint8_t*)p-data-5]; + fan_val_str[2]=(data[(uint8_t*)p-data-4]=='|' || data[(uint8_t*)p-data-4]==' ')?'0':data[(uint8_t*)p-data-4]; + fan_val_str[3]=(data[(uint8_t*)p-data-3]=='|' || data[(uint8_t*)p-data-3]==' ')?'0':data[(uint8_t*)p-data-3]; + fan_val_str[4]=(data[(uint8_t*)p-data-2]=='|' || data[(uint8_t*)p-data-2]==' ')?'0':data[(uint8_t*)p-data-2]; + /* take the min value from front/rear fan speed + */ + if(!fan_val_int) + { + if(fan_val_int < ONLPLIB_ATOI(fan_val_str)) + { + fan_val_int=ONLPLIB_ATOI(fan_val_str); + } + } + else + fan_val_int=ONLPLIB_ATOI(fan_val_str); + } + + if(fan_val_int==0) + { + info->status &= ~ONLP_FAN_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->rpm=fan_val_int; + info->percentage=0; + snprintf(cmd , (FAN_MAX_LENGTH/2)-1, "cat %s > %s", FAN_IPMI_PWM_FILE, FAN_IPMI_TMP_FILE_PERCENT); + system(cmd); + + if(onlp_file_read(data, FAN_MAX_LENGTH, &size, FAN_IPMI_TMP_FILE_PERCENT)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + p=strstr((char*)data, FAN_IPMI_TMP_FILE_FIND_PERCENT); + if(p==NULL) + { + return ONLP_STATUS_E_INTERNAL; + } + if(((uint8_t*)p-data) < sizeof(fan_val_str)/sizeof(char)) + { + return ONLP_STATUS_E_INTERNAL; + } + memset(fan_val_str, 0x0, sizeof(fan_val_str)); + fan_val_str[0]=data[(uint8_t*)p-data+3]; + fan_val_str[1]=data[(uint8_t*)p-data+4]; + info->percentage = ONLPLIB_ATOI(fan_val_str); + + 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) +{ + char cmd[FAN_MAX_LENGTH/2] = {0}; + + snprintf(cmd, (FAN_MAX_LENGTH/2) -1, "echo 0 > %s ", FAN_CHECK_TIME); + system(cmd); + 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_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 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 cmd[FAN_MAX_LENGTH/2]={0}; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + + switch (fid) + { + 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: + break; + default: + return ONLP_STATUS_E_INVALID; + } + + snprintf(cmd,FAN_MAX_LENGTH/2, "%s %d > /dev/null 2>&1", FAN_IPMI_PWM_SET, p); + system(cmd); + + 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-csp9250/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..17f4bb29 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,261 @@ +/************************************************************ + * + * + * 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_csp9250_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_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} +}; + +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_RED | ONLP_LED_CAPS_ORANGE, + }, + { + { 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_ID_CREATE(LED_FAN), "LED 3 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "LED 4 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "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) +{ + 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-csp9250/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..55af3d15 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_csp9250 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..8d46f100 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,176 @@ +#include +#include +#include "platform_lib.h" +#include +#include "x86_64_accton_csp9250_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}; + 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 (strncmp(model_name, "YM-2651Y", strlen("YM-2651Y")) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (modelname) { + strncpy(modelname, model_name, modelname_len-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) { + 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; +} diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..a4be5348 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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 +#include "x86_64_accton_csp9250_log.h" + +#define CHASSIS_FAN_COUNT 5 +#define CHASSIS_THERMAL_COUNT 9 +#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/11-0059/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/10-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/11-0051/" +#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/bus/i2c/devices/2-0066/" +#define FAN_NODE(node) FAN_BOARD_PATH#node + +#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-1/1-0057/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_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_AC_F2B, + PSU_TYPE_AC_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_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-csp9250/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..89508e55 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/psui.c @@ -0,0 +1,252 @@ +/************************************************************ + * + * + * 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_MAX_LENGTH 256 + +#define PSU_IPMI_TMP_FILE_RM "rm -f /tmp/psu_bmc_info > /dev/null 2>&1" +#define PSU_IPMI_TMP_FILE_ONE_ENTRY_RM "rm -f /tmp/psu_bmc_info_one_entry > /dev/null 2>&1" +#define PSU_IPMI_TMP_FILE "/tmp/psu_bmc_info" +#define PSU_IPMI_TMP_FILE_ONE_ENTRY "/tmp/psu_bmc_info_one_entry" +#define PSU_IPMI_TMP_FILE_FIND_NO_READ "No Reading" +#define PSU_IPMI_SDR_CMD_PSU "ipmitool sdr type 0x08" + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + + +typedef enum onlp_psu_info_id_s +{ + PSU_INFO_VIN=0, + PSU_INFO_VOUT, + PSU_INFO_IIN, + PSU_INFO_IOUT, + PSU_INFO_PIN, + PSU_INFO_POUT, + PSU_INFO_TEMP, + PSU_INFO_MAX, +}onlp_psu_info_id_t; + +typedef struct onlp_psu_dev_info_s +{ + onlp_psu_info_id_t info_id; + char *tag; + char *find; +}onlp_psu_dev_info_t; + + +typedef struct onlp_psu_dev_s +{ + onlp_psu_dev_info_t psu_dev_info_table[PSU_INFO_MAX]; +}onlp_psu_dev_t; + + +onlp_psu_dev_t psu_sensor_table[]= +{ + { + { + {PSU_INFO_VIN, "PSU1_VIN", "Volts"}, + {PSU_INFO_VOUT, "PSU1_VOUT", "Volts"}, + {PSU_INFO_IIN, "PSU1_IIN", "Amps"}, + {PSU_INFO_IOUT, "PSU1_IOUT", "Amps"}, + {PSU_INFO_PIN, "PSU1_PIN", "Watts"}, + {PSU_INFO_POUT, "PSU1_POUT", "Watts"}, + {PSU_INFO_TEMP, "PSU1_TEMP", "degrees"} + }, + //"ipmitool sdr type 0x08", + }, + { + { + {PSU_INFO_VIN, "PSU2_VIN", "Volts"}, + {PSU_INFO_VOUT, "PSU2_VOUT", "Volts"}, + {PSU_INFO_IIN, "PSU2_IIN", "Amps"}, + {PSU_INFO_IOUT, "PSU2_IOUT", "Amps"}, + {PSU_INFO_PIN, "PSU2_PIN", "Watts"}, + {PSU_INFO_POUT, "PSU2_POUT", "Watts"}, + {PSU_INFO_TEMP, "PSU2_TEMP", "degrees"}, + }, + //"ipmitool sdr type 0x08", + } +}; + + + + + +//ipmitool sdr type 0x08s + +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 }, + } +}; +/* return code=0:no such file or the file content is invalid + * return code=1:file content is valid + */ +static int onlp_psui_check_file_valid(char* const file_path) +{ + struct stat file_info; + if(stat(file_path ,&file_info)==0) + { + if(file_info.st_size==0) + return 0; + return 1; + } + else + return 0; +} + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + int size=0; + onlp_psu_info_id_t i; + char cmd[PSU_MAX_LENGTH/2]={0}; + char psu_val_str[4]; + int psu_val_int=0; + uint8_t data[PSU_MAX_LENGTH] = {0}; + char /* *ipmi_cmd,*/ * tag, *find, *p; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + snprintf(cmd , (PSU_MAX_LENGTH/2)-1, "%s > %s", PSU_IPMI_SDR_CMD_PSU, PSU_IPMI_TMP_FILE); + system(cmd); + for(i=PSU_INFO_VIN;i %s", PSU_IPMI_TMP_FILE, tag, PSU_IPMI_TMP_FILE_ONE_ENTRY); + system(cmd); + if(!onlp_psui_check_file_valid(PSU_IPMI_TMP_FILE_ONE_ENTRY)) + { + continue; + } + if(onlp_file_read(data, PSU_MAX_LENGTH, &size, PSU_IPMI_TMP_FILE_ONE_ENTRY)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + p=strstr((char*)data, find); + if(p==NULL) + { + p=strstr((char*)data, PSU_IPMI_TMP_FILE_FIND_NO_READ); + if(p==NULL) + return ONLP_STATUS_E_INTERNAL; + else + continue; + } + if(((uint8_t*)p-data) < sizeof(psu_val_str)/sizeof(char)) + { + return ONLP_STATUS_E_INTERNAL; + } + psu_val_str[0]=(data[(uint8_t*)p-data-4]=='|' || data[(uint8_t*)p-data-4]==' ')?'0':data[(uint8_t*)p-data-4]; + psu_val_str[1]=(data[(uint8_t*)p-data-3]=='|' || data[(uint8_t*)p-data-3]==' ')?'0':data[(uint8_t*)p-data-3]; + psu_val_str[2]=(data[(uint8_t*)p-data-2]=='|' || data[(uint8_t*)p-data-2]==' ')?'0':data[(uint8_t*)p-data-2]; + + psu_val_int=ONLPLIB_ATOI(psu_val_str); + if(!strcmp(tag, "PSU1_VIN") || !strcmp(tag, "PSU2_VIN")) + { + info->mvin= psu_val_int*100; + info->caps |= ONLP_PSU_CAPS_VIN; + } + if(!strcmp(tag, "PSU1_VOUT") || !strcmp(tag, "PSU2_VOUT")) + { + info->mvout= psu_val_int*100; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + if(!strcmp(tag, "PSU1_IIN") || !strcmp(tag, "PSU2_IIN")) + { + info->miin= psu_val_int*100; + info->caps |= ONLP_PSU_CAPS_IIN; + } + if(!strcmp(tag, "PSU1_IOUT") || !strcmp(tag, "PSU2_IOUT")) + { + info->miout= psu_val_int*100; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + if(!strcmp(tag, "PSU1_PIN") || !strcmp(tag, "PSU2_PIN")) + { + info->mpin= psu_val_int*100; + info->caps |= ONLP_PSU_CAPS_PIN; + } + if(!strcmp(tag, "PSU1_POUT") || !strcmp(tag, "PSU2_POUT")) + { + info->mpout= psu_val_int*100; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + } + system(PSU_IPMI_TMP_FILE_RM); + if(info->mvin==0 && info->mvout ==0 && info->miin==0) + info->status &= ~ONLP_PSU_STATUS_PRESENT; + else + info->status |= ONLP_PSU_STATUS_PRESENT; + + if(info->mpout == 0) + info->status |= ONLP_PSU_STATUS_FAILED; + + ret = ONLP_STATUS_OK; + + 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-csp9250/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..9380d97f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,353 @@ +/************************************************************ + * + * + * 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 +#include "platform_lib.h" + +#include "x86_64_accton_csp9250_log.h" + +#define NUM_OF_SFP_PORT 54 +#define MAX_SFP_PATH 64 +#define QSFP_START_PORT 48 +static char sfp_node_path[MAX_SFP_PATH] = {0}; +#define FRONT_PORT_BUS_INDEX(port) (port+17) +#define FRONT_QSFP_PORT_BUS_INDEX(port) (port-39) + +static char* +sfp_get_port_path_addr(int port, int addr, char *node_name) +{ + if(port < QSFP_START_PORT) + sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", + FRONT_PORT_BUS_INDEX(port), addr, node_name); + else + sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", + FRONT_QSFP_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; + 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, "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[7]; + 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 %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; + } + + /* 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]; + char* path; + FILE* fp; + + path = sfp_get_port_path(0, "sfp_rx_los_all"); + fp = fopen(path, "r"); + + 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; + } + + /* Convert to 64 bit integer in port order */ + int 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]) +{ + 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]) +{ + char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom"); + memset(data, 0, 256); + + if (onlp_file_read_binary(path, (char*)data, 256, 256) != 0) { + AIM_LOG_INFO("Unable to read eeprom from port(%d)\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: + { + /* QSFP tx_disable that need to set eeprom. + * So if present=0. So not need to set + */ + if(port >=QSFP_START_PORT && port < NUM_OF_SFP_PORT) + { + rv = ONLP_STATUS_OK; + if(!onlp_sfpi_is_present(port)) + { + break; + } + break; + } + + 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_RX_LOS: + { + path = sfp_get_port_path(port, "sfp_rx_los"); + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + 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: + { + + /* QSFP tx_disable that need to set eeprom. + * So if present=0. So not need to set + */ + if(port >=QSFP_START_PORT && port <= NUM_OF_SFP_PORT) + { + if(!onlp_sfpi_is_present(port)) + { + rv = ONLP_STATUS_OK; + *value =0; + break; + } + } + 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-csp9250/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..8b4050dd --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,676 @@ +/************************************************************ + * + * + * 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" +#include "x86_64_accton_csp9250_int.h" +#include "x86_64_accton_csp9250_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*/ + + +#define SYS_MAX_LENGTH 1024 +#define SYS_MAC_ADDR_LEN 6 +#define SYS_BUFFER_MAC_ADDR_LEN 17 +#define SYS_IPMI_FRU_CMD_0 "ipmitool fru print 0" +#define SYS_IPMI_FRU_CMD_1 "ipmitool fru print 1" +#define SYS_IPMI_TMP_FILE_0_RM "rm -f /tmp/sys_bmc_info_0 > /dev/null 2>&1" +#define SYS_IPMI_TMP_FILE_1_RM "rm -f /tmp/sys_bmc_info_0 > /dev/null 2>&1" +#define SYS_IPMI_TMP_FILE_0 "/tmp/sys_bmc_info_0" +#define SYS_IPMI_TMP_FILE_1 "/tmp/sys_bmc_info_1" +#define SYS_NETWORK_MAC_GET "cat /sys/class/net/ma1/address" +#define SYS_IPMI_TMP_FILE_MAC "/tmp/sys_network_mac" +#define SYS_IPMI_TMP_FILE_MAC_RM "rm -f /tmp/sys_network_mac > /dev/null 2>&1" + +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] = +{ + "1-0060", + "2-0062", + "3-0064" +}; + +/* + * 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 SYS_EEPROM_SIZE 256 +#define TLV_INFO_ID_STRING "TlvInfo" +#define TLV_INFO_VERSION 0x01 +#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t)) + +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 + + + +typedef struct onlp_sys_eeprom_dev_s +{ + int tcode; + int size; + char *tag; + char *content; +}onlp_sys_eeprom_dev_t; + + +onlp_sys_eeprom_dev_t sys_eeprom_table[]= +{ + {TLV_CODE_PRODUCT_NAME, 0, "Board Part Number :", NULL}, + {TLV_CODE_PART_NUMBER, 0, "Chassis Part Number :", NULL}, + {TLV_CODE_SERIAL_NUMBER, 0, "Chassis Serial :", NULL}, + {TLV_CODE_MAC_BASE, SYS_MAC_ADDR_LEN, "MAC", "NULL"}, + {TLV_CODE_MANUF_DATE, 0, "Board Mfg Date :", NULL}, + {TLV_CODE_MAC_SIZE, 0, "MAC Range :", "55"}, + {TLV_CODE_LABEL_REVISION,0, "Product Version :", NULL}, + {TLV_CODE_PLATFORM_NAME, 0, "Product Part Number :", NULL}, + //{TLV_CODE_ONIE_VERSION, 4, "Fixed" ,"Onie"}, + {TLV_CODE_MANUF_NAME, 0, "Board Mfg :", NULL}, + //{TLV_CODE_MANUF_COUNTRY, 2, "Fixed", "TW"}, + //{TLV_CODE_VENDOR_NAME, 8, "Fixed", "Edgecore"}, + //{TLV_CODE_DIAG_VERSION, 4, "Fixed", "diag"} +}; + + +extern uint32_t +onlp_crc32(uint32_t crc, const void *buf, int size); + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-csp9250-r0"; +} + +char *ptr=NULL, *ptr_start=NULL, *ptr_end=NULL; + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + int byte=0,i=0; + int index=0, new_tlv_len=0; + uint8_t* eeprom = aim_zmalloc(SYS_EEPROM_SIZE); + char mac_addr[SYS_MAC_ADDR_LEN]={0}; + char cmd[SYS_MAX_LENGTH/4]={0}; + uint8_t read_buf[SYS_MAX_LENGTH] = {0}; + tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom; + tlvinfo_tlv_t *eeprom_tlv; + tlvinfo_tlv_t * eeprom_crc; + unsigned int calc_crc; + + + memset(eeprom, 0x0, SYS_EEPROM_SIZE); + strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING); + eeprom_hdr->version = TLV_INFO_VERSION; + eeprom_hdr->totallen =htons(0); + + system(SYS_IPMI_TMP_FILE_0_RM); + system(SYS_IPMI_TMP_FILE_MAC_RM); + snprintf(cmd , (SYS_MAX_LENGTH/4)-1, "%s > %s", SYS_NETWORK_MAC_GET, SYS_IPMI_TMP_FILE_MAC); + system(cmd); + if(onlp_file_read(read_buf, SYS_BUFFER_MAC_ADDR_LEN, &byte, SYS_IPMI_TMP_FILE_MAC)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + sscanf((char*)read_buf, "%02x:%02x:%02x:%02x:%02x:%02x", (int*)&mac_addr[0], (int*)&mac_addr[1], (int*)&mac_addr[2], (int*)&mac_addr[3], (int*)&mac_addr[4], (int*)&mac_addr[5]); + + snprintf(cmd , (SYS_MAX_LENGTH/4)-1, "%s > %s", SYS_IPMI_FRU_CMD_0, SYS_IPMI_TMP_FILE_0); + system(cmd); + + if(onlp_file_read(read_buf, SYS_MAX_LENGTH, &byte, SYS_IPMI_TMP_FILE_0)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + + index +=sizeof(tlvinfo_header_t); + + for(i=0; i < sizeof(sys_eeprom_table)/sizeof(onlp_sys_eeprom_dev_t); i++) + { + if(sys_eeprom_table[i].size!=0) + { + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[index]; + eeprom_tlv->type = sys_eeprom_table[i].tcode; + if(sys_eeprom_table[i].tcode==TLV_CODE_MAC_BASE) + { + eeprom_tlv->length = SYS_MAC_ADDR_LEN; + memcpy(eeprom_tlv->value, mac_addr, eeprom_tlv->length); + + } + else + { + eeprom_tlv->length = sys_eeprom_table[i].size; + memcpy(eeprom_tlv->value, sys_eeprom_table[i].content, eeprom_tlv->length); + } + index+=sizeof(tlvinfo_tlv_t); + index+=eeprom_tlv->length; + } + else + { + ptr=strstr((char*)read_buf, sys_eeprom_table[i].tag); + if(ptr!=NULL) + { + ptr_end = strchr(ptr, '\n'); + ptr_start = strchr(ptr, ':'); + if(ptr_start !=NULL && ptr_end!=NULL) + { + new_tlv_len=ptr_end-ptr_start-2; + eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[index]; + eeprom_tlv->type = sys_eeprom_table[i].tcode; + eeprom_tlv->length = new_tlv_len; + memcpy(eeprom_tlv->value, ptr_start+2, new_tlv_len); + index+=sizeof(tlvinfo_tlv_t); + index+=new_tlv_len; + + } + } + } + + } + + eeprom_hdr->totallen = htons(index - sizeof(tlvinfo_header_t) +sizeof(tlvinfo_tlv_t)+4); + + eeprom_crc = (tlvinfo_tlv_t *) &eeprom[index]; + eeprom_crc->type = TLV_CODE_CRC_32; + eeprom_crc->length = 4; + + /* Calculate the checksum */ + calc_crc = onlp_crc32(0, (void *)eeprom, + sizeof(tlvinfo_header_t) + + htons(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; + *size = SYS_EEPROM_SIZE; + *data = eeprom; + + return ONLP_STATUS_OK; +} + +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 < 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-csp9250/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..e0b0c75f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,333 @@ +/************************************************************ + * + * + * 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 PSU_THERMAL_PATH_FORMAT "/sys/bus/i2c/devices/%s/*psu_temp1_input" +#define THERMAL_IPMI_TMP_FILE "/tmp/thermal_bmc_info" +#define THERMAL_IPMI_TMP_FILE_RM "rm -f /tmp/thermal_bmc_info > /dev/null 2>&1" +#define THERMAL_IPMI_TMP_FILE_FIND "degrees" +#define THERMAL_CHECK_TIME "/usr/bin/thermal_check_time" +#define THERMAL_IPMI_SDR_CMD "ipmitool sdr list" +#define THERMAL_IPMI_SDR_FILE "/usr/bin/thermal_bmc_sdr" +#define THERMAL_IPMI_SDR_FILE_RM "rm -f /usr/bin/thermal_bmc_sdr > /dev/null 2>&1" + +#define THERMAL_CAN_SET_IPMI_TIME 10 +#define THERMAL_MAX_LENGTH 256 +#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_SWITCH_BOARD, + THERMAL_2_ON_SWITCH_BOARD, + THERMAL_3_ON_SWITCH_BOARD, + THERMAL_1_ON_SERVER_BOARD, + THERMAL_2_ON_SERVER_BOARD, + THERMAL_3_ON_SERVER_BOARD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +typedef struct onlp_thermal_dev_s +{ + int thermal_id; + char *ipmi_cmd; + char *tag; + +}onlp_thermal_dev_t; + +onlp_thermal_dev_t thermal_sensor_table[]= +{ + {THERMAL_RESERVED, NULL, NULL}, + {THERMAL_CPU_CORE, NULL, NULL}, + {THERMAL_1_ON_SWITCH_BOARD, "ipmitool sdr list", "Temp_LM75_Power"}, + {THERMAL_2_ON_SWITCH_BOARD, "ipmitool sdr list", "Temp_LM75_LEFT"}, + {THERMAL_3_ON_SWITCH_BOARD, "ipmitool sdr list", "Temp_LM75_HS"}, + {THERMAL_1_ON_SERVER_BOARD, "ipmitool sdr list", "Temp_LM75_CPU0"}, + {THERMAL_2_ON_SERVER_BOARD, "ipmitool sdr list", "Temp_LM75_CPU1"}, + {THERMAL_3_ON_SERVER_BOARD, "ipmitool sdr list", "Temp_LM75_PCH"}, + {THERMAL_1_ON_PSU1, "ipmitool sdr list", "PSU1_TEMP"}, + {THERMAL_1_ON_PSU2, "ipmitool sdr list", "PSU2_TEMP"} +}; + +char *onlp_find_thermal_sensor_cmd(unsigned int id) +{ + int i; + for(i=0; i %s ", THERMAL_CHECK_TIME); + system(cmd); + system("echo V0002 > /etc/onlp_drv_version"); + return ONLP_STATUS_OK; +} + + +static int +thermali_time_exist(void) +{ + struct stat file_info; + if(stat(THERMAL_CHECK_TIME ,&file_info)==0) + { + if(file_info.st_size==0) + return 0; + return 1; + } + else + return 1; + +} +static int +thermali_sdr_file_exist(void) +{ + struct stat file_info; + if(stat(THERMAL_IPMI_SDR_FILE ,&file_info)==0) + { + if(file_info.st_size==0) + return 0; + return 1; + } + else + return 0; + +} + + +/* + * 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; + int size; + char cmd[THERMAL_MAX_LENGTH/2] = {0}; + char temp[4]; + uint8_t data[THERMAL_MAX_LENGTH] = {0}; + //char *ipmi_cmd; + char * tag, *p; + struct timeval new_tv; + long last_time; + int get_data_by_ipmi=0; + + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + if(tid > THERMAL_1_ON_PSU2 || tid <= THERMAL_RESERVED) + return ONLP_STATUS_E_INTERNAL; + /* 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); + } + if(thermali_time_exist()) + { + if(onlp_file_read(data, THERMAL_MAX_LENGTH, &size, THERMAL_CHECK_TIME)!=ONLP_STATUS_OK) + { + last_time=0; + } + else + last_time = atol((char*)data); + } + else + last_time=0; + + gettimeofday(&new_tv,NULL); + + if(last_time==0) /* first time */ + { + get_data_by_ipmi=1; + } + else + { + if(new_tv.tv_sec > last_time) + { + if((new_tv.tv_sec - last_time) > THERMAL_CAN_SET_IPMI_TIME) + { + get_data_by_ipmi=1; + } + else + get_data_by_ipmi=0; + } + else if(new_tv.tv_sec == last_time) + get_data_by_ipmi=0; + else + get_data_by_ipmi=1; + + } + memset(data ,0x0, THERMAL_MAX_LENGTH); + snprintf((char*)data, THERMAL_MAX_LENGTH-1, "%ld", new_tv.tv_sec); + if(onlp_file_write_str((char*)data, THERMAL_CHECK_TIME)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + if(get_data_by_ipmi || !thermali_sdr_file_exist()) /* Set ipmitool cmd to get all data and save to file*/ + { + /* set ipmi cmd */ + snprintf(cmd, (THERMAL_MAX_LENGTH/2) -1, "%s > %s ", THERMAL_IPMI_SDR_CMD, THERMAL_IPMI_SDR_FILE); + system(cmd); + fflush(stdout); + } + tag= thermal_sensor_table[tid].tag; + + if(tag==NULL) + return ONLP_STATUS_E_INTERNAL; + + snprintf(cmd, (THERMAL_MAX_LENGTH/2) -1, "cat %s|grep %s > %s ", THERMAL_IPMI_SDR_FILE, tag, THERMAL_IPMI_TMP_FILE); + system(cmd); + + if(onlp_file_read(data, THERMAL_MAX_LENGTH, &size, THERMAL_IPMI_TMP_FILE)!=ONLP_STATUS_OK) + { + return ONLP_STATUS_E_INTERNAL; + } + p=strstr((char*)data, THERMAL_IPMI_TMP_FILE_FIND); + if(p==NULL) + { + return ONLP_STATUS_E_INTERNAL; + } + if(((uint8_t*)p-data) < sizeof(temp)/sizeof(char)) + { + return ONLP_STATUS_E_INTERNAL; + } + + temp[0]=data[(uint8_t*)p-data-4]; + temp[1]=data[(uint8_t*)p-data-3]; + temp[2]=data[(uint8_t*)p-data-2]; + info->mcelsius=ONLPLIB_ATOI(temp) * 1000; + + return ONLP_STATUS_OK; +} + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_config.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_config.c new file mode 100755 index 00000000..9caedcad --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_csp9250_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_csp9250_config_STRINGIFY_VALUE(_x) __x86_64_accton_csp9250_config_STRINGIFY_NAME(_x) +x86_64_accton_csp9250_config_settings_t x86_64_accton_csp9250_config_settings[] = +{ +#ifdef x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_accton_csp9250_CONFIG_INCLUDE_LOGGING(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_PORTING_STDLIB + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_PORTING_STDLIB), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_accton_csp9250_CONFIG_PORTING_STDLIB(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_csp9250_config_STRINGIFY_NAME(x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_csp9250_config_STRINGIFY_VALUE(x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_accton_csp9250_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_csp9250_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_csp9250_config_STRINGIFY_VALUE +#undef __x86_64_accton_csp9250_config_STRINGIFY_NAME + +const char* +x86_64_accton_csp9250_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_csp9250_config_settings[i].name; i++) { + if(strcmp(x86_64_accton_csp9250_config_settings[i].name, setting)) { + return x86_64_accton_csp9250_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_csp9250_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_csp9250_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_csp9250_config_settings[i].name, x86_64_accton_csp9250_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_enums.c new file mode 100755 index 00000000..9d9fda58 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_int.h b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_int.h new file mode 100755 index 00000000..51f3f205 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_csp9250 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_csp9250_INT_H__ +#define __x86_64_accton_csp9250_INT_H__ + +#include + + +#endif /* __x86_64_accton_csp9250_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_log.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_log.c new file mode 100755 index 00000000..58133bcf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_csp9250_log.h" +/* + * x86_64_accton_csp9250 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_accton_csp9250_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_accton_csp9250_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_accton_csp9250_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_log.h b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_log.h new file mode 100755 index 00000000..a82a3299 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_csp9250_LOG_H__ +#define __x86_64_accton_csp9250_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_csp9250 +#include + +#endif /* __x86_64_accton_csp9250_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_module.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_module.c new file mode 100755 index 00000000..75fdc6e7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_csp9250_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_csp9250_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_csp9250_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-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_ucli.c new file mode 100755 index 00000000..4159759e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/module/src/x86_64_accton_csp9250_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_csp9250_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_csp9250) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_csp9250_ucli_module__ = + { + "x86_64_accton_csp9250_ucli", + NULL, + x86_64_accton_csp9250_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_csp9250_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_csp9250_ucli_module__); + n = ucli_node_create("x86_64_accton_csp9250", NULL, &x86_64_accton_csp9250_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_csp9250")); + return n; +} + +#else +void* +x86_64_accton_csp9250_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/x86_64_accton_csp9250.mk b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/x86_64_accton_csp9250.mk new file mode 100755 index 00000000..c0a81e05 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/builds/src/x86_64_accton_csp9250.mk @@ -0,0 +1,13 @@ + +############################################################################### +# +# Inclusive Makefile for the x86_64_accton_csp9250 module. +# +# Autogenerated 2017-08-10 09:44:26.279780 +# +############################################################################### +x86_64_accton_csp9250_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(x86_64_accton_csp9250_BASEDIR)module/make.mk +include $(x86_64_accton_csp9250_BASEDIR)module/src/make.mk +include $(x86_64_accton_csp9250_BASEDIR)module/auto/make.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/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-csp9250/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/PKG.yml new file mode 100755 index 00000000..4d70dcab --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-csp9250 REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml new file mode 100755 index 00000000..8425af5c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml @@ -0,0 +1,24 @@ +--- + +###################################################################### +# +# platform-config for csp9250 +# +###################################################################### + +x86-64-accton-csp9250-r0: + + grub: + serial: >- + console=tty0 + kernel: + <<: *kernel-3-16 + + args: >- + console=tty0, + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/python/x86_64_accton_csp9250_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/python/x86_64_accton_csp9250_r0/__init__.py new file mode 100755 index 00000000..373781f3 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/python/x86_64_accton_csp9250_r0/__init__.py @@ -0,0 +1,108 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_csp9250_r0(OnlPlatformAccton, + OnlPlatformPortConfig_48x25_6x100): + + PLATFORM='x86-64-accton-csp9250-r0' + MODEL="CSP9250" + SYS_OBJECT_ID=".9250.54" + + def baseconfig(self): + self.insmod('ym2651y') + for m in [ 'cpld', 'sfp', 'leds' ]: + self.insmod("x86-64-accton-csp9250-%s.ko" % m) + + ########### initialize I2C bus 0 ########### + + # initiate multiplexer (PCA9548) + self.new_i2c_devices( + [ + # initiate multiplexer (PCA9548) + ('pca9548', 0x71, 0), + ('pca9548', 0x70, 0), + ('pca9548', 0x72, 0), + ('pca9548', 0x73, 0), + ('pca9548', 0x74, 0), + ('pca9548', 0x75, 0), + ('pca9548', 0x76, 0), + ('pca9548', 0x77, 0), + ] + ) + + self.new_i2c_devices([ + # initialize CPLD + ('accton_i2c_cpld', 0x60, 1), + ('accton_i2c_cpld', 0x62, 2), + ('accton_i2c_cpld', 0x64, 3), + ]) + + # initialize QSFP port 1~54 + self.new_i2c_devices( + [ + ('csp9250_sfp1', 0x50, 17), + ('csp9250_sfp2', 0x50, 18), + ('csp9250_sfp3', 0x50, 19), + ('csp9250_sfp4', 0x50, 20), + ('csp9250_sfp5', 0x50, 21), + ('csp9250_sfp6', 0x50, 22), + ('csp9250_sfp7', 0x50, 23), + ('csp9250_sfp8', 0x50, 24), + + ('csp9250_sfp9' , 0x50, 25), + ('csp9250_sfp10', 0x50, 26), + ('csp9250_sfp11', 0x50, 27), + ('csp9250_sfp12', 0x50, 28), + ('csp9250_sfp13', 0x50, 29), + ('csp9250_sfp14', 0x50, 30), + ('csp9250_sfp15', 0x50, 31), + ('csp9250_sfp16', 0x50, 32), + + ('csp9250_sfp17', 0x50, 33), + ('csp9250_sfp18', 0x50, 34), + ('csp9250_sfp19', 0x50, 35), + ('csp9250_sfp20', 0x50, 36), + ('csp9250_sfp21', 0x50, 37), + ('csp9250_sfp22', 0x50, 38), + ('csp9250_sfp23', 0x50, 39), + ('csp9250_sfp24', 0x50, 40), + + ('csp9250_sfp25', 0x50, 41), + ('csp9250_sfp26', 0x50, 42), + ('csp9250_sfp27', 0x50, 43), + ('csp9250_sfp28', 0x50, 44), + ('csp9250_sfp29', 0x50, 45), + ('csp9250_sfp30', 0x50, 46), + ('csp9250_sfp31', 0x50, 47), + ('csp9250_sfp32', 0x50, 48), + + ('csp9250_sfp33', 0x50, 49), + ('csp9250_sfp34', 0x50, 50), + ('csp9250_sfp35', 0x50, 51), + ('csp9250_sfp36', 0x50, 52), + ('csp9250_sfp37', 0x50, 53), + ('csp9250_sfp38', 0x50, 54), + ('csp9250_sfp39', 0x50, 55), + ('csp9250_sfp40', 0x50, 56), + ('csp9250_sfp41', 0x50, 57), + ('csp9250_sfp42', 0x50, 58), + + ('csp9250_sfp43', 0x50, 59), + ('csp9250_sfp44', 0x50, 60), + ('csp9250_sfp45', 0x50, 61), + ('csp9250_sfp46', 0x50, 62), + ('csp9250_sfp47', 0x50, 63), + ('csp9250_sfp48', 0x50, 64), + + ('csp9250_sfp49', 0x50, 9), + ('csp9250_sfp50', 0x50, 10), + ('csp9250_sfp51', 0x50, 11), + ('csp9250_sfp52', 0x50, 12), + ('csp9250_sfp53', 0x50, 13), + ('csp9250_sfp54', 0x50, 14), + ] + ) + + return True + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/.gitignore b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/.gitignore new file mode 100644 index 00000000..76483140 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/.gitignore @@ -0,0 +1,3 @@ +*x86*64*delta_agc7648a*.mk +onlpdump.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448/modules/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448/modules/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/PKG.yml new file mode 100644 index 00000000..57ce3c19 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=delta BASENAME=x86-64-delta-ak7448 ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/.gitignore b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/Makefile new file mode 100644 index 00000000..e34dd4b8 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := delta +BASENAME := x86-64-delta-ak7448 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk 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 new file mode 100755 index 00000000..a01354e4 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_psu.c @@ -0,0 +1,513 @@ +/* + * 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 +#define SWPLD_BUS 5 +#define SWPLD_REG 0x32 +#define SWPLD_PSU_MUX_REG 0x04 +#define SELECT_PSU1_EEPROM 0x01 +#define SELECT_PSU2_EEPROM 0x02 + +/* 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); + +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); +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; + + /* Select SWPLD PSU offset */ + i2c_cpld_write(SWPLD_BUS, SWPLD_REG, + SWPLD_PSU_MUX_REG, SELECT_PSU2_EEPROM); + + 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); + /* Select SWPLD PSU offset */ + i2c_cpld_write(SWPLD_BUS, SWPLD_REG, SWPLD_PSU_MUX_REG, SELECT_PSU2_EEPROM); + + 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_temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, \ + S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUGO | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); + +static 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_ak7448_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ak7448_psu", dni_ak7448_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-ak7448/modules/builds/dni_ak7448_sfp.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_sfp.c new file mode 100755 index 00000000..1c69ed28 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_ak7448_sfp.c @@ -0,0 +1,698 @@ +/* + * 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/modules/builds/dni_emc2305.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_emc2305.c new file mode 100755 index 00000000..d0788899 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_emc2305.c @@ -0,0 +1,372 @@ +/* + * + * + * 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 + +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); + +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 show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t show_percentage(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 set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +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 19000 + +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(fan1_input_percentage, S_IWUSR | S_IRUGO, show_percentage, set_fan_percentage, 0); +static SENSOR_DEVICE_ATTR(fan2_input_percentage, S_IWUSR | S_IRUGO, show_percentage, set_fan_percentage, 1); +static SENSOR_DEVICE_ATTR(fan3_input_percentage, S_IWUSR | S_IRUGO, show_percentage, set_fan_percentage, 2); +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 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_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_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + NULL +}; + + +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 * 190; + 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_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 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 > 19000) + { + 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 < 4; 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-ak7448/onlp/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448/onlp/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/PKG.yml new file mode 100644 index 00000000..67186671 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-delta-ak7448 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448/onlp/builds/lib/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/lib/Makefile new file mode 100644 index 00000000..d1482b0d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_delta_ak7448 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-delta-ak7448.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-ak7448/onlp/builds/lib/libonlp-x86-64-delta-ak7448.mk b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/lib/libonlp-x86-64-delta-ak7448.mk new file mode 100644 index 00000000..e70f23f0 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/lib/libonlp-x86-64-delta-ak7448.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-delta-ak7448 module. +# +# Autogenerated 2017-03-15 04:06:44.303111 +# +############################################################################### +libonlp-x86-64-delta-ak7448_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/onlpdump/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..cfb370a0 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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_ak7448 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-ak7448/onlp/builds/src/.module b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/.module new file mode 100644 index 00000000..55992d2a --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_delta_ak7448 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/Makefile new file mode 100644 index 00000000..cbec2174 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_delta_ak7448 +AUTOMODULE := x86_64_delta_ak7448 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/README b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/README new file mode 100644 index 00000000..08c98b11 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_delta_ak7448 README +# +############################################################################### + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/auto/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..b1be69fe --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_delta_ak7448 Autogeneration +# +############################################################################### +x86_64_delta_ak7448_AUTO_DEFS := module/auto/x86_64_delta_ak7448.yml +x86_64_delta_ak7448_AUTO_DIRS := module/inc/x86_64_delta_ak7448 module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/auto/x86_64_delta_ak7448.yml b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/auto/x86_64_delta_ak7448.yml new file mode 100644 index 00000000..f62499f7 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/auto/x86_64_delta_ak7448.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_delta_ak7448 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB +- X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_DELTA_AK7448_CONFIGHEADER: + defs: *cdefs + basename: x86_64_delta_ak7448_config + + portingmacro: + x86_64_delta_ak7448: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448.x b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448.x new file mode 100644 index 00000000..ecaf91b7 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_config.h b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_config.h new file mode 100644 index 00000000..2febf314 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_ak7448 Configuration Header + * + * @addtogroup x86_64_delta_ak7448-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_DELTA_AK7448_CONFIGH__ +#define __X86_64_DELTA_AK7448_CONFIGH__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_delta_ak7448_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING +#define X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING 1 +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT +#define X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT +#define X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT +#define X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB +#define X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB 1 +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI +#define X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI 0 +#endif + +/** + * X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_delta_ak7448_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_delta_ak7448_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_delta_ak7448_config_settings table. */ +extern x86_64_delta_ak7448_config_settings_t x86_64_delta_ak7448_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_delta_ak7448_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_delta_ak7448_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_delta_ak7448_porting.h" + +#endif /* __X86_64_DELTA_AK7448_CONFIGH__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_dox.h b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_dox.h new file mode 100644 index 00000000..40eaf266 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_delta_ak7448 Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_delta_ak7448_DOX_H__ +#define __x86_64_delta_ak7448_DOX_H__ + +/** + * @defgroup x86_64_delta_ak7448 x86_64_delta_ak7448 - x86_64_delta_ak7448 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_delta_ak7448-x86_64_delta_ak7448 Public Interface + * @defgroup x86_64_delta_ak7448-config Compile Time Configuration + * @defgroup x86_64_delta_ak7448-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_delta_ak7448_DOX_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_porting.h b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_porting.h new file mode 100644 index 00000000..3fcb3c4b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/inc/x86_64_delta_ak7448/x86_64_delta_ak7448_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_ak7448 Porting Macros. + * + * @addtogroup x86_64_delta_ak7448-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_delta_ak7448_PORTING_H__ +#define __x86_64_delta_ak7448_PORTING_H__ + + +/* */ +#if X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_delta_ak7448_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_delta_ak7448_MALLOC GLOBAL_MALLOC + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_MALLOC malloc + #else + #error The macro x86_64_delta_ak7448_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_FREE + #if defined(GLOBAL_FREE) + #define x86_64_delta_ak7448_FREE GLOBAL_FREE + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_FREE free + #else + #error The macro x86_64_delta_ak7448_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_delta_ak7448_MEMSET GLOBAL_MEMSET + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_MEMSET memset + #else + #error The macro x86_64_delta_ak7448_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_delta_ak7448_MEMCPY GLOBAL_MEMCPY + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_MEMCPY memcpy + #else + #error The macro x86_64_delta_ak7448_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_delta_ak7448_STRNCPY GLOBAL_STRNCPY + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_STRNCPY strncpy + #else + #error The macro x86_64_delta_ak7448_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_delta_ak7448_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_VSNPRINTF vsnprintf + #else + #error The macro x86_64_delta_ak7448_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_delta_ak7448_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_SNPRINTF snprintf + #else + #error The macro x86_64_delta_ak7448_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_ak7448_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_delta_ak7448_STRLEN GLOBAL_STRLEN + #elif X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB == 1 + #define x86_64_delta_ak7448_STRLEN strlen + #else + #error The macro x86_64_delta_ak7448_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_delta_ak7448_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..2dceee4e --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_delta_ak7448_INCLUDES := -I $(THIS_DIR)inc +x86_64_delta_ak7448_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_delta_ak7448_DEPENDMODULE_ENTRIES := init:x86_64_delta_ak7448 ucli:x86_64_delta_ak7448 + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..2b02407c --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_delta_ak7448_ucli.c + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/debug.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..7a1eeb6d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_delta_ak7448_int.h" + +#if X86_64_DELTA_AK7448_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_delta_ak7448_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/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 new file mode 100755 index 00000000..dd670ef2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/fani.c @@ -0,0 +1,398 @@ +/************************************************************ + * + * + * 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 +#include +#include +#include "platform_lib.h" +#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 }, + { "/7-002c/fan1_fault", "/7-002c/fan1_input", "/7-002c/fan1_input_percentage" }, + { "/7-002c/fan2_fault", "/7-002c/fan2_input", "/7-002c/fan2_input_percentage" }, + { "/7-002c/fan3_fault", "/7-002c/fan3_input", "/7-002c/fan3_input_percentage" }, + { "/7-002d/fan1_fault", "/7-002d/fan1_input", "/7-002d/fan1_input_percentage" }, + { "/7-002d/fan2_fault", "/7-002d/fan2_input", "/7-002d/fan2_input_percentage" }, + { "/7-002d/fan3_fault", "/7-002d/fan3_input", "/7-002d/fan3_input_percentage" }, + { "/4-0058/psu_fan1_fault", "/4-0058/psu_fan1_speed_rpm", "/4-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_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_PERCENTAGE | ONLP_FAN_CAPS_SET_RPM | ONLP_FAN_CAPS_GET_RPM), \ + 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_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_PSU(1,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) +{ + int rpm = 0; + char fullpath[100] = {0}; + uint8_t present_bit=0x00, bit=0x00; + 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; + + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + rpm = dni_i2c_lock_read_attribute(&mux_info, fullpath); + if(rpm == -1){ + AIM_LOG_ERROR("Unable to read rpm from fan(%d)\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + + info->rpm = rpm; + + if(info->rpm == FAN_ZERO_RPM) + info->rpm = 0; + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + mux_info.channel = FAN_I2C_SEL_FAN_IO_CTRL; + present_bit = dni_i2c_lock_read(&mux_info, &dev_info); + switch(local_id) + { + case FAN_1_ON_FAN_BOARD: + case FAN_4_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_5_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_6_ON_FAN_BOARD: + if((present_bit & ((bit+1)<<2)) == 0) + info->status |= ONLP_FAN_STATUS_PRESENT; + else + info->status |= ONLP_FAN_STATUS_FAILED; + break; + } + return ONLP_STATUS_OK; +} + + +static int +dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) +{ + int r_data = 0; + char fullpath[80] = {0}; + 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; + dev_info.offset = 0x00; /* In EEPROM address 0x00 */ + dev_info.flags = DEFAULT_FLAG; + + /* Check PSU is PRESENT or not + * Read PSU EEPROM 1 byte from adress 0x00 + * if not present, return Negative value. + */ + if(dni_i2c_lock_read(&mux_info, &dev_info) >= 0) { + info->status |= ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F; + } + + /* Check PSU FAN is fault or not + * Read PSU FAN Fault from psu_fan1_fault + * Return 1 is PSU fan fault + */ + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].status); + r_data = dni_i2c_lock_read_attribute(&mux_info, fullpath); + + if ((r_data == -1)) { + info->status |= ONLP_FAN_STATUS_FAILED; + AIM_LOG_ERROR("Unable to read status from fan(%d)\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + + /* 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(&mux_info, fullpath); + if(r_data == -1){ + AIM_LOG_ERROR("Unable to read rpm from fan(%d)\r\n",local_id); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = r_data; + + /* get speed percentage from rpm */ + 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 local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + + 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: + rc = dni_fani_info_get_fan(local_id, info); + if(rc != ONLP_STATUS_OK){ + rc = ONLP_STATUS_E_INVALID; + } + break; + case FAN_1_ON_PSU1: + rc = dni_fani_info_get_fan_on_psu(local_id, info); + if(rc != ONLP_STATUS_OK){ + rc = ONLP_STATUS_E_INVALID; + } + + 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) +{ + int local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + mux_info_t mux_info; + int ret = 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: + sprintf(fullpath, "%s%s", PREFIX_PATH, fan_path[local_id].speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + 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){ + AIM_LOG_ERROR("Unable to set fan(%d) rpm\r\n",local_id); + return ONLP_STATUS_E_INVALID; + } + 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 percentage) +{ + int local_id; + char data[10] = {0}; + 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); + + 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: + mux_info.offset = FAN_I2C_MUX_SEL_REG; + mux_info.channel = FAN_I2C_SEL_FAN_CTRL; + + break; + case FAN_1_ON_PSU1: + mux_info.offset = PSU_I2C_MUX_SEL_REG; + mux_info.channel = PSU_I2C_SEL_PSU_EEPROM; + 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", percentage); + + if(dni_i2c_lock_write_attribute(&mux_info, data, fullpath) == -1){ + AIM_LOG_ERROR("Unable to set fan(%d) percentage\r\n",local_id); + return ONLP_STATUS_E_INVALID; + } + + 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-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 new file mode 100755 index 00000000..8a5fbf7d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,431 @@ +/************************************************************ + * + * + * 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 +#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) + +/* + * 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_ORANGE | 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_BLINKING | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_PWR), "FRONT LED (PWR LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE_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, + }, +}; + +/* + * 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 r_data = 0, fantray_present = -1; + mux_info_t mux_info; + dev_info_t dev_info; + + VALIDATE(id); + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + dev_info.bus = I2C_BUS_7; + 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); + if(r_data == -1){ + AIM_LOG_ERROR("Unable to read front panel led status from reg\r\n"); + return ONLP_STATUS_E_INTERNAL; + } + int local_id = ONLP_OID_ID_GET(id); + switch(local_id) + { + case LED_FRONT_FAN: + if((r_data & 0x30) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x30) == 0x20) + info->mode = ONLP_LED_MODE_ORANGE; + break; + + case LED_FRONT_SYS: + if((r_data & 0x03) == 0x03) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x03) == 0x01) + info->mode = ONLP_LED_MODE_ORANGE; + else if((r_data & 0x03) == 0x02) + info->mode = ONLP_LED_MODE_GREEN_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((r_data & 0x0c) == 0x0c) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x0c) == 0x08) + info->mode = ONLP_LED_MODE_ORANGE; + else if((r_data & 0x0c) == 0x04) + info->mode = ONLP_LED_MODE_ORANGE_BLINKING; + else + info->mode = ONLP_LED_MODE_OFF; + break; + + 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); + if(r_data == -1){ + AIM_LOG_ERROR("Unable to read fan tray 1 led status from reg\r\n"); + return ONLP_STATUS_E_INTERNAL; + } + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data & 0x20) == 0x20) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x10) == 0x10) + info->mode = ONLP_LED_MODE_RED; + else + info->mode = ONLP_LED_MODE_OFF; + } + else + info->status = ONLP_LED_STATUS_FAILED; + break; + + 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); + if(r_data == -1){ + AIM_LOG_ERROR("Unable to read fan tray 2 led status from reg\r\n"); + return ONLP_STATUS_E_INTERNAL; + } + + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data & 0x08) == 0x08) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x04) == 0x04) + info->mode = ONLP_LED_MODE_RED; + else + info->mode = ONLP_LED_MODE_OFF; + } + else + info->status = ONLP_LED_STATUS_FAILED; + break; + + 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); + if(r_data == -1){ + AIM_LOG_ERROR("Unable to read fan tray 3 led status from reg\r\n"); + return ONLP_STATUS_E_INTERNAL; + } + + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data & 0x02) == 0x02) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x01) == 0x01) + info->mode = ONLP_LED_MODE_RED; + else + info->mode = ONLP_LED_MODE_OFF; + } + else + info->status = ONLP_LED_STATUS_FAILED; + break; + + default: + 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) +{ + VALIDATE(id); + if(on_or_off == 0) + onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + else + onlp_ledi_mode_set(id,ONLP_LED_MODE_AUTO); + return ONLP_STATUS_OK; +} + +/* + * 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,fan_tray_led_reg_value; + + switch(local_id) + { + case LED_FRONT_FAN: + front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_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; + } + + front_panel_led_value &= ~0x30; + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x10; + } + else if(mode == ONLP_LED_MODE_ORANGE){ + front_panel_led_value |= 0x20; + } + else{ + front_panel_led_value = front_panel_led_value; + } + + if(dni_lock_cpld_write_attribute(CPLD_B_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; + } + + break; + + case LED_FRONT_SYS: + front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_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; + } + + front_panel_led_value &= ~0x03; + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x03; + } + else if(mode == ONLP_LED_MODE_ORANGE){ + front_panel_led_value |= 0x01; + } + else if(mode == ONLP_LED_MODE_GREEN_BLINKING){ + front_panel_led_value |= 0x02; + } + else{ + front_panel_led_value = front_panel_led_value; + } + + if(dni_lock_cpld_write_attribute(CPLD_B_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; + } + + break; + + case LED_FRONT_PWR: + front_panel_led_value = dni_lock_cpld_read_attribute(CPLD_B_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; + } + + front_panel_led_value &= ~0x0c; + if(mode == ONLP_LED_MODE_GREEN){ + front_panel_led_value |= 0x0c; + } + else if(mode == ONLP_LED_MODE_ORANGE){ + front_panel_led_value |= 0x08; + } + else if(mode == ONLP_LED_MODE_ORANGE_BLINKING){ + front_panel_led_value |= 0x04; + } + else{ + front_panel_led_value = front_panel_led_value; + } + + if(dni_lock_cpld_write_attribute(CPLD_B_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; + } + + break; + + case LED_REAR_FAN_TRAY_1: + fan_tray_led_reg_value = dni_lock_cpld_read_attribute(CPLD_B_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; + } + + fan_tray_led_reg_value &= ~0x30; + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x20; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x10; + } + else{ + 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){ + 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(CPLD_B_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; + } + + fan_tray_led_reg_value &= ~0x0c; + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x08; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x04; + } + else{ + 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){ + 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(CPLD_B_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; + } + + fan_tray_led_reg_value &= ~0x03; + if(mode == ONLP_LED_MODE_GREEN){ + fan_tray_led_reg_value |= 0x02; + } + else if(mode == ONLP_LED_MODE_RED){ + fan_tray_led_reg_value |= 0x01; + } + else{ + 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){ + 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-ak7448/onlp/builds/src/module/src/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..5ff8e3f1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_delta_ak7448 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk 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 new file mode 100755 index 00000000..f2d663db --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,314 @@ +/************************************************************ + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include +#include + +int dni_i2c_read_attribute_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 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; +} + +/* Lock function */ +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) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); + } + 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); + return r_data; +} + +int dni_i2c_lock_write( mux_info_t * mux_info, dev_info_t * dev_info) +{ + pthread_mutex_lock(&mutex); + if(mux_info != NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + 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); + else + onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); + + pthread_mutex_unlock(&mutex); + return 0; +} + +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath) +{ + int fd, len, nbytes = 10; + char r_data[10] = {0}; + + pthread_mutex_lock(&mutex); + if(mux_info != NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); + } + if ((fd = open(fullpath, O_RDONLY)) == -1) + { + goto ERROR; + } + if ((len = read(fd, r_data, nbytes)) <= 0) + { + goto ERROR; + } + close(fd); + pthread_mutex_unlock(&mutex); + return atoi(r_data); +ERROR: + close(fd); + pthread_mutex_unlock(&mutex); + return -1; +} + +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data,char * fullpath) +{ + int fd, len, nbytes = 10; + pthread_mutex_lock(&mutex); + if(mux_info!=NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", PREFIX_PATH, mux_info->bus, mux_info->addr); + 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) + { + goto ERROR; + } + len = write (fd, data, (ssize_t) nbytes); + if (len != nbytes) + { + goto ERROR; + } + close(fd); + pthread_mutex_unlock(&mutex); + return 0; +ERROR: + close(fd); + pthread_mutex_unlock(&mutex); + return -1; +} + +/* Use this function to select MUX and read data on CPLD */ +int dni_lock_cpld_read_attribute(char *cpld_path, int addr) +{ + int fd, len, nbytes = 10,data = 0; + 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/data", cpld_path); + sprintf(cpld_addr_path, "%s/addr", cpld_path); + sprintf(address, "%02x", addr); + + pthread_mutex_lock(&mutex1); + /* Create output file descriptor */ + fd = open(cpld_addr_path, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + + len = write (fd, address, 2); + if (len <= 0) + { + goto ERR_HANDLE; + } + close(fd); + + if ((fd = open(cpld_data_path, O_RDONLY)) == -1) + { + goto ERR_HANDLE; + } + + if ((len = read(fd, r_data, nbytes)) <= 0) + { + goto ERR_HANDLE; + } + close(fd); + pthread_mutex_unlock(&mutex1); + + sscanf(r_data, "%x", &data); + return data; + + ERR_HANDLE: + close(fd); + pthread_mutex_unlock(&mutex1); + return -1; +} + +/* 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, len; + char address[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + + sprintf(cpld_data_path, "%s/data", cpld_path); + sprintf(cpld_addr_path, "%s/addr", cpld_path); + sprintf(address, "%02x", addr); + + pthread_mutex_lock(&mutex1); + /* Create output file descriptor */ + fd = open(cpld_addr_path, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + len = write(fd, address, 2); + if(len <= 0) + { + goto ERR_HANDLE; + } + close(fd); + + fd = open(cpld_data_path, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + sprintf(address, "%02x", data); + len = write (fd, address, 2); + if(len <= 0) + { + goto ERR_HANDLE; + } + close(fd); + pthread_mutex_unlock(&mutex1); + + return 0; + + ERR_HANDLE: + close(fd); + pthread_mutex_unlock(&mutex1); + return -1; +} + + +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); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + + rpm = dni_i2c_lock_read_attribute(&mux_info, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(&mux_info, FAN2_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + + rpm = dni_i2c_lock_read_attribute(&mux_info, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(&mux_info, FAN3_REAR); + if(rpm != 0 && rpm != FAN_ZERO_RPM && rpm1 != 0 && rpm1 != FAN_ZERO_RPM) + speed_good++; + + return speed_good; +} + 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 new file mode 100755 index 00000000..cf0ef7a8 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,186 @@ +/************************************************************ + * + * + * 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_ak7448_log.h" + +/* CPLD numbrt & peripherals */ +#define NUM_OF_THERMAL_ON_BOARDS 7 +#define NUM_OF_FAN_ON_FAN_BOARD 6 +#define NUM_OF_PSU_ON_PSU_BOARD 1 +#define NUM_OF_LED_ON_BOARDS 6 +#define NUM_OF_CPLD 3 +#define CHASSIS_FAN_COUNT 6 +#define CHASSIS_THERMAL_COUNT 6 + +#define MAX_FAN_SPEED 19000 +#define MAX_PSU_FAN_SPEED 18240 + +#define NUM_OF_SFP 48 +#define NUM_OF_QSFP 4 +#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 + +#define FAN1_FRONT PREFIX_PATH "/7-002c/fan3_input" +#define FAN1_REAR PREFIX_PATH "/7-002d/fan3_input" +#define FAN2_FRONT PREFIX_PATH "/7-002c/fan2_input" +#define FAN2_REAR PREFIX_PATH "/7-002d/fan2_input" +#define FAN3_FRONT PREFIX_PATH "/7-002c/fan1_input" +#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 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" + +/* BUS define */ +#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_6 (6) +#define I2C_BUS_7 (7) +#define I2C_BUS_8 (8) +#define I2C_BUS_9 (9) +#define PSU1_ID (1) +#define ALL_FAN_TRAY_EXIST (3) +#define FAN_SPEED_NORMALLY (3) +#define PSU_NODE_MAX_PATH_LEN (64) +#define FAN_ZERO_RPM (960) +#define SPEED_100_PERCENTAGE (100) + + +/* REG define*/ +#define PSU_EEPROM (0x50) +#define DEFAULT_FLAG (0x00) +#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) +#define LED_REG (0x09) +#define FAN_STATUS_REG (0x16) +#define FAN_TRAY (0x50) +#define FAN_TRAY_LED_REG (0x18) +#define FAN_I2C_MUX_SEL_REG (0x0A) +#define FAN_I2C_SEL_FAN_IO_CTRL (0x07) +#define FAN_I2C_SEL_THERMAL (0x06) +#define FAN_I2C_SEL_FAN_CTRL (0x05) +#define PSU_I2C_MUX_SEL_REG (0x04) +#define PSU_I2C_SEL_PSU_EEPROM (0x02) +#define PORT_ADDR (0x50) +#define FAN_IO_CTL (0x27) + +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); + +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; + +typedef struct mux_info_s +{ + int bus; + uint8_t addr; + uint8_t offset; + uint8_t channel; + char dev_data[10]; + uint32_t flags; +}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_cpld_write_attribute(char *cpld_path, int addr, int data); +int dni_lock_cpld_read_attribute(char *cpld_path, int addr); +int dni_fan_speed_good(); + +typedef enum +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_CPU_BOARD, + THERMAL_2_ON_MAIN_BOARD, + THERMAL_3_ON_MAIN_BOARD, + THERMAL_4_ON_MAIN_BOARD, + THERMAL_5_ON_FAN_BOARD, + THERMAL_1_ON_PSU1, +} onlp_thermal_id; + +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_1_ON_PSU1, +} onlp_fan_id; + +typedef enum +{ + LED_RESERVED = 0, + LED_FRONT_FAN, + LED_FRONT_SYS, + LED_FRONT_PWR, + LED_REAR_FAN_TRAY_1, + LED_REAR_FAN_TRAY_2, + LED_REAR_FAN_TRAY_3, +}onlp_led_id; + +#endif /* __PLATFORM_LIB_H__ */ + 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 new file mode 100755 index 00000000..ecae9b60 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/psui.c @@ -0,0 +1,203 @@ +/************************************************************ + * + * + * 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 +#include +#include +#include "platform_lib.h" +#include + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(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", PSU_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) +{ + return ONLP_STATUS_OK; +} + +static int +dni_psu_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + char val_char_mod[12] = {'\0'}; + char val_char_sel[12] = {'\0'}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {'\0'}; + + /* Set capability */ + info->caps |= ONLP_PSU_CAPS_AC; + + /* Set the associated oid_table + * Set PSU's fan and thermal to child OID + */ + 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 PSU module name from attribute */ + sprintf(node_path, "%s%s", PSU_AC_PMBUS_PREFIX, "psu_mfr_model"); + dni_i2c_read_attribute_string(node_path, val_char_mod, sizeof(val_char_mod), 0); + strcpy(info->model, val_char_mod); + + /* Read PSU serial number from attribute */ + sprintf(node_path, "%s%s", PSU_AC_PMBUS_PREFIX, "psu_mfr_serial"); + dni_i2c_read_attribute_string(node_path, val_char_sel, sizeof(val_char_sel), 0); + strcpy(info->serial, val_char_sel); + + /* 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; +} + +/* + * 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 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + mux_info_t mux_info; + dev_info_t dev_info; + + int index = ONLP_OID_ID_GET(id); + VALIDATE(id); + + /* Set the onlp_oid_hdr_t */ + 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 */ + dev_info.addr = PSU_EEPROM; + dev_info.flags = DEFAULT_FLAG; + + if(index == PSU1_ID) + { + info->status |= ONLP_PSU_STATUS_PRESENT; + } + else + { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + + /* 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(&mux_info, &dev_info) < 0) + { + /* Unable to read PSU(%d) node(psu_present) */ + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } + else if (val <= 0) + { + /* Unable to read PSU(%d) node(psu_power_good) */ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + } + + ret = dni_psu_info_get(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-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 new file mode 100755 index 00000000..4c0a8dc1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,644 @@ +/************************************************************ + * + * + * 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 "platform_lib.h" +/******************* Utility Function *****************************************/ + +int +ak7448_get_respond_val(int port){ + int respond_default = 0xff; + int value = 0x00; + + if(port > NUM_OF_SFP && port <= (NUM_OF_SFP + NUM_OF_QSFP)){ + value = respond_default & (~(1 << ((port % 8)-1))); + return value; + } + else{ + return respond_default; + } +} + +int +ak7448_get_respond_reg(int port){ + return QSFP_RESPOND_REG; +} + +/************************************************************ + * + * 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 {1, 52}*/ + 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 < 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_ERROR("Unable to select port(%d)\r\n", port); + } + + /* Read 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 + * 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-52, 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[24] = {0}; + uint32_t bytes[7]; + /* Read presence bitmap from CPLD SFP28/QSFP28 Presence Register + * if only port 0 is present, return 7F FF FF FF FF FF FF + * if only port 0 and 1 present, return 3F FF FF FF 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; + } + int count = sscanf(present_all_data, "%x %x %x %x %x %x %x", + bytes+0, + bytes+1, + bytes+2, + bytes+3, + bytes+4, + bytes+5, + bytes+6 + ); + + 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 SFP/QSFP ports */ + bytes[6] &= 0xF; + + /* Convert to 64 bit integer in port order */ + uint64_t presence_all = 0 ; + int i = 0; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; i < NUM_OF_PORT; 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]) +{ + char port_data[2]; + int sfp_respond_reg; + int sfp_respond_val; + + + /* 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) + { + /* 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; + } + + } + 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; + } + } + + 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 < 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; + } + + } + 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: + *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 < 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; + } + + } + 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: + 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) +{ + 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; + } + + } + 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); +} + +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; + + /* 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; + } + } + 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); +} + +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; + } + + } + 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); +} + +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; + } + } + 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); +} + +int +onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) +{ + char port_data[2] ; + + 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; + } + } + 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: + if(port > NUM_OF_SFP && port <= (NUM_OF_SFP +NUM_OF_QSFP)){ + *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 > NUM_OF_SFP && port <= (NUM_OF_SFP +NUM_OF_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) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +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; +} + +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-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 new file mode 100755 index 00000000..22d687ba --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,373 @@ +/************************************************************ + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "x86_64_delta_ak7448_int.h" +#include "x86_64_delta_ak7448_log.h" +#include "platform_lib.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-delta-ak7448-r0"; +} + +int +onlp_sysi_init(void) +{ + return ONLP_STATUS_OK; +} + +/******************* Utility Function *****************************************/ +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; +} +/******************************************************************************/ + + +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; +} + +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + aim_free(data); +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + 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); + + pi->cpld_versions = aim_fstrdup("SYSTEM-CPLD = %d, CPLD-A = %d, CPLD-B = %d", sys_cpld_version, cpld_a_version, cpld_b_version); + + return ONLP_STATUS_OK; +} + +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; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 7 Thermal sensors on the chassis */ + for (i = 1; i <= NUM_OF_THERMAL_ON_BOARDS; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 6 LEDs on the chassis */ + for (i = 1; i <= NUM_OF_LED_ON_BOARDS; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 7 Fans on the chassis */ + for (i = 1; i <= NUM_OF_FAN_ON_FAN_BOARD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + /* 1 PSUs on the chassis */ + for (i = 1; i <= NUM_OF_PSU_ON_PSU_BOARD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + return 0; +} + +int +dni_sysi_set_fan(int new_percentage) +{ + int ret = 0; + int i = 0; + for(i = 1; i <= 6 ; i++) + { + ret = onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(i), MAX_FAN_SPEED * new_percentage / 100); + if(ret != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to set fan(%d) rpm\r\n",ONLP_FAN_ID_CREATE(i)); + return ret; + } + } + if(onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1) , new_percentage) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to set fan(%d) percentage\r\n",ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1)); + return ret; + } + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_fans(void) +{ + int i = 0; + int new_percentage; + int highest_temp = 0; + onlp_thermal_info_t thermal[NUM_OF_THERMAL_ON_BOARDS]; + + for(i = 1; i <= NUM_OF_THERMAL_ON_BOARDS; i++) + { + //ret = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i),&thermal[i-1]); + if(onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i),&thermal[i-1]) != ONLP_STATUS_OK) + { + /* Setting all fans speed to maximum */ + new_percentage = SPEED_100_PERCENTAGE; + if(dni_sysi_set_fan(new_percentage) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to set fan\r\n"); + return ONLP_STATUS_E_INTERNAL; + } + + AIM_LOG_ERROR("Unable to read status from thermal(%d)\r\n",i); + return ONLP_STATUS_E_INTERNAL; + } + } + + + for (i = 0; i < NUM_OF_THERMAL_ON_BOARDS; i++) + { + if (thermal[i].mcelsius > highest_temp) + { + highest_temp = thermal[i].mcelsius; + } + } + + highest_temp = highest_temp/1000; + decide_percentage(&new_percentage, highest_temp); + + if(dni_sysi_set_fan(new_percentage) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to set fan\r\n"); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + int fantray_present = -1, rpm = 0, rpm1 = 0, count = 0; + int fantray_count; + uint8_t psu_state; + 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; + dev_info.flags = DEFAULT_FLAG; + + /* Fan tray 1 */ + dev_info.addr = FAN_TRAY; + mux_info.channel = 0x02; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + mux_info.channel = FAN_I2C_SEL_FAN_CTRL; + rpm = dni_i2c_lock_read_attribute(&mux_info, FAN1_FRONT); + rpm1 = dni_i2c_lock_read_attribute(&mux_info, 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) + return 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) + return ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 2 */ + dev_info.addr = FAN_TRAY; + mux_info.channel = 0x01; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + mux_info.channel = FAN_I2C_SEL_FAN_CTRL; + rpm = dni_i2c_lock_read_attribute(&mux_info, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(&mux_info, 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) + return 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) + return ONLP_STATUS_E_INTERNAL; + } + + /* Fan tray 3 */ + dev_info.addr = FAN_TRAY; + mux_info.channel = 0x00; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + mux_info.channel = FAN_I2C_SEL_FAN_CTRL; + rpm = dni_i2c_lock_read_attribute(&mux_info, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(&mux_info, 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) + return 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) + return ONLP_STATUS_E_INTERNAL; + } + + /* FRONT FAN & SYS LED */ + for(fantray_count = 0; fantray_count < 3; fantray_count++) + { + mux_info.channel = fantray_count; + dev_info.addr = FAN_TRAY; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if( fantray_present >= 0) + count++; + } + + if(count == ALL_FAN_TRAY_EXIST && dni_fan_speed_good() == FAN_SPEED_NORMALLY) + { + /* Green FAN operates 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)) + return 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_ORANGE) != ONLP_STATUS_OK) || + (onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_SYS),ONLP_LED_MODE_ORANGE) != ONLP_STATUS_OK)) + return ONLP_STATUS_E_INTERNAL; + } + + /* 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; + dev_info.flags = DEFAULT_FLAG; + dev_info.addr = PSU_EEPROM; + + psu_state = dni_i2c_lock_read(&mux_info, &dev_info); + + if(psu_state == 1) + { + /* Green */ + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR), ONLP_LED_MODE_GREEN) != ONLP_STATUS_OK) + return ONLP_STATUS_E_INTERNAL; + } + else + { + if(onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR), ONLP_LED_MODE_OFF) != ONLP_STATUS_OK) + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + 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 new file mode 100755 index 00000000..fdf24864 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,174 @@ +/************************************************************ + * + * + * 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#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) + +#define dni_onlp_thermal_threshold(WARNING_DEFAULT, ERROR_DEFAULT, SHUTDOWN_DEFAULT){ \ + WARNING_DEFAULT, \ + ERROR_DEFAULT, \ + SHUTDOWN_DEFAULT, \ +} + +static char* last_path[] = /* must map with onlp_thermal_id */ +{ + "reserved", + NULL, /* CPU Core */ + "/2-004d/hwmon/hwmon4/temp1_input", + "/6-004c/hwmon/hwmon5/temp1_input", + "/6-004d/hwmon/hwmon6/temp1_input", + "/6-004e/hwmon/hwmon7/temp1_input", + "/7-004f/hwmon/hwmon8/temp1_input", + "/4-0058/psu_temp1_input", +}; + +static char* cpu_coretemp_files[] = +{ + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp2_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp3_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_CPU_BOARD), "Thermal sensor near CPU (U57)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BOARD), "Thermal sensor near MAC (U10)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BOARD), "Thermal sensor near middle SFP cage (U11)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, dni_onlp_thermal_threshold(65000,75000,80000) + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BOARD), "Thermal sensor near QSFP cage (U13)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_FAN_BOARD), "Thermal sensor near FAN (U334)", 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 + }, +}; + +/* + * 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 temp_base = 1; + int local_id, r_data; + char fullpath[256] = {0}; + uint8_t channel, offset; + mux_info_t mux_info; + + 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) { + int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + + switch (local_id) { + case THERMAL_1_ON_CPU_BOARD: + case THERMAL_2_ON_MAIN_BOARD: + case THERMAL_3_ON_MAIN_BOARD: + case THERMAL_4_ON_MAIN_BOARD: + channel = 0x00; /* DEFAULT */ + break; + case THERMAL_5_ON_FAN_BOARD: + offset = FAN_I2C_MUX_SEL_REG; + channel = FAN_I2C_SEL_THERMAL; + break; + case THERMAL_1_ON_PSU1: + offset = PSU_I2C_MUX_SEL_REG; + channel = PSU_I2C_SEL_PSU_EEPROM; + break; + default: + 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]); + + r_data = dni_i2c_lock_read_attribute(&mux_info, fullpath); + if(r_data == -1){ + return ONLP_STATUS_E_INTERNAL; + } + + /* Current temperature in milli-celsius */ + info->mcelsius = r_data / temp_base; + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_config.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_config.c new file mode 100644 index 00000000..fe20b6a8 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_delta_ak7448_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_delta_ak7448_config_STRINGIFY_VALUE(_x) __x86_64_delta_ak7448_config_STRINGIFY_NAME(_x) +x86_64_delta_ak7448_config_settings_t x86_64_delta_ak7448_config_settings[] = +{ +#ifdef X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING) }, +#else +{ X86_64_DELTA_AK7448_CONFIGINCLUDE_LOGGING(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT) }, +#else +{ X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB) }, +#else +{ X86_64_DELTA_AK7448_CONFIGPORTING_STDLIB(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI) }, +#else +{ X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_delta_ak7448_config_STRINGIFY_NAME(X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_delta_ak7448_config_STRINGIFY_VALUE(X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_DELTA_AK7448_CONFIGINCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_delta_ak7448_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_delta_ak7448_config_STRINGIFY_VALUE +#undef __x86_64_delta_ak7448_config_STRINGIFY_NAME + +const char* +x86_64_delta_ak7448_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_delta_ak7448_config_settings[i].name; i++) { + if(strcmp(x86_64_delta_ak7448_config_settings[i].name, setting)) { + return x86_64_delta_ak7448_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_delta_ak7448_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_delta_ak7448_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_delta_ak7448_config_settings[i].name, x86_64_delta_ak7448_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_enums.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_enums.c new file mode 100644 index 00000000..14a7601b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_int.h b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_int.h new file mode 100644 index 00000000..ff053e8f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_delta_ak7448 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_delta_ak7448_INT_H__ +#define __x86_64_delta_ak7448_INT_H__ + +#include + + +#endif /* __x86_64_delta_ak7448_INT_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_log.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_log.c new file mode 100644 index 00000000..b8f6f02d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_ak7448_log.h" +/* + * x86_64_delta_ak7448 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_DELTA_AK7448_CONFIGLOG_OPTIONS_DEFAULT, + X86_64_DELTA_AK7448_CONFIGLOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_DELTA_AK7448_CONFIGLOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_log.h b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_log.h new file mode 100644 index 00000000..5c43ac98 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_delta_ak7448_LOG_H__ +#define __x86_64_delta_ak7448_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_delta_ak7448 +#include + +#endif /* __x86_64_delta_ak7448_LOG_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_module.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_module.c new file mode 100644 index 00000000..b57c5290 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_ak7448_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_delta_ak7448_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_ak7448_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-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_ucli.c b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_ucli.c new file mode 100644 index 00000000..d6641532 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/onlp/builds/src/module/src/x86_64_delta_ak7448_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_DELTA_AK7448_CONFIGINCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_delta_ak7448_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_delta_ak7448) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_delta_ak7448_ucli_module__ = + { + "x86_64_delta_ak7448_ucli", + NULL, + x86_64_delta_ak7448_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_delta_ak7448_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_delta_ak7448_ucli_module__); + n = ucli_node_create("x86_64_delta_ak7448", NULL, &x86_64_delta_ak7448_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_delta_ak7448")); + return n; +} + +#else +void* +x86_64_delta_ak7448_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448/platform-config/r0/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/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-ak7448/platform-config/r0/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/PKG.yml new file mode 100644 index 00000000..d746f9d1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=delta BASENAME=x86-64-delta-ak7448 REVISION=r0 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/lib/x86-64-delta-ak7448-r0.yml b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/lib/x86-64-delta-ak7448-r0.yml new file mode 100644 index 00000000..c93ce300 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/lib/x86-64-delta-ak7448-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AK7448 +# +###################################################################### + +x86-64-delta-ak7448-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/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 new file mode 100755 index 00000000..82527b9d --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-ak7448/platform-config/r0/src/python/x86_64_delta_ak7448_r0/__init__.py @@ -0,0 +1,60 @@ +from onl.platform.base import * +from onl.platform.delta import * + +class OnlPlatform_x86_64_delta_ak7448_r0(OnlPlatformDelta, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-delta-ak7448-r0' + MODEL="AK7448" + SYS_OBJECT_ID=".7448" + + def baseconfig(self): + #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) + + #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") + 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") + self.new_i2c_device('emc2305', 0x2c, 7) + self.new_i2c_device('emc2305', 0x2d, 7) + + #Insert temperature modules + self.new_i2c_device('tmp75', 0x4d, 2) + 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") + 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") + + #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") + + return True + + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs/modules/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs/modules/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/PKG.yml new file mode 100644 index 00000000..dbef625e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d6254qs ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/Makefile new file mode 100644 index 00000000..fb965b07 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := inventec +BASENAME := x86-64-inventec-d6254qs +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/inv_cpld.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/inv_cpld.c new file mode 100644 index 00000000..683ffa0f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/inv_cpld.c @@ -0,0 +1,415 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_PSU_OFFSET 0x08 +#define CPLD_LED_OFFSET 0x0E +#define CPLD_LED_STATU_OFFSET 0x0D +#define CPLD_CTL_OFFSET 0x0C + + + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[4]; + + memset(b, 0, 4); + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + if(status != 4) return sprintf(buf, "read cpld info fail\n"); + + status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/ + status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf); + status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf); + + return strlen(buf); +} + + +static ssize_t show_ctl(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld ctl fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_ctl(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1); + if(temp) byte |= (1<<0); + else byte &= ~(1<<0); + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + + +static char* led_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "NA", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); + + byte = (byte >> shift) & 0x7; + + /* + 0: off + 1: 0.5hz + 2: 1 hz + 3: 2 hz + 4~6: not define + 7: on + */ + + status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); + + return strlen(buf); +} + +static ssize_t set_led(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + //validate temp value: 0,1,2,3,7, TBD + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu0 | psu1 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 1)?0:3; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1); + +static struct attribute *cpld_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_ctl.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpld_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/inv_platform.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/inv_platform.c new file mode 100644 index 00000000..0a4a1786 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/modules/builds/inv_platform.c @@ -0,0 +1,370 @@ +#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; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct at24_platform_data at24c64_eeprom_data = { + .byte_len = 256,//SZ_64K/8 + .page_size = 1, + .flags = 0,//AT24_FLAG_ADDR8, +}; + +static int pca9555_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context) +{ + //TBD + printk("%s : gpio=%d, ngpio=%d\n ", __func__, gpio, ngpio); + return 0; +} + +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = 2,}, {.adap_id = 3,}, + {.adap_id = 4,}, {.adap_id = 5,}, + {.adap_id = 6,}, {.adap_id = 7,}, + {.adap_id = 8,}, {.adap_id = 9,}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = 10,}, {.adap_id = 11,}, + {.adap_id = 12,}, {.adap_id = 13,}, + {.adap_id = 14,}, {.adap_id = 15,}, + {.adap_id = 16,}, {.adap_id = 17,}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = 18,}, {.adap_id = 19,}, + {.adap_id = 20,}, {.adap_id = 21,}, + {.adap_id = 22,}, {.adap_id = 23,}, + {.adap_id = 24,}, {.adap_id = 25,}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = 26,}, {.adap_id = 27,}, + {.adap_id = 28,}, {.adap_id = 29,}, + {.adap_id = 30,}, {.adap_id = 31,}, + {.adap_id = 32,}, {.adap_id = 33,}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = 34,}, {.adap_id = 35,}, + {.adap_id = 36,}, {.adap_id = 37,}, + {.adap_id = 38,}, {.adap_id = 39,}, + {.adap_id = 40,}, {.adap_id = 41,}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = 42,}, {.adap_id = 43,}, + {.adap_id = 44,}, {.adap_id = 45,}, + {.adap_id = 46,}, {.adap_id = 47,}, + {.adap_id = 48,}, {.adap_id = 49,}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = 50,}, {.adap_id = 51,}, + {.adap_id = 52,}, {.adap_id = 53,}, + {.adap_id = 54,}, {.adap_id = 55,}, + {.adap_id = 56,}, {.adap_id = 57,}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = 58,}, {.adap_id = 59,}, + {.adap_id = 60,}, {.adap_id = 61,}, + {.adap_id = 62,}, {.adap_id = 63,}, + {.adap_id = 64,}, {.adap_id = 65,}, +}; + +//no i2c device driver attach to mux 7 + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_4 = { + .modes = mux_modes_0_4, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_5 = { + .modes = mux_modes_0_5, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_6 = { + .modes = mux_modes_0_6, + .num_modes = 8, +}; + + +#define IO_EXPAND_BASE_CHIP (IO_EXPAND_BASE) //64 +#define IO_EXPAND_BASE_CHIP00 (IO_EXPAND_BASE + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP01 (IO_EXPAND_BASE_CHIP00 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP10 (IO_EXPAND_BASE_CHIP01 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP11 (IO_EXPAND_BASE_CHIP10 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP20 (IO_EXPAND_BASE_CHIP11 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP21 (IO_EXPAND_BASE_CHIP20 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP30 (IO_EXPAND_BASE_CHIP21 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP31 (IO_EXPAND_BASE_CHIP30 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP40 (IO_EXPAND_BASE_CHIP31 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP41 (IO_EXPAND_BASE_CHIP40 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP50 (IO_EXPAND_BASE_CHIP41 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP51 (IO_EXPAND_BASE_CHIP50 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP60 (IO_EXPAND_BASE_CHIP51 + IO_EXPAND_NGPIO) +#define IO_EXPAND_BASE_CHIP61 (IO_EXPAND_BASE_CHIP60 + IO_EXPAND_NGPIO) + +static struct pca953x_platform_data pca9555_data = { + .gpio_base = IO_EXPAND_BASE_CHIP, + .setup = pca9555_setup, +}; + +#if 0 +static struct pca953x_platform_data pca9555_data00 = { + .gpio_base = IO_EXPAND_BASE_CHIP00, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data01 = { + .gpio_base = IO_EXPAND_BASE_CHIP01, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data10 = { + .gpio_base = IO_EXPAND_BASE_CHIP10, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data11 = { + .gpio_base = IO_EXPAND_BASE_CHIP11, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data20 = { + .gpio_base = IO_EXPAND_BASE_CHIP20, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data21 = { + .gpio_base = IO_EXPAND_BASE_CHIP21, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data30 = { + .gpio_base = IO_EXPAND_BASE_CHIP30, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data31 = { + .gpio_base = IO_EXPAND_BASE_CHIP31, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data40 = { + .gpio_base = IO_EXPAND_BASE_CHIP40, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data41 = { + .gpio_base = IO_EXPAND_BASE_CHIP41, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data50 = { + .gpio_base = IO_EXPAND_BASE_CHIP50, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data51 = { + .gpio_base = IO_EXPAND_BASE_CHIP51, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data60 = { + .gpio_base = IO_EXPAND_BASE_CHIP60, + .setup = pca9555_setup, +}; +static struct pca953x_platform_data pca9555_data61 = { + .gpio_base = IO_EXPAND_BASE_CHIP61, + .setup = pca9555_setup, +}; +#endif + +static struct i2c_board_info xlp_i2c_device_info0[] __initdata = { +// {"24c02", 0, 0x57, &at24c64_eeprom_data, 0, 0}, //VPD + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld + {"pca9555", 0, 0x22, &pca9555_data, 0, 0}, + {"pca9548", 0, 0x71, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info1[] __initdata = { + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld +}; + +static struct i2c_board_info xlp_i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data00, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data01, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data10, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data11, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data20, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data21, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data30, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data31, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data40, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data41, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data50, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data51, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +// {"pca9555", 0, 0x20, &pca9555_data60, 0, 0}, +// {"pca9555", 0, 0x21, &pca9555_data61, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(xlp_i2c_device_info0), xlp_i2c_device_info0 }, //smbus 0 +// {1, ARRAY_SIZE(xlp_i2c_device_info1), xlp_i2c_device_info1 }, //smbus 1 or gpio11+12 + + {2, ARRAY_SIZE(xlp_i2c_device_info2), xlp_i2c_device_info2 }, //mux 0 + {3, ARRAY_SIZE(xlp_i2c_device_info3), xlp_i2c_device_info3 }, //mux 1 + {4, ARRAY_SIZE(xlp_i2c_device_info4), xlp_i2c_device_info4 }, //mux 2 + {5, ARRAY_SIZE(xlp_i2c_device_info5), xlp_i2c_device_info5 }, //mux 3 + {6, ARRAY_SIZE(xlp_i2c_device_info6), xlp_i2c_device_info6 }, //mux 4 + {7, ARRAY_SIZE(xlp_i2c_device_info7), xlp_i2c_device_info7 }, //mux 5 + {8, ARRAY_SIZE(xlp_i2c_device_info8), xlp_i2c_device_info8 }, //mux 6 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct i2c_gpio_platform_data i2c_gpio_platdata = { + .scl_pin = 8, + .sda_pin = 9, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct platform_device magnolia_device_i2c_gpio = { + .name = "i2c-gpio", + .id = 0, // adapter number + .dev.platform_data = &i2c_gpio_platdata, +}; + +#define PLAT_MAX_I2C_CLIENTS 32 +static struct i2c_client *plat_i2c_client[PLAT_MAX_I2C_CLIENTS]; +static int num_i2c_clients = 0; +static int plat_i2c_client_add(struct i2c_client *e) +{ + if (num_i2c_clients >= PLAT_MAX_I2C_CLIENTS) + return -1; + + plat_i2c_client[num_i2c_clients] = e; + num_i2c_clients++; + return num_i2c_clients; +} + +static void plat_i2c_client_remove_all(void); + +static void plat_i2c_client_remove_all() +{ + int i; + for (i = num_i2c_clients-1; i >= 0; i--) + i2c_unregister_device(plat_i2c_client[i]); +} + +static int __init plat_magnolia_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j; + + printk("el6661 plat_magnolia_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(&magnolia_device_i2c_gpio); + if (ret) { + printk(KERN_ERR "i2c-gpio: magnolia_device_i2c_gpio register fail %d\n", ret); + } +#endif + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +#define FAN_NUM 4 +#define PSU_NUM 2 + +struct __attribute__ ((__packed__)) psoc_psu_layout { + u16 psu1_iin; + u16 psu2_iin; + u16 psu1_iout; + u16 psu2_iout; + + u16 psu1_pin; + u16 psu2_pin; + u16 psu1_pout; + u16 psu2_pout; + + u16 psu1_vin; + u16 psu2_vin; + u16 psu1_vout; + u16 psu2_vout; + + u8 psu1_vendor[16]; + u8 psu2_vendor[16]; + u8 psu1_model[20]; + u8 psu2_model[20]; + u8 psu1_version[8]; + u8 psu2_version[8]; + u8 psu1_date[6]; + u8 psu2_date[6]; + u8 psu1_sn[20]; + u8 psu2_sn[20]; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + u8 reserve0; //offset: 3 + + u8 fw_upgrade; //offset: 4 + + //i2c bridge + u8 i2c_st; //offset: 5 + u8 i2c_ctl; //offset: 6 + u8 i2c_addr; //offset: 7 + u8 i2c_data[0x20]; //offset: 8 + + //gpo + u8 led_ctl; //offset: 28 + + u8 gpio; //offset: 29 + + //pwm duty + u8 pwm[FAN_NUM]; //offset: 2a + u8 pwm_psu[PSU_NUM]; //offset: 2e + + //fan rpm + u16 fan[FAN_NUM*2]; //offset: 30 + + u8 reserve1[4]; //offset: 40 + + //gpi + u8 gpi_fan; //offset: 44 + + //psu state + u8 psu_state; //offset: 45 + + //temperature + u16 temp[5]; //offset: 46 + u16 temp_psu[PSU_NUM]; //offset: 50 + + //version + u8 version[2]; //offset: 54 + + u8 reserve2[4]; //offset: 56 + struct psoc_psu_layout psu_info; //offset: 5a +}; + +/* definition */ +/* definition */ +#define PSOC_OFF(m) offsetof(struct psoc_layout, m) +#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) + +#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) +#define PWM_OFFSET PSOC_OFF(pwm) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_ctl) +#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) +#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) +#define VERSION_OFFSET PSOC_OFF(version) +#define PSU_INFO_OFFSET PSOC_OFF(psu_info) + +/* Each client has this additional data */ +struct psoc_data { + struct device *hwmon_dev; + struct mutex update_lock; + u32 diag; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t psoc_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +#if 0 +static u32 psoc_read32(struct i2c_client *client, u8 offset) +{ + u32 value = 0; + u8 buf[4]; + + if( psoc_i2c_read(client, buf, offset, 4) == 4) + value = (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]); + + return value; +} +#endif + +static u16 psoc_read16(struct i2c_client *client, u8 offset) +{ + u16 value = 0; + u8 buf[2]; + + if(psoc_i2c_read(client, buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(struct i2c_client *client, u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_i2c_read(client, &buf, offset, 1) == 1) + value = buf; + + return value; +} + +//PSOC i2c bridge regsters +#define PSOC_I2C_STATUS 0x05 +#define PSOC_I2C_CNTRL 0x06 +#define PSOC_I2C_ADDR 0x07 +#define PSOC_I2C_DATA 0x08 + +//status bit definition +#define PSOC_I2C_START (1 << 0) +#define PSOC_PMB_SEL (1 << 7) + +//addr bits definition +#define PSOC_I2C_READ (1 << 0) + +//PMBUS registers definition +#define PMBUS_READ_VIN (0x88) +#define PMBUS_READ_IIN (0x89) +#define PMBUS_READ_VOUT (0x8B) +#define PMBUS_READ_IOUT (0x8C) +#define PMBUS_READ_POUT (0x96) +#define PMBUS_READ_PIN (0x97) + +#define PMBUS_MFR_ID (0x99) +#define PMBUS_MFR_MODEL (0x9A) +#define PMBUS_MFR_REVISION (0x9B) +#define PMBUS_MFR_DATE (0x9D) +#define PMBUS_MFR_SERIAL (0x9E) + +static int psoc_i2c_bridge_read(struct i2c_client *client, + unsigned char bus, + unsigned char chip, + char *addr, int alen, + unsigned char *data, int len ) +{ + unsigned char txdata[28], rxdata[28]; + int index, timeout; + + txdata[PSOC_I2C_STATUS] = 0; /* the status */ + txdata[PSOC_I2C_CNTRL] = ((alen & 3) << 5) | (len & 0x1f); /* the sizes */ + txdata[PSOC_I2C_ADDR] = (chip << 1) | PSOC_I2C_READ; /* read address */ + for(index = 0; index < alen; index++) + txdata[PSOC_I2C_DATA + index] = addr[index]; /* the chip address */ + for(; index < alen+len; index++) + txdata[PSOC_I2C_DATA + index] = 0; /* clear the chip data */ + + psoc_i2c_write(client, &txdata[PSOC_I2C_CNTRL], PSOC_I2C_CNTRL, 2 + alen + len); + + //delay a while ??? + //--------------------------------------------------------------------- + //start write + txdata[PSOC_I2C_STATUS] = PSOC_I2C_START | PSOC_PMB_SEL; /* the start bit for the PM bus */ + psoc_i2c_write(client, &txdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //delay a while + timeout = 40; //40*20==>800 ms + do { + psoc_i2c_read(client, &rxdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //check rxdata[5] error bit(1) and complete bit(0) ,TBD + if((rxdata[PSOC_I2C_STATUS] & 0x2) == 0x2) { + //printk("i2c bridge fail!!!\n"); + timeout = 0; + break; + } + if((rxdata[PSOC_I2C_STATUS] & PSOC_I2C_START) == 0) { + /* comand complete */ + psoc_i2c_read(client, &rxdata[PSOC_I2C_DATA+alen], PSOC_I2C_DATA+alen, len); + break; + } + + //delay + msleep(20); + } while(timeout--); + + if(timeout <= 0) { + return -1; + } + + //--------------------------------------------------------------------- + + for(index=0; index < len; index++) { + data[index] = rxdata[PSOC_I2C_DATA + alen + index]; + } + + return 0; +} + + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu1 | psu0 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu_st(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, &byte, PSOC_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (s8)(status>>8) * 1000 ); +} + + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PWM_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PWM_OFFSET; + + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + + if(data->diag) { + mutex_lock(&data->update_lock); + psoc_i2c_write(client, &pwm, offset, 1); + mutex_unlock(&data->update_lock); + } + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index*2 + RPM_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u16 temp = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 ); + + return strlen(buf); +} + +static ssize_t set_switch_tmp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF)); + + mutex_lock(&data->update_lock); + psoc_i2c_write(client, (u8*)&temp2, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 diag_flag = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + data->diag = (diag_flag & 0x80)?1:0; + status = sprintf (buf, "%d\n", data->diag); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + data->diag = diag; + + mutex_lock(&data->update_lock); + psoc_i2c_read(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_i2c_write(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, VERSION_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 bit = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, FAN_LED_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + if(data->diag) { + mutex_lock(&data->update_lock); + led_state = psoc_read8(client, FAN_LED_OFFSET); + if(v) led_state |= (1<update_lock); + } + + return count; +} + +static ssize_t show_value8(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "0x%02X\n", status ); +} + +static long pmbus_reg2data_linear(int data, int linear16) +{ + s16 exponent; + s32 mantissa; + long val; + + if (linear16) { /* LINEAR16 */ + exponent = -9; + mantissa = (u16) data; + } else { /* LINEAR11 */ + exponent = ((s16)data) >> 11; + exponent = ((s16)( data & 0xF800) ) >> 11; + mantissa = ((s32)((data & 0x7ff) << 5)) >> 5; + } + + //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); + val = mantissa; + + /* scale result to micro-units for power sensors */ + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 reg = attr->index & 0xFF; + u8 len = ((attr->index & 0xFF00) >> 8); + u8 chip = (attr->index >> 16)? 0x59:0x58; + u8 bus = 1; + unsigned char value[2] = {0,0};; + + if (len == 2) + { + mutex_lock(&data->update_lock); + psoc_i2c_bridge_read(client, bus, chip, ®, 1, value, 2); + mutex_unlock(&data->update_lock); + + status = value[1]<<8 | value[0]; + //status1 = value[1]<<8 | value[0]; + + return sprintf(buf, "%ld\n", pmbus_reg2data_linear(status, (reg==PMBUS_READ_VOUT)?1:0) ); + } + else + { //len is not defined. + u8 tmpbuf[32]; + mutex_lock(&data->update_lock); + //length of block read + psoc_i2c_bridge_read(client, bus, chip, ®, 1, &len, 1); + //data included length + psoc_i2c_bridge_read(client, bus, chip, ®, 1, tmpbuf, len+1); + mutex_unlock(&data->update_lock); + + memcpy(buf, tmpbuf+1, len); + buf[len]='\n'; + + return len+1; + } +} + +static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = (attr->index & 0xFF) + PSU_INFO_OFFSET; + u8 len = (attr->index >> 8)& 0xFF; + u8 rxbuf[21] = {0}; + if (len == 2) + { + mutex_lock(&data->update_lock); + status = psoc_read16(client, offset); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 )); + } + else + { + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client,rxbuf,offset,len); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s \n",rxbuf); + } +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4); +static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7); +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9); + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); + +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); + +static SENSOR_DEVICE_ATTR(psu1_vin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu1_vout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu1_iout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu1_pin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu1_pout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu1_vendor, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu1_model, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_version, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu1_date, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu1_sn, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psu2_vin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu2_vout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu2_iout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu2_pout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu2_vendor, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu2_model, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_version, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu2_date, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu2_sn, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu1_vendor)); +static SENSOR_DEVICE_ATTR(psoc_psu1_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_model)); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu1_version)); +static SENSOR_DEVICE_ATTR(psoc_psu1_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu1_date)); +static SENSOR_DEVICE_ATTR(psoc_psu1_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_sn)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu2_vendor)); +static SENSOR_DEVICE_ATTR(psoc_psu2_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_model)); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu2_version)); +static SENSOR_DEVICE_ATTR(psoc_psu2_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu2_date)); +static SENSOR_DEVICE_ATTR(psoc_psu2_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_sn)); + +static struct attribute *psoc_attributes[] = { + //thermal + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + + &sensor_dev_attr_thermal_psu1.dev_attr.attr, + &sensor_dev_attr_thermal_psu2.dev_attr.attr, + + + //pwm + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + + //rpm + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + + //diag flag + &sensor_dev_attr_diag.dev_attr.attr, + + //version + &sensor_dev_attr_version.dev_attr.attr, + + //fan led + &sensor_dev_attr_fan_led_grn1.dev_attr.attr, + &sensor_dev_attr_fan_led_grn2.dev_attr.attr, + &sensor_dev_attr_fan_led_grn3.dev_attr.attr, + &sensor_dev_attr_fan_led_grn4.dev_attr.attr, + &sensor_dev_attr_fan_led_red1.dev_attr.attr, + &sensor_dev_attr_fan_led_red2.dev_attr.attr, + &sensor_dev_attr_fan_led_red3.dev_attr.attr, + &sensor_dev_attr_fan_led_red4.dev_attr.attr, + + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + + //psu + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + + &sensor_dev_attr_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psu1_model.dev_attr.attr, + &sensor_dev_attr_psu1_version.dev_attr.attr, + &sensor_dev_attr_psu1_date.dev_attr.attr, + &sensor_dev_attr_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psu2_model.dev_attr.attr, + &sensor_dev_attr_psu2_version.dev_attr.attr, + &sensor_dev_attr_psu2_date.dev_attr.attr, + &sensor_dev_attr_psu2_sn.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + + //psu_psoc, new added on psoc 1.9 + &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, + + //add info + &sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_model.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_date.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_model.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_date.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_sn.dev_attr.attr, + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +psoc_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct psoc_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct psoc_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->diag = 0; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &psoc_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &psoc_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int psoc_remove(struct i2c_client *client) +{ + struct psoc_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &psoc_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id psoc_ids[] = { + { "inv_psoc", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, psoc_ids); + +static struct i2c_driver psoc_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_psoc", + }, + .probe = psoc_probe, + .remove = psoc_remove, + .id_table = psoc_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_psoc_init(void) +{ + return i2c_add_driver(&psoc_driver); +} + +static void __exit inv_psoc_exit(void) +{ + i2c_del_driver(&psoc_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv psoc driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_psoc_init); +module_exit(inv_psoc_exit); diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs/onlp/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/PKG.yml new file mode 100644 index 00000000..ed838c3a --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-inventec-d6254qs ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs/onlp/builds/lib/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/lib/Makefile new file mode 100644 index 00000000..f7e24c9b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_inventec_d6254qs onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-inventec-d6254qs.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-d6254qs/onlp/builds/onlpdump/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..34a494be --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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_d6254qs 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-d6254qs/onlp/builds/src/.module b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/.module new file mode 100644 index 00000000..623e61c3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_inventec_d6254qs diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/Makefile new file mode 100644 index 00000000..5df565a9 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_inventec_d6254qs +AUTOMODULE := x86_64_inventec_d6254qs +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/auto/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..b6f3d5e8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_inventec_d6254qs Autogeneration +# +############################################################################### +x86_64_inventec_d6254qs_AUTO_DEFS := module/auto/x86_64_inventec_d6254qs.yml +x86_64_inventec_d6254qs_AUTO_DIRS := module/inc/x86_64_inventec_d6254qs module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/auto/x86_64_inventec_d6254qs.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/auto/x86_64_inventec_d6254qs.yml new file mode 100644 index 00000000..27ca30f2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/auto/x86_64_inventec_d6254qs.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_inventec_d6254qs Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_INVENTEC_D7032Q28B_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_INVENTEC_D7032Q28B_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_INVENTEC_D7032Q28B_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_INVENTEC_D7032Q28B_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_INVENTEC_D7032Q28B_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_INVENTEC_D7032Q28B_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_INVENTEC_D7032Q28B_CONFIG_PORTING_STDLIB +- X86_64_INVENTEC_D7032Q28B_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_INVENTEC_D7032Q28B_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_D7032Q28B_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_inventec_d6254qs_config + + portingmacro: + X86_64_INVENTEC_D7032Q28B: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs.x b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs.x new file mode 100644 index 00000000..597131ff --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs.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-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_config.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_config.h new file mode 100644 index 00000000..647081d3 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d6254qs Configuration Header + * + * @addtogroup x86_64_inventec_d6254qs-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6254qs_CONFIG_H__ +#define __x86_64_inventec_d6254qs_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_inventec_d6254qs_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING +#define x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT +#define x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB +#define x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI +#define x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_inventec_d6254qs_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_inventec_d6254qs_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_inventec_d6254qs_config_settings table. */ +extern x86_64_inventec_d6254qs_config_settings_t x86_64_inventec_d6254qs_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_inventec_d6254qs_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_inventec_d6254qs_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_inventec_d6254qs_porting.h" + +#endif /* __x86_64_inventec_d6254qs_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_dox.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_dox.h new file mode 100644 index 00000000..a8a512b7 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_inventec_d6254qs Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6254qs_DOX_H__ +#define __x86_64_inventec_d6254qs_DOX_H__ + +/** + * @defgroup x86_64_inventec_d6254qs x86_64_inventec_d6254qs - x86_64_inventec_d6254qs Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_inventec_d6254qs-x86_64_inventec_d6254qs Public Interface + * @defgroup x86_64_inventec_d6254qs-config Compile Time Configuration + * @defgroup x86_64_inventec_d6254qs-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_inventec_d6254qs_DOX_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_porting.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_porting.h new file mode 100644 index 00000000..66f0981e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/inc/x86_64_inventec_d6254qs/x86_64_inventec_d6254qs_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_inventec_d6254qs Porting Macros. + * + * @addtogroup x86_64_inventec_d6254qs-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6254qs_PORTING_H__ +#define __x86_64_inventec_d6254qs_PORTING_H__ + + +/* */ +#if x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_inventec_d6254qs_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_inventec_d6254qs_MALLOC GLOBAL_MALLOC + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_MALLOC malloc + #else + #error The macro x86_64_inventec_d6254qs_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_FREE + #if defined(GLOBAL_FREE) + #define x86_64_inventec_d6254qs_FREE GLOBAL_FREE + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_FREE free + #else + #error The macro x86_64_inventec_d6254qs_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_inventec_d6254qs_MEMSET GLOBAL_MEMSET + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_MEMSET memset + #else + #error The macro x86_64_inventec_d6254qs_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_inventec_d6254qs_MEMCPY GLOBAL_MEMCPY + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_MEMCPY memcpy + #else + #error The macro x86_64_inventec_d6254qs_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_inventec_d6254qs_STRNCPY GLOBAL_STRNCPY + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_STRNCPY strncpy + #else + #error The macro x86_64_inventec_d6254qs_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_inventec_d6254qs_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_VSNPRINTF vsnprintf + #else + #error The macro x86_64_inventec_d6254qs_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_inventec_d6254qs_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_SNPRINTF snprintf + #else + #error The macro x86_64_inventec_d6254qs_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_inventec_d6254qs_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_inventec_d6254qs_STRLEN GLOBAL_STRLEN + #elif x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB == 1 + #define x86_64_inventec_d6254qs_STRLEN strlen + #else + #error The macro x86_64_inventec_d6254qs_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_inventec_d6254qs_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..6071088e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_inventec_d6254qs_INCLUDES := -I $(THIS_DIR)inc +x86_64_inventec_d6254qs_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_inventec_d6254qs_DEPENDMODULE_ENTRIES := init:x86_64_inventec_d6254qs ucli:x86_64_inventec_d6254qs + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..3eedeea2 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_inventec_d6254qs_ucli.c + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/fani.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..25addc7f --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/fani.c @@ -0,0 +1,329 @@ +/************************************************************ + * + * + * 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 PREFIX_PATH_ON_MAIN_BOARD "/sys/bus/i2c/devices/2-0066/" +#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_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, +}; + +#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), \ + 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_MAIN_BOARD(6), + 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; + + /* get fan present status + */ + ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + if (ret < 0) { + 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) { + 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) { + 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; +} + + +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_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_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 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: + 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_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: + 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-d6254qs/onlp/builds/src/module/src/ledi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/ledi.c new file mode 100644 index 00000000..7eb2d62b --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,253 @@ +/************************************************************ + * + * + * 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 prefix_path "/sys/class/leds/inventec_d6254qs_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_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} +}; + +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_RED | 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_BLUE, + }, + { + { 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) +{ + /* + * Diag LED Off + */ + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), 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_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-d6254qs/onlp/builds/src/module/src/make.mk b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..5e9bf505 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_inventec_d6254qs +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/platform_lib.c new file mode 100644 index 00000000..9e4c5e06 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,189 @@ +/************************************************************ + * + * + * 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" + +#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 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) { + 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; + } + } + + 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", PSU1_AC_PMBUS_PREFIX, node); + } + else { + ret = onlp_file_read_int(value, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + } + + 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", 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, 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-d6254qs/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/platform_lib.h new file mode 100644 index 00000000..fcba1f3d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,82 @@ +/************************************************************ + * + * + * 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_d6254qs_log.h" + +#define CHASSIS_FAN_COUNT 6 +#define CHASSIS_THERMAL_COUNT 5 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/11-005b/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/10-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/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); + +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 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-d6254qs/onlp/builds/src/module/src/psui.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/psui.c new file mode 100644 index 00000000..8d12741e --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/psui.c @@ -0,0 +1,272 @@ +/************************************************************ + * + * + * 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 "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 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_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 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) +{ + 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; + } + + 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; + } + + /* 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/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/sfpi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..0b568114 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,223 @@ +/************************************************************ + * + * + * 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 +#include "platform_lib.h" + +#define MAX_SFP_PATH 64 +static char sfp_node_path[MAX_SFP_PATH] = {0}; + +#define MUX_START_INDEX 18 +#define NUM_OF_SFP_PORT 32 +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 +}; + +#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]+MUX_START_INDEX) + +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/bus/i2c/devices/%d-0050/%s", + FRONT_PORT_TO_MUX_INDEX(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, 32} + */ + 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, "sfp_is_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; + } + + 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]; + } + + /* 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_eeprom_read(int port, uint8_t data[256]) +{ + char* path = sfp_get_port_path(port, "sfp_eeprom"); + 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); + + if (onlp_file_read((uint8_t*)data, 256, &len, path) < 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 = 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-d6254qs/onlp/builds/src/module/src/sysi.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/sysi.c new file mode 100644 index 00000000..55a0de92 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,295 @@ +/************************************************************ + * + * + * 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_inventec_d6254qs_int.h" +#include "x86_64_inventec_d6254qs_log.h" + +#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 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" +}; + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-inventec-d6254qs-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_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) +{ + 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/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) +{ + 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_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); + 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); +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/thermali.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/thermali.c new file mode 100644 index 00000000..94f5353c --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,141 @@ +/************************************************************ + * + * + * 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) + +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 */ +{ + "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", +}; + +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), "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_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]; + + if(local_id == 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__[local_id]); +} diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_config.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_config.c new file mode 100644 index 00000000..146c25c0 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(_x) __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(_x) +x86_64_inventec_d6254qs_config_settings_t x86_64_inventec_d6254qs_config_settings[] = +{ +#ifdef x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_INCLUDE_LOGGING(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_PORTING_STDLIB(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_inventec_d6254qs_config_STRINGIFY_NAME(x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE(x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_inventec_d6254qs_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_inventec_d6254qs_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_inventec_d6254qs_config_STRINGIFY_VALUE +#undef __x86_64_inventec_d6254qs_config_STRINGIFY_NAME + +const char* +x86_64_inventec_d6254qs_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_inventec_d6254qs_config_settings[i].name; i++) { + if(strcmp(x86_64_inventec_d6254qs_config_settings[i].name, setting)) { + return x86_64_inventec_d6254qs_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_inventec_d6254qs_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_inventec_d6254qs_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_inventec_d6254qs_config_settings[i].name, x86_64_inventec_d6254qs_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_enums.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_enums.c new file mode 100644 index 00000000..a5831953 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_int.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_int.h new file mode 100644 index 00000000..b6dfd9c6 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_inventec_d6254qs Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6254qs_INT_H__ +#define __x86_64_inventec_d6254qs_INT_H__ + +#include + + +#endif /* __x86_64_inventec_d6254qs_INT_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_log.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_log.c new file mode 100644 index 00000000..368a0420 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d6254qs_log.h" +/* + * x86_64_inventec_d6254qs log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_inventec_d6254qs_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_inventec_d6254qs_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_inventec_d6254qs_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_log.h b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_log.h new file mode 100644 index 00000000..299afb96 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_inventec_d6254qs_LOG_H__ +#define __x86_64_inventec_d6254qs_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_inventec_d6254qs +#include + +#endif /* __x86_64_inventec_d6254qs_LOG_H__ */ diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_module.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_module.c new file mode 100644 index 00000000..a4e26c3d --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_inventec_d6254qs_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_inventec_d6254qs_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_d6254qs_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-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_ucli.c b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_ucli.c new file mode 100644 index 00000000..10626fc8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/onlp/builds/src/module/src/x86_64_inventec_d6254qs_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_inventec_d6254qs_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_inventec_d6254qs_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_inventec_d6254qs) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_inventec_d6254qs_ucli_module__ = + { + "x86_64_inventec_d6254qs_ucli", + NULL, + x86_64_inventec_d6254qs_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_inventec_d6254qs_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_inventec_d6254qs_ucli_module__); + n = ucli_node_create("x86_64_inventec_d6254qs", NULL, &x86_64_inventec_d6254qs_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_inventec_d6254qs")); + return n; +} + +#else +void* +x86_64_inventec_d6254qs_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs/platform-config/r0/Makefile b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/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-d6254qs/platform-config/r0/PKG.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/PKG.yml new file mode 100644 index 00000000..463c8da8 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=inventec BASENAME=x86-64-inventec-d6254qs REVISION=r0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/src/lib/x86-64-inventec-d6254qs-r0.yml b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/src/lib/x86-64-inventec-d6254qs-r0.yml new file mode 100644 index 00000000..94bed6c5 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/src/lib/x86-64-inventec-d6254qs-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for d6254qs +# +###################################################################### + +x86-64-inventec-d6254qs-r0: + + grub: + + serial: >- + --port=0x2f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + nopat + console=ttyS1,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/src/python/x86_64_inventec_d6254qs_r0/__init__.py b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/src/python/x86_64_inventec_d6254qs_r0/__init__.py new file mode 100644 index 00000000..5fe08df1 --- /dev/null +++ b/packages/platforms/inventec/x86-64/x86-64-inventec-d6254qs/platform-config/r0/src/python/x86_64_inventec_d6254qs_r0/__init__.py @@ -0,0 +1,15 @@ +from onl.platform.base import * +from onl.platform.inventec import * + +class OnlPlatform_x86_64_inventec_d6254qs_r0(OnlPlatformInventec, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-inventec-d6254qs-r0' + MODEL="X86-D6254QS" + SYS_OBJECT_ID="6254.10" + + 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') + return True 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 181b07cc..62c0e953 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,7 +5,7 @@ class OnlPlatform_x86_64_inventec_d7032q28b_r0(OnlPlatformInventec, OnlPlatformPortConfig_32x100): PLATFORM='x86-64-inventec-d7032q28b-r0' MODEL="X86-D7032Q28B" - SYS_OBJECT_ID=".1.32" + SYS_OBJECT_ID="7032.28" def baseconfig(self): os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0") 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 f21f488b..b88a70fa 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 @@ -5,7 +5,7 @@ class OnlPlatform_x86_64_inventec_d7054q28b_r0(OnlPlatformInventec, OnlPlatformPortConfig_32x100): PLATFORM='x86-64-inventec-d7054q28b-r0' MODEL="X86-D7054Q28B" - SYS_OBJECT_ID=".1.32" + SYS_OBJECT_ID="7054.28" def baseconfig(self): os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0") diff --git a/packages/platforms/quanta/x86-64/modules/builds/qci_cpld_led.c b/packages/platforms/quanta/x86-64/modules/builds/qci_cpld_led.c new file mode 100644 index 00000000..869966b3 --- /dev/null +++ b/packages/platforms/quanta/x86-64/modules/builds/qci_cpld_led.c @@ -0,0 +1,277 @@ +/* + * A LED CPLD driver for Quanta Switch Platform + * + * The CPLD is customize by Quanta for decode led bit stream, + * This driver modify from Quanta CPLD I/O driver. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * Author: Roger Chang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_led_ida); + +enum platform_type { + IX7 = 0, + IX8, + NONE +}; + +static struct class *cpld_class = NULL; + +struct cpld_data { + struct i2c_client *cpld_client; + char name[8]; + u8 cpld_id; +}; + +struct cpld_led_data { + struct mutex lock; + struct device *port_dev; + struct cpld_data *cpld_data; +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_led_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_led_id[] = { + { "CPLDLED_IX7", IX7 }, + { "CPLDLED_IX8", IX8 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_led_id); + +static struct i2c_driver cpld_led_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_led", + }, + .probe = cpld_led_probe, + .remove = cpld_led_remove, + .id_table = cpld_led_id, +// .address_list = normal_i2c, +}; + +#define CPLD_LED_ID_PREFIX "CPLDLED-" +#define CPLD_LED_ID_FORMAT CPLD_LED_ID_PREFIX "%d" + +#define CPLD_DECODER_OFFSET 0x4 +#define CPLD_DECODER_MASK 0x1 +#define CPLD_USERCODE_START_OFFSET 0x0 + +static ssize_t get_led_decode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 offset = (u8)(CPLD_DECODER_OFFSET); + s32 value; + + value = i2c_smbus_read_byte_data(client, offset); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value &= CPLD_DECODER_MASK; + + return sprintf(buf, "%d\n", (value == 0) ? 1 : 0); +} + +static ssize_t get_usercode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 i = 0; + s32 value = 0, reading = 0; + + for (i = 0; i < 4; i++) + { + reading = i2c_smbus_read_byte_data(client, CPLD_USERCODE_START_OFFSET + i); + if (reading < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led usercode reg %d value= %x\n", i, reading); + + value |= reading << (24 - 8 * i); + } + + return sprintf(buf, "%X\n", value); +} + +static ssize_t set_led_decode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + s32 value; + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_byte_data(client, CPLD_DECODER_OFFSET); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value |= CPLD_DECODER_MASK; + if (enable) + value &= ~CPLD_DECODER_MASK; + + dev_dbg(&client->dev, "write led decode value= %x\n", value); + + i2c_smbus_write_byte_data(client, CPLD_DECODER_OFFSET, (u8)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(led_decode, S_IWUSR | S_IRUGO, get_led_decode, set_led_decode); +static DEVICE_ATTR(usercode, S_IRUGO, get_usercode, NULL); + +static const struct attribute *led_attrs[] = { + &dev_attr_usercode.attr, + &dev_attr_led_decode.attr, + NULL, +}; + +static const struct attribute_group led_attr_group = { + .attrs = (struct attribute **) led_attrs, +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_led_data *data; + struct cpld_data *led_data; + struct device *port_dev; + int nr, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-led"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_led_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Test */ + nr = ida_simple_get(&cpld_led_ida, 1, 99, GFP_KERNEL); + if (nr < 0) + return ERR_PTR(nr); + + led_data = kzalloc(sizeof(struct cpld_led_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), led_data, CPLD_LED_ID_FORMAT, nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev = port_dev; + data->cpld_data = led_data; + + dev_info(&client->dev, "Register CPLDLED %d\n", nr); + + sprintf(led_data->name, "LED%d-data", nr); + led_data->cpld_id = nr; + dev_set_drvdata(port_dev, led_data); + port_dev->init_name = led_data->name; + led_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &led_attr_group); + // if (status) printk("err status\n"); + /* end */ + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +//FIXME: implement error check +exit_remove: +// sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_led_remove(struct i2c_client *client) +{ + struct cpld_led_data *data = i2c_get_clientdata(client); + + dev_info(data->port_dev, "Remove CPLDLED-%d\n", data->cpld_data->cpld_id); + device_unregister(data->port_dev); + ida_simple_remove(&cpld_led_ida, data->cpld_data->cpld_id); + kfree(data->cpld_data); + + if (cpld_idr_is_empty(&cpld_led_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_led_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_AUTHOR("Roger Chang "); +MODULE_DESCRIPTION("Quanta Switch LED CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/.gitignore b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/.gitignore new file mode 100644 index 00000000..0f1e9df7 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/.gitignore @@ -0,0 +1,2 @@ +*x86*64*quanta*ix7*rglbmc.mk +onlpdump.mk diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/PKG.yml b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/PKG.yml new file mode 100644 index 00000000..8c671886 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml ARCH=amd64 VENDOR=quanta BASENAME=x86-64-quanta-ix7-rglbmc KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/.gitignore b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/Makefile new file mode 100644 index 00000000..af745769 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := quanta +BASENAME := x86-64-quanta-ix7-rglbmc +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/quanta_platform_ix7.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/quanta_platform_ix7.c new file mode 100644 index 00000000..4fac884b --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/modules/builds/quanta_platform_ix7.c @@ -0,0 +1,323 @@ +/* + * Quanta IX7 platform driver + * + * + * Copyright (C) 2014 Quanta Computer inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) +#include +#else +#include +#endif + +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9546_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_data = { + .modes = pca9546_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), + MUX_INFO(0x18, 1), + MUX_INFO(0x19, 1), + MUX_INFO(0x1a, 1), + MUX_INFO(0x1b, 1), +}; + +static struct pca954x_platform_data pca9548_data = { + .modes = pca9548_modes, + .num_modes = 8, +}; + +/* CPU Board i2c device */ +static struct pca954x_platform_mode pca9546_cpu_modes[] = { + MUX_INFO(0x02, 1), + MUX_INFO(0x03, 1), + MUX_INFO(0x04, 1), + MUX_INFO(0x05, 1), +}; + +static struct pca954x_platform_data pca9546_cpu_data = { + .modes = pca9546_cpu_modes, + .num_modes = 4, +}; +//MB Board Data +static struct pca953x_platform_data pca9555_1_data = { + .gpio_base = 0x10, +}; +//CPU Board pca9555 +static struct pca953x_platform_data pca9555_CPU_data = { + .gpio_base = 0x20, +}; + +static struct i2c_board_info ix7_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x72), // 0 + .platform_data = &pca9546_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x77), // 1 + .platform_data = &pca9548_data, + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 2 0x72 ch2 eeprom + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 3 0x77 ch0 + .platform_data = &pca9548sfp1_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 4 0x77 ch1 + .platform_data = &pca9548sfp2_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 5 0x77 ch2 + .platform_data = &pca9548sfp3_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 6 0x77 ch3 + .platform_data = &pca9548sfp4_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x23), // 7 0x72 ch3 pca9555 MB Board Data + .platform_data = &pca9555_1_data, + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x38), // 8 0x72 ch0 + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x38), // 9 0x72 ch1 + }, + { + I2C_BOARD_INFO("pca9546", 0x71), // 10 CPU Board i2c device + .platform_data = &pca9546_cpu_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x20), // 11 0x71 ch0 CPU Board Data + .platform_data = &pca9555_CPU_data, + }, + { + I2C_BOARD_INFO("24c02", 0x50), // 12 0x50 SFP, QSFP28 EEPROM + }, + { + I2C_BOARD_INFO("CPLDLED_IX7", 0x39), // 13 0x72 ch0 CPLD_led_1 + }, + { + I2C_BOARD_INFO("CPLDLED_IX7", 0x39), // 14 0x72 ch1 CPLD_led_1 + }, +}; + +static struct platform_driver ix7_platform_driver = { + .driver = { + .name = "qci-ix7", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *ix7_device; + +static int __init ix7_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + int ret, i; + + ret = platform_driver_register(&ix7_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix7_device = platform_device_alloc("qci-ix7", -1); + if (!ix7_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix7_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix7_i2c_devices[0]); // pca9546 + client = i2c_new_device(adapter, &ix7_i2c_devices[1]); // pca9548 + client = i2c_new_device(adapter, &ix7_i2c_devices[10]); // pca9546 in CPU board + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x02); + client = i2c_new_device(adapter, &ix7_i2c_devices[11]); // CPU Board Data + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix7_i2c_devices[8]); // CPLD2 + client = i2c_new_device(adapter, &ix7_i2c_devices[13]); // CPLD_led_1 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix7_i2c_devices[9]); // CPLD3 + client = i2c_new_device(adapter, &ix7_i2c_devices[14]); // CPLD_led_2 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x12); + client = i2c_new_device(adapter, &ix7_i2c_devices[2]); // MB_BOARDINFO_EEPROM + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x13); + client = i2c_new_device(adapter, &ix7_i2c_devices[7]); // pca9555 MB Board Data + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix7_i2c_devices[3]); // pca9548_1 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix7_i2c_devices[4]); // pca9548_2 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix7_i2c_devices[5]); // pca9548_3 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix7_i2c_devices[6]); // pca9548_4 SFP + i2c_put_adapter(adapter); + for(i = 32; i < 64; i ++){ // QSFP28 1~32 EEPROM + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix7_i2c_devices[12]); + i2c_put_adapter(adapter); + } + + return 0; + +fail_platform_device: + platform_device_put(ix7_device); + +fail_platform_driver: + platform_driver_unregister(&ix7_platform_driver); + return ret; +} + +static void __exit ix7_platform_exit(void) +{ + platform_device_unregister(ix7_device); + platform_driver_unregister(&ix7_platform_driver); +} + +module_init(ix7_platform_init); +module_exit(ix7_platform_exit); + + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta IX7 Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/PKG.yml b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/PKG.yml new file mode 100644 index 00000000..a56e0715 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-quanta-ix7-rglbmc ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/lib/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/lib/Makefile new file mode 100644 index 00000000..286d8d69 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/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-quanta-ix7-rglbmc +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_quanta_ix7_rglbmc quanta_sys_eeprom onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-quanta-ix7-rglbmc.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/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/onlpdump/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..55a8e9d3 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/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_quanta_ix7_rglbmc quanta_sys_eeprom 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/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/.module b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/.module new file mode 100644 index 00000000..dc4a368f --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/.module @@ -0,0 +1 @@ +name: x86_64_quanta_ix7_rglbmc diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/Makefile new file mode 100644 index 00000000..b4f54d53 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_quanta_ix7_rglbmc +AUTOMODULE := x86_64_quanta_ix7_rglbmc +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/auto/make.mk b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/auto/make.mk new file mode 100644 index 00000000..0263bd02 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_quanta_ix7_rglbmc Autogeneration +# +############################################################################### +x86_64_quanta_ix7_rglbmc_AUTO_DEFS := module/auto/x86_64_quanta_ix7_rglbmc.yml +x86_64_quanta_ix7_rglbmc_AUTO_DIRS := module/inc/x86_64_quanta_ix7_rglbmc module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/auto/x86_64_quanta_ix7_rglbmc.yml b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/auto/x86_64_quanta_ix7_rglbmc.yml new file mode 100644 index 00000000..0fcb7c86 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/auto/x86_64_quanta_ix7_rglbmc.yml @@ -0,0 +1,134 @@ +############################################################################### +# +# x86_64_quanta_ix7_rglbmc Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD: + doc: "RPM Threshold at which the fan is considered to have failed." + default: 3000 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX: + doc: "Maximum system front-to-back fan speed." + default: 18000 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX: + doc: "Maximum system back-to-front fan speed." + default: 18000 +- X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS: + doc: "Time to hold Phy GPIO in reset, in ms" + default: 100 + +definitions: + cdefs: + X86_64_QUANTA_IX7_RGLBMC_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_quanta_ix7_rglbmc_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 + - THERMAL8 : 8 + - THERMAL9 : 9 + - THERMAL10 : 10 + - THERMAL11 : 11 + - THERMAL12 : 12 + - THERMAL13 : 13 + - THERMAL14 : 14 + - THERMAL15 : 15 + - THERMAL16 : 16 + + + 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) + - THERMAL8 : ONLP_THERMAL_ID_CREATE(8) + - THERMAL9 : ONLP_THERMAL_ID_CREATE(9) + - THERMAL10 : ONLP_THERMAL_ID_CREATE(10) + - THERMAL11 : ONLP_THERMAL_ID_CREATE(11) + - THERMAL12 : ONLP_THERMAL_ID_CREATE(12) + - THERMAL13 : ONLP_THERMAL_ID_CREATE(13) + - THERMAL14 : ONLP_THERMAL_ID_CREATE(14) + - THERMAL15 : ONLP_THERMAL_ID_CREATE(15) + - THERMAL16 : ONLP_THERMAL_ID_CREATE(16) + + + portingmacro: + X86_64_QUANTA_IX7_RGLBMC: + macros: + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc.x b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc.x new file mode 100644 index 00000000..2ac54ec5 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_config.h b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_config.h new file mode 100644 index 00000000..4fc0258e --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_config.h @@ -0,0 +1,167 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_quanta_ix7_rglbmc Configuration Header + * + * @addtogroup x86_64_quanta_ix7_rglbmc-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_QUANTA_IX7_RGLBMC_CONFIG_H__ +#define __X86_64_QUANTA_IX7_RGLBMC_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD + * + * RPM Threshold at which the fan is considered to have failed. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD 3000 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX + * + * Maximum system front-to-back fan speed. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX 18000 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX + * + * Maximum system back-to-front fan speed. */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX 18000 +#endif + +/** + * X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS + * + * Time to hold Phy GPIO in reset, in ms */ + + +#ifndef X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS +#define X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS 100 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_quanta_ix7_rglbmc_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_quanta_ix7_rglbmc_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_quanta_ix7_rglbmc_config_settings table. */ +extern x86_64_quanta_ix7_rglbmc_config_settings_t x86_64_quanta_ix7_rglbmc_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_quanta_ix7_rglbmc_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_quanta_ix7_rglbmc_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_quanta_ix7_rglbmc_porting.h" + +#endif /* __X86_64_QUANTA_IX7_RGLBMC_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_dox.h b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_dox.h new file mode 100644 index 00000000..fa83667a --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_quanta_ix7_rglbmc Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_QUANTA_IX7_RGLBMC_DOX_H__ +#define __X86_64_QUANTA_IX7_RGLBMC_DOX_H__ + +/** + * @defgroup x86_64_quanta_ix7_rglbmc x86_64_quanta_ix7_rglbmc - x86_64_quanta_ix7_rglbmc Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_quanta_ix7_rglbmc-x86_64_quanta_ix7_rglbmc Public Interface + * @defgroup x86_64_quanta_ix7_rglbmc-config Compile Time Configuration + * @defgroup x86_64_quanta_ix7_rglbmc-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_QUANTA_IX7_RGLBMC_DOX_H__ */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_gpio_table.h b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_gpio_table.h new file mode 100644 index 00000000..0347c6e9 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_gpio_table.h @@ -0,0 +1,25 @@ +#ifndef __X86_64_QUANTA_IX7_RGLBMC_GPIO_TABLE_H__ +#define __X86_64_QUANTA_IX7_RGLBMC_GPIO_TABLE_H__ + +/* + * defined within platform/quanta_switch.c + * Quanta Switch Platform driver + */ +#define QUANTA_IX7_PCA953x_GPIO(P1, P2) (P1*8+P2) + +#define QUANTA_IX7_PCA9555_GPIO_SIZE 0x10 + +#define QUANTA_IX7_I2C_GPIO_BASE 0x10 + +#define QUANTA_IX7_I2C_GPIO_CPU_BASE 0x20 + +#define QUANTA_IX7_CPU_BOARD_GPIO_BASE (QUANTA_IX7_I2C_GPIO_CPU_BASE) +#define QUANTA_IX7_CPU_BOARD_SYS_P1 (QUANTA_IX7_CPU_BOARD_GPIO_BASE + QUANTA_IX7_PCA953x_GPIO(1,2)) +#define QUANTA_IX7_CPU_BOARD_SYS_P2 (QUANTA_IX7_CPU_BOARD_GPIO_BASE + QUANTA_IX7_PCA953x_GPIO(1,3)) + +#define QUANTA_IX7_ZQSFP_EN_GPIO_BASE QUANTA_IX7_I2C_GPIO_BASE +#define QUANTA_IX7_ZQSFP_EN_GPIO_SIZE QUANTA_IX7_PCA9555_GPIO_SIZE +#define QUANTA_IX7_ZQSFP_EN_GPIO_P3V3_PW_GD (QUANTA_IX7_ZQSFP_EN_GPIO_BASE + QUANTA_IX7_PCA953x_GPIO(0,4)) +#define QUANTA_IX7_ZQSFP_EN_GPIO_P3V3_PW_EN (QUANTA_IX7_ZQSFP_EN_GPIO_BASE + QUANTA_IX7_PCA953x_GPIO(0,5)) + +#endif /* __X86_64_QUANTA_IX7_RGLBMC_GPIO_TABLE_H__ */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_porting.h b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_porting.h new file mode 100644 index 00000000..b32454a3 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/inc/x86_64_quanta_ix7_rglbmc/x86_64_quanta_ix7_rglbmc_porting.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_quanta_ix7_rglbmc Porting Macros. + * + * @addtogroup x86_64_quanta_ix7_rglbmc-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_QUANTA_IX7_RGLBMC_PORTING_H__ +#define __X86_64_QUANTA_IX7_RGLBMC_PORTING_H__ + + +/* */ +#if X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_QUANTA_IX7_RGLBMC_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_QUANTA_IX7_RGLBMC_MEMSET GLOBAL_MEMSET + #elif X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB == 1 + #define X86_64_QUANTA_IX7_RGLBMC_MEMSET memset + #else + #error The macro X86_64_QUANTA_IX7_RGLBMC_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_QUANTA_IX7_RGLBMC_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_QUANTA_IX7_RGLBMC_MEMCPY GLOBAL_MEMCPY + #elif X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB == 1 + #define X86_64_QUANTA_IX7_RGLBMC_MEMCPY memcpy + #else + #error The macro X86_64_QUANTA_IX7_RGLBMC_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_QUANTA_IX7_RGLBMC_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_QUANTA_IX7_RGLBMC_STRNCPY GLOBAL_STRNCPY + #elif X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB == 1 + #define X86_64_QUANTA_IX7_RGLBMC_STRNCPY strncpy + #else + #error The macro X86_64_QUANTA_IX7_RGLBMC_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_QUANTA_IX7_RGLBMC_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_QUANTA_IX7_RGLBMC_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB == 1 + #define X86_64_QUANTA_IX7_RGLBMC_VSNPRINTF vsnprintf + #else + #error The macro X86_64_QUANTA_IX7_RGLBMC_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_QUANTA_IX7_RGLBMC_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_QUANTA_IX7_RGLBMC_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB == 1 + #define X86_64_QUANTA_IX7_RGLBMC_SNPRINTF snprintf + #else + #error The macro X86_64_QUANTA_IX7_RGLBMC_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_QUANTA_IX7_RGLBMC_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_QUANTA_IX7_RGLBMC_STRLEN GLOBAL_STRLEN + #elif X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB == 1 + #define X86_64_QUANTA_IX7_RGLBMC_STRLEN strlen + #else + #error The macro X86_64_QUANTA_IX7_RGLBMC_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_QUANTA_IX7_RGLBMC_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/make.mk b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/make.mk new file mode 100644 index 00000000..e5947b4f --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_quanta_ix7_rglbmc_INCLUDES := -I $(THIS_DIR)inc +x86_64_quanta_ix7_rglbmc_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_quanta_ix7_rglbmc_DEPENDMODULE_ENTRIES := init:x86_64_quanta_ix7_rglbmc ucli:x86_64_quanta_ix7_rglbmc + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/Makefile new file mode 100644 index 00000000..ee8004c4 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_quanta_ix7_rglbmc_ucli.c + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/fani.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/fani.c new file mode 100644 index 00000000..7594b0ca --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/fani.c @@ -0,0 +1,31 @@ +/************************************************************ + * + * + * 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 + +int +onlp_fani_init(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/ledi.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/ledi.c new file mode 100644 index 00000000..7385dd68 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/ledi.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +#include "x86_64_quanta_ix7_rglbmc_int.h" +#include +#include + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t led_info[] = +{ + { }, /* Not used */ + { + { LED_OID_SYSTEM, "System LED", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + } +}; + +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; + + led_id = ONLP_OID_ID_GET(id); + + *info = led_info[led_id]; + info->status |= ONLP_LED_STATUS_ON; + info->mode |= ONLP_LED_MODE_ON; + + return ONLP_STATUS_OK; +} + +void +Sysfs_Set_System_LED(onlp_led_mode_t mode) +{ + if(mode == ONLP_LED_MODE_GREEN){ + onlp_gpio_set(QUANTA_IX7_CPU_BOARD_SYS_P1, 0); + onlp_gpio_set(QUANTA_IX7_CPU_BOARD_SYS_P2, 1); + } + else if(mode == ONLP_LED_MODE_ORANGE){ + onlp_gpio_set(QUANTA_IX7_CPU_BOARD_SYS_P1, 1); + onlp_gpio_set(QUANTA_IX7_CPU_BOARD_SYS_P2, 0); + } + else{ + onlp_gpio_set(QUANTA_IX7_CPU_BOARD_SYS_P1, 1); + onlp_gpio_set(QUANTA_IX7_CPU_BOARD_SYS_P2, 1); + } +} + +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int led_id; + + led_id = ONLP_OID_ID_GET(id); + switch (led_id) { + case LED_ID_SYSTEM: + Sysfs_Set_System_LED(mode); + break; + default: + return ONLP_STATUS_E_INTERNAL; + break; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/make.mk b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/make.mk new file mode 100644 index 00000000..053efbeb --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_quanta_ix7_rglbmc +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/psui.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/psui.c new file mode 100644 index 00000000..b5cedce1 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/psui.c @@ -0,0 +1,15 @@ +/************************************************************ + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/sfpi.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/sfpi.c new file mode 100644 index 00000000..dbb7a9de --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/sfpi.c @@ -0,0 +1,244 @@ +/************************************************************ + * + * + * 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 Quanta IX7 + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "x86_64_quanta_ix7_rglbmc_log.h" +#include +#include +#include + +/** + * This table maps the presence gpio, reset gpio, and eeprom file + * for each SFP port. + */ +typedef struct sfpmap_s { + int port; + const char* present_cpld; + const char* reset_gpio; + const char* eeprom; + const char* dom; +} sfpmap_t; + +static sfpmap_t sfpmap__[] = + { + { 1, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-1/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-32/32-0050/eeprom", NULL }, + { 2, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-2/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-33/33-0050/eeprom", NULL }, + { 3, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-3/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-34/34-0050/eeprom", NULL }, + { 4, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-4/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-35/35-0050/eeprom", NULL }, + { 5, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-5/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-36/36-0050/eeprom", NULL }, + { 6, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-6/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-37/37-0050/eeprom", NULL }, + { 7, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-7/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-38/38-0050/eeprom", NULL }, + { 8, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-8/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-20/i2c-39/39-0050/eeprom", NULL }, + { 9, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-9/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-40/40-0050/eeprom", NULL }, + { 10, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-10/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-41/41-0050/eeprom", NULL }, + { 11, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-11/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-42/42-0050/eeprom", NULL }, + { 12, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-12/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-43/43-0050/eeprom", NULL }, + { 13, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-13/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-44/44-0050/eeprom", NULL }, + { 14, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-14/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-45/45-0050/eeprom", NULL }, + { 15, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-15/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-46/46-0050/eeprom", NULL }, + { 16, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-0038/cpld-qsfp28/port-16/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-21/i2c-47/47-0050/eeprom", NULL }, + { 17, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-17/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-48/48-0050/eeprom", NULL }, + { 18, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-18/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-49/49-0050/eeprom", NULL }, + { 19, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-19/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-50/50-0050/eeprom", NULL }, + { 20, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-20/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-51/51-0050/eeprom", NULL }, + { 21, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-21/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-52/52-0050/eeprom", NULL }, + { 22, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-22/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-53/53-0050/eeprom", NULL }, + { 23, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-23/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-54/54-0050/eeprom", NULL }, + { 24, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-24/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-22/i2c-55/55-0050/eeprom", NULL }, + { 25, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-25/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-56/56-0050/eeprom", NULL }, + { 26, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-26/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-57/57-0050/eeprom", NULL }, + { 27, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-27/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-58/58-0050/eeprom", NULL }, + { 28, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-28/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-59/59-0050/eeprom", NULL }, + { 29, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-29/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-60/60-0050/eeprom", NULL }, + { 30, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-30/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-61/61-0050/eeprom", NULL }, + { 31, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-31/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-62/62-0050/eeprom", NULL }, + { 32, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-17/17-0038/cpld-qsfp28/port-32/%s", NULL, "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-23/i2c-63/63-0050/eeprom", NULL }, + }; + +#define SFP_GET(_port) (sfpmap__ + _port - 1) +#define MAX_SFP_PATH 128 +static char sfp_node_path[MAX_SFP_PATH] = {0}; + +static char* +sfp_get_port_path(int port, char *node_name) +{ + sfpmap_t* sfp = SFP_GET(port); + + sprintf(sfp_node_path, sfp->present_cpld, + node_name); + return sfp_node_path; +} + +int +onlp_sfpi_init(void) +{ + int ret; + + onlp_gpio_export(QUANTA_IX7_ZQSFP_EN_GPIO_P3V3_PW_EN, ONLP_GPIO_DIRECTION_OUT); + ret = onlp_gpio_set(QUANTA_IX7_ZQSFP_EN_GPIO_P3V3_PW_EN, 1); + sleep(1); + + return ret; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + + for(p = 1; p < 33; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + return onlplib_sfp_is_present_file(sfp_get_port_path(port, "module_present"), /* Present */ "1\n", /* Absent */ "0\n"); +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + sfpmap_t* sfp = SFP_GET(port); + return onlplib_sfp_eeprom_read_file(sfp->eeprom, data); +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + sfpmap_t* sfp = SFP_GET(port); + return onlplib_sfp_eeprom_read_file(sfp->dom, data); +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + char* path = NULL; + + switch(control){ + case ONLP_SFP_CONTROL_RESET_STATE: + { + path = sfp_get_port_path(port, "reset"); + + if (onlp_file_write_int(value, path) != 0) { + AIM_LOG_ERROR("Unable to set reset status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_LP_MODE: + { + path = sfp_get_port_path(port, "lpmode"); + + if (onlp_file_write_int(value, path) != 0) { + AIM_LOG_ERROR("Unable to set lp_mode status to 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_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + char* path = NULL; + + switch(control){ + case ONLP_SFP_CONTROL_RESET_STATE: + { + path = sfp_get_port_path(port, "reset"); + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read reset status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + if(*value == 0){ + *value = 1; + } + else{ + *value = 0; + } + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_LP_MODE: + { + path = sfp_get_port_path(port, "lpmode"); + + if (onlp_file_read_int(value, path) < 0) { + AIM_LOG_ERROR("Unable to read lpmode status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_RX_LOS: + { + *value = 0; + rv = ONLP_STATUS_OK; + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + *value = 0; + rv = ONLP_STATUS_OK; + break; + } + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + } + + return rv; +} + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/sysi.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/sysi.c new file mode 100644 index 00000000..a6c8e902 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/sysi.c @@ -0,0 +1,66 @@ +/************************************************************ + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include "x86_64_quanta_ix7_rglbmc_int.h" +#include "x86_64_quanta_ix7_rglbmc_log.h" +#include +#include +#include +#include +#include + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-quanta-ix7-rglbmc-r0"; +} + +int +onlp_sysi_init(void) +{ + /* Config GPIO */ + /* LED Output */ + onlp_gpio_export(QUANTA_IX7_CPU_BOARD_SYS_P1, ONLP_GPIO_DIRECTION_OUT); + onlp_gpio_export(QUANTA_IX7_CPU_BOARD_SYS_P2, ONLP_GPIO_DIRECTION_OUT); + + /* Set LED to green */ + onlp_ledi_mode_set(LED_OID_SYSTEM, ONLP_LED_MODE_GREEN); + + return ONLP_STATUS_OK; +} + +#define QUANTA_SYS_EEPROM_PATH \ +"/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-18/18-0054/eeprom" + +int +onlp_sysi_onie_info_get(onlp_onie_info_t* onie) +{ + int rv; + + rv = onlp_onie_decode_file(onie, QUANTA_SYS_EEPROM_PATH); + if(rv >= 0) { + onie->platform_name = aim_strdup("x86-64-quanta-ix7-rglbmc-r0"); + rv = quanta_onie_sys_eeprom_custom_format(onie); + } + 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)); + + /* + * 1 LEDs + */ + *e++ = LED_OID_SYSTEM; + + return 0; +} diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/thermali.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/thermali.c new file mode 100644 index 00000000..2a84c017 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/thermali.c @@ -0,0 +1,31 @@ +/************************************************************ + * + * + * 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 + +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_config.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_config.c new file mode 100644 index 00000000..881cd788 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_config.c @@ -0,0 +1,95 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(_x) __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(_x) +x86_64_quanta_ix7_rglbmc_config_settings_t x86_64_quanta_ix7_rglbmc_config_settings[] = +{ +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_LOGGING(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_STDLIB(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_F2B_RPM_MAX(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_SYSFAN_B2F_RPM_MAX(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS + { __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME(X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS), __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE(X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS) }, +#else +{ X86_64_QUANTA_IX7_RGLBMC_CONFIG_PHY_RESET_DELAY_MS(__x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_VALUE +#undef __x86_64_quanta_ix7_rglbmc_config_STRINGIFY_NAME + +const char* +x86_64_quanta_ix7_rglbmc_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_quanta_ix7_rglbmc_config_settings[i].name; i++) { + if(strcmp(x86_64_quanta_ix7_rglbmc_config_settings[i].name, setting)) { + return x86_64_quanta_ix7_rglbmc_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_quanta_ix7_rglbmc_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_quanta_ix7_rglbmc_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_quanta_ix7_rglbmc_config_settings[i].name, x86_64_quanta_ix7_rglbmc_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_enums.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_enums.c new file mode 100644 index 00000000..5f67ff26 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_int.h b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_int.h new file mode 100644 index 00000000..f0d72f37 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_int.h @@ -0,0 +1,281 @@ +/**************************************************************************//** + * + * x86_64_quanta_ix7_rglbmc Internal Header + * + *****************************************************************************/ +#ifndef __X86_64_QUANTA_IX7_RGLBMC_INT_H__ +#define __X86_64_QUANTA_IX7_RGLBMC_INT_H__ + +#include +#include + +/* */ +/** 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_THERMAL8 = ONLP_THERMAL_ID_CREATE(8), + THERMAL_OID_THERMAL9 = ONLP_THERMAL_ID_CREATE(9), + THERMAL_OID_THERMAL10 = ONLP_THERMAL_ID_CREATE(10), + THERMAL_OID_THERMAL11 = ONLP_THERMAL_ID_CREATE(11), + THERMAL_OID_THERMAL12 = ONLP_THERMAL_ID_CREATE(12), + THERMAL_OID_THERMAL13 = ONLP_THERMAL_ID_CREATE(13), + THERMAL_OID_THERMAL14 = ONLP_THERMAL_ID_CREATE(14), + THERMAL_OID_THERMAL15 = ONLP_THERMAL_ID_CREATE(15), + THERMAL_OID_THERMAL16 = ONLP_THERMAL_ID_CREATE(16), +} 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_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_THERMAL8 = 8, + THERMAL_ID_THERMAL9 = 9, + THERMAL_ID_THERMAL10 = 10, + THERMAL_ID_THERMAL11 = 11, + THERMAL_ID_THERMAL12 = 12, + THERMAL_ID_THERMAL13 = 13, + THERMAL_ID_THERMAL14 = 14, + THERMAL_ID_THERMAL15 = 15, + THERMAL_ID_THERMAL16 = 16, +} 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[]; + +/** 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[]; + +/** 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[]; + +/** 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[]; +/* */ + +/* psu info table */ +struct psu_info_s { + char path[PATH_MAX]; + int present; + int busno; + int addr; +}; + +/** led_id */ +typedef enum led_id_e { + LED_ID_SYSTEM = 1, +} 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_SYSTEM = ONLP_LED_ID_CREATE(LED_ID_SYSTEM), +} 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[]; +/* */ + +#endif /* __X86_64_QUANTA_IX7_RGLBMC_INT_H__ */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_log.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_log.c new file mode 100644 index 00000000..672c0741 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_quanta_ix7_rglbmc_log.h" +/* + * x86_64_quanta_ix7_rglbmc log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_QUANTA_IX7_RGLBMC_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_log.h b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_log.h new file mode 100644 index 00000000..87d0af1f --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __X86_64_QUANTA_IX7_RGLBMC_LOG_H__ +#define __X86_64_QUANTA_IX7_RGLBMC_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_quanta_ix7_rglbmc +#include + +#endif /* __X86_64_QUANTA_IX7_RGLBMC_LOG_H__ */ diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_module.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_module.c new file mode 100644 index 00000000..03d49c15 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_quanta_ix7_rglbmc_log.h" + +static int +datatypes_init__(void) +{ +#define X86_64_QUANTA_IX7_RGLBMC_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_quanta_ix7_rglbmc_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_ucli.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_ucli.c new file mode 100644 index 00000000..8aa3b6bc --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/onlp/builds/src/x86_64_quanta_ix7_rglbmc/module/src/x86_64_quanta_ix7_rglbmc_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_QUANTA_IX7_RGLBMC_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_quanta_ix7_rglbmc_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_quanta_ix7_rglbmc) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_quanta_ix7_rglbmc_ucli_module__ = + { + "x86_64_quanta_ix7_rglbmc_ucli", + NULL, + x86_64_quanta_ix7_rglbmc_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_quanta_ix7_rglbmc_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_quanta_ix7_rglbmc_ucli_module__); + n = ucli_node_create("x86_64_quanta_ix7_rglbmc", NULL, &x86_64_quanta_ix7_rglbmc_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_quanta_ix7_rglbmc")); + return n; +} + +#else +void* +x86_64_quanta_ix7_rglbmc_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/Makefile b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/PKG.yml b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/PKG.yml new file mode 100644 index 00000000..0c770340 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=quanta BASENAME=x86-64-quanta-ix7-rglbmc REVISION=r0 diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/src/lib/x86-64-quanta-ix7-rglbmc-r0.yml b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/src/lib/x86-64-quanta-ix7-rglbmc-r0.yml new file mode 100644 index 00000000..91127310 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/src/lib/x86-64-quanta-ix7-rglbmc-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for IX7 +# +###################################################################### + +x86-64-quanta-ix7-rglbmc-r0: + + grub: + + serial: >- + --port=0x2f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + console=ttyS1,115200n8 + reboot=c,p + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix7_rglbmc_r0/__init__.py b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix7_rglbmc_r0/__init__.py new file mode 100644 index 00000000..3446a8e5 --- /dev/null +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix7-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix7_rglbmc_r0/__init__.py @@ -0,0 +1,23 @@ +from onl.platform.base import * +from onl.platform.quanta import * + +class OnlPlatform_x86_64_quanta_ix7_rglbmc_r0(OnlPlatformQuanta, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-quanta-ix7-rglbmc-r0' + MODEL="IX7" + """ Define Quanta SYS_OBJECT_ID rule. + + SYS_OBJECT_ID = .xxxx.ABCC + "xxxx" define QCT device mark. For example, LB9->1048, LY2->3048 + "A" define QCT switch series name: LB define 1, LY define 2, IX define 3 + "B" define QCT switch series number 1: For example, LB9->9, LY2->2 + "CC" define QCT switch series number 2: For example, LY2->00, LY4R->18(R is 18th english letter) + """ + SYS_OBJECT_ID=".7032.3700" + + def baseconfig(self): + self.insmod("qci_cpld") + self.insmod("qci_cpld_led") + self.insmod("quanta_platform_ix7") + + return True diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/modules/builds/qci_platform_ix8.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/modules/builds/qci_platform_ix8.c index fe38f3fe..75379fcf 100644 --- a/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/modules/builds/qci_platform_ix8.c +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/modules/builds/qci_platform_ix8.c @@ -283,6 +283,12 @@ static struct i2c_board_info ix8_i2c_devices[] = { I2C_BOARD_INFO("pca9555", 0x20), // 17 0x71 ch0 CPU Board Data .platform_data = &pca9555_CPU_data, }, + { + I2C_BOARD_INFO("CPLDLED_IX8", 0x3a), // 18 0x72 ch0 CPLD4 LED function of SFP28 & QSFP28 (Port27~56) + }, + { + I2C_BOARD_INFO("CPLDLED_IX8", 0x39), // 19 0x72 ch0 CPLD6 LED function of SFP28 & QSFP28 (Port1~26) + }, }; static struct platform_driver ix8_platform_driver = { @@ -327,6 +333,8 @@ static int __init ix8_platform_init(void) adapter = i2c_get_adapter(0x10); client = i2c_new_device(adapter, &ix8_i2c_devices[10]); // CPLD_1 + client = i2c_new_device(adapter, &ix8_i2c_devices[18]); // CPLD_4 + client = i2c_new_device(adapter, &ix8_i2c_devices[19]); // CPLD_6 i2c_put_adapter(adapter); adapter = i2c_get_adapter(0x11); diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix8_rglbmc_r0/__init__.py b/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix8_rglbmc_r0/__init__.py index 24e6c3d8..7e6016bb 100644 --- a/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix8_rglbmc_r0/__init__.py +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ix8-rglbmc/platform-config/r0/src/python/x86_64_quanta_ix8_rglbmc_r0/__init__.py @@ -17,6 +17,7 @@ class OnlPlatform_x86_64_quanta_ix8_rglbmc_r0(OnlPlatformQuanta, def baseconfig(self): self.insmod("qci_cpld_sfp28") + self.insmod("qci_cpld_led") self.insmod("qci_platform_ix8") return True diff --git a/tools/onl-nos-create.py b/tools/onl-nos-create.py new file mode 100755 index 00000000..2cbdf596 --- /dev/null +++ b/tools/onl-nos-create.py @@ -0,0 +1,1172 @@ +#!/usr/bin/python +############################################################ +# +# This script generates a repository skeleton for a new +# Network Operating System based on ONL. +# +############################################################ +import os +import sys +import argparse +import inspect +import logging + +logging.basicConfig() +logger = logging.getLogger("onl-nos-create") +logger.setLevel(logging.INFO) + +ap = argparse.ArgumentParser("onl-nos-create"); + +ap.add_argument('--root', help="The root directory for the new NOS repository.", required=True) +ap.add_argument("--name", help="The name of this NOS.", required=True) +ap.add_argument('--prefix', help="Package prefix for this NOS.", required=True) +ap.add_argument('--arches', help="The architectures to include in this new NOS.", nargs='+', choices=['amd64', 'powerpc', 'armel', 'arm64'], required=True) +ap.add_argument('--debian', help="The debian distributions to incldue in this new NOS.", nargs='+', choices=['jessie', 'stretch'], required=True) +ap.add_argument('--copyright', help="The copyright to use for debian packages.", required=True) +ap.add_argument('--maintainer', help="The maintainer to use for debian packages.", required=True) +ap.add_argument('--version', help="The version to use for debian packages.", default="1.0.0") +ap.add_argument('--changelog', help="Initial changelog for debian packages.", default="Initial.") +ap.add_argument('--support', help="The support to use for debian packages.", required=True) +ap.add_argument("--csr-C", help="CSR Generation: C", required=True) +ap.add_argument("--csr-ST", help="CSR Generation: S", required=True) +ap.add_argument("--csr-O", help="CSR Generation: O", required=True) +ap.add_argument("--csr-localityName", help="CSR Generation: localityName", required=True) +ap.add_argument("--csr-commonName", help="CSR Generation: commonName", required=True) +ap.add_argument("--csr-organizationUnitName", help="CSR Generation: organizationUnitName", required=True) +ap.add_argument("--csr-emailAddress", help="CSR Generation: emailAddress", required=True) +ap.add_argument("--file", help="Output file object to stdout.") +ap.add_argument("--list-files", help="Show all files.", action='store_true') +ap.add_argument("--write-files", help="Write out all files.", action='store_true') +ap.add_argument("--overwrite", help="Overwrite existing files.", action='store_true') +ap.add_argument("--dry", "-n", help="Dry run.", action='store_true') + +class NOSFile(object): + path=None + template=None + + def default_path(self): + # + # The file path is implicit in the classname. + # + clsname = self.__class__.__name__.split('_') + + replacements = { + 'APKG' : 'APKG.yml', + 'PKG' : 'PKG.yml', + 'gitignore' : '.gitignore', + 'bootconfig' : 'boot-config', + } + + clsname = map(lambda t: replacements.get(t, t), clsname) + return os.path.join(*clsname) + + + def __init__(self, root, keywords, path=None, template=None): + self.root = root + self.keywords = keywords + self.keywords['MTOP'] = "$(%(PREFIX)s)" % keywords + self.keywords['TOP'] = "$%(PREFIX)s" % keywords + + path = path if path else self.path + path = path if path else self.default_path() + template = template if template else self.template + + if template.startswith('\n'): + template = template[1:] + if not template.endswith('\n'): + template = template + '\n' + + self.epath = path % self.keywords + try: + self.etemplate = template % self.keywords + except: + logger.error("Error evaluating template.") + for line in template.split('\n'): + logger.error("Running: '%s'" % line) + logger.error(line % keywords) + raise + + def write(self, stdout=False, overwrite=False, dry=False): + if stdout: + print self.etemplate + else: + abspath = os.path.join(self.root, self.epath) + if not os.path.isdir(os.path.dirname(abspath)): + os.makedirs(os.path.dirname(abspath)) + + if os.path.exists(abspath): + if not overwrite: + logger.debug("SKIP %s" % abspath) + return + else: + logger.info("OVER %s" % abspath) + else: + logger.info("WRITE %s" % abspath) + + if not dry: + with open(abspath, "w") as f: + f.write(self.etemplate) + + @classmethod + def is_file(klass): + return klass.template + +class PKGFile(NOSFile): + + def __init__(self, root, keywords): + common = """version: %(version)s + copyright: %(copyright)s + maintainer: %(maintainer)s + changelog: %(changelog)s + support: %(support)s""" % keywords + keywords['COMMON'] = common + + common_nv = """copyright: %(copyright)s + maintainer: %(maintainer)s + changelog: %(changelog)s + support: %(support)s""" % keywords + + keywords['COMMON_NV'] = common_nv + + NOSFile.__init__(self, root, keywords) + +class CommonFile(PKGFile): + pass + +class ArchFile(PKGFile): + arches = [ 'amd64', 'powerpc', 'armel', 'arm64' ] + + def __init__(self, root, keywords, arch): + keywords['arch'] = arch + self.arch = arch + PKGFile.__init__(self, root, keywords) + + def default_path(self): + path = NOSFile.default_path(self) + return path.replace('arch', self.arch) + +class ArchFileUboot(ArchFile): + arches = [ 'arm64', 'armel', 'powerpc' ] + def default_path(self): + path = ArchFile.default_path(self) + return path.replace('archuboot', self.arch) + +class ArchFileGrub(ArchFile): + arches = [ 'amd64' ] + def default_path(self): + path = ArchFile.default_path(self) + return path.replace('archgrub', self.arch) + +class OnlPkgMakefile(PKGFile): + template="""include $(ONL)/make/pkg.mk""" + +class OnlSubdirsMakefile(PKGFile): + template="""include $(ONL)/make/subdirs.mk""" + + +class gitignore(CommonFile): + template=""" +# Everything in the REPO directory is ignored by default. + +# Build products +BUILD/ +dependmodules.x +*.deb +*.cpio.gz +*.sqsh +*.pyc +*.pyo + +# Package cache and lock files +.lock +.PKGs.cache* + +# Local module manifest. +.manifest.mk +RELEASE/ + +.bash_history +.buildroot-ccache + +# temporary files +*~ +.#* +""" + +class make_config(CommonFile): + path='make/config.mk' + template=""" +include $(ONL)/make/config.mk +# +# Custom configuration here +# +""" + +class make_gitignore(CommonFile): + template="""versions""" + +class make_arch_config(ArchFile): + path='make/config.%(arch)s.mk' + template=""" +include $(ONL)/make/config.%(arch)s.mk +include %(MTOP)s/make/config.mk +""" + +class packages_Makefile(CommonFile,OnlPkgMakefile): + pass + +class packages_base_Makefile(CommonFile,OnlPkgMakefile): + pass + +class packages_base_any_initrd_loader_APKG(CommonFile): + template = """ +############################################################ +# +# %(PREFIX)s Loader Package Template +# +# Requires: ARCH +# +############################################################ +prerequisites: + packages: [ "onl-loader-initrd:$ARCH" ] + +packages: + - name: %(prefix)s-loader-initrd + arch: $ARCH + %(COMMON)s + summary: %(PREFIX)s Loader Initrd CPIO ($ARCH) + + files: + builds/%(prefix)s-loader-initrd-$ARCH.cpio.gz : $$PKG_INSTALL/ + builds/manifest.json : $$PKG_INSTALL/ + +""" + + +class packages_base_any_initrd_loader_builds_Makefile(CommonFile): + template=""" +############################################################ +# +# %(PREFIX)s Loader initrd build template. +# +############################################################ +ifndef ARCH + $(error $$ARCH must be set) +endif + +ROOT := root +TARGET := %(prefix)s-loader-initrd-$(ARCH).cpio.gz +.PHONY: $(TARGET) + +$(TARGET): +\t$(ONLPM) --copy-file onl-loader-initrd:$(ARCH) onl-loader-initrd-$(ARCH).cpio.gz . +\t$(ONLPM) --copy-file onl-loader-initrd:$(ARCH) manifest.json . +\t$(ONL)/tools/sjson.py --inout manifest.json --kj version %(MTOP)s/make/versions/version-%(prefix)s.json +\tsudo rm -rf $(ROOT) && mkdir $(ROOT) +\tsudo mkdir -p $(ROOT)/etc/%(prefix)s/loader && sudo cp manifest.json $(ROOT)/etc/%(prefix)s/loader +\tsudo cp %(MTOP)s/make/versions/version-%(prefix)s.json $(ROOT)/etc/%(prefix)s/loader/versions.json +\tsudo cp %(MTOP)s/make/versions/version-%(prefix)s.sh $(ROOT)/etc/%(prefix)s/loader/versions.sh +\tsudo cp %(MTOP)s/make/versions/version-%(prefix)s.mk $(ROOT)/etc/%(prefix)s/loader/versions.mk +\t$(ONLPM) --sudo --force --extract-dir %(prefix)s-sysconfig:all $(ROOT) +\t$(ONLPM) --sudo --force --extract-dir %(prefix)s-loader-files:all $(ROOT) +\tsudo $(ONL)/tools/cpiomod.py --cpio onl-loader-initrd-$(ARCH).cpio.gz --add-directory $(ROOT) --out $@ +\tsudo rm -rf $(ROOT) onl-loader-initrd-$(ARCH).cpio.gz + +""" + +class packages_base_arch_initrd_loader_builds_Makefile(ArchFile): + template=""" +include %(MTOP)s/make/config.%(arch)s.mk +include %(MTOP)s/packages/base/any/initrd/loader/builds/Makefile +""" + +class packages_base_arch_initrd_loader_builds_gitignore(ArchFile): + template="""manifest.json""" + +class packages_base_arch_initrd_loader_PKG(ArchFile): + template=""" +!include %(TOP)s/packages/base/any/initrd/loader/APKG.yml ARCH=%(arch)s +""" + +class packages_base_arch_initrd_loader_Makefile(ArchFile,OnlPkgMakefile): + pass + +class packages_base_arch_initrd_Makefile(ArchFile,OnlPkgMakefile): + pass + +class packages_base_any_hw_hw(CommonFile): + path='packages/base/any/hw/hw.c' + template=""" +/** This is simply an example of building a local package into your NOS */ +#include + +int +main(int argc, char* argv[]) +{ + printf("%(PREFIX)s Hello, World!\\n"); + return 0; +} +""" + +class packages_base_any_hw_APKG(CommonFile): + template=""" +packages: + - name: %(prefix)s-hw + arch: $ARCH + %(COMMON)s + summary: %(PREFIX)s Hello World + files: + builds/%(prefix)s-hw : /usr/bin/ +""" + +class packages_base_all_initrd_loaderfiles_Makefile(CommonFile,OnlPkgMakefile): + path='packages/base/all/initrd/loader-files/Makefile' + +class packages_base_all_initrd_loaderfiles_PKG(CommonFile): + path='packages/base/all/initrd/loader-files/PKG.yml' + template=""" +packages: + - name: %(prefix)s-loader-files + arch: all + %(COMMON)s + summary: %(PREFIX)s Loader Files + + files: + - src/lib : /lib + +""" + +class packages_base_all_initrd_loaderfiles_src_lib_bootcustom(CommonFile): + path='packages/base/all/initrd/loader-files/src/lib/boot-custom' + template=""" +############################################################ +# +# Included by the ONL boot1 script to perform +# custom preparation prior to switching root. +# +############################################################ +cp -R /etc/%(prefix)s /newroot/etc + +if [ -d /var/run/udhcpc ]; then + cp -R /var/run/udhcpc /newroot/etc/%(prefix)s/loader +fi +""" + +class packages_base_all_initrd_loaderfiles_src_lib_customize(CommonFile): + path='packages/base/all/initrd/loader-files/src/lib/customize.sh' + template=""" +LOADER_SYSTEM_NAME="%(name)s" +LOADER_LOADER_NAME="Loader" +LOADER_PROMPT="loader# " +ONL_UDHCPC_VENDOR="%(PREFIX)s" + +if [ -f /etc/%(prefix)s/loader/versions.sh ]; then + . /etc/%(prefix)s/loader/versions.sh +fi +""" + +class packages_base_all_sysconfig_PKG(CommonFile): + template=""" +packages: + - name: %(prefix)s-sysconfig + %(COMMON)s + arch: all + summary: %(PREFIX)s Sysconfig Package + + files: + src/%(prefix)s.yml : /etc/onl/sysconfig/01-%(prefix)s.yml + +""" + +class packages_base_all_sysconfig_Makefile(OnlPkgMakefile,CommonFile): + pass + +class packages_base_all_sysconfig_src(CommonFile): + path='packages/base/all/sysconfig/src/%(prefix)s.yml' + template=""" +############################################################ +# +# %(PREFIX)s System Configuration +# +############################################################ +installer: + menu_name: %(PREFIX)s + os_name: %(name)s + grub: + - $PLATFORM.cpio.gz + - %(prefix)s-loader-initrd-$PARCH.cpio.gz + fit: + - $PLATFORM.itb + - %(prefix)s-loader-fit.itb + +upgrade: + + system: + auto: force + + onie: + auto: advisory + package: + dir: /lib/platform-config/current/%(prefix)s/upgrade/onie + + firmware: + auto: advisory + package: + dir: /lib/platform-config/current/%(prefix)s/upgrade/firmware + + loader: + auto: force + versions: /etc/%(prefix)s/loader/versions.json + package: + dir: /etc/%(prefix)s/upgrade/$PARCH + grub: + - $PLATFORM.cpio.gz + - %(prefix)s-loader-initrd-$PARCH.cpio.gz + fit: + - $PLATFORM.itb + - %(prefix)s-loader-fit.itb + +pki: + key: + name: key.pem + len: 2048 + cert: + name: certificate + csr: + fields: + C: %(csr_C)s + ST: %(csr_ST)s + O: %(csr_O)s + localityName: %(csr_localityName)s + commonName: %(csr_commonName)s + organizationalUnitName: %(csr_organizationUnitName)s + emailAddress: %(csr_emailAddress)s + cdays: 3600 + +""" + +class packages_base_arch_hw_Makefile(ArchFile,OnlPkgMakefile): + pass + +class packages_base_arch_hw_PKG(ArchFile): + template=""" +!include %(TOP)s/packages/base/any/hw/APKG.yml ARCH=%(arch)s +""" + +class packages_base_arch_hw_builds_Makefile(ArchFile): + template=""" +include %(MTOP)s/make/config.%(arch)s.mk +include %(MTOP)s/packages/base/any/hw/builds/Makefile + +""" + +class packages_base_any_hw_builds_Makefile(CommonFile): + template=""" +all: +\t$(CROSS_COMPILER)gcc -o %(prefix)s-hw %(MTOP)s/packages/base/any/hw/hw.c +""" + +class packages_base_arch_hw_builds_gitignore(ArchFile): + template="""%(prefix)s-hw""" + +class packages_base_arch_Makefile(ArchFile, OnlPkgMakefile): + pass + +class REPO_Makefile(CommonFile, OnlSubdirsMakefile): + pass + +class REPO_gitignore(CommonFile): + template=""" +extracts +*.deb +Packages +Packages.gz +""" + +class tools_vi(CommonFile): + path='tools/%(prefix)svi.py' + template=""" +import subprocess + +class OnlVersionImplementation(object): + + PRODUCTS = [ + { + "id" : "%(PREFIX)s", +# "version": "Your poduct version here."" + } + ] + + def __init__(self): + if 'version' in self.PRODUCTS[0]: + # Release builds have a specific version. + self.release = True + else: + # The current branch is used as the release version. + self.release = False + cmd = ('git', 'rev-parse', '--abbrev-ref', 'HEAD') + branch = subprocess.check_output(cmd).strip() + self.PRODUCTS[0]['version'] = branch + + def V_OS_NAME(self, data): + return "%(name)s" + + def V_BUILD_SHA1(self, data): + return data['build_sha1'] + + def V_BUILD_SHORT_SHA1(self, data): + return self.V_BUILD_SHA1(data)[0:7] + + def V_BUILD_TIMESTAMP(self, data): + return data['build_timestamp'] + + def V_FNAME_BUILD_TIMESTAMP(self, data): + return self.V_BUILD_TIMESTAMP(data).replace(':', '') + + def V_BUILD_ID(self, data): + return "{}-{}".format(self.V_BUILD_TIMESTAMP(data), self.V_BUILD_SHORT_SHA1(data)) + + def V_FNAME_BUILD_ID(self, data): + return "{}-{}".format(self.V_FNAME_BUILD_TIMESTAMP(data), self.V_BUILD_SHORT_SHA1(data)) + + def V_PRODUCT_ID_VERSION(self, data): + return data['product']['version'] + + def V_VERSION_ID(self, data): + return "%(PREFIX)s-{}".format(self.V_PRODUCT_ID_VERSION(data)) + + def V_FNAME_VERSION_ID(self, data): + return self.V_VERSION_ID(data) + + def V_PRODUCT_VERSION(self, data): + return "%(PREFIX)s-{}".format(self.V_PRODUCT_ID_VERSION(data)) + + def V_FNAME_PRODUCT_VERSION(self, data): + return "%(PREFIX)s-{}".format(self.V_PRODUCT_ID_VERSION(data)) + + def V_VERSION_STRING(self, data): + return "{} {}, {}".format(self.V_OS_NAME(data), self.V_VERSION_ID(data), self.V_BUILD_ID(data)) + + def V_RELEASE_ID(self, data): + return "{},{}".format(self.V_VERSION_ID(data), self.V_BUILD_ID(data)) + + def V_FNAME_RELEASE_ID(self, data): + return "{}-{}".format(self.V_VERSION_ID(data), self.V_FNAME_BUILD_ID(data)) + + def V_SYSTEM_COMPATIBILITY_VERSION(self, data): + return "2" + + def V_ISSUE(self, data): + if self.release: + return "{} {}".format(self.V_OS_NAME(data), self.V_VERSION_ID(data)) + else: + return self.V_VERSION_STRING(data) +""" + +class tools_gitignore(CommonFile): + template="""*.pyc""" + +class packages_base_amd64_upgrade_PKG(ArchFileGrub): + template=""" +prerequisites: + packages: + - onl-kernel-3.16-lts-x86-64-all:amd64 + - onl-kernel-4.9-lts-x86-64-all:amd64 + - onl-kernel-4.14-lts-x86-64-all:amd64 + - %(prefix)s-loader-initrd:amd64 + +packages: + - name: %(prefix)s-upgrade + arch: amd64 + %(COMMON)s + summary: %(PREFIX)s Upgrade Package + + files: + builds/files : /etc/%(prefix)s/upgrade/amd64 +""" + +class packages_base_amd64_upgrade_builds_gitignore(ArchFileGrub): + template="""files""" + +class packages_base_amd64_upgrade_Makefile(ArchFileGrub,OnlPkgMakefile): + pass + + +class packages_base_amd64_upgrade_builds_Makefile(ArchFileGrub): + template=""" +include %(MTOP)s/make/config.amd64.mk + +# All amd64 kernels +KERNELS := $(shell $(ONLPM) --find-file onl-kernel-3.16-lts-x86-64-all:amd64 kernel-3.16-lts-x86_64-all) \\ + $(shell $(ONLPM) --find-file onl-kernel-4.9-lts-x86-64-all:amd64 kernel-4.9-lts-x86_64-all) \\ + $(shell $(ONLPM) --find-file onl-kernel-4.14-lts-x86-64-all:amd64 kernel-4.14-lts-x86_64-all) + + +# Loader initrd +INITRD := $(shell $(ONLPM) --find-file %(prefix)s-loader-initrd:amd64 %(prefix)s-loader-initrd-amd64.cpio.gz) +MANIFEST := $(shell $(ONLPM) --find-file %(prefix)s-loader-initrd:amd64 manifest.json) + +all: +\tmkdir -p files +\tcp $(KERNELS) files +\tcp $(INITRD) files +\tcp $(MANIFEST) files + +""" + +class setup(CommonFile): + path='setup.env' + template=""" +#!/bin/bash +############################################################ +# +# The settings in this script are required +# and should be sourced into your local build shell. +# +############################################################ + +# The root of the %(PREFIX)s build tree is here +export %(PREFIX)s=$( cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd) + +# The root of the ONL tree is here +export ONL=%(TOP)s/sm/ONL + +# Checkout ONL if necessary +if [ ! -f $ONL/LICENSE ]; then + git submodule update --init sm/ONL + # Versions and setup. + (cd sm/ONL && . setup.env) +fi + +# All package directories. +export ONLPM_OPTION_PACKAGEDIRS="$ONL/packages:$ONL/builds:%(TOP)s/packages:%(TOP)s/builds" + +# Repo directory. +export ONLPM_OPTION_REPO="%(TOP)s/REPO" + +# RELEASE directory. +export ONLPM_OPTION_RELEASE_DIR="%(TOP)s/RELEASE" + +# The ONL build tools should be included in the local path: +export PATH="$ONL/tools/scripts:$ONL/tools:$PATH" + +# Parallel Make Jobs +# Default parallel build settings +export ONL_MAKE_PARALLEL=-j16 + +# Export the current debian suite +export ONL_DEBIAN_SUITE=$(lsb_release -c -s) + +export BUILDER_MODULE_DATABASE_ROOT=%(TOP)s + +# Version files +$ONL/tools/make-versions.py --force --import-file=%(TOP)s/tools/%(prefix)svi --class-name=OnlVersionImplementation --output-dir %(TOP)s/make/versions +( . %(TOP)s/make/versions/version-%(prefix)s.sh && echo BuildID is $FNAME_BUILD_ID ) + +# Enable local post-merge githook +if [ ! -f %(TOP)s/.git/hooks/post-merge ]; then + cp $ONL/tools/scripts/post-merge.hook %(TOP)s/.git/hooks/post-merge +fi + +export ONL_SUBMODULE_UPDATED_SCRIPTS="%(TOP)s/tools/scripts/submodule-updated.sh:$ONL/tools/scripts/submodule-updated.sh" + +# Update %(PREFIX)s REPO from ONL build-artifacts +cp -R $ONL/sm/build-artifacts/REPO/* %(TOP)s/REPO + + + +""" + +class builds_any_rootfs_APKG(CommonFile): + template=""" +variables: + !include %(TOP)s/make/versions/version-%(prefix)s.yml + +prerequisites: + broken: true + +packages: + - name: %(prefix)s-rootfs + summary: %(name)s Root Filesystem + arch: $ARCH + version: 0.$FNAME_RELEASE_ID + %(COMMON_NV)s + + files: + builds/rootfs-$ARCH.cpio.gz : $$PKG_INSTALL/ + builds/rootfs-$ARCH.sqsh : $$PKG_INSTALL/ + builds/manifest.json : $$PKG_INSTALL/ + +""" + +class packages_base_any_fit_loader_builds_Makefile(CommonFile): + template=""" +ifndef ARCH +$(error $$ARCH must be set) +endif + +.PHONY: %(prefix)s-loader-fit.itb %(prefix)s-loader-fit.its + +%(prefix)s-loader-fit.itb: +\t$(ONL)/tools/flat-image-tree.py --initrd %(prefix)s-loader-initrd:$(ARCH),%(prefix)s-loader-initrd-$(ARCH).cpio.gz --arch $(ARCH) --add-platform initrd --itb $@ +\t$(ONLPM) --copy-file %(prefix)s-loader-initrd:$(ARCH) manifest.json . + +%(prefix)s-loader-fit.its: + $(ONL)/tools/flat-image-tree.py --initrd %(prefix)s-loader-initrd:$(ARCH),%(prefix)s-loader-initrd-$(ARCH).cpio.gz --arch $(ARCH) --add-platform initrd --its $@ + +its: %(prefix)s-loader-fit.itspass +""" + + +class packages_base_any_fit_loader_APKG(CommonFile): + template=""" +prerequisites: + packages: + - %(prefix)s-loader-initrd:$ARCH + +packages: + - name: %(prefix)s-loader-fit + arch: $ARCH + %(COMMON)s + summary: %(name)s FIT Loader Image for $ARCH + + files: + builds/%(prefix)s-loader-fit.itb : /etc/%(prefix)s/upgrade/$ARCH/ + builds/manifest.json : /etc/%(prefix)s/upgrade/$ARCH/ + + +""" + +class packages_base_arch_fit_Makefile(ArchFileUboot,OnlPkgMakefile): + pass + +class packages_base_arch_fit_loader_PKG(ArchFileUboot): + template=""" +!include %(TOP)s/packages/base/any/fit/loader/APKG.yml ARCH=%(arch)s +""" + +class packages_base_arch_fit_loader_builds_gitignore(ArchFileUboot): + template=""" +kernel-* +*.itb +*.its +loader-initrd-powerpc +manifest.json +""" + +class packages_base_arch_fit_loader_builds_Makefile(ArchFileUboot): + template=""" +include %(MTOP)s/make/config.%(arch)s.mk +include %(MTOP)s/packages/base/any/fit/loader/builds/Makefile +""" + +class packages_base_arch_fit_loader_Makefile(ArchFileUboot,OnlPkgMakefile): + pass + +class builds_gitignore(CommonFile): + template=""" +*.swi +*.md5sum +""" + +class builds_arch_Makefile(ArchFile): + template=""" +include $(ONL)/make/arch-build.mk +""" + +class builds_arch_installer_Makefile(ArchFile,OnlPkgMakefile): + pass + +class builds_arch_installer_installed_Makefile(ArchFile,OnlPkgMakefile): + pass + + +class builds_arch_installer_installed_PKG(ArchFile): + template=""" +!include %(TOP)s/builds/any/installer/APKG.yml ARCH=%(arch)s BOOTMODE=installed +""" + +class builds_arch_installer_installed_builds_gitignore(ArchFile): + template="""*INSTALLER""" + +class builds_arch_installer_installed_builds_Makefile(ArchFile): + template=""" +BOOTMODE=INSTALLED +include %(MTOP)s/make/config.%(arch)s.mk +include %(MTOP)s/builds/any/installer/builds/Makefile +""" + +class builds_arch_installer_installed_builds_bootconfig(ArchFile): + template=""" +NETDEV=ma1 +BOOTMODE=INSTALLED +SWI=images::latest +""" + +class builds_arch_installer_swi_Makefile(ArchFile,OnlPkgMakefile): + pass + +class builds_arch_installer_swi_PKG(ArchFile): + template=""" +!include %(TOP)s/builds/any/installer/APKG.yml ARCH=%(arch)s BOOTMODE=swi +""" + +class builds_arch_installer_swi_builds_gitignore(ArchFile): + template="""*INSTALLER""" + +class builds_arch_installer_swi_builds_Makefile(ArchFile): + template=""" +BOOTMODE=SWI +include %(MTOP)s/make/config.%(arch)s.mk +include %(MTOP)s/builds/any/installer/builds/Makefile +""" + + +class builds_arch_installer_swi_builds_bootconfig(ArchFile): + template=""" +NETDEV=ma1 +BOOTMODE=SWI +SWI=images::latest +""" + +class builds_arch_rootfs_gitignore(ArchFile): + template="""*.d/""" + +class builds_arch_rootfs_Makefile(ArchFile,OnlPkgMakefile): + pass + +class builds_arch_rootfs_PKG(ArchFile): + template=""" +!include %(TOP)s/builds/any/rootfs/APKG.yml ARCH=%(arch)s +""" + +class builds_arch_rootfs_builds_gitignore(ArchFile): + template="""manifest.json""" + +class builds_arch_rootfs_builds_Makefile(ArchFile): + template=""" +include %(MTOP)s/make/config.%(arch)s.mk + +export PLATFORM_LIST=$(shell onlpm --list-platforms --arch %(arch)s --csv ) + +RFS_CONFIG := %(MTOP)s/builds/any/rootfs/rfs.yml +RFS_DIR := rootfs-%(arch)s.d +RFS_CPIO := rootfs-%(arch)s.cpio.gz +RFS_SQUASH := rootfs-%(arch)s.sqsh +RFS_MANIFEST := /etc/%(prefix)s/rootfs/manifest.json + +include $(ONL)/make/rfs.mk +""" + +class builds_arch_swi_Makefile(ArchFile,OnlPkgMakefile): + pass + +class builds_arch_swi_PKG(ArchFile): + template=""" +!include %(TOP)s/builds/any/swi/APKG.yml ARCH=%(arch)s +""" + +class builds_arch_swi_builds_gitignore(ArchFile): + template="""manifest.json""" + +class builds_arch_swi_builds_Makefile(ArchFile): + template=""" +ROOTFS_PACKAGE := %(prefix)s-rootfs +include %(MTOP)s/make/config.%(arch)s.mk +include $(ONL)/make/swi.mk +""" + +class builds_any_installer_gitignore(CommonFile): + template="installer.sh.in" + +class builds_any_installer_APKG(CommonFile): + template=""" +variables: + !include %(TOP)s/make/versions/version-%(prefix)s.yml + +prerequisites: + broken: true + packages: [ "%(prefix)s-swi:$ARCH" ] + +packages: + - name: %(prefix)s-installer-$BOOTMODE + summary: %(name)s $ARCH Installer + arch: $ARCH + version: 0.$FNAME_RELEASE_ID + %(COMMON_NV)s + + files: + builds/*INSTALLER : $$PKG_INSTALL/ + builds/*.md5sum : $$PKG_INSTALL/ + + +release: + - builds/*INSTALLER : $ARCH/ + - builds/*.md5sum : $ARCH/ +""" + +class builds_any_installer_builds_Makefile(CommonFile): + template=""" +ifndef ARCH +$(error $$ARCH not set) +endif + +ifndef BOOTMODE +$(error $$BOOTMODE not set) +endif + +# Hardcoded to match ONL File naming conventions. +include %(MTOP)s/make/versions/version-%(prefix)s.mk +INSTALLER_NAME=$(FNAME_PRODUCT_VERSION)_ONL-OS_$(FNAME_BUILD_ID)_$(UARCH)_$(BOOTMODE)_INSTALLER + +MKINSTALLER_OPTS := \ + --arch $(ARCH) \ + --boot-config boot-config \ + --swi %(prefix)s-swi:$(ARCH) + + +ifeq ($(ARCH_BOOT),uboot) + MKINSTALLER_OPTS += --fit %(prefix)s-loader-fit:$(ARCH) %(prefix)s-loader-fit.itb +else ifeq ($(ARCH_BOOT),grub) + MKINSTALLER_OPTS += --initrd %(prefix)s-loader-initrd:$(ARCH) %(prefix)s-loader-initrd-$(ARCH).cpio.gz +else + $(error ARCH_BOOT=$(ARCH_BOOT) not recognized.) +endif + +__installer: +\t$(ONL)/tools/mkinstaller.py $(MKINSTALLER_OPTS) --out $(INSTALLER_NAME) +\tmd5sum "$(INSTALLER_NAME)" | awk '{ print $$1 }' > "$(INSTALLER_NAME).md5sum" +""" + + +class builds_any_rootfs_APKG(CommonFile): + template=""" +variables: + !include %(TOP)s/make/versions/version-%(prefix)s.yml + +prerequisites: + broken: true + +packages: + - name: %(prefix)s-rootfs + summary: %(name)s Root Filesystem + arch: $ARCH + version: 0.$FNAME_RELEASE_ID + %(COMMON_NV)s + + files: + builds/rootfs-$ARCH.cpio.gz : $$PKG_INSTALL/ + builds/rootfs-$ARCH.sqsh : $$PKG_INSTALL/ + builds/manifest.json : $$PKG_INSTALL/ +""" + + + +class builds_any_swi_APKG(CommonFile): + template=""" +variables: + !include %(TOP)s/make/versions/version-%(prefix)s.yml + +prerequisites: + broken: true + packages: [ "%(prefix)s-rootfs:$ARCH" ] + +packages: + - name: %(prefix)s-swi + summary: %(name)s Switch Image (All $ARCH) Platforms) + arch: $ARCH + version: 0.$FNAME_RELEASE_ID + %(COMMON_NV)s + + files: + builds/*.swi : $$PKG_INSTALL/ + builds/*.md5sum : $$PKG_INSTALL/ + builds/manifest.json : $$PKG_INSTALL/ + +release: + - builds/*.swi : $ARCH/ + - builds/*.md5sum : $ARCH/ + +""" + +class builds_any_rootfs_all_packages(CommonFile): + path='builds/any/rootfs/all-packages.yml' + template=""" +- %(prefix)s-sysconfig +- %(prefix)s-hw +""" + + +class builds_any_rootfs_archgrub_packages(ArchFileGrub): + path="builds/any/rootfs/%(arch)s-packages.yml" + template=""" +- %(prefix)s-upgrade +""" + +class builds_any_rootfs_archuboot_packages(ArchFileUboot): + path="builds/any/rootfs/%(arch)s-packages.yml" + template=""" +- %(prefix)s-loader-fit +""" + +class builds_any_rootfs_rfs(CommonFile): + path="builds/any/rootfs/rfs.yml" + template=""" +variables: + !include %(TOP)s/make/versions/version-%(prefix)s.yml + +Packages: &Packages + - !include $ONL/builds/any/rootfs/$ONL_DEBIAN_SUITE/common/all-base-packages.yml + - !include $ONL/builds/any/rootfs/$ONL_DEBIAN_SUITE/common/${ARCH}-base-packages.yml + - !include $ONL/builds/any/rootfs/$ONL_DEBIAN_SUITE/common/${ARCH}-onl-packages.yml + - !script $ONL/tools/onl-platform-pkgs.py ${PLATFORM_LIST} + - !include %(TOP)s/builds/any/rootfs/all-packages.yml + - !include %(TOP)s/builds/any/rootfs/${ARCH}-packages.yml + +Multistrap: + General: + arch: ${ARCH} + cleanup: true + noauth: true + explicitsuite: false + unpack: true + debootstrap: Debian-Local Local-All Local-Arch ONL-Local + aptsources: Debian ONL + + Debian: + packages: *Packages + source: http://${DEBIAN_MIRROR} + suite: ${ONL_DEBIAN_SUITE} + keyring: debian-archive-keyring + omitdebsrc: true + + Debian-Local: + packages: *Packages + source: http://${APT_CACHE}${DEBIAN_MIRROR} + suite: ${ONL_DEBIAN_SUITE} + keyring: debian-archive-keyring + omitdebsrc: true + + ONL: + packages: *Packages + source: http://apt.opennetlinux.org/debian + suite: unstable + omitdebsrc: true + + ONL-Local: + packages: *Packages + source: http://${APT_CACHE}apt.opennetlinux.org/debian + suite: unstable + omitdebsrc: true + + Local-All: + source: ${ONLPM_OPTION_REPO}/${ONL_DEBIAN_SUITE}/packages/binary-all + omitdebsrc: true + + Local-Arch: + source: ${ONLPM_OPTION_REPO}/${ONL_DEBIAN_SUITE}/packages/binary-${ARCH} + omitdebsrc: true + +Configure: + overlays: + - $ONL/builds/any/rootfs/${ONL_DEBIAN_SUITE}/common/overlay + + update-rc.d: + - 'faultd defaults' + - 'onlpd defaults' + - 'snmpd defaults' + - 'onlp-snmpd defaults' + - 'ssh defaults' + - 'openbsd-inetd remove' + - 'ntp remove' + - 'nfs-common remove' + - 'rpcbind remove' + - 'motd remove' + - 'mountall-bootclean.sh remove' + - 'mountall.sh remove' + - 'checkfs.sh remove' + - 'mtab.sh remove' + - 'checkroot-bootclean.sh remove' + - 'checkroot.sh remove' + - 'mountnfs-bootclean.sh remove' + - 'mountnfs.sh remove' + - 'lm-sensors remove' + - 'netplug defaults' + - 'watchdog defaults' + - 'wd_keepalive remove' + + options: + clean: True + securetty: False + ttys: False + console: True + PermitRootLogin: 'yes' + + users: + root: + password: %(prefix)s + + manifests: + '/etc/onl/rootfs/manifest.json' : + version : $ONL/make/versions/version-onl.json + platforms : $PLATFORM_LIST + + '/etc/%(prefix)s/rootfs/manifest.json' : + version : %(TOP)s/make/versions/version-%(prefix)s.json + platforms : $PLATFORM_LIST + keys: + version : + CONFIGURATION: RELEASE + + issue: $VERSION_STRING + + files: + remove: + - /etc/motd +""" + +ALL_FILE_CLASSES = [ klass for klass in inspect.getmembers(sys.modules[__name__], inspect.isclass) if issubclass(klass[1], NOSFile) and klass[1].is_file() ] +ALL_COMMON_CLASSES = [ klass for klass in ALL_FILE_CLASSES if issubclass(klass[1], CommonFile) ] +ALL_ARCH_CLASSES = [ klass for klass in ALL_FILE_CLASSES if issubclass(klass[1], ArchFile) ] + + +if __name__ == '__main__': + + ops = ap.parse_args() + variables = {} + variables.update(vars(ops)) + variables['PREFIX'] = variables['prefix'].upper() + + # Create all required common and arch objects + OBJECTS = [] + for klass in ALL_COMMON_CLASSES: + OBJECTS.append(klass[1](ops.root, variables.copy())) + + for arch in ops.arches: + for klass in ALL_ARCH_CLASSES: + if arch in klass[1].arches: + OBJECTS.append(klass[1](ops.root, variables.copy(), arch)) + + + for distro in ops.debian: + OBJECTS.append(NOSFile(ops.root, variables.copy(), + path='REPO/%s/Makefile' % distro, + template='include $(ONL)/make/repo-suite.mk')) + + OBJECTS.append(NOSFile(ops.root, variables.copy(), + path='REPO/%s/packages/binary-all/Makefile' % distro, + template='include $(ONL)/make/repo.mk')) + for arch in ops.arches: + OBJECTS.append(NOSFile(ops.root, variables.copy(), + path='REPO/%s/packages/binary-%s/Makefile' % (distro, arch), + template="include $(ONL)/make/repo.mk")) + + + + OBJECTS = sorted(OBJECTS,key=lambda entry: entry.epath) + + for obj in OBJECTS: + if ops.list_files: + print "%-60s" % (obj.epath) + if ops.write_files: + obj.write(overwrite=ops.overwrite, dry=ops.dry) diff --git a/tools/onlpm.py b/tools/onlpm.py index 6faa6e2c..3d89e6d9 100755 --- a/tools/onlpm.py +++ b/tools/onlpm.py @@ -301,8 +301,11 @@ class OnlPackage(object): # if dst.endswith('/'): dstpath = os.path.join(root, dst) - if not os.path.exists(dstpath): + try: os.makedirs(dstpath) + except OSError, e: + if e.errno != os.errno.EEXIST: + raise shutil.copy(src, dstpath) else: dstpath = os.path.join(root, os.path.dirname(dst))