mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 09:17:08 +00:00
Merge branch 'master' into K4.14
This commit is contained in:
2
Makefile
2
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
1146
packages/base/any/kernels/modules/optoe.c
Normal file
1146
packages/base/any/kernels/modules/optoe.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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", \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,508 +0,0 @@
|
||||
/*
|
||||
* An hwmon driver for accton as5812_54x sfp
|
||||
*
|
||||
* Copyright (C) 2015 Accton Technology Corporation.
|
||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||
*
|
||||
* Based on ad7414.c
|
||||
* Copyright 2006 Stefan Roese <sr at denx.de>, 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 <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#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 <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("accton as5812_54x_sfp driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
File diff suppressed because it is too large
Load Diff
3
packages/platforms/accton/x86-64/x86-64-accton-csp9250/.gitignore
vendored
Executable file
3
packages/platforms/accton/x86-64/x86-64-accton-csp9250/.gitignore
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
*x86*64*accton*as7312*54x*.mk
|
||||
onlpdump.mk
|
||||
|
||||
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/Makefile
Executable file
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/Makefile
Executable file
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/Makefile
Executable file
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/Makefile
Executable file
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml
Executable file
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml
Executable file
@@ -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"
|
||||
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/.gitignore
vendored
Executable file
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
lib
|
||||
@@ -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
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* A hwmon driver for the accton_i2c_cpld
|
||||
*
|
||||
* Copyright (C) 2014 Accton Technology Corporation.
|
||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||
*
|
||||
* Based on ad7414.c
|
||||
* Copyright 2006 Stefan Roese <sr at denx.de>, 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 <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
|
||||
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 <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("accton_i2c_cpld driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(accton_i2c_cpld_init);
|
||||
module_exit(accton_i2c_cpld_exit);
|
||||
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
* A hwmon driver for the Accton as7312 54x fan
|
||||
*
|
||||
* Copyright (C) 2014 Accton Technology Corporation.
|
||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||
*
|
||||
* This program is free software; you can 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 <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#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 <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("csp9250_fan driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* A LED driver for the accton_csp9250_led
|
||||
*
|
||||
* Copyright (C) 2014 Accton Technology Corporation.
|
||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||
*
|
||||
* This program is free software; you can 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 <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
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<<LED_TYPE_LOC) | (1<<LED_TYPE_DIAG), 0x41},
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
struct led_type_mode {
|
||||
enum led_type type;
|
||||
enum led_light_mode mode;
|
||||
int reg_bit_mask;
|
||||
int mode_value;
|
||||
};
|
||||
|
||||
static struct led_type_mode led_type_mode_data[] = {
|
||||
{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
|
||||
{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ON_VALUE},
|
||||
{LED_TYPE_FAN, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
|
||||
{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
|
||||
{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_RED_VALUE},
|
||||
{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE},
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void accton_csp9250_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness led_light_mode, enum led_type type);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int accton_getLedReg(enum led_type type, u8 *reg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(led_reg_map); i++) {
|
||||
if(led_reg_map[i].types & (type<<1)) {
|
||||
*reg = led_reg_map[i].reg_addr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
|
||||
|
||||
if (type != led_type_mode_data[i].type)
|
||||
continue;
|
||||
|
||||
if ((led_type_mode_data[i].reg_bit_mask & reg_val) ==
|
||||
led_type_mode_data[i].mode_value)
|
||||
{
|
||||
return led_type_mode_data[i].mode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 led_light_mode_to_reg_val(enum led_type type,
|
||||
enum led_light_mode mode, u8 reg_val) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
|
||||
if (type != led_type_mode_data[i].type)
|
||||
continue;
|
||||
|
||||
if (mode != led_type_mode_data[i].mode)
|
||||
continue;
|
||||
|
||||
reg_val = led_type_mode_data[i].mode_value |
|
||||
(reg_val & (~led_type_mode_data[i].reg_bit_mask));
|
||||
break;
|
||||
}
|
||||
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
static int accton_csp9250_led_read_value(u8 reg)
|
||||
{
|
||||
return csp9250_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
|
||||
}
|
||||
|
||||
static int accton_csp9250_led_write_value(u8 reg, u8 value)
|
||||
{
|
||||
return csp9250_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
|
||||
}
|
||||
|
||||
static void accton_csp9250_led_update(void)
|
||||
{
|
||||
mutex_lock(&ledctl->update_lock);
|
||||
|
||||
if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
|
||||
|| !ledctl->valid) {
|
||||
int i;
|
||||
|
||||
dev_dbg(&ledctl->pdev->dev, "Starting accton_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 <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("accton_csp9250_led driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* An hwmon driver for accton csp9250 Power Module
|
||||
*
|
||||
* Copyright (C) 2014 Accton Technology Corporation.
|
||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||
*
|
||||
* Based on ad7414.c
|
||||
* Copyright 2006 Stefan Roese <sr at denx.de>, 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 <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
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 <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("csp9250_psu driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/Makefile
Executable file
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/Makefile
Executable file
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/PKG.yml
Executable file
1
packages/platforms/accton/x86-64/x86-64-accton-csp9250/onlp/PKG.yml
Executable file
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-csp9250 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu
|
||||
@@ -0,0 +1,2 @@
|
||||
FILTER=src
|
||||
include $(ONL)/make/subdirs.mk
|
||||
@@ -0,0 +1,45 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2014 v=onl>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
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
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2014 v=onl>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
name: x86_64_accton_csp9250
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
include ../../init.mk
|
||||
MODULE := x86_64_accton_csp9250
|
||||
AUTOMODULE := x86_64_accton_csp9250
|
||||
include $(BUILDER)/definemodule.mk
|
||||
@@ -0,0 +1,6 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_accton_csp9250 README
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,14 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
/* <--auto.start.xmacro(ALL).define> */
|
||||
/* <auto.end.xmacro(ALL).define> */
|
||||
|
||||
/* <--auto.start.xenum(ALL).define> */
|
||||
/* <auto.end.xenum(ALL).define> */
|
||||
|
||||
|
||||
@@ -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 <global_custom_config.h>
|
||||
#endif
|
||||
#ifdef x86_64_accton_csp9250_INCLUDE_CUSTOM_CONFIG
|
||||
#include <x86_64_accton_csp9250_custom_config.h>
|
||||
#endif
|
||||
|
||||
/* <auto.start.cdefs(x86_64_accton_csp9250_CONFIG_HEADER).header> */
|
||||
#include <AIM/aim.h>
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/* <auto.end.cdefs(x86_64_accton_csp9250_CONFIG_HEADER).header> */
|
||||
|
||||
#include "x86_64_accton_csp9250_porting.h"
|
||||
|
||||
#endif /* __x86_64_accton_csp9250_CONFIG_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__ */
|
||||
@@ -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__
|
||||
|
||||
|
||||
/* <auto.start.portingmacro(ALL).define> */
|
||||
#if x86_64_accton_csp9250_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <memory.h>
|
||||
#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
|
||||
|
||||
/* <auto.end.portingmacro(ALL).define> */
|
||||
|
||||
|
||||
#endif /* __x86_64_accton_csp9250_PORTING_H__ */
|
||||
/* @} */
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Local source generation targets.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
ucli:
|
||||
@../../../../tools/uclihandlers.py x86_64_accton_csp9250.c
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "x86_64_accton_csp9250_int.h"
|
||||
|
||||
#if x86_64_accton_csp9250_CONFIG_INCLUDE_DEBUG == 1
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
* Fan Platform Implementation Defaults.
|
||||
*
|
||||
***********************************************************/
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <onlp/platformi/fani.h>
|
||||
#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<FAN_LEAVE_NUM; i++)
|
||||
{
|
||||
tag=fan_sensor_table[fid].tag[i];
|
||||
snprintf(cmd , (FAN_MAX_LENGTH/2)-1, "cat %s |grep %s > %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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/ledi.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <onlplib/mmap.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
LIBRARY := x86_64_accton_csp9250
|
||||
$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
include $(BUILDER)/lib.mk
|
||||
@@ -0,0 +1,176 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "platform_lib.h"
|
||||
#include <onlp/platformi/sfpi.h>
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#ifndef __PLATFORM_LIB_H__
|
||||
#define __PLATFORM_LIB_H__
|
||||
|
||||
#include <onlplib/file.h>
|
||||
#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__ */
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/psui.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#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<PSU_INFO_MAX;i++)
|
||||
{
|
||||
system(PSU_IPMI_TMP_FILE_ONE_ENTRY_RM);
|
||||
memset(psu_val_str, 0x0, sizeof(psu_val_str));
|
||||
|
||||
tag=psu_sensor_table[index-1].psu_dev_info_table[i].tag;
|
||||
find=psu_sensor_table[index-1].psu_dev_info_table[i].find;
|
||||
snprintf(cmd , (PSU_MAX_LENGTH/2)-1, "cat %s|grep %s > %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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/sfpi.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,676 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <onlp/platformi/sysi.h>
|
||||
#include <onlp/platformi/ledi.h>
|
||||
#include <onlp/platformi/thermali.h>
|
||||
#include <onlp/platformi/fani.h>
|
||||
#include <onlp/platformi/psui.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
* Thermal Sensor Platform Implementation.
|
||||
*
|
||||
***********************************************************/
|
||||
//#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlp/platformi/thermali.h>
|
||||
#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<sizeof(thermal_sensor_table)/sizeof(onlp_thermal_dev_t) ; i++)
|
||||
{
|
||||
if(thermal_sensor_table[i].thermal_id == id)
|
||||
return thermal_sensor_table[i].ipmi_cmd;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *onlp_find_thermal_sensor_tag(unsigned int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<sizeof(thermal_sensor_table)/sizeof(onlp_thermal_dev_t) ; i++)
|
||||
{
|
||||
if(thermal_sensor_table[i].thermal_id == id)
|
||||
return thermal_sensor_table[i].tag;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char* directory[] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
NULL,
|
||||
NULL, /* CPU_CORE files */
|
||||
"3-0048",
|
||||
"3-0049",
|
||||
"3-004a",
|
||||
"3-004b",
|
||||
"11-0059",
|
||||
"10-0058",
|
||||
};
|
||||
#endif
|
||||
|
||||
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_SWITCH_BOARD), "Temp_LM75_Power", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_SWITCH_BOARD), "Temp_LM75_LEFT", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_SWITCH_BOARD), " Temp_LM75_HS", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_SERVER_BOARD), "Temp_LM75_CPU0", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_SERVER_BOARD), "Temp_LM75_CPU1", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_SERVER_BOARD), "Temp_LM75_PCH", 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)
|
||||
{
|
||||
char cmd[THERMAL_MAX_LENGTH/2] = {0};
|
||||
snprintf(cmd, (THERMAL_MAX_LENGTH/2) -1, "echo 0 > %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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
/* <auto.start.cdefs(x86_64_accton_csp9250_CONFIG_HEADER).source> */
|
||||
#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;
|
||||
}
|
||||
|
||||
/* <auto.end.cdefs(x86_64_accton_csp9250_CONFIG_HEADER).source> */
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
/* <--auto.start.enum(ALL).source> */
|
||||
/* <auto.end.enum(ALL).source> */
|
||||
|
||||
@@ -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 <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
|
||||
#endif /* __x86_64_accton_csp9250_INT_H__ */
|
||||
@@ -0,0 +1,18 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
#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
|
||||
);
|
||||
|
||||
@@ -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 <AIM/aim_log.h>
|
||||
|
||||
#endif /* __x86_64_accton_csp9250_LOG_H__ */
|
||||
@@ -0,0 +1,24 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
#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 <x86_64_accton_csp9250/x86_64_accton_csp9250.x>
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __x86_64_accton_csp9250_module_init__(void)
|
||||
{
|
||||
AIM_LOG_STRUCT_REGISTER();
|
||||
datatypes_init__();
|
||||
}
|
||||
|
||||
int __onlp_platform_version__ = 1;
|
||||
@@ -0,0 +1,50 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_accton_csp9250/x86_64_accton_csp9250_config.h>
|
||||
|
||||
#if x86_64_accton_csp9250_CONFIG_INCLUDE_UCLI == 1
|
||||
|
||||
#include <uCli/ucli.h>
|
||||
#include <uCli/ucli_argparse.h>
|
||||
#include <uCli/ucli_handler_macros.h>
|
||||
|
||||
static ucli_status_t
|
||||
x86_64_accton_csp9250_ucli_ucli__config__(ucli_context_t* uc)
|
||||
{
|
||||
UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_csp9250)
|
||||
}
|
||||
|
||||
/* <auto.ucli.handlers.start> */
|
||||
/* <auto.ucli.handlers.end> */
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-csp9250 REVISION=r0
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
3
packages/platforms/delta/x86-64/x86-64-delta-ak7448/.gitignore
vendored
Normal file
3
packages/platforms/delta/x86-64/x86-64-delta-ak7448/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*x86*64*delta_agc7648a*.mk
|
||||
onlpdump.mk
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -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"
|
||||
1
packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/.gitignore
vendored
Normal file
1
packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lib
|
||||
@@ -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
|
||||
@@ -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 <aries.lin@deltaww.com>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#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 <aries.lin@deltaww.com>");
|
||||
MODULE_DESCRIPTION("DPS_800AB_16_D Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(dps_800ab_16_d_init);
|
||||
module_exit(dps_800ab_16_d_exit);
|
||||
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* An hwmon driver for agema ak7448 qsfp
|
||||
*
|
||||
* Copyright (C) 2017 Delta Networks, Inc.
|
||||
*
|
||||
* DNI <DNIsales@delta.com.tw>
|
||||
*
|
||||
* 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 <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
|
||||
#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 <aries.lin@deltaww.com>");
|
||||
MODULE_DESCRIPTION("ak7448 SFP Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(ak7448_sfp_init);
|
||||
module_exit(ak7448_sfp_exit);
|
||||
372
packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_emc2305.c
Executable file
372
packages/platforms/delta/x86-64/x86-64-delta-ak7448/modules/builds/dni_emc2305.c
Executable file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* <bsn.cl fy=2013 v=gpl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* </bsn.cl>
|
||||
*
|
||||
*
|
||||
* 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 <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
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<neal.tai@deltaww.com>");
|
||||
MODULE_DESCRIPTION("SMSC EMC2305 fan controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-delta-ak7448 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu
|
||||
@@ -0,0 +1,2 @@
|
||||
FILTER=src
|
||||
include $(ONL)/make/subdirs.mk
|
||||
@@ -0,0 +1,45 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2014 v=onl>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
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
|
||||
|
||||
@@ -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))))
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2014 v=onl>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
name: x86_64_delta_ak7448
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
include ../../init.mk
|
||||
MODULE := x86_64_delta_ak7448
|
||||
AUTOMODULE := x86_64_delta_ak7448
|
||||
include $(BUILDER)/definemodule.mk
|
||||
@@ -0,0 +1,6 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_delta_ak7448 README
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,14 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_delta_ak7448/x86_64_delta_ak7448_config.h>
|
||||
|
||||
/* <--auto.start.xmacro(ALL).define> */
|
||||
/* <auto.end.xmacro(ALL).define> */
|
||||
|
||||
/* <--auto.start.xenum(ALL).define> */
|
||||
/* <auto.end.xenum(ALL).define> */
|
||||
|
||||
|
||||
@@ -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 <global_custom_config.h>
|
||||
#endif
|
||||
#ifdef x86_64_delta_ak7448_INCLUDE_CUSTOM_CONFIG
|
||||
#include <x86_64_delta_ak7448_custom_config.h>
|
||||
#endif
|
||||
|
||||
/* <auto.start.cdefs(X86_64_DELTA_AK7448_CONFIGHEADER).header> */
|
||||
#include <AIM/aim.h>
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/* <auto.end.cdefs(X86_64_DELTA_AK7448_CONFIGHEADER).header> */
|
||||
|
||||
#include "x86_64_delta_ak7448_porting.h"
|
||||
|
||||
#endif /* __X86_64_DELTA_AK7448_CONFIGH__ */
|
||||
/* @} */
|
||||
@@ -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__ */
|
||||
@@ -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__
|
||||
|
||||
|
||||
/* <auto.start.portingmacro(ALL).define> */
|
||||
#if X86_64_DELTA_AK7448_CONFIGPORTING_INCLUDE_STDLIB_HEADERS == 1
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <memory.h>
|
||||
#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
|
||||
|
||||
/* <auto.end.portingmacro(ALL).define> */
|
||||
|
||||
|
||||
#endif /* __x86_64_delta_ak7448_PORTING_H__ */
|
||||
/* @} */
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Local source generation targets.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
ucli:
|
||||
@../../../../tools/uclihandlers.py x86_64_delta_ak7448_ucli.c
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "x86_64_delta_ak7448_int.h"
|
||||
|
||||
#if X86_64_DELTA_AK7448_CONFIG_INCLUDE_DEBUG == 1
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
* Fan Platform Implementation Defaults.
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/fani.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <fcntl.h>
|
||||
#include "platform_lib.h"
|
||||
#include <onlplib/i2c.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user