From a582c13e98a58251899e13f7c86608cfed3bf581 Mon Sep 17 00:00:00 2001 From: "ruijie.com.cn" Date: Thu, 25 Feb 2021 08:45:27 +0800 Subject: [PATCH] [Ruijie] Add ruijie platform & device (#4954) Add new platform x86_64-ruijie_b6510-48vs8cq-r0 (Trident 3) ASIC Vendor: Broadcom Switch ASIC: Trident 3 Port Config: 48x25G+8x100G Signed-off-by: tim-rj --- .../B6510-48VS8CQ/port_config.ini | 57 + .../B6510-48VS8CQ/sai.profile | 1 + ...td3-b6510-48vs8cq-48x25G+8x100G.config.bcm | 569 +++++ .../custom_led.bin | Bin 0 -> 300 bytes .../default_sku | 1 + .../x86_64-ruijie_b6510-48vs8cq-r0/dev.xml | 122 ++ .../installer.conf | 1 + .../led_proc_init.soc | 7 + .../x86_64-ruijie_b6510-48vs8cq-r0/monitor.py | 244 +++ .../x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml | 429 ++++ .../platform_env.conf | 0 .../plugins/eeprom.py | 12 + .../plugins/psuutil.py | 63 + .../plugins/sfputil.py | 359 ++++ .../pmon_daemon_control.json | 5 + .../sensors.conf | 21 + .../sonic_platform_config/chassis.json | 3 + .../sonic_platform_config/component.json | 60 + .../sonic_platform_config/fan.json | 152 ++ .../sonic_platform_config/psu.json | 134 ++ .../sonic_platform_config/thermal.json | 130 ++ .../x86_64-ruijie_b6510-48vs8cq-r0/systest.py | 43 + platform/broadcom/one-image.mk | 3 +- platform/broadcom/platform-modules-ruijie.dep | 8 + platform/broadcom/platform-modules-ruijie.mk | 10 + platform/broadcom/rules.mk | 1 + .../sonic-platform-modules-ruijie/LICENSE | 15 + .../b6510-48vs8cq/LICENSE | 15 + .../b6510-48vs8cq/MAINTAINERS | 6 + .../b6510-48vs8cq/Makefile | 22 + .../b6510-48vs8cq/README.md | 2 + .../x86_64_ruijie_b6510_48vs8cq_r0_config.py | 787 +++++++ .../b6510-48vs8cq/modules/driver/Makefile | 1 + .../b6510-48vs8cq/modules/driver/rg_cpld.c | 602 ++++++ .../scripts/b6510-48vs8cq_platform.sh | 27 + .../b6510-48vs8cq/setup.py | 34 + .../b6510-48vs8cq/sonic_pcie/__init__.py | 1 + .../b6510-48vs8cq/sonic_pcie/pcie_common.py | 107 + .../b6510-48vs8cq/sonic_platform/__init__.py | 1 + .../b6510-48vs8cq/sonic_platform/chassis.py | 448 ++++ .../b6510-48vs8cq/sonic_platform/common.py | 44 + .../b6510-48vs8cq/sonic_platform/component.py | 85 + .../b6510-48vs8cq/sonic_platform/config.py | 558 +++++ .../b6510-48vs8cq/sonic_platform/eeprom.py | 155 ++ .../b6510-48vs8cq/sonic_platform/fan.py | 289 +++ .../sonic_platform/fan_drawer.py | 71 + .../b6510-48vs8cq/sonic_platform/logger.py | 19 + .../b6510-48vs8cq/sonic_platform/pcie.py | 43 + .../b6510-48vs8cq/sonic_platform/platform.py | 22 + .../b6510-48vs8cq/sonic_platform/psu.py | 413 ++++ .../b6510-48vs8cq/sonic_platform/regutil.py | 245 +++ .../b6510-48vs8cq/sonic_platform/rotor.py | 41 + .../b6510-48vs8cq/sonic_platform/sfp.py | 1566 ++++++++++++++ .../b6510-48vs8cq/sonic_platform/thermal.py | 217 ++ .../b6510-48vs8cq/sonic_platform/watchdog.py | 70 + .../platform-modules-b6510-48vs8cq.service | 13 + .../common/Makefile | 37 + .../common/lib/eepromutil/__init__.py | 0 .../common/lib/eepromutil/fantlv.py | 212 ++ .../common/lib/eepromutil/fru.py | 954 +++++++++ .../common/lib/plat_hal/__init__.py | 1 + .../common/lib/plat_hal/osutil.py | 222 ++ .../common/lib/rjutil/__init__.py | 0 .../common/lib/rjutil/baseutil.py | 23 + .../common/lib/rjutil/smbus.py | 705 +++++++ .../common/modules/Makefile | 7 + .../common/modules/csu550.c | 209 ++ .../common/modules/i2c-mux-pca954x.c | 1763 ++++++++++++++++ .../common/modules/i2c-mux-pca9641.c | 645 ++++++ .../common/modules/pmbus.h | 424 ++++ .../common/modules/rg-gpio-xeon.c | 357 ++++ .../common/modules/rg_fan.c | 266 +++ .../common/modules/rg_psu.c | 340 +++ .../common/modules/ruijie_platform.c | 97 + .../common/script/avscontrol.py | 100 + .../common/script/device_i2c.py | 336 +++ .../common/script/fancontrol.py | 838 ++++++++ .../common/script/ruijiecommon.py | 717 +++++++ .../common/script/ruijieconfig.py | 186 ++ .../common/script/ruijieutil.py | 1828 +++++++++++++++++ .../common/service/device_i2c.service | 15 + .../debian/changelog | 5 + .../debian/compat | 1 + .../debian/control | 10 + .../debian/copyright | 16 + ...platform-modules-ruijie-b6510-48vs8cq.init | 39 + ...tform-modules-ruijie-b6510-48vs8cq.install | 3 + ...form-modules-ruijie-b6510-48vs8cq.postinst | 15 + .../debian/rules | 93 + 89 files changed, 18817 insertions(+), 1 deletion(-) create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/custom_led.bin create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/default_sku create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/dev.xml create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/platform_env.conf create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json create mode 100755 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json create mode 100644 device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py create mode 100644 platform/broadcom/platform-modules-ruijie.dep create mode 100644 platform/broadcom/platform-modules-ruijie.mk create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/LICENSE create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/debian/changelog create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/debian/compat create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/debian/control create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/debian/copyright create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init create mode 100644 platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst create mode 100755 platform/broadcom/sonic-platform-modules-ruijie/debian/rules diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini new file mode 100755 index 000000000..823f53160 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed admin_status +Ethernet1 1 twentyfiveGigE0/1 0 25000 up +Ethernet2 2 twentyfiveGigE0/2 1 25000 up +Ethernet3 3 twentyfiveGigE0/3 2 25000 up +Ethernet4 4 twentyfiveGigE0/4 3 25000 up +Ethernet5 5 twentyfiveGigE0/5 4 25000 up +Ethernet6 6 twentyfiveGigE0/6 5 25000 up +Ethernet7 7 twentyfiveGigE0/7 6 25000 up +Ethernet8 8 twentyfiveGigE0/8 7 25000 up +Ethernet9 13 twentyfiveGigE0/9 8 25000 up +Ethernet10 14 twentyfiveGigE0/10 9 25000 up +Ethernet11 15 twentyfiveGigE0/11 10 25000 up +Ethernet12 16 twentyfiveGigE0/12 11 25000 up +Ethernet13 21 twentyfiveGigE0/13 12 25000 up +Ethernet14 22 twentyfiveGigE0/14 13 25000 up +Ethernet15 23 twentyfiveGigE0/15 14 25000 up +Ethernet16 24 twentyfiveGigE0/16 15 25000 up +Ethernet17 29 twentyfiveGigE0/17 16 25000 up +Ethernet18 30 twentyfiveGigE0/18 17 25000 up +Ethernet19 31 twentyfiveGigE0/19 18 25000 up +Ethernet20 32 twentyfiveGigE0/20 19 25000 up +Ethernet21 33 twentyfiveGigE0/21 20 25000 up +Ethernet22 34 twentyfiveGigE0/22 21 25000 up +Ethernet23 35 twentyfiveGigE0/23 22 25000 up +Ethernet24 36 twentyfiveGigE0/24 23 25000 up +Ethernet25 41 twentyfiveGigE0/25 24 25000 up +Ethernet26 42 twentyfiveGigE0/26 25 25000 up +Ethernet27 43 twentyfiveGigE0/27 26 25000 up +Ethernet28 44 twentyfiveGigE0/28 27 25000 up +Ethernet29 49 twentyfiveGigE0/29 28 25000 up +Ethernet30 50 twentyfiveGigE0/30 29 25000 up +Ethernet31 51 twentyfiveGigE0/31 30 25000 up +Ethernet32 52 twentyfiveGigE0/32 31 25000 up +Ethernet33 57 twentyfiveGigE0/33 32 25000 up +Ethernet34 58 twentyfiveGigE0/34 33 25000 up +Ethernet35 59 twentyfiveGigE0/35 34 25000 up +Ethernet36 60 twentyfiveGigE0/36 35 25000 up +Ethernet37 61 twentyfiveGigE0/37 36 25000 up +Ethernet38 62 twentyfiveGigE0/38 37 25000 up +Ethernet39 63 twentyfiveGigE0/39 38 25000 up +Ethernet40 64 twentyfiveGigE0/40 39 25000 up +Ethernet41 65 twentyfiveGigE0/41 40 25000 up +Ethernet42 66 twentyfiveGigE0/42 41 25000 up +Ethernet43 67 twentyfiveGigE0/43 42 25000 up +Ethernet44 68 twentyfiveGigE0/44 43 25000 up +Ethernet45 69 twentyfiveGigE0/45 44 25000 up +Ethernet46 70 twentyfiveGigE0/46 45 25000 up +Ethernet47 71 twentyfiveGigE0/47 46 25000 up +Ethernet48 72 twentyfiveGigE0/48 47 25000 up +Ethernet49 85,86,87,88 hundredGigE0/1 48 100000 up +Ethernet50 77,78,79,80 hundredGigE0/2 49 100000 up +Ethernet51 97,98,99,100 hundredGigE0/3 50 100000 up +Ethernet52 93,94,95,96 hundredGigE0/4 51 100000 up +Ethernet53 113,114,115,116 hundredGigE0/5 52 100000 up +Ethernet54 105,106,107,108 hundredGigE0/6 53 100000 up +Ethernet55 121,122,123,124 hundredGigE0/7 54 100000 up +Ethernet56 125,126,127,128 hundredGigE0/8 55 100000 up diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile new file mode 100755 index 000000000..042c8060d --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm new file mode 100644 index 000000000..69fd8c362 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm @@ -0,0 +1,569 @@ +l2_mem_entries=32768 +l2xmsg_mode=0 +l3_max_ecmp_mode=1 +l3_mem_entries=49152 +l3_alpm_enable=0 +bcm_num_cos=8 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +core_clock_frequency=1525 +dpp_clock_ratio=2:3 +help_cli_enable=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +#lpm_scaling_enable=1 +max_vp_lags=0 +mem_cache_enable=0 +memlist_enable=1 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 +parity_enable=1 +pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 +#pbmp_xport_xe.0=0x00000000000000000000000000000000888ffffffffffff9fffffffffffffffe +pbmp_xport_xe=0x488080808808087f9fe1e1e1fe1e1e1fe +phy_chain_rx_lane_map_physical{1.0}=0x1032 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{5.0}=0x1032 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x0123 +phy_chain_rx_lane_map_physical{49.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x1032 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{61.0}=0x0123 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x1032 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x1032 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x2031 +phy_chain_tx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x1 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x1 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x1 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_rx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +port_flex_enable=1 +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_32=32:25 +portmap_33=33:25 +portmap_34=34:25 +portmap_35=35:25 +portmap_36=36:25 +portmap_41=41:25 +portmap_42=42:25 +portmap_43=43:25 +portmap_44=44:25 +portmap_49=49:25 +portmap_50=50:25 +portmap_51=51:25 +portmap_52=52:25 +portmap_57=57:25 +portmap_58=58:25 +portmap_59=59:25 +portmap_60=60:25 +portmap_61=61:25 +portmap_62=62:25 +portmap_63=63:25 +portmap_64=64:25 +portmap_67=65:25 +portmap_68=66:25 +portmap_69=67:25 +portmap_70=68:25 +portmap_71=69:25 +portmap_72=70:25 +portmap_73=71:25 +portmap_74=72:25 +portmap_79=77:100 +portmap_87=85:100 +portmap_95=93:100 +portmap_99=97:100 +portmap_107=105:100 +portmap_115=113:100 +portmap_123=121:100 +portmap_127=125:100 + +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_13=9 +dport_map_port_14=10 +dport_map_port_15=11 +dport_map_port_16=12 +dport_map_port_21=13 +dport_map_port_22=14 +dport_map_port_23=15 +dport_map_port_24=16 +dport_map_port_29=17 +dport_map_port_30=18 +dport_map_port_31=19 +dport_map_port_32=20 +dport_map_port_33=21 +dport_map_port_34=22 +dport_map_port_35=23 +dport_map_port_36=24 +dport_map_port_41=25 +dport_map_port_42=26 +dport_map_port_43=27 +dport_map_port_44=28 +dport_map_port_49=29 +dport_map_port_50=30 +dport_map_port_51=31 +dport_map_port_52=32 +dport_map_port_57=33 +dport_map_port_58=34 +dport_map_port_59=35 +dport_map_port_60=36 +dport_map_port_61=37 +dport_map_port_62=38 +dport_map_port_63=39 +dport_map_port_64=40 +dport_map_port_67=41 +dport_map_port_68=42 +dport_map_port_69=43 +dport_map_port_70=44 +dport_map_port_71=45 +dport_map_port_72=46 +dport_map_port_73=47 +dport_map_port_74=48 +dport_map_port_87=49 +dport_map_port_79=50 +dport_map_port_99=51 +dport_map_port_95=52 +dport_map_port_115=53 +dport_map_port_107=54 +dport_map_port_123=55 +dport_map_port_127=56 + +serdes_preemphasis_lane0_1=0x0f480d +serdes_preemphasis_lane1_1=0x0f480d +serdes_preemphasis_lane2_1=0x0f480d +serdes_preemphasis_lane3_1=0x0f480d +serdes_preemphasis_lane0_2=0x0f480d +serdes_preemphasis_lane1_2=0x0f480d +serdes_preemphasis_lane2_2=0x0f480d +serdes_preemphasis_lane3_2=0x0f480d +serdes_preemphasis_lane0_3=0x0f480d +serdes_preemphasis_lane1_3=0x0f480d +serdes_preemphasis_lane2_3=0x0f480d +serdes_preemphasis_lane3_3=0x0f480d +serdes_preemphasis_lane0_4=0x0f480d +serdes_preemphasis_lane1_4=0x0f480d +serdes_preemphasis_lane2_4=0x0f480d +serdes_preemphasis_lane3_4=0x0f480d +serdes_preemphasis_lane0_5=0x0f480d +serdes_preemphasis_lane1_5=0x0f480d +serdes_preemphasis_lane2_5=0x0f480d +serdes_preemphasis_lane3_5=0x0f480d +serdes_preemphasis_lane0_6=0x0f480d +serdes_preemphasis_lane1_6=0x0f480d +serdes_preemphasis_lane2_6=0x0f480d +serdes_preemphasis_lane3_6=0x0f480d +serdes_preemphasis_lane0_7=0x0d4b0c +serdes_preemphasis_lane1_7=0x0d4b0c +serdes_preemphasis_lane2_7=0x0d4b0c +serdes_preemphasis_lane3_7=0x0d4b0c +serdes_preemphasis_lane0_8=0x0d4b0c +serdes_preemphasis_lane1_8=0x0d4b0c +serdes_preemphasis_lane2_8=0x0d4b0c +serdes_preemphasis_lane3_8=0x0d4b0c +serdes_preemphasis_lane0_13=0x0d4b0c +serdes_preemphasis_lane1_13=0x0d4b0c +serdes_preemphasis_lane2_13=0x0d4b0c +serdes_preemphasis_lane3_13=0x0d4b0c +serdes_preemphasis_lane0_14=0x0d4b0c +serdes_preemphasis_lane1_14=0x0d4b0c +serdes_preemphasis_lane2_14=0x0d4b0c +serdes_preemphasis_lane3_14=0x0d4b0c +serdes_preemphasis_lane0_15=0x0d4b0c +serdes_preemphasis_lane1_15=0x0d4b0c +serdes_preemphasis_lane2_15=0x0d4b0c +serdes_preemphasis_lane3_15=0x0d4b0c +serdes_preemphasis_lane0_16=0x0d4b0c +serdes_preemphasis_lane1_16=0x0d4b0c +serdes_preemphasis_lane2_16=0x0d4b0c +serdes_preemphasis_lane3_16=0x0d4b0c +serdes_preemphasis_lane0_21=0x0d4b0c +serdes_preemphasis_lane1_21=0x0d4b0c +serdes_preemphasis_lane2_21=0x0d4b0c +serdes_preemphasis_lane3_21=0x0d4b0c +serdes_preemphasis_lane0_22=0x0d4b0c +serdes_preemphasis_lane1_22=0x0d4b0c +serdes_preemphasis_lane2_22=0x0d4b0c +serdes_preemphasis_lane3_22=0x0d4b0c +serdes_preemphasis_lane0_23=0x0d4b0c +serdes_preemphasis_lane1_23=0x0d4b0c +serdes_preemphasis_lane2_23=0x0d4b0c +serdes_preemphasis_lane3_23=0x0d4b0c +serdes_preemphasis_lane0_24=0x0d4b0c +serdes_preemphasis_lane1_24=0x0d4b0c +serdes_preemphasis_lane2_24=0x0d4b0c +serdes_preemphasis_lane3_24=0x0d4b0c +serdes_preemphasis_lane0_29=0x0d4b0c +serdes_preemphasis_lane1_29=0x0d4b0c +serdes_preemphasis_lane2_29=0x0d4b0c +serdes_preemphasis_lane3_29=0x0d4b0c +serdes_preemphasis_lane0_30=0x0d4b0c +serdes_preemphasis_lane1_30=0x0d4b0c +serdes_preemphasis_lane2_30=0x0d4b0c +serdes_preemphasis_lane3_30=0x0d4b0c +serdes_preemphasis_lane0_31=0x0d4b0c +serdes_preemphasis_lane1_31=0x0d4b0c +serdes_preemphasis_lane2_31=0x0d4b0c +serdes_preemphasis_lane3_31=0x0d4b0c +serdes_preemphasis_lane0_32=0x0d4b0c +serdes_preemphasis_lane1_32=0x0d4b0c +serdes_preemphasis_lane2_32=0x0d4b0c +serdes_preemphasis_lane3_32=0x0d4b0c +serdes_preemphasis_lane0_33=0x0d4b0c +serdes_preemphasis_lane1_33=0x0d4b0c +serdes_preemphasis_lane2_33=0x0d4b0c +serdes_preemphasis_lane3_33=0x0d4b0c +serdes_preemphasis_lane0_34=0x0d4b0c +serdes_preemphasis_lane1_34=0x0d4b0c +serdes_preemphasis_lane2_34=0x0d4b0c +serdes_preemphasis_lane3_34=0x0d4b0c +serdes_preemphasis_lane0_35=0x0d4b0c +serdes_preemphasis_lane1_35=0x0d4b0c +serdes_preemphasis_lane2_35=0x0d4b0c +serdes_preemphasis_lane3_35=0x0d4b0c +serdes_preemphasis_lane0_36=0x0d4b0c +serdes_preemphasis_lane1_36=0x0d4b0c +serdes_preemphasis_lane2_36=0x0d4b0c +serdes_preemphasis_lane3_36=0x0d4b0c +serdes_preemphasis_lane0_41=0x0d4b0c +serdes_preemphasis_lane1_41=0x0d4b0c +serdes_preemphasis_lane2_41=0x0d4b0c +serdes_preemphasis_lane3_41=0x0d4b0c +serdes_preemphasis_lane0_42=0x0d4b0c +serdes_preemphasis_lane1_42=0x0d4b0c +serdes_preemphasis_lane2_42=0x0d4b0c +serdes_preemphasis_lane3_42=0x0d4b0c +serdes_preemphasis_lane0_43=0x0d4b0c +serdes_preemphasis_lane1_43=0x0d4b0c +serdes_preemphasis_lane2_43=0x0d4b0c +serdes_preemphasis_lane3_43=0x0d4b0c +serdes_preemphasis_lane0_44=0x0d4b0c +serdes_preemphasis_lane1_44=0x0d4b0c +serdes_preemphasis_lane2_44=0x0d4b0c +serdes_preemphasis_lane3_44=0x0d4b0c +serdes_preemphasis_lane0_49=0x0d4b0c +serdes_preemphasis_lane1_49=0x0d4b0c +serdes_preemphasis_lane2_49=0x0d4b0c +serdes_preemphasis_lane3_49=0x0d4b0c +serdes_preemphasis_lane0_50=0x0d4b0c +serdes_preemphasis_lane1_50=0x0d4b0c +serdes_preemphasis_lane2_50=0x0d4b0c +serdes_preemphasis_lane3_50=0x0d4b0c +serdes_preemphasis_lane0_51=0x0d4b0c +serdes_preemphasis_lane1_51=0x0d4b0c +serdes_preemphasis_lane2_51=0x0d4b0c +serdes_preemphasis_lane3_51=0x0d4b0c +serdes_preemphasis_lane0_52=0x0d4b0c +serdes_preemphasis_lane1_52=0x0d4b0c +serdes_preemphasis_lane2_52=0x0d4b0c +serdes_preemphasis_lane3_52=0x0d4b0c +serdes_preemphasis_lane0_57=0x0d4b0c +serdes_preemphasis_lane1_57=0x0d4b0c +serdes_preemphasis_lane2_57=0x0d4b0c +serdes_preemphasis_lane3_57=0x0d4b0c +serdes_preemphasis_lane0_58=0x0d4b0c +serdes_preemphasis_lane1_58=0x0d4b0c +serdes_preemphasis_lane2_58=0x0d4b0c +serdes_preemphasis_lane3_58=0x0d4b0c +serdes_preemphasis_lane0_59=0x0d4b0c +serdes_preemphasis_lane1_59=0x0d4b0c +serdes_preemphasis_lane2_59=0x0d4b0c +serdes_preemphasis_lane3_59=0x0d4b0c +serdes_preemphasis_lane0_60=0x0d4b0c +serdes_preemphasis_lane1_60=0x0d4b0c +serdes_preemphasis_lane2_60=0x0d4b0c +serdes_preemphasis_lane3_60=0x0d4b0c +serdes_preemphasis_lane0_61=0x0d4b0c +serdes_preemphasis_lane1_61=0x0d4b0c +serdes_preemphasis_lane2_61=0x0d4b0c +serdes_preemphasis_lane3_61=0x0d4b0c +serdes_preemphasis_lane0_62=0x0d4b0c +serdes_preemphasis_lane1_62=0x0d4b0c +serdes_preemphasis_lane2_62=0x0d4b0c +serdes_preemphasis_lane3_62=0x0d4b0c +serdes_preemphasis_lane0_63=0x0d4b0c +serdes_preemphasis_lane1_63=0x0d4b0c +serdes_preemphasis_lane2_63=0x0d4b0c +serdes_preemphasis_lane3_63=0x0d4b0c +serdes_preemphasis_lane0_64=0x0d4b0c +serdes_preemphasis_lane1_64=0x0d4b0c +serdes_preemphasis_lane2_64=0x0d4b0c +serdes_preemphasis_lane3_64=0x0d4b0c +serdes_preemphasis_lane0_67=0x0d4b0c +serdes_preemphasis_lane1_67=0x0d4b0c +serdes_preemphasis_lane2_67=0x0d4b0c +serdes_preemphasis_lane3_67=0x0d4b0c +serdes_preemphasis_lane0_68=0x0d4b0c +serdes_preemphasis_lane1_68=0x0d4b0c +serdes_preemphasis_lane2_68=0x0d4b0c +serdes_preemphasis_lane3_68=0x0d4b0c +serdes_preemphasis_lane0_69=0x0d4b0c +serdes_preemphasis_lane1_69=0x0d4b0c +serdes_preemphasis_lane2_69=0x0d4b0c +serdes_preemphasis_lane3_69=0x0d4b0c +serdes_preemphasis_lane0_70=0x0d4b0c +serdes_preemphasis_lane1_70=0x0d4b0c +serdes_preemphasis_lane2_70=0x0d4b0c +serdes_preemphasis_lane3_70=0x0d4b0c +serdes_preemphasis_lane0_71=0x0d4b0c +serdes_preemphasis_lane1_71=0x0d4b0c +serdes_preemphasis_lane2_71=0x0d4b0c +serdes_preemphasis_lane3_71=0x0d4b0c +serdes_preemphasis_lane0_72=0x0d4b0c +serdes_preemphasis_lane1_72=0x0d4b0c +serdes_preemphasis_lane2_72=0x0d4b0c +serdes_preemphasis_lane3_72=0x0d4b0c +serdes_preemphasis_lane0_73=0x0d4b0c +serdes_preemphasis_lane1_73=0x0d4b0c +serdes_preemphasis_lane2_73=0x0d4b0c +serdes_preemphasis_lane3_73=0x0d4b0c +serdes_preemphasis_lane0_74=0x0d4b0c +serdes_preemphasis_lane1_74=0x0d4b0c +serdes_preemphasis_lane2_74=0x0d4b0c +serdes_preemphasis_lane3_74=0x0d4b0c +serdes_preemphasis_lane0_87=0x0d4b0c +serdes_preemphasis_lane1_87=0x0d4b0c +serdes_preemphasis_lane2_87=0x0d4b0c +serdes_preemphasis_lane3_87=0x0d4b0c +serdes_preemphasis_lane0_79=0x0d4b0c +serdes_preemphasis_lane1_79=0x0d4b0c +serdes_preemphasis_lane2_79=0x0d4b0c +serdes_preemphasis_lane3_79=0x0d4b0c +serdes_preemphasis_lane0_99=0x0d4b0c +serdes_preemphasis_lane1_99=0x0d4b0c +serdes_preemphasis_lane2_99=0x0d4b0c +serdes_preemphasis_lane3_99=0x0d4b0c +serdes_preemphasis_lane0_95=0x0d4b0c +serdes_preemphasis_lane1_95=0x0d4b0c +serdes_preemphasis_lane2_95=0x0d4b0c +serdes_preemphasis_lane3_95=0x0d4b0c +serdes_preemphasis_lane0_115=0x0f480d +serdes_preemphasis_lane1_115=0x0f480d +serdes_preemphasis_lane2_115=0x0f480d +serdes_preemphasis_lane3_115=0x0f480d +serdes_preemphasis_lane0_107=0x0f480d +serdes_preemphasis_lane1_107=0x0f480d +serdes_preemphasis_lane2_107=0x0f480d +serdes_preemphasis_lane3_107=0x0f480d +serdes_preemphasis_lane0_123=0x0f480d +serdes_preemphasis_lane1_123=0x0f480d +serdes_preemphasis_lane2_123=0x0f480d +serdes_preemphasis_lane3_123=0x0f480d +serdes_preemphasis_lane0_127=0x0f480d +serdes_preemphasis_lane1_127=0x0f480d +serdes_preemphasis_lane2_127=0x0f480d +serdes_preemphasis_lane3_127=0x0f480d + +reglist_enable=1 +scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/custom_led.bin b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..1fe5585e07796a7e30facd1faf391c9969ab8b08 GIT binary patch literal 300 zcmV~$Jxc-s9Khk<`5MuS6lMfjo>FKzoEp^irsw%D2$v$4h&pXBr&^+h79((Ih@zor zYP3b78lr~q3wUEq5<#mUq37wm>_|cKVoK-vtkF$$?I3g^_a+g?q))5K>71Uv7C)8X zO{PAoTz$z%tq^?0T|U}6FV|(=RP=%4x2!wnvJFWX6Si0FY3F1nT`?+|t0&^_mS#9x zc_B_qQFG(dHoN^wlf6syH%u~};Fx!TH|X8hV7 z_23qD;f`S7lF5GzV(nT+Q^y9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf new file mode 100755 index 000000000..5e62742c1 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=115200 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc new file mode 100755 index 000000000..59238f5cd --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc @@ -0,0 +1,7 @@ +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin + +led auto on + +led start + +linkscan SwPortBitMap=xe,ce diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py new file mode 100755 index 000000000..f9cbb31be --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py @@ -0,0 +1,244 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- +""" +* onboard temperature sensors +* FAN trays +* PSU +""" +import os +import xml.etree.ElementTree as ET +import glob + +MAILBOX_DIR = "/sys/bus/i2c/devices/" +PORTS_DIR = "/sys/class/net/" +CONFIG_NAME = "dev.xml" + + +def getPMCreg(location): + retval = "ERR" + if not os.path.isfile(location): + return "%s %s notfound" % (retval, location) + try: + with open(location, "r") as fd: + retval = fd.read() + except Exception: + pass + # logging.error("Unable to open ", location, "file !") + + retval = retval.rstrip("\r\n") + retval = retval.lstrip(" ") + return retval + + +# Get a mailbox register +def get_pmc_register(reg_name): + retval = "ERR" + if reg_name[0:4] == "/rif" or reg_name[0:4] == "/ma1" or reg_name[0:4] == "/eth": + mb_reg_file = PORTS_DIR + reg_name + else: + mb_reg_file = MAILBOX_DIR + reg_name + filepath = glob.glob(mb_reg_file) + if len(filepath) == 0: + return "%s %s notfound" % (retval, mb_reg_file) + mb_reg_file = filepath[0] # use first found patch + if not os.path.isfile(mb_reg_file): + return "%s %s notfound" % (retval, mb_reg_file) + try: + with open(mb_reg_file, "r") as fd: + retval = fd.read() + except Exception: + pass + # logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip("\r\n") + retval = retval.lstrip(" ") + return retval + + +class checktype: + def __init__(self, test1): + self.test1 = test1 + + @staticmethod + def check(name, location, bit, value, tips, err1): + psu_status = int(get_pmc_register(location), 16) + val = (psu_status & (1 << bit)) >> bit + if val != value: + err1["errmsg"] = tips + err1["code"] = -1 + return -1 + else: + err1["errmsg"] = "none" + err1["code"] = 0 + return 0 + + @staticmethod + def getValue(location, bit, type): + value_t = get_pmc_register(location) + if value_t.startswith("ERR"): + return value_t + if type == 1: + return float(value_t) / 1000 + elif type == 2: + return float(value_t) / 100 + elif type == 3: + psu_status = int(value_t, 16) + return (psu_status & (1 << bit)) >> bit + elif type == 4: + return int(value_t, 10) + else: + return value_t + + # temperature + @staticmethod + def getTemp(self, name, location, ret_t): + ret2 = self.getValue(location + "temp1_input", " ", 1) + ret3 = self.getValue(location + "temp1_max", " ", 1) + ret4 = self.getValue(location + "temp1_max_hyst", " ", 1) + ret_t["temp1_input"] = ret2 + ret_t["temp1_max"] = ret3 + ret_t["temp1_max_hyst"] = ret4 + + @staticmethod + def getLM75(name, location, result): + c1 = checktype + r1 = {} + c1.getTemp(c1, name, location, r1) + result[name] = r1 + + +class status: + def __init__(self, productname): + self.productname = productname + + @staticmethod + def getETroot(filename): + tree = ET.parse(filename) + root = tree.getroot() + return root + + @staticmethod + def getDecodValue(collection, decode): + decodes = collection.find("decode") + testdecode = decodes.find(decode) + test = {} + for neighbor in testdecode.iter("code"): + test[neighbor.attrib["key"]] = neighbor.attrib["value"] + return test + + @staticmethod + def getfileValue(location): + return checktype.getValue(location, " ", " ") + + @staticmethod + def getETValue(a, filename, tagname): + root = status.getETroot(filename) + for neighbor in root.iter(tagname): + prob_t = {} + prob_t = neighbor.attrib + prob_t["errcode"] = 0 + prob_t["errmsg"] = "" + for pros in neighbor.iter("property"): + ret = dict(neighbor.attrib.items() + pros.attrib.items()) + if "type" not in ret.keys(): + val = "0" + else: + val = ret["type"] + if "bit" not in ret.keys(): + bit = "0" + else: + bit = ret["bit"] + s = checktype.getValue(ret["location"], int(bit), int(val)) + if isinstance(s, str) and s.startswith("ERR"): + prob_t["errcode"] = -1 + prob_t["errmsg"] = s + if "default" in ret.keys(): + rt = status.getDecodValue(root, ret["decode"]) + prob_t["errmsg"] = rt[str(s)] + if str(s) != ret["default"]: + prob_t["errcode"] = -1 + break + else: + if "decode" in ret.keys(): + rt = status.getDecodValue(root, ret["decode"]) + if ( + ret["decode"] == "psutype" + and s.replace("\x00", "").rstrip() not in rt.keys() + ): # PSU type detect + prob_t["errcode"] = -1 + prob_t["errmsg"] = "%s" % ("The power type does not match, please check whether the power is correct!") + else: + s = rt[str(s).replace("\x00", "").rstrip()] + name = ret["name"] + prob_t[name] = str(s) + a.append(prob_t) + + @staticmethod + def getCPUValue(a, filename, tagname): + root = status.getETroot(filename) + for neighbor in root.iter(tagname): + location = neighbor.attrib["location"] + L = [] + for dirpath, dirnames, filenames in os.walk(location): + for file in filenames: + if file.endswith("input"): + L.append(os.path.join(dirpath, file)) + L = sorted(L, reverse=False) + for i in range(len(L)): + prob_t = {} + prob_t["name"] = getPMCreg("%s/temp%d_label" % (location, i + 1)) + prob_t["temp"] = ( + float(getPMCreg("%s/temp%d_input" % (location, i + 1))) / 1000 + ) + prob_t["alarm"] = ( + float(getPMCreg("%s/temp%d_crit_alarm" % (location, i + 1))) / 1000 + ) + prob_t["crit"] = ( + float(getPMCreg("%s/temp%d_crit" % (location, i + 1))) / 1000 + ) + prob_t["max"] = float(getPMCreg("%s/temp%d_max" % (location, i + 1))) / 1000 + a.append(prob_t) + + @staticmethod + def getFileName(): + return os.path.dirname(os.path.realpath(__file__)) + "/" + CONFIG_NAME + + @staticmethod + def getFan(ret): + _filename = status.getFileName() + _tagname = "fan" + status.getvalue(ret, _filename, _tagname) + + @staticmethod + def checkFan(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "fan" + status.getETValue(ret, _filename, _tagname) + + @staticmethod + def getTemp(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "temp" + status.getETValue(ret, _filename, _tagname) + + @staticmethod + def getPsu(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "psu" + status.getETValue(ret, _filename, _tagname) + + @staticmethod + def getcputemp(ret): + _filename = status.getFileName() + _tagname = "cpus" + status.getCPUValue(ret, _filename, _tagname) + + @staticmethod + def getMgmtRx(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "mgmt_rx" + status.getETValue(ret, _filename, _tagname) diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml new file mode 100644 index 000000000..90ebf1740 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml @@ -0,0 +1,429 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: '16' + fn: '0' + id: 8c3a + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #1 (rev 04)' +- bus: '00' + dev: '16' + fn: '1' + id: 8c3b + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #2 (rev 04)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '01' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '04' + dev: '00' + fn: '0' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '04' + dev: '00' + fn: '1' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '07' + dev: '00' + fn: '0' + id: b873 + name: 'Ethernet controller: Broadcom Limited Device b873 (rev 01)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/platform_env.conf b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/platform_env.conf new file mode 100644 index 000000000..e69de29bb diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py new file mode 100755 index 000000000..53f57c2a3 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/2-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, "", True) diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py new file mode 100755 index 000000000..e1513d14c --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py @@ -0,0 +1,63 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + return 2 + + def get_psu_status(self, index): + if index != 1 and index != 2: + return False + + psu_path = "/sys/bus/i2c/devices/2-0037/psu_status" + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(2), 16) + data.close() + + if index == 1 and (result & 0x2): + return True + + if index == 2 and (result & 0x20): + return True + + return False + + def get_psu_presence(self, index): + if index != 1 and index != 2: + return False + + psu_path = "/sys/bus/i2c/devices/2-0037/psu_status" + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(2), 16) + data.close() + + if index == 1 and (result & 0x1) == 0: + return True + + if index == 2 and (result & 0x10) == 0: + return True + + return False diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py new file mode 100755 index 000000000..cfc294972 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py @@ -0,0 +1,359 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 55 + PORTS_IN_BLOCK = 56 + + EEPROM_OFFSET = 11 + SFP_DEVICE_TYPE = "optoe2" + QSFP_DEVICE_TYPE = "optoe1" + I2C_MAX_ATTEMPT = 3 + + SFP_STATUS_INSERTED = '1' + SFP_STATUS_REMOVED = '0' + + QSFP_POWERMODE_OFFSET = 93 + QSFP_CONTROL_OFFSET = 86 + QSFP_CONTROL_WIDTH = 8 + + _port_to_eeprom_mapping = {} + port_to_i2cbus_mapping ={} + port_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return range(48, self.PORTS_IN_BLOCK) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET) + if self.get_presence(x): + self.port_dict[x] = self.SFP_STATUS_INSERTED + else: + self.port_dict[x] = self.SFP_STATUS_REMOVED + SfpUtilBase.__init__(self) + + def _sfp_read_file_path(self, file_path, offset, num_bytes): + attempts = 0 + while attempts < self.I2C_MAX_ATTEMPT: + try: + file_path.seek(offset) + read_buf = file_path.read(num_bytes) + except BaseException: + attempts += 1 + time.sleep(0.05) + else: + return True, read_buf + return False, None + + def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset): + if not os.path.exists(sysfs_sfp_i2c_client_eeprompath): + return False + else: + with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile: + rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1) + return rv + + def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): + try: + sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path + + # Write device address to new_device file + nd_file = open(sysfs_nd_path, "w") + nd_str = "%s %s" % (devtype, hex(devaddr)) + nd_file.write(nd_str) + nd_file.close() + + except Exception as err: + print("Error writing to new device file: %s" % str(err)) + return 1 + else: + return 0 + + def _get_port_eeprom_path(self, port_num, devid): + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + + if port_num in self.port_to_eeprom_mapping.keys(): + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num] + else: + i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) + if i2c_adapter_id is None: + print("Error getting i2c bus num") + return None + + # Get i2c virtual bus path for the sfp + sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, + str(i2c_adapter_id)) + + # If i2c bus for port does not exist + if not os.path.exists(sysfs_sfp_i2c_adapter_path): + print("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path) + return None + + sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, + str(i2c_adapter_id), + hex(devid)[-2:]) + + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + if port_num in self.qsfp_ports: + self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) + else: + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + + return sysfs_sfp_i2c_client_eeprom_path + + def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes) + if rv == False: + return None + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except BaseException: + return None + + return eeprom_raw + + def get_eeprom_dom_raw(self, port_num): + if port_num in self.qsfp_ports: + # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw + return None + else: + # Read dom eeprom at addr 0x51 + return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 256) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num <= 7: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence1" + elif port_num >= 8 and port_num <= 15: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence2" + elif port_num >= 16 and port_num <= 23: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence3" + elif port_num >= 24 and port_num <= 31: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence4" + elif port_num >= 32 and port_num <= 39: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence5" + elif port_num >= 40 and port_num <= 47: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence6" + elif port_num >= 48 and port_num <= 55: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence7" + else: + return False + + try: + data = open(presence_path, "rb") + except IOError: + return False + + presence_data = data.read(2) + if presence_data == "": + return False + result = int(presence_data, 16) + data.close() + + # ModPrsL is active low + if result & (1 << (port_num % 8)) == 0: + return True + + return False + + def set_power_override(self, port_num, power_override, power_set): + if port_num < self.port_start or port_num > self.port_end: + return False + if self.get_presence(port_num) is False: + return False + if port_num in self.qsfp_ports: + offset = 0 + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + self.QSFP_POWERMODE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + else: + # SFP doesn't support this feature + return False + + def get_low_power_mode(self, port_num): + """ + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + """ + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num in self.qsfp_ports: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + sysfs_sfp_i2c_client_eeprom_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + with open(sysfs_sfp_i2c_client_eeprom_path, "rb", buffering=0) as sysfsfile: + dom_control_raw = self._read_eeprom_specific_bytes(sysfsfile, + offset + self.QSFP_CONTROL_OFFSET, self.QSFP_CONTROL_WIDTH) if self.get_presence(port_num) else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + lpmode = ('On' == dom_control_data['data']['PowerSet']['value']) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + if lpmode == power_override == True: + return True + else: + # SFP doesn't support this feature + return False + return False + + def set_low_power_mode(self, port_num, lpmode): + """ + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + """ + if port_num < self.port_start or port_num > self.port_end: + return False + if lpmode: + return self.set_power_override(port_num, True, lpmode) + else: + return self.set_power_override(port_num, False, lpmode) + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num in self.qsfp_ports: + reset_path = "/sys/bus/i2c/devices/1-0036/qsfp_reset" + try: + data = open(reset_path, "r+") + reset_data = data.read(2) + if reset_data == "": + return False + result = int(reset_data, 16) + result = result & (~(1 << (port_num % 8))) + data.seek(0) + sres = hex(result)[2:] + data.write(sres) + data.close() + + time.sleep(1) + + data = open(reset_path, "r+") + reset_data = data.read(2) + if reset_data == "": + return False + result = int(reset_data, 16) + data.seek(0) + result = result | (1 << (port_num % 8)) + sres = hex(result)[2:] + data.write(sres) + data.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + return True + else: + # SFP doesn't support this feature + return False + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + currernt_port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print("get_transceiver_change_event: time wrap / invalid timeout value", timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + if self.get_presence(x): + currernt_port_dict[x] = self.SFP_STATUS_INSERTED + else: + currernt_port_dict[x] = self.SFP_STATUS_REMOVED + if (currernt_port_dict == self.port_dict): + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + else: + # Update reg value + self.port_dict = currernt_port_dict + return True, self.port_dict + print("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json new file mode 100644 index 000000000..590def37b --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf new file mode 100755 index 000000000..9b0569d15 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf @@ -0,0 +1,21 @@ +# libsensors configuration file +# ---------------------------------------------- +# + +bus "i2c-2" "i2c-0-mux (chan_id 0)" + +chip "lm75-i2c-2-48" + label temp1 "LM75_0 air_inlet" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "lm75-i2c-2-49" + label temp1 "LM75_1 air_outlet" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "lm75-i2c-2-4a" + label temp1 "LM75_2 hottest" + set temp1_max 80 + set temp1_max_hyst 75 + diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json new file mode 100644 index 000000000..c5ea46918 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json @@ -0,0 +1,3 @@ +{ + "eeprom": {"bus": 2, "loc": "0057"} +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json new file mode 100644 index 000000000..35f4b4586 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json @@ -0,0 +1,60 @@ +{ + "components": [ + { + "name": "CPLD1 (MAC Board A)", + "firmware_version": { + "bus": 2, + "addr": 51, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 0 + }, + { + "name": "CPLD2 (MAC Board B)", + "firmware_version": { + "bus": 2, + "addr": 53, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 0 + }, + { + "name": "CPLD3 (CONNECT Board A)", + "firmware_version": { + "bus": 2, + "addr": 55, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 0 + }, + { + "name": "CPLD4 (CPU Board)", + "firmware_version": { + "bus": 0, + "addr": 13, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 1 + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json new file mode 100644 index 000000000..de7030ec1 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json @@ -0,0 +1,152 @@ +{ + "fans": [ + { + "name": "fan1", + "e2loc": {"bus": 3, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 0 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 0 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/3-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/3-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan0_led", + "format": 6, + "mask": 11 + }, + "led_colors": { + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan1_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + }, + { + "name": "fan2", + "e2loc": {"bus": 4, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 1 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 1 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/4-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/4-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan1_led", + "format": 6, + "mask": 11 + }, + "led_colors": { + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan2_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + }, + { + "name": "fan3", + "e2loc": {"bus": 3, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 2 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 2 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/5-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/5-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan2_led", + "format": 6, + "mask": 11 + }, + "led_colors": { + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan3_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + }, + { + "name": "fan4", + "e2loc": {"bus": 3, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 3 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 3 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/6-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/6-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan3_led", + "format": 6, + "mask": 11 + }, + "led_colors":{ + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan4_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json new file mode 100644 index 000000000..c807b51fc --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json @@ -0,0 +1,134 @@ +{ + "psus": [ + { + "name": "psu1", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 0 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 1 + }, + "sn": {"loc": "/sys/bus/i2c/devices/7-0050/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr1_input", + "format": 4 + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in1_input", + "format": 4 + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in2_input", + "format": 4 + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr2_input", + "format": 4 + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/temp1_input", + "format": 4 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/7-0050/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/7-0050/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_fault" + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 1 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_input" + }, + "speed_max": 28000 + } + ] + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power1_input", + "format": 5 + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power2_input", + "format": 5 + } + }, + { + "name": "psu2", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 4 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 5 + }, + "sn": {"loc": "/sys/bus/i2c/devices/8-0053/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr1_input", + "format": 4 + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in1_input", + "format": 4 + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in2_input", + "format": 4 + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr2_input", + "format": 4 + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/temp1_input", + "format": 4 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/8-0053/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/8-0053/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_fault" + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 5 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_input" + }, + "speed_max": 28000 + } + ] + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power1_input", + "format": 5 + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power2_input", + "format": 5 + } + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json new file mode 100644 index 000000000..319336673 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json @@ -0,0 +1,130 @@ +{"thermals": [ + { + "name": "INLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": null, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_input", + "format": 4 + } + }, + { + "name": "OUTLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": null, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_input", + "format": 4 + } + }, + { + "name": "BOARD TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": null, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_input", + "format": 4 + } + }, + { + "name": "PHYSICAL ID 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp1_input", + "format": 4 + } + }, + { + "name": "CPU CORE 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp2_input", + "format": 4 + } + }, + { + "name": "CPU CORE 1", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp3_input", + "format": 4 + } + }, + { + "name": "CPU CORE 2", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp4_input", + "format": 4 + } + }, + { + "name": "CPU CORE 3", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp5_input", + "format": 4 + } + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py new file mode 100644 index 000000000..e1972959f --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +""" +* onboard temperature sensors +* FAN trays +* PSU +""" +import time +import datetime +from monitor import status + +def doWork(): + a=[]; + ''' + return: [{'status': '1', 'hw_version': '1.00', 'errcode': 0, 'fan_type': 'M6510-FAN-F', 'errmsg': 'OK', 'Speed': '9778', 'id': 'fan1', 'present': '0', 'sn': '1000000000014'}, + {'id': 'fan2', 'errmsg': 'not present', 'errcode': -1}, + {'id': 'fan3', 'errmsg': 'not present', 'errcode': -1}, + {'id': 'fan4', 'errmsg': 'not present', 'errcode': -1} + ] + description: 1.get id + 2.errcode equal 0 : dev normal + not equal 0 : get errmsg + 3.other message add when all check success + ''' + status.checkFan(a) + #status.getTemp(a) + #status.getPsu(a) + + nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + print(nowTime) + print(a) +def run(interval): + while True: + try: + time_remaining = interval - time.time()%interval + time.sleep(time_remaining) + doWork() + except Exception as e: + print(e) + +if __name__ == '__main__': + interval = 1 + run(interval) diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index f557f17c7..b9813256f 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -62,7 +62,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(JUNIPER_QFX5210_PLATFORM_MODULE) \ $(CEL_SILVERSTONE_PLATFORM_MODULE) \ $(JUNIPER_QFX5200_PLATFORM_MODULE) \ - $(DELTA_AGC032_PLATFORM_MODULE) + $(DELTA_AGC032_PLATFORM_MODULE) \ + $(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) diff --git a/platform/broadcom/platform-modules-ruijie.dep b/platform/broadcom/platform-modules-ruijie.dep new file mode 100644 index 000000000..8910bfcf2 --- /dev/null +++ b/platform/broadcom/platform-modules-ruijie.dep @@ -0,0 +1,8 @@ +MPATH := $($(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-ruijie.mk platform/broadcom/platform-modules-ruijie.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) diff --git a/platform/broadcom/platform-modules-ruijie.mk b/platform/broadcom/platform-modules-ruijie.mk new file mode 100644 index 000000000..b712f67fe --- /dev/null +++ b/platform/broadcom/platform-modules-ruijie.mk @@ -0,0 +1,10 @@ +# Ruijie platform modules +RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE_VERSION = 1.0 +export RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE_VERSION + +RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE = platform-modules-ruijie-b6510-48vs8cq_$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE_VERSION)_amd64.deb +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ruijie +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_PLATFORM = x86_64-ruijie_b6510-48vs8cq-r0 +SONIC_DPKG_DEBS += $(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) +SONIC_STRETCH_DEBS += $(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk index fbe0dd689..73bf93c3d 100644 --- a/platform/broadcom/rules.mk +++ b/platform/broadcom/rules.mk @@ -12,6 +12,7 @@ include $(PLATFORM_PATH)/platform-modules-quanta.mk #include $(PLATFORM_PATH)/platform-modules-mitac.mk include $(PLATFORM_PATH)/platform-modules-juniper.mk include $(PLATFORM_PATH)/platform-modules-brcm-xlr-gts.mk +include $(PLATFORM_PATH)/platform-modules-ruijie.mk include $(PLATFORM_PATH)/docker-syncd-brcm.mk include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk include $(PLATFORM_PATH)/docker-saiserver-brcm.mk diff --git a/platform/broadcom/sonic-platform-modules-ruijie/LICENSE b/platform/broadcom/sonic-platform-modules-ruijie/LICENSE new file mode 100755 index 000000000..68463127d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Ruijie Network Corporation +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE new file mode 100755 index 000000000..68463127d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Ruijie Network Corporation +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS new file mode 100755 index 000000000..7b2f22c03 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS @@ -0,0 +1,6 @@ +# This file describes the maintainers for sonic-platform-modules-ruijie +# See the SONiC project governance document for more information + +Name = "sonic_rd" +Email = "sonic_rd@ruijie.com.cn" +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile new file mode 100755 index 000000000..1b09fe02b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile @@ -0,0 +1,22 @@ +PWD = $(shell pwd) +DIR_KERNEL_SRC = $(PWD)/modules/driver +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +SUB_BUILD_DIR = $(PWD)/build +INSTALL_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) +INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin + +KBUILD_EXTRA_SYMBOLS += $(DIR_KERNEL_SRC)/Module.symvers +export KBUILD_EXTRA_SYMBOLS + +all: + $(MAKE) -C $(KBUILD_OUTPUT) M=$(DIR_KERNEL_SRC) modules + @if [ ! -d ${INSTALL_DIR} ]; then mkdir -p ${INSTALL_DIR} ;fi + cp -r $(DIR_KERNEL_SRC)/*.ko $(INSTALL_DIR) + @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi + cp -r $(PWD)/config/* $(INSTALL_SCRIPT_DIR) +clean: + rm -f ${DIR_KERNEL_SRC}/*.o ${DIR_KERNEL_SRC}/*.ko ${DIR_KERNEL_SRC}/*.mod.c ${DIR_KERNEL_SRC}/.*.cmd + rm -f ${DIR_KERNEL_SRC}/Module.markers ${DIR_KERNEL_SRC}/Module.symvers ${DIR_KERNEL_SRC}/modules.order + rm -rf ${DIR_KERNEL_SRC}/.tmp_versions + rm -rf $(SUB_BUILD_DIR) diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md new file mode 100755 index 000000000..b4dbacd5e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-ruijie +Device drivers for support of ruijie platform for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py new file mode 100755 index 000000000..23684230f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py @@ -0,0 +1,787 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- + +fancontrol_loc = "/usr/local/bin" +fancontrol_config_loc = "/usr/local/bin" + +GLOBALCONFIG = "GLOBALCONFIG" +MONITOR_CONST = "MONITOR_CONST" + +RUIJIE_PART_NUMBER = "RJ000001" +RUIJIE_LABEL_REVISION = "R01" +RUIJIE_ONIE_VERSION = "2018.02" +RUIJIE_MAC_SIZE = 3 +RUIJIE_MANUF_NAME = "Ruijie" +RUIJIE_MANUF_COUNTRY = "CHN" +RUIJIE_VENDOR_NAME = "Ruijie" +RUIJIE_DIAG_VERSION = "0.1.0.15" +RUIJIE_SERVICE_TAG = "www.ruijie.com.cn" + +DEV_LEDS = {} +MEM_SLOTS = [] + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +FIRMWARE_TOOLS = {} + +################################################################################################### +##### fan board ID reference +################################################################################################### +FANS_DEF = { + 0x8100:"M6500-FAN-F", + 0x8101:"M6510-FAN-F", + 0x8102:"M6520-FAN-F", + 0x8103:"M6510-FAN-R" +} + +factest_module = { + "sysinfo_showfanmsg":1, + "sysinfo_showPsumsg":1, + "sysinfo_showrestfanmsg":0, + "sysinfo_showrestpsumsg":0 +} + +MONITOR_MAC_SOURCE_SYSFS = 0 #1 get mac temperature from sysfs ,0 get mac temperature from bcmcmd +MONITOR_MAC_SOURCE_PATH = None #sysfs path + +################################################################### + +SLOT_MONITOR_PARAM = {} + +FAN_PROTECT = {"bus":0, "devno":0x32, "addr":0x19, "open":0x00, "close":0x0f} +rg_eeprom = "2-0057/eeprom" +E2_LOC = {"bus":2, "devno":0x57} +E2_PROTECT ={"bus":2, "devno":0x33, "addr":0xb0, "open":0, "close":1} +MAC_LED_RESET = {"pcibus": 8, "slot": 0, "fn": 0, "bar": 0, "offset": 64, "reset": 0x98} + +PCA9548START = -1 +PCA9548BUSEND = -2 + + +RUIJIE_CARDID = 0x00004040 +RUIJIE_PRODUCTNAME = "B6510-48VS8CQ" + +STARTMODULE = { + "fancontrol":1, + "avscontrol":1, + "dev_monitor":1 +} + +i2ccheck_params = {"busend":"i2c-66","retrytime":6} + +DEV_MONITOR_PARAM = { + "polling_time": 10, + "psus": [ + { + "name": "psu1", + "present": { + "gettype": "i2c", + "bus": 2, + "loc": 0x37, + "offset": 0x51, + "presentbit": 0, + "okval": 0, + }, + "device": [ + { + "id": "psu1pmbus", + "name": "dps550", + "bus": 7, + "loc": 0x58, + "attr": "hwmon", + }, + ], + }, + { + "name": "psu2", + "present": { + "gettype": "i2c", + "bus": 2, + "loc": 0x37, + "offset": 0x51, + "presentbit": 4, + "okval": 0, + }, + "device": [ + { + "id": "psu2pmbus", + "name": "dps550", + "bus": 8, + "loc": 0x5B, + "attr": "hwmon", + }, + ], + }, + ], +} + +fanlevel = { + "tips":["low","medium","high"], + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanloc =[ {"name":"FAN1/FAN2/FAN3/FAN4", "location":"0-0032/fan_speed_set", + "childfans":[{"name":"FAN1", "location":"2-0037/hwmon/hwmon4/fan1_input"}, + {"name":"FAN2", "location":"2-0037/hwmon/hwmon4/fan2_input"}, + {"name":"FAN3", "location":"2-0037/hwmon/hwmon4/fan3_input"}, + {"name":"FAN4", "location":"2-0037/hwmon/hwmon4/fan4_input"} ]}, + ] + + +#################FAN-Speed-Adjustment-Parameters############################## +MONITOR_TEMP_MIN = 38 # temperature before speed-adjsutment +MONITOR_K = 11 # speed-adjustment algorithm +MONITOR_MAC_IN = 35 # temperature difference between mac and chip +MONITOR_DEFAULT_SPEED = 0x60 # default speed +MONITOR_MAX_SPEED = 0xFF # maximum speed +MONITOR_MIN_SPEED = 0x33 # minimum speed +MONITOR_MAC_ERROR_SPEED = 0XBB # MAC abnormal speed +MONITOR_FAN_TOTAL_NUM = 4 # 3+1 redundancy design, report to syslog if there exists a error +MONITOR_MAC_UP_TEMP = 50 # MAC compared with temperature inlet up +MONITOR_MAC_LOWER_TEMP = -50 # MAC compared with temperature outlet down +MONITOR_MAC_MAX_TEMP = 100 # + +MONITOR_FALL_TEMP = 4 # speed-adjustment reduced temperature +MONITOR_MAC_WARNING_THRESHOLD = 100 #100 +MONITOR_OUTTEMP_WARNING_THRESHOLD = 85 +MONITOR_BOARDTEMP_WARNING_THRESHOLD = 85 +MONITOR_CPUTEMP_WARNING_THRESHOLD = 85 +MONITOR_INTEMP_WARNING_THRESHOLD = 70 #70 + +MONITOR_MAC_CRITICAL_THRESHOLD = 105 #105 +MONITOR_OUTTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_BOARDTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_CPUTEMP_CRITICAL_THRESHOLD = 100 #100 +MONITOR_INTEMP_CRITICAL_THRESHOLD = 80 # 80 +MONITOR_CRITICAL_NUM = 3 #retry times +MONITOR_SHAKE_TIME = 20 #anti-shake intervals +MONITOR_INTERVAL = 60 + +MONITOR_SYS_LED = [ + {"bus":2,"devno":0x33, "addr":0xb2, "yellow":0x03, "red":0x02,"green":0x01}, + {"bus":2,"devno":0x37, "addr":0xb2, "yellow":0x03, "red":0x02,"green":0x01}] + +MONITOR_SYS_FAN_LED =[ + {"bus":2,"devno":0x33, "addr":0xb4, "yellow":0x06, "red":0x02,"green":0x04}, + ] +MONITOR_FANS_LED = [ + {"bus":2,"devno":0x32, "addr":0x23, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x24, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x25, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x26, "green":0x09, "red":0x0a}] + + +CPLDVERSIONS = [ + {"bus":2, "devno":0x33, "name":"MAC board CPLD-A"}, + {"bus":2, "devno":0x35, "name":"MAC board CPLD-B"}, + {"bus":2, "devno":0x37, "name":"CONNECT board CPLD-A"}, + {"bus":0, "devno":0x0d, "name":"CPU board CPLD"}, +] + +MONITOR_SYS_PSU_LED =[ + {"bus":2,"devno":0x33, "addr":0xb3, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FAN_STATUS = [ + {'status':'green', 'minOkNum':4,'maxOkNum':4}, + {'status':'yellow', 'minOkNum':3,'maxOkNum':3}, + {'status':'red' , 'minOkNum':0,'maxOkNum':2}, + ] + +MONITOR_PSU_STATUS = [ + {'status':'green', 'minOkNum':2,'maxOkNum':2}, + {'status':'yellow', 'minOkNum':1,'maxOkNum':1}, + {'status':'red' , 'minOkNum':0,'maxOkNum':0}, + ] + + +MONITOR_DEV_STATUS = { + "temperature": [ + {"name":"lm75in", "location":"/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_input"}, + {"name":"lm75out", "location":"/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_input"}, + {"name":"lm75hot", "location":"/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_input"}, + {"name":"cpu", "location":"/sys/class/hwmon/hwmon0"}, + ], + "fans": [ + { + "name":"fan1", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':0}, + "rollstatus": [ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':0}, + ] + }, + { + "name":"fan2", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':1}, + "rollstatus":[ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':1}, + ] + }, + { + "name":"fan3", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':2}, + "rollstatus":[ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':2}, + ] + }, + { + "name":"fan4", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':3}, + "rollstatus":[ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':3}, + ] + }, + ], + "psus": [ + {"name":"psu1", "bus":2, "loc":0x37, "offset":0x51, "gettype":"i2c", 'presentbit': 0, 'statusbit':1,'alertbit':2}, + {"name":"psu2", "bus":2, "loc":0x37, "offset":0x51, "gettype":"i2c", 'presentbit': 4, 'statusbit':5,'alertbit':6}, + ], + "mac_temp" : { + "flag" : {"bus":2, "loc":0x33, "offset":0xd4, "gettype":"i2c", 'okbit': 0, 'okval':1}, + "loc" : [ + "2-0035/mac_temp_input", + ], + "try_bcmcmd" : 0, + }, +} + +MONITOR_DEV_STATUS_DECODE = { + 'fanpresent': {0:'PRESENT', 1:'ABSENT', 'okval':0}, + 'fanroll' : {0:'STALL' , 1:'ROLL', 'okval':1}, + 'psupresent': {0:'PRESENT', 1:'ABSENT', 'okval':0}, + 'psuoutput' : {0:'FAULT' , 1:'NORMAL', 'okval':1}, + 'psualert' : {0:'FAULT' , 1:'NORMAL', 'okval':1}, +} +################################################################### + + +#####################MAC-Voltage-Adjustment-Parameters(B6510)#################################### +MAC_AVS_PARAM ={ + 0x72:0x0384, + 0x73:0x037e, + 0x74:0x0378, + 0x75:0x0372, + 0x76:0x036b, + 0x77:0x0365, + 0x78:0x035f, + 0x79:0x0359, + 0x7a:0x0352, + 0x7b:0x034c, + 0x7c:0x0346, + 0x7d:0x0340, + 0x7e:0x0339, + 0x7f:0x0333, + 0x80:0x032d, + 0x81:0x0327, + 0x82:0x0320, + 0x83:0x031a, + 0x84:0x0314, + 0x85:0x030e, + 0x86:0x0307, + 0x87:0x0301, + 0x88:0x02fb, + 0x89:0x02f5, + 0x8A:0x02ee +} +# 6510 Default Configuration +MAC_DEFAULT_PARAM = { + "type": 1, # type 1 represents default if out of range / 0 represents no voltage-adjustment if out of range + "default":0x74, # should be used with type + "loopaddr":0x00, # AVS loop address + "loop":0x00, # AVS loop value + "open":0x00, # diasble write-protection value + "close":0x40, # enable write-protection value + "bus":2, # AVSI2C bus address + "devno":0x60, # AVS address + "addr":0x21, # AVS voltage-adjustment address + "protectaddr":0x10, # AVS write-protection address + "sdkreg":"TOP_AVS_SEL_REG", # SDK register name + "sdktype": 0, # type 0 represents no shift operation / 1 represents shift operation + "macregloc":24, # shift operation + "mask": 0xff # mask after shift +} +#####################MAC-Voltage-Adjustment-Parameters#################################### + +## Drivers List +## +DRIVERLISTS = [ + {"name":"i2c_dev", "delay":0}, + {"name":"i2c_gpio", "delay":0}, + {"name":"i2c_algo_bit","delay":0}, + {"name":"i2c_mux_pca9641", "delay":0}, + {"name":"i2c_mux_pca954x force_create_bus=1", "delay":0},# force_deselect_on_exit=1 + {"name":"i2c_mux", "delay":0}, + {"name":"lm75", "delay":0}, + {"name":"optoe", "delay":0}, + {"name":"at24", "delay":0}, + {"name":"ruijie_platform", "delay":0}, + {"name":"rg_cpld", "delay":0}, + {"name":"rg_fan", "delay":0}, + {"name":"rg_psu", "delay":0}, + {"name":"pmbus_core", "delay":0}, + {"name":"csu550", "delay":0}, + {"name":"rg_gpio_xeon", "delay":0}, + {"name":"ipmi_devintf", "delay":0}, + {"name":"ipmi_si", "delay":0}, + {"name":"ipmi_msghandler", "delay":0}, +] + +DEVICE = [ + {"name":"pca9541","bus":0,"loc":0x10 }, + {"name":"pca9548","bus":2,"loc":0x70 }, + {"name":"lm75","bus": 2, "loc":0x48 }, + {"name":"lm75","bus": 2, "loc":0x49 }, + {"name":"lm75","bus": 2, "loc":0x4a }, + {"name":"24c02","bus":2, "loc":0x57 }, + {"name":"rg_cpld","bus":0,"loc":0x32 }, + {"name":"rg_cpld","bus":1,"loc":0x34 }, + {"name":"rg_cpld","bus":1,"loc":0x36 }, + {"name":"rg_cpld","bus":2,"loc":0x33 }, + {"name":"rg_cpld","bus":2,"loc":0x35 }, + {"name":"rg_cpld","bus":2,"loc":0x37 }, + {"name":"pca9548","bus":1,"loc":0x70 }, + {"name":"pca9548","bus":1,"loc":0x71 }, + {"name":"pca9548","bus":1,"loc":0x72 }, + {"name":"pca9548","bus":1,"loc":0x73 }, + {"name":"pca9548","bus":1,"loc":0x74 }, + {"name":"pca9548","bus":1,"loc":0x75 }, + {"name":"pca9548","bus":1,"loc":0x76 }, + {"name":"rg_fan","bus":3,"loc":0x53 }, + {"name":"rg_fan","bus":4,"loc":0x53 }, + {"name":"rg_fan","bus":5,"loc":0x53 }, + {"name":"rg_fan","bus":6,"loc":0x53 }, + {"name":"rg_psu","bus":7,"loc":0x50 }, + {"name":"dps550","bus":7,"loc":0x58 }, + {"name":"rg_psu","bus":8,"loc":0x53 }, + {"name":"dps550","bus":8,"loc":0x5b }, +] + +INIT_PARAM = [ + {"loc":"1-0034/sfp_enable","value": "01"}, + {"loc":"2-0035/sfp_enable2","value":"ff"}, + {"loc":"2-0033/mac_led", "value":"ff"}, + {"loc":"1-0034/sfp_txdis1","value":"00"}, + {"loc":"1-0034/sfp_txdis2","value":"00"}, + {"loc":"1-0034/sfp_txdis3","value":"00"}, + {"loc":"1-0036/sfp_txdis4","value":"00"}, + {"loc":"1-0036/sfp_txdis5","value":"00"}, + {"loc":"1-0036/sfp_txdis6","value":"00"}, + {"loc":fanloc[0]["location"], "value":"80"}, + {"loc":"2-0033/sfp_led1_yellow","value":"ad"}, + {"loc":"2-0035/sfp_led2_yellow","value":"ad"}, +] + +INIT_COMMAND = [ +] + +## Driver List +## + +#####################FRU-Info-Adaption################################# +E2TYPE = {"1": "tlveeprom", + "2": "x86cpueeprom", + "3": "bmceeprom", + "4": "cpueeprom", + "5": "maceeprom", + "6": "sloteeprom", + "7": "fanconnecteeprom", + "8": "M1HFANI-F", + "9": "M1HFANI-R", + "A": "M2HFANI-F", + "B": "M2HFANI-R", + "C": "psu"} +FRULISTS = [] +################################Manufacturing-Test-Adaption-Area####################################################### +# need to export interface +fanlevel_6510 = { + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanlevel_6520 = { + "level":[75,150,255], + "low_speed":[750,4250,6750], + "high_speed":[4500,7500,10000] +} + +TEMPIDCHANGE = { + "lm75in":"inlet", + "lm75out":"outlet", + "lm75hot":"hot-point", + "inlet":"lm75in", + "outlet":"lm75out", + "hot-point":"lm75hot", +} + +# Manufacturing-Test module +FACTESTMODULE = { } + +##################################Manufacturing-Test-Menu +item1 = {"name":"Single Test", "deal" :"test_signal", "childid":1} +test_sys_reload_item = {"name":"reset-system", "deal" :"test_sys_reload"} + +test_sys_item = { "name":"Product information test", "deal" :"test_sysinfo"} +test_temp_item = { "name":"temperature test", "deal" :"test_tempinfo"} +test_mem_item = { "name":"Memory test", "deal" :"test_cpumemoryinfo"} +test_hd_item = { "name":"Hard disk test", "deal" :"test_hard"} +test_rtc_item = { "name":"RTC test ", "deal" :"test_rtc"} +test_i2c_item = { "name":"I2c test ", "deal" :"test_i2c"} +test_cpld_item = { "name":"CPLD test", "deal" :"test_cpld"} +test_portframe_item = { "name":"Port transmit-receive frame test", "deal" :"test_portframe"} +test_sysled_item = { "name":"System led test", "deal" :"test_led"} +test_fan_item = { "name":"Fan status test", "deal" :"test_fan"} +test_power_item = { "name":"PSU status test", "deal" :"test_power"} +test_usb_item = { "name":"USB test", "deal" :"test_usb"} +test_prbs_item = { "name":"PRBS test", "deal" :"test_prbs"} +test_portbroadcast_item = { "name":"Port broadcast", "deal" :"test_portbroadcast"} + +test_debug_level = {"name":"Change debug level", "deal" :"test_setdebug"} +test_log_level = {"name":"Log output level", "deal" :"test_loginfolevel"} +test_setmac = {"name":"setmac", "deal" :"test_setmac"} +test_setrtc = {"name":"Set RTC", "deal" :"test_set_rtc"} + +log_level_critical = {"name":"CRITICAL", "deal" :"test_log_critical"} +log_level_debug = {"name":"DEBUG", "deal" :"test_log_debug"} +log_level_error = {"name":"ERROR", "deal" :"test_log_error"} +log_level_info = {"name":"INFO", "deal" :"test_log_info"} +log_level_notset = {"name":"NOTSET", "deal" :"test_log_notset"} +log_level_warning = {"name":"WARNING", "deal" :"test_log_warning"} + + +test_e2_setmac_item = {"name":"E2SETMAC", "deal" :"test_e2_setmac"} +test_bmc_setmac_item = {"name":"BMCSETMAC", "deal" :"test_bmc_setmac"} +test_fan_setmac_item = {"name":"fan SETMAC", "deal" :"test_fan_setmac"} + +alltest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_sysled_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item + ] + +looptest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item , +] + +diagtestall = [ +] + +menuList =[ + { + "menuid":0, "value":[ + {"name":"Single test", "deal" :"test_signal", "childid":1}, + {"name":"All test", "deal" :"test_all"}, + {"name":"Loop test", "deal" :"test_loop"}, + #{"name":"Check loop-test result", "deal" :"test_loop_read"}, + #{"name":"Delete loop-test result", "deal" :"test_loop_delete"}, +# {"name":"Load configuration", "deal" :"test_config"}, + test_sys_reload_item, + {"name":"System Configuration", "deal" :"test_sysconfig","childid":2}, + ] + }, + { + "menuid":1, "parentid":0, "value":[ + test_sys_item , + test_temp_item , + test_mem_item , + test_hd_item , + test_rtc_item , + test_i2c_item , + test_cpld_item , + test_portframe_item , + test_sysled_item , + test_fan_item , + test_power_item , + test_usb_item , + test_prbs_item , + test_portbroadcast_item , + ]}, + { + "menuid":2, "parentid":0, "value":[ + test_debug_level, + test_log_level , + test_setmac , + test_setrtc , + ]}, + { + "menuid":3, "parentid":2, "value":[ + log_level_critical , + log_level_debug , + log_level_error , + log_level_info , + log_level_notset , + log_level_warning , + ]}, + { + "menuid":4, "parentid":2, "value":[ + test_e2_setmac_item , + test_bmc_setmac_item, + test_fan_setmac_item, + ]}, +] + + +TESTCASE={ + "CPLD":[ + {"name":"CONNECT BOARD CPLD-A" ,"cases":[ + {"name":"cpld32", "cmd":"grtd_test.py cpld_check 0 0x32 0xAA"}, + {"name":"cpld37", "cmd":"grtd_test.py cpld_check 2 0x37 0xAC"}, + ] + }, + {"name":"MAC BOARD CPLD-A" ,"cases":[ + {"name":"cpld33", "cmd":"grtd_test.py cpld_check 2 0x33 0xAB"}, + {"name":"cpld34", "cmd":"grtd_test.py cpld_check 1 0x34 0xAA"}, + ] + }, + {"name":"MAC BOARD CPLD-B" ,"cases":[ + {"name":"cpld36", "cmd":"grtd_test.py cpld_check 1 0x36 0xAA"}, + {"name":"cpld35", "cmd":"grtd_test.py cpld_check 2 0x35 0xAB"}, + ] + }, + ], + "TEMPERATURE":[ + { + "name":"-->temperature test" , "cases":[ + {"name":"inlet","cmd":"grtd_test.py temp 2-0048/hwmon/hwmon1/temp1_input"}, + {"name":"outlet","cmd":"grtd_test.py temp 2-0049/hwmon/hwmon2/temp1_input"}, + {"name":"hot-point","cmd":"grtd_test.py temp 2-004a/hwmon/hwmon3/temp1_input"}, + ] + } + ], + "MEMTORY":{ + "cases":[ + {"name":"->memory test 1M","cmd":"memtester 1M 1"}, + {"name":"->memory test 2M","cmd":"memtester 2M 1"}, + {"name":"->memory test 8M","cmd":"memtester 8M 1"}, +# {"name":"->memory test 16M","cmd":"memtester 16M 1"}, +# {"name":"->memory test 256M","cmd":"memtester 256M 1"}, + ] + }, + "SMARTCTLCMDS":{ + "cases":[ + {"name":"->Check Hard Disk Info", "cmd":"smartctl -i /dev/sda"}, + {"name":"->Check Hard Disk Monitor Status", "cmd":"smartctl -H /dev/sda"}, + ] + }, + "LED":[ + {"name":"Light Port Led test","cases":[ + {"name":"-> Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Red Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + + {"name":"-> Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Yellow Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + ] + }, + {"name":"fan 1 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + ] + }, + {"name":"fan 2 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + ] + }, + {"name":"fan 3 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + ] + }, + {"name":"Front panel CPU Led", "cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x00"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x02"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x03"}, + {"name":"-> Green Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x11"}, + {"name":"-> Green Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x21"}, + {"name":"-> Green Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x41"}, + {"name":"-> Green Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x81"}, + {"name":"-> Red Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x12"}, + {"name":"-> Red Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x22"}, + {"name":"-> Red Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x42"}, + {"name":"-> Red Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x82"}, + {"name":"-> Yellow Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x13"}, + {"name":"-> Yellow Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x23"}, + {"name":"-> Yellow Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x43"}, + {"name":"-> Yellow Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x83"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + ] + }, + {"name":"Front panel BMC Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + ] + }, + {"name":"Front panel location Led" , "cases":[ + {"name":"-> LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + {"name":"-> LedOn","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xfe"}, + {"name":"->Recovery LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + ] + }, + + {"name":"Front panel pwr Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + ] + }, + {"name":"Front panel fan Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + ] + }, + + ], + "I2C":[ + ####type 1 represents value obtained compated with value + ####type 2 represents return True or False + {"name":"I2C device test" ,"cases":[ + {"name":" PCA9641 test", "cmd":"grtd_test.py dev_rd 0 10 0","deal_type":2}, + {"name":" cpld32 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld33 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld34 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld35 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld36 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld37 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" inlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" outlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" hot-point LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" EEPROM", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" Port 1", "cmd":"grtd_test.py dev_rd 11 0050 0","deal_type":2}, + {"name":" Port 2", "cmd":"grtd_test.py dev_rd 12 0050 0","deal_type":2}, + {"name":" Port 3", "cmd":"grtd_test.py dev_rd 13 0050 0","deal_type":2}, + {"name":" Port 4", "cmd":"grtd_test.py dev_rd 14 0050 0","deal_type":2}, + {"name":" Port 5", "cmd":"grtd_test.py dev_rd 15 0050 0","deal_type":2}, + {"name":" Port 6", "cmd":"grtd_test.py dev_rd 16 0050 0","deal_type":2}, + {"name":" Port 7", "cmd":"grtd_test.py dev_rd 17 0050 0","deal_type":2}, + {"name":" Port 8", "cmd":"grtd_test.py dev_rd 18 0050 0","deal_type":2}, + {"name":" Port 9", "cmd":"grtd_test.py dev_rd 19 0050 0","deal_type":2}, + {"name":" Port 10", "cmd":"grtd_test.py dev_rd 20 0050 0","deal_type":2}, + {"name":" Port 11", "cmd":"grtd_test.py dev_rd 21 0050 0","deal_type":2}, + {"name":" Port 12", "cmd":"grtd_test.py dev_rd 22 0050 0","deal_type":2}, + {"name":" Port 13", "cmd":"grtd_test.py dev_rd 23 0050 0","deal_type":2}, + {"name":" Port 14", "cmd":"grtd_test.py dev_rd 24 0050 0","deal_type":2}, + {"name":" Port 15", "cmd":"grtd_test.py dev_rd 25 0050 0","deal_type":2}, + {"name":" Port 16", "cmd":"grtd_test.py dev_rd 26 0050 0","deal_type":2}, + {"name":" Port 17", "cmd":"grtd_test.py dev_rd 27 0050 0","deal_type":2}, + {"name":" Port 18", "cmd":"grtd_test.py dev_rd 28 0050 0","deal_type":2}, + {"name":" Port 19", "cmd":"grtd_test.py dev_rd 29 0050 0","deal_type":2}, + {"name":" Port 20", "cmd":"grtd_test.py dev_rd 30 0050 0","deal_type":2}, + {"name":" Port 21", "cmd":"grtd_test.py dev_rd 31 0050 0","deal_type":2}, + {"name":" Port 22", "cmd":"grtd_test.py dev_rd 32 0050 0","deal_type":2}, + {"name":" Port 23", "cmd":"grtd_test.py dev_rd 33 0050 0","deal_type":2}, + {"name":" Port 24", "cmd":"grtd_test.py dev_rd 34 0050 0","deal_type":2}, + {"name":" Port 25", "cmd":"grtd_test.py dev_rd 35 0050 0","deal_type":2}, + {"name":" Port 26", "cmd":"grtd_test.py dev_rd 36 0050 0","deal_type":2}, + {"name":" Port 27", "cmd":"grtd_test.py dev_rd 37 0050 0","deal_type":2}, + {"name":" Port 28", "cmd":"grtd_test.py dev_rd 38 0050 0","deal_type":2}, + {"name":" Port 29", "cmd":"grtd_test.py dev_rd 39 0050 0","deal_type":2}, + {"name":" Port 30", "cmd":"grtd_test.py dev_rd 40 0050 0","deal_type":2}, + {"name":" Port 31", "cmd":"grtd_test.py dev_rd 41 0050 0","deal_type":2}, + {"name":" Port 32", "cmd":"grtd_test.py dev_rd 42 0050 0","deal_type":2}, + {"name":" Port 33", "cmd":"grtd_test.py dev_rd 43 0050 0","deal_type":2}, + {"name":" Port 34", "cmd":"grtd_test.py dev_rd 44 0050 0","deal_type":2}, + {"name":" Port 35", "cmd":"grtd_test.py dev_rd 45 0050 0","deal_type":2}, + {"name":" Port 36", "cmd":"grtd_test.py dev_rd 46 0050 0","deal_type":2}, + {"name":" Port 37", "cmd":"grtd_test.py dev_rd 47 0050 0","deal_type":2}, + {"name":" Port 38", "cmd":"grtd_test.py dev_rd 48 0050 0","deal_type":2}, + {"name":" Port 39", "cmd":"grtd_test.py dev_rd 49 0050 0","deal_type":2}, + {"name":" Port 40", "cmd":"grtd_test.py dev_rd 50 0050 0","deal_type":2}, + {"name":" Port 41", "cmd":"grtd_test.py dev_rd 51 0050 0","deal_type":2}, + {"name":" Port 42", "cmd":"grtd_test.py dev_rd 52 0050 0","deal_type":2}, + {"name":" Port 43", "cmd":"grtd_test.py dev_rd 53 0050 0","deal_type":2}, + {"name":" Port 44", "cmd":"grtd_test.py dev_rd 54 0050 0","deal_type":2}, + {"name":" Port 45", "cmd":"grtd_test.py dev_rd 55 0050 0","deal_type":2}, + {"name":" Port 46", "cmd":"grtd_test.py dev_rd 56 0050 0","deal_type":2}, + {"name":" Port 47", "cmd":"grtd_test.py dev_rd 57 0050 0","deal_type":2}, + {"name":" Port 48", "cmd":"grtd_test.py dev_rd 58 0050 0","deal_type":2}, + {"name":" Port 49", "cmd":"grtd_test.py dev_rd 59 0050 0","deal_type":2}, + {"name":" Port 50", "cmd":"grtd_test.py dev_rd 60 0050 0","deal_type":2}, + {"name":" Port 51", "cmd":"grtd_test.py dev_rd 61 0050 0","deal_type":2}, + {"name":" Port 52", "cmd":"grtd_test.py dev_rd 62 0050 0","deal_type":2}, + {"name":" Port 53", "cmd":"grtd_test.py dev_rd 63 0050 0","deal_type":2}, + {"name":" Port 54", "cmd":"grtd_test.py dev_rd 64 0050 0","deal_type":2}, + {"name":" Port 55", "cmd":"grtd_test.py dev_rd 65 0050 0","deal_type":2}, + {"name":" Port 56", "cmd":"grtd_test.py dev_rd 66 0050 0","deal_type":2}, + {"name":" Port 57", "cmd":"grtd_test.py dev_rd 67 0050 0","deal_type":2}, + {"name":" Port 58", "cmd":"grtd_test.py dev_rd 68 0050 0","deal_type":2}, + {"name":" Port 59", "cmd":"grtd_test.py dev_rd 69 0050 0","deal_type":2}, + {"name":" Port 60", "cmd":"grtd_test.py dev_rd 70 0050 0","deal_type":2}, + {"name":" Port 61", "cmd":"grtd_test.py dev_rd 71 0050 0","deal_type":2}, + {"name":" Port 62", "cmd":"grtd_test.py dev_rd 72 0050 0","deal_type":2}, + {"name":" Port 63", "cmd":"grtd_test.py dev_rd 73 0050 0","deal_type":2}, + {"name":" Port 64", "cmd":"grtd_test.py dev_rd 74 0050 0","deal_type":2}, + ] + }, + ], +} + +PCIe_DEV_LIST = [] +PCIe_SPEED_ITEM = [] + +################################Manufacturing-Test-Adaption-Area####################################################### diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile new file mode 100755 index 000000000..f10216ec4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile @@ -0,0 +1 @@ +obj-m := rg_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c new file mode 100755 index 000000000..0d890d5ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c @@ -0,0 +1,602 @@ +/* + * rg_cpld.c - A driver for cpld + * + * Copyright (c) 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* debug level */ +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; +module_param(debuglevel, int, S_IRUGO); + +#define DBG_DEBUG(fmt, arg...) do { \ + if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else if ( debuglevel >= DBG_ERROR ) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else { } \ +} while (0) + +#define DBG_ERROR(fmt, arg...) do { \ + if ( debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } \ +} while (0) + +static const unsigned short rg_i2c_cpld[] = { 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, I2C_CLIENT_END }; + +#define CPLD_SIZE 256 +#define CPLD_I2C_RETRY_TIMES 3 +#define READ_TEMP_FAIL 1000000 + +struct cpld_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static s32 cpld_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_byte_data(client, command) ) >= 0 ) + break; + } + return ret; +} + +static s32 cpld_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values) ) >= 0 ) + break; + } + return ret; +} + +static ssize_t show_fan_rpm_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + uint8_t size; + s32 status; + s32 ret_t; + + ret_t = 0; + status = -1; + size = 0; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_byte_data(client, index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[0] = status; + status = cpld_i2c_smbus_read_byte_data(client, index + 1); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[1] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index, data->data[0]); + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index + 1, data->data[1]); + ret_t = (data->data[1] << 8) + data->data[0] ; + if (ret_t == 0 ) { + size = snprintf(buf, CPLD_SIZE, "%d\n", ret_t); + } else if (ret_t == 0xffff) { + size = snprintf(buf, CPLD_SIZE, "%d\n", 0); + } else { + size = snprintf(buf, CPLD_SIZE, "%d\n", 15000000 / ret_t); + } + mutex_unlock(&data->update_lock); + return size; +} + +static ssize_t set_cpld_sysfs_value(struct device *dev, struct device_attribute *da, const char *buf, size_t +count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + unsigned long val; + int err; + + err = kstrtoul(buf, 16, &val); + if (err) + return err; + if ((val < 0) || (val > 0xff)) { + DBG_ERROR("please enter 0x00 ~ 0xff\n"); + return -1; + } + mutex_lock(&data->update_lock); + data->data[0] = (u8)val; + DBG_DEBUG("pos: 0x%02x count = %ld, data = 0x%02x\n", attr->index, count, data->data[0]); + i2c_smbus_write_byte_data(client, attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_i2c_block_data(client, 0, 4, data->data); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x %02x %02x %02x \n", data->data[0], data->data[1], data->data[2], + data->data[3]); +} + +static ssize_t show_cpld_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_byte_data(client, attr->index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[0] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%02x\n", attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t show_mac_temp_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + int tmp_value, value; + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + + status = cpld_i2c_smbus_read_byte_data(client, index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + data->data[0] = status; + status = cpld_i2c_smbus_read_byte_data(client, index + 1); + if (status < 0) { + mutex_unlock(&data->update_lock); + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + data->data[1] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index, data->data[0]); + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index + 1, data->data[1]); + mutex_unlock(&data->update_lock); + + tmp_value = (data->data[1] << 8) + data->data[0]; + if (tmp_value == 0) { + DBG_ERROR("invalid cpld value : %d.\n", tmp_value); + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + + DBG_DEBUG("tmp_value = 0x%x\n", tmp_value); + value = 434100 - (12500000 / (tmp_value * 100 - 1) *535); + if ((value / 1000 < -70) || (value / 1000 > 200)) { + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + + return snprintf(buf, CPLD_SIZE, "%d\n", value); + +} + +/* common */ +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO | S_IWUSR, show_cpld_version, NULL, 0); + +/*0x37 hwmon*/ +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x1B); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x1D); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x1F); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x21); + +/* 0x32 */ +static SENSOR_DEVICE_ATTR(fan_speed_set, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x15); +static SENSOR_DEVICE_ATTR(fan0_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x23); +static SENSOR_DEVICE_ATTR(fan1_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x24); +static SENSOR_DEVICE_ATTR(fan2_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x25); +static SENSOR_DEVICE_ATTR(fan3_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x26); + +/* 0x37 */ +static SENSOR_DEVICE_ATTR(fan_present, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(fan_status, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, NULL, 0x31); +static SENSOR_DEVICE_ATTR(psu_status, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, NULL, 0x51); +static SENSOR_DEVICE_ATTR(broad_back_lct, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x2a); +static SENSOR_DEVICE_ATTR(broad_back_sys, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb2); + +/* 0x33 */ +static SENSOR_DEVICE_ATTR(mac_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa0); +static SENSOR_DEVICE_ATTR(broad_front_lct, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x2a); +static SENSOR_DEVICE_ATTR(broad_front_bmc, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb1); +static SENSOR_DEVICE_ATTR(broad_front_cpu, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb2); +static SENSOR_DEVICE_ATTR(broad_front_pwr, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb3); +static SENSOR_DEVICE_ATTR(broad_front_fan, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb4); +static SENSOR_DEVICE_ATTR(sfp_led1_yellow, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xad); +static SENSOR_DEVICE_ATTR(mac_temp_flag, S_IRUGO, show_cpld_sysfs_value, NULL, 0xd4); + +/* 0x34 */ +static SENSOR_DEVICE_ATTR(sfp_presence1, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(sfp_presence2, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, NULL, 0x31); +static SENSOR_DEVICE_ATTR(sfp_presence3, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, NULL, 0x32); + +static SENSOR_DEVICE_ATTR(sfp_enable, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa1); +static SENSOR_DEVICE_ATTR(sfp_led1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa2); +static SENSOR_DEVICE_ATTR(sfp_led2, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa3); +static SENSOR_DEVICE_ATTR(sfp_led3, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa4); +static SENSOR_DEVICE_ATTR(sfp_led_flash1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa5); +static SENSOR_DEVICE_ATTR(sfp_led_flash2, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa6); +static SENSOR_DEVICE_ATTR(sfp_led_flash3, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa7); +static SENSOR_DEVICE_ATTR(sfp_txdis1, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x60); +static SENSOR_DEVICE_ATTR(sfp_txdis2, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x61); +static SENSOR_DEVICE_ATTR(sfp_txdis3, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x62); + +static SENSOR_DEVICE_ATTR(port_speed1, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc0); +static SENSOR_DEVICE_ATTR(port_speed2, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc1); +static SENSOR_DEVICE_ATTR(port_speed3, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc2); +static SENSOR_DEVICE_ATTR(port_speed4, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc3); +static SENSOR_DEVICE_ATTR(port_speed5, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc4); +static SENSOR_DEVICE_ATTR(port_speed6, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc5); + +/* 0x35 */ +static SENSOR_DEVICE_ATTR(sfp_enable2, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa0); +static SENSOR_DEVICE_ATTR(sfp_led2_yellow, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xad); +static SENSOR_DEVICE_ATTR(mac_temp_input, S_IRUGO, show_mac_temp_value, NULL, 0xca); + +/* 0x36 */ +static SENSOR_DEVICE_ATTR(sfp_presence4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(sfp_presence5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x31); +static SENSOR_DEVICE_ATTR(sfp_presence6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x32); +static SENSOR_DEVICE_ATTR(sfp_presence7, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x33); +static SENSOR_DEVICE_ATTR(sfp_led4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa2); +static SENSOR_DEVICE_ATTR(sfp_led5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa3); +static SENSOR_DEVICE_ATTR(sfp_led6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa4); +static SENSOR_DEVICE_ATTR(sfp_led7, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa5); +static SENSOR_DEVICE_ATTR(sfp_led_flash4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa6); +static SENSOR_DEVICE_ATTR(sfp_led_flash5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa7); +static SENSOR_DEVICE_ATTR(sfp_led_flash6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa8); +static SENSOR_DEVICE_ATTR(sfp_led_flash7, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa9); + +static SENSOR_DEVICE_ATTR(sfp_txdis4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0x60); +static SENSOR_DEVICE_ATTR(sfp_txdis5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0x61); +static SENSOR_DEVICE_ATTR(sfp_txdis6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0x62); + +static SENSOR_DEVICE_ATTR(port_speed7, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc0); +static SENSOR_DEVICE_ATTR(port_speed8, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc1); +static SENSOR_DEVICE_ATTR(port_speed9, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc2); +static SENSOR_DEVICE_ATTR(port_speed10, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc3); +static SENSOR_DEVICE_ATTR(port_speed11, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc4); +static SENSOR_DEVICE_ATTR(port_speed12, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc5); +static SENSOR_DEVICE_ATTR(port_speed13, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc6); +static SENSOR_DEVICE_ATTR(port_speed14, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc7); + +static struct attribute *cpld32_sysfs_attrs[] = { + &sensor_dev_attr_fan_speed_set.dev_attr.attr, + &sensor_dev_attr_fan0_led.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + NULL +}; + +static struct attribute *cpld37_sysfs_attrs[] = { + &sensor_dev_attr_fan_present.dev_attr.attr, + &sensor_dev_attr_fan_status.dev_attr.attr, + &sensor_dev_attr_psu_status.dev_attr.attr, + &sensor_dev_attr_broad_back_lct.dev_attr.attr, + &sensor_dev_attr_broad_back_sys.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + NULL +}; + +static struct attribute *cpld33_sysfs_attrs[] = { + &sensor_dev_attr_mac_led.dev_attr.attr, + &sensor_dev_attr_broad_front_lct.dev_attr.attr, + &sensor_dev_attr_broad_front_bmc.dev_attr.attr, + &sensor_dev_attr_broad_front_cpu.dev_attr.attr, + &sensor_dev_attr_broad_front_pwr.dev_attr.attr, + &sensor_dev_attr_broad_front_fan.dev_attr.attr, + &sensor_dev_attr_sfp_led1_yellow.dev_attr.attr, + &sensor_dev_attr_mac_temp_flag.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + NULL +}; + +static struct attribute *cpld34_sysfs_attrs[] = { + &sensor_dev_attr_sfp_presence1.dev_attr.attr, + &sensor_dev_attr_sfp_presence2.dev_attr.attr, + &sensor_dev_attr_sfp_presence3.dev_attr.attr, + &sensor_dev_attr_sfp_enable.dev_attr.attr, + &sensor_dev_attr_sfp_led1.dev_attr.attr, + &sensor_dev_attr_sfp_led2.dev_attr.attr, + &sensor_dev_attr_sfp_led3.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash1.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash2.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash3.dev_attr.attr, + &sensor_dev_attr_sfp_txdis1.dev_attr.attr, + &sensor_dev_attr_sfp_txdis2.dev_attr.attr, + &sensor_dev_attr_sfp_txdis3.dev_attr.attr, + &sensor_dev_attr_port_speed1.dev_attr.attr, + &sensor_dev_attr_port_speed2.dev_attr.attr, + &sensor_dev_attr_port_speed3.dev_attr.attr, + &sensor_dev_attr_port_speed4.dev_attr.attr, + &sensor_dev_attr_port_speed5.dev_attr.attr, + &sensor_dev_attr_port_speed6.dev_attr.attr, + NULL +}; + +static struct attribute *cpld36_sysfs_attrs[] = { + &sensor_dev_attr_sfp_presence4.dev_attr.attr, + &sensor_dev_attr_sfp_presence5.dev_attr.attr, + &sensor_dev_attr_sfp_presence6.dev_attr.attr, + &sensor_dev_attr_sfp_presence7.dev_attr.attr, + &sensor_dev_attr_sfp_led4.dev_attr.attr, + &sensor_dev_attr_sfp_led5.dev_attr.attr, + &sensor_dev_attr_sfp_led6.dev_attr.attr, + &sensor_dev_attr_sfp_led7.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash4.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash5.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash6.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash7.dev_attr.attr, + &sensor_dev_attr_sfp_txdis4.dev_attr.attr, + &sensor_dev_attr_sfp_txdis5.dev_attr.attr, + &sensor_dev_attr_sfp_txdis6.dev_attr.attr, + &sensor_dev_attr_port_speed7.dev_attr.attr, + &sensor_dev_attr_port_speed8.dev_attr.attr, + &sensor_dev_attr_port_speed9.dev_attr.attr, + &sensor_dev_attr_port_speed10.dev_attr.attr, + &sensor_dev_attr_port_speed11.dev_attr.attr, + &sensor_dev_attr_port_speed12.dev_attr.attr, + &sensor_dev_attr_port_speed13.dev_attr.attr, + &sensor_dev_attr_port_speed14.dev_attr.attr, + NULL +}; + +static struct attribute *cpld35_sysfs_attrs[] = { + &sensor_dev_attr_sfp_enable2.dev_attr.attr, + &sensor_dev_attr_broad_front_lct.dev_attr.attr, + &sensor_dev_attr_broad_front_bmc.dev_attr.attr, + &sensor_dev_attr_broad_front_cpu.dev_attr.attr, + &sensor_dev_attr_broad_front_pwr.dev_attr.attr, + &sensor_dev_attr_broad_front_fan.dev_attr.attr, + &sensor_dev_attr_sfp_led2_yellow.dev_attr.attr, + &sensor_dev_attr_mac_temp_input.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld32_sysfs_group = { + .attrs = cpld32_sysfs_attrs, +}; + +static const struct attribute_group cpld37_sysfs_group = { + .attrs = cpld37_sysfs_attrs, +}; + +static const struct attribute_group cpld33_sysfs_group = { + .attrs = cpld33_sysfs_attrs, +}; + +static const struct attribute_group cpld34_sysfs_group = { + .attrs = cpld34_sysfs_attrs, +}; + +static const struct attribute_group cpld36_sysfs_group = { + .attrs = cpld36_sysfs_attrs, +}; + +static const struct attribute_group cpld35_sysfs_group = { + .attrs = cpld35_sysfs_attrs, +}; + +static struct attribute *cpld_hwmon_attrs[] = { + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + NULL +}; +ATTRIBUTE_GROUPS(cpld_hwmon); + +struct cpld_attr_match_group { + int bus_nr; /* I2C BUS */ + unsigned short addr; /* slave addr*/ + const struct attribute_group *attr_group_ptr; + const struct attribute_group *attr_hwmon_ptr; +}; + +static struct cpld_attr_match_group g_cpld_attr_match[] = { + {0, 0x32, &cpld32_sysfs_group, NULL}, + {2, 0x37, &cpld37_sysfs_group, (struct attribute_group *)cpld_hwmon_groups}, + {2, 0x33, &cpld33_sysfs_group, NULL}, + {1, 0x34, &cpld34_sysfs_group, NULL}, + {1, 0x36, &cpld36_sysfs_group, NULL}, + {2, 0x35, &cpld35_sysfs_group, NULL}, +}; + +static const struct attribute_group *cpld_get_attr_group(struct i2c_client *client, int is_hwmon) +{ + int i; + struct cpld_attr_match_group *group; + + for (i = 0; i < ARRAY_SIZE(g_cpld_attr_match); i++) { + group = &g_cpld_attr_match[i]; + DBG_DEBUG("is_hwmon %d i %d client(nr:%d,addr:0x%x), group(nr:%d,addr:0x0%x).\n", is_hwmon, + i, client->adapter->nr, client->addr, group->bus_nr, group->addr); + if ((client->addr == group->addr) && (client->adapter->nr == group->bus_nr)) { + DBG_DEBUG("is_hwmon %d i %d nr %d addr %d .\n", is_hwmon, i, client->adapter->nr, client->addr); + return (is_hwmon) ? (group->attr_hwmon_ptr) : (group->attr_group_ptr); + } + } + + DBG_DEBUG("is_hwmon %d nr %d addr %d dismatch, return NULL.\n", is_hwmon, client->adapter->nr, client->addr); + return NULL; +} + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + const struct attribute_group *sysfs_group, *hwmon_group; + + status = -1; + DBG_DEBUG("=========cpld_probe(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + status = sysfs_create_group(&client->dev.kobj, sysfs_group); + DBG_DEBUG("=========(addr:0x%x, nr:%d) sysfs_create_group status %d===========\n", client->addr, client->adapter->nr, status); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_create_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + data->hwmon_dev = hwmon_device_register_with_groups(&client->dev, client->name, data, (const struct attribute_group **)hwmon_group); + if (IS_ERR(data->hwmon_dev)) { + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + DBG_ERROR("hwmon_device_register_with_groups failed ret %ld.\n", PTR_ERR(data->hwmon_dev)); + return PTR_ERR(data->hwmon_dev); + } + DBG_DEBUG("=========(addr:0x%x, nr:%d) hwmon_device_register_with_groups success===========\n", client->addr, client->adapter->nr); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_register_with_groups \n", client->addr, client->adapter->nr); + } + +error: + return status; + +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *sysfs_group, *hwmon_group; + + DBG_DEBUG("=========cpld_remove(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do sysfs_remove_group \n", client->addr, client->adapter->nr); + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_remove_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do hwmon_device_unregister \n", client->addr, client->adapter->nr); + hwmon_device_unregister(data->hwmon_dev); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_unregister \n", client->addr, client->adapter->nr); + } + + return 0; +} + + +static const struct i2c_device_id cpld_id[] = { + { "rg_cpld", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver rg_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "rg_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +}; + +module_i2c_driver(rg_cpld_driver); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh new file mode 100755 index 000000000..c7833deea --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +#platform init script for B6510-48VS8CQ + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +remove_python_api_package() { + rv=$(pip show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +if [[ "$1" == "init" ]]; then + echo "b6510 init" + install_python_api_package + +elif [[ "$1" == "deinit" ]]; then + remove_python_api_package +else + echo "B6510-48VS8CQ_PLATFORM : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py new file mode 100644 index 000000000..2dfacd39b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on RUIJIE B6510 Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='sonic_rd@ruijie.com.cn', + url='', + maintainer='RUIJIE B6510', + maintainer_email='', + packages=[ + 'sonic_platform', + 'plat_hal', + 'rjutil', + 'eepromutil', + 'sonic_pcie' + ], + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Plugins', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py new file mode 100644 index 000000000..73e2a89c8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py @@ -0,0 +1 @@ +__all__ = ["pcie_common"] \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py new file mode 100644 index 000000000..56e9d8664 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py @@ -0,0 +1,107 @@ +# pcie_common.py +# Common PCIE check interfaces for SONIC +# + +import os +import yaml +import subprocess +import re +import sys +from copy import deepcopy +try: + from .pcie import PcieBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PcieUtil(PcieBase): + """Platform-specific PCIEutil class""" + # got the config file path + def __init__(self, path): + self.config_path = path + + # load the config file + def load_config_file(self): + config_file = self.config_path + "/" + "pcie.yaml" + try: + with open(config_file) as conf_file: + self.confInfo = yaml.load(conf_file) + except IOError as e: + print("Error: {}".format(str(e))) + print("Not found config file, please add a config file manually, or generate it by running [pcieutil pcie_generate]") + sys.exit() + + # load current PCIe device + def get_pcie_device(self): + pciDict = {} + pciList = [] + p1 = "^(\w+):(\w+)\.(\w)\s(.*)\s*\(*.*\)*" + p2 = "^.*:.*:.*:(\w+)\s*\(*.*\)*" + command1 = "sudo lspci" + command2 = "sudo lspci -n" + # run command 1 + proc1 = subprocess.Popen(command1, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + output1 = proc1.stdout.readlines() + proc1.communicate() + # run command 2 + proc2 = subprocess.Popen(command2, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + output2 = proc2.stdout.readlines() + proc2.communicate() + + if proc1.returncode > 0: + for line1 in output1: + print(line1.strip()) + return + elif proc2.returncode > 0: + for line2 in output2: + print(line2.strip()) + return + else: + for (line1, line2) in zip(output1, output2): + pciDict.clear() + match1 = re.search(p1, line1.strip()) + match2 = re.search(p2, line2.strip()) + if match1 and match2: + Bus = match1.group(1) + Dev = match1.group(2) + Fn = match1.group(3) + Name = match1.group(4) + Id = match2.group(1) + pciDict["name"] = Name + pciDict["bus"] = Bus + pciDict["dev"] = Dev + pciDict["fn"] = Fn + pciDict["id"] = Id + pciList.append(pciDict) + pciDict = deepcopy(pciDict) + else: + print("CAN NOT MATCH PCIe DEVICE") + return pciList + + # check the sysfs tree for each PCIe device + def check_pcie_sysfs(self, domain=0, bus=0, device=0, func=0): + dev_path = os.path.join('/sys/bus/pci/devices', '%04x:%02x:%02x.%d' % (domain, bus, device, func)) + if os.path.exists(dev_path): + return True + return False + + # check the current PCIe device with config file and return the result + def get_pcie_check(self): + self.load_config_file() + for item_conf in self.confInfo: + bus_conf = item_conf["bus"] + dev_conf = item_conf["dev"] + fn_conf = item_conf["fn"] + if self.check_pcie_sysfs(bus=int(bus_conf, base=16), device=int(dev_conf, base=16), func=int(fn_conf, base=16)): + item_conf["result"] = "Passed" + else: + item_conf["result"] = "Failed" + return self.confInfo + + # generate the config file with current pci device + def dump_conf_yaml(self): + curInfo = self.get_pcie_device() + with open(self.config_path + "/" + "pcie.yaml", "w") as conf_file: + yaml.dump(curInfo, conf_file, default_flow_style=False) + return + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py new file mode 100644 index 000000000..f6c1757b8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu", "sfp", "thermal", "common"] diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py new file mode 100644 index 000000000..ea4048e19 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py @@ -0,0 +1,448 @@ +# -*- coding: utf-8 -*- + +############################################################################# +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.common import Common + from sonic_platform.sfp import Sfp + from sonic_platform.sfp import PORT_START + from sonic_platform.sfp import PORTS_IN_BLOCK + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(ChassisBase): + """ + Ruijie B6510-48VS8CQ Platform-specific Chassis class + """ + def __init__(self): + ChassisBase.__init__(self) + self.CHASSIS_CONFIG = 'chassis.json' + self.THERMAL_CONFIG = 'thermal.json' + self.SFP_CONFIG = 'sfp.json' + self.PSU_CONFIG = 'psu.json' + self.FAN_CONFIG = 'fan.json' + self.COMPONENT_CONFIG = 'component.json' + + self.SFP_STATUS_INSERTED = "1" + self.SFP_STATUS_REMOVED = "0" + self.port_dict = {} + self.enable_read= "i2cset -f -y 2 0x35 0x2a 0x01" + self.disable_read = "i2cset -f -y 2 0x35 0x2a 0x00" + self.enable_write = "i2cset -f -y 2 0x35 0x2b 0x00" + self.disable_write = "i2cset -f -y 2 0x35 0x2b 0x01" + self.enable_erase = "i2cset -f -y 2 0x35 0x2c 0x01" + self.disable_erase = "i2cset -f -y 2 0x35 0x2c 0x00" + self.read_value = "i2cget -f -y 2 0x35 0x25" + self.write_value = "i2cset -f -y 2 0x35 0x21 0x0a" + self.set_sys_led_cmd = "i2cset -f -y 2 0x33 0xb2 " + self.get_sys_led_cmd = "i2cget -f -y 2 0x33 0xb2" + self.led_status = "red" + # Initialize SFP list + # sfp.py will read eeprom contents and retrive the eeprom data. + # It will also provide support sfp controls like reset and setting + # low power mode. + # We pass the eeprom path and sfp control path from chassis.py + # So that sfp.py implementation can be generic to all platforms + for index in range(PORT_START, PORTS_IN_BLOCK): + sfp_node = Sfp(index) + self._sfp_list.append(sfp_node) + if sfp_node.get_presence(): + self.port_dict[index] = self.SFP_STATUS_INSERTED + else: + self.port_dict[index] = self.SFP_STATUS_REMOVED + + self._api_common = Common() + config_path = self._api_common.get_config_path(self.CHASSIS_CONFIG) + self._config = self._api_common.load_json_file(config_path) + self.__initialize_eeprom() + + if self._api_common.is_host(): + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + else: + self.__initialize_components() + + def __initialize_fan(self): + from sonic_platform.fan import Fan + from sonic_platform.fan_drawer import FanDrawer + + fan_config_path = self._api_common.get_config_path(self.FAN_CONFIG) + self.fan_config = self._api_common.load_json_file(fan_config_path)["fans"] + + if self.fan_config: + drawer_fan_list = [] + for index in range(0, len(self.fan_config)): + fan = Fan(index, config=self.fan_config[index]) + self._fan_list.append(fan) + drawer_fan_list.append(fan) + fan_drawer = FanDrawer(0, fan_list=drawer_fan_list) + self._fan_drawer_list.append(fan_drawer) + + def __initialize_psu(self): + from sonic_platform.psu import Psu + + psu_config_path = self._api_common.get_config_path(self.PSU_CONFIG) + self.psu_config = self._api_common.load_json_file(psu_config_path)["psus"] + + if self.psu_config: + for index in range(0, len(self.psu_config)): + psu = Psu(index, config=self.psu_config[index]) + self._psu_list.append(psu) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + + thermal_config_path = self._api_common.get_config_path(self.THERMAL_CONFIG) + self.thermal_config = self._api_common.load_json_file(thermal_config_path)['thermals'] + + if self.thermal_config: + for index in range(0, len(self.thermal_config)): + thermal = Thermal(index, config=self.thermal_config[index]) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Eeprom + self._eeprom = Eeprom(config=self._config["eeprom"]) + + + def __initialize_components(self): + from sonic_platform.component import Component + + component_config_path = self._api_common.get_config_path(self.COMPONENT_CONFIG) + self.component_config = self._api_common.load_json_file(component_config_path)['components'] + + if self.component_config: + for index in range(0, len(self.component_config)): + component = Component(index, config=self.component_config[index]) + self._component_list.append(component) + + def _init_standard_config(self, conflist, class_name, objlist): + for conf in conflist: + obj = globals()[class_name](conf.get("name"), config=conf) + objlist.append(obj) + + def _init_by_hal(self, hal_interface): + self.hal_interface = hal_interface + self.hal_interface.get_fans() + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + try: + is_power_loss = False + # enable read + subprocess.getstatusoutput(self.disable_write) + subprocess.getstatusoutput(self.enable_read) + ret , log = subprocess.getstatusoutput(self.read_value) + if ret == 0 and "0x0a" in log: + is_power_loss = True + + # erase i2c and e2 + subprocess.getstatusoutput(self.enable_erase) + time.sleep(1) + subprocess.getstatusoutput(self.disable_erase) + # clear data + subprocess.getstatusoutput(self.enable_write) + subprocess.getstatusoutput(self.disable_read) + subprocess.getstatusoutput(self.disable_write) + subprocess.getstatusoutput(self.enable_read) + # enable write and set data + subprocess.getstatusoutput(self.enable_write) + subprocess.getstatusoutput(self.disable_read) + subprocess.getstatusoutput(self.write_value) + if is_power_loss: + return(self.REBOOT_CAUSE_POWER_LOSS, None) + except Exception as e: + logger.error(str(e)) + + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + change_event_dict = {"fan": {}, "sfp": {}} + sfp_status, sfp_change_dict = self.get_transceiver_change_event(timeout) + change_event_dict["sfp"] = sfp_change_dict + if sfp_status is True: + return True, change_event_dict + + return False, {} + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + currernt_port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print( + "get_transceiver_change_event:" "time wrap / invalid timeout value", + timeout, + ) + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + for index in range(PORT_START, PORTS_IN_BLOCK): + if self._sfp_list[index].get_presence(): + currernt_port_dict[index] = self.SFP_STATUS_INSERTED + else: + currernt_port_dict[index] = self.SFP_STATUS_REMOVED + if currernt_port_dict == self.port_dict: + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + else: + # Update reg value + self.port_dict = currernt_port_dict + print(self.port_dict) + return True, self.port_dict + print("get_transceiver_change_event: Should not reach here.") + return False, {} + + def get_all_components(self): + return self._component_list + + def get_all_fans(self): + return self._fan_list + + def get_all_psus(self): + return self._psu_list + + def get_all_thermals(self): + return self._thermal_list + + def get_supervisor_slot(self): + """ + Retrieves the physical-slot of the supervisor-module in the modular + chassis. On the supervisor or line-card modules, it will return the + physical-slot of the supervisor-module. + On the fixed-platforms, the API can be ignored. + Users of the API can catch the exception and return a default + ModuleBase.MODULE_INVALID_SLOT and bypass code for fixed-platforms. + Returns: + An integer, the vendor specific physical slot identifier of the + supervisor module in the modular-chassis. + """ + return 0 + + def get_my_slot(self): + """ + Retrieves the physical-slot of this module in the modular chassis. + On the supervisor, it will return the physical-slot of the supervisor + module. On the linecard, it will return the physical-slot of the + linecard module where this instance of SONiC is running. + On the fixed-platforms, the API can be ignored. + Users of the API can catch the exception and return a default + ModuleBase.MODULE_INVALID_SLOT and bypass code for fixed-platforms. + Returns: + An integer, the vendor specific physical slot identifier of this + module in the modular-chassis. + """ + return 0 + + def is_modular_chassis(self): + """ + Retrieves whether the sonic instance is part of modular chassis + Returns: + A bool value, should return False by default or for fixed-platforms. + Should return True for supervisor-cards, line-cards etc running as part + of modular-chassis. + """ + return True + + def init_midplane_switch(self): + """ + Initializes the midplane functionality of the modular chassis. For + example, any validation of midplane, populating any lookup tables etc + can be done here. The expectation is that the required kernel modules, + ip-address assignment etc are done before the pmon, database dockers + are up. + Returns: + A bool value, should return True if the midplane initialized + successfully. + """ + return True + + def get_module_index(self, module_name): + """ + Retrieves module index from the module name + Args: + module_name: A string, prefixed by SUPERVISOR, LINE-CARD or FABRIC-CARD + Ex. SUPERVISOR0, LINE-CARD1, FABRIC-CARD5 + Returns: + An integer, the index of the ModuleBase object in the module_list + """ + return 0 + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + colors = { + "amber" : "0x00", + "red" : "0x02", + "green" : "0x04" + } + regval = colors.get(color, None) + if regval is None: + print("Invaild color input.") + return False + ret , log = subprocess.getstatusoutput(self.set_sys_led_cmd + regval) + if ret != 0: + print("Cannot execute %s" % self.set_sys_led_cmd + regval) + return False + self.led_status = color + return True + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + ret , log = subprocess.getstatusoutput(self.get_sys_led_cmd) + if ret != 0: + print("Cannot execute %s" % self.get_sys_led_cmd) + return False + colors = { + "0x00" : "amber", + "0x02" : "red", + "0x04" : "green" + } + color = colors.get(log, None) + if color is None: + return "Unknown color status" + self.led_status = color + return self.led_status + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py new file mode 100644 index 000000000..c1a85f618 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py @@ -0,0 +1,44 @@ +import os +import yaml + +from sonic_py_common import device_info + + +class Common: + + DEVICE_PATH = '/usr/share/sonic/device/' + PMON_PLATFORM_PATH = '/usr/share/sonic/platform/' + CONFIG_DIR = 'sonic_platform_config' + + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def load_json_file(self, path): + """ + Retrieves the json object from json file path + + Returns: + A json object + """ + with open(path, 'r') as f: + json_data = yaml.safe_load(f) + + return json_data + + def get_config_path(self, config_name): + """ + Retrieves the path to platform api config directory + + Args: + config_name: A string containing the name of config file. + + Returns: + A string containing the path to json file + """ + return os.path.join(self.DEVICE_PATH, self.platform, self.CONFIG_DIR, config_name) if self.is_host() else os.path.join(self.PMON_PLATFORM_PATH, self.CONFIG_DIR, config_name) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py new file mode 100644 index 000000000..33ff6ef8b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py @@ -0,0 +1,85 @@ +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Component(ComponentBase): + """Ruijie Platform-specific Component class""" + + def __init__(self, index, config=None): + self.index = index + self.name = config.get("name") + self._reg_fm_ver = Reg(config.get("firmware_version")) + self.description = config.get("desc") + self.slot = config.get("slot") + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + try: + return self._reg_fm_ver.decode() + except Exception as e: + logger.error(str(e)) + + return "" + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + try: + successtips = "CPLD Upgrade succeeded!" + status, output = subprocess.getstatusoutput("which firmware_upgrade") + if status or len(output) <= 0: + logger.error("no upgrade tool.") + return False + cmdstr = "%s %s cpld %d cpld"%(output,image_path,self.slot) + ret, log = subprocess.getstatusoutput(cmdstr) + if ret == 0 and successtips in log: + return True + logger.error("upgrade failed. ret:%d, log:\n%s" % (ret, log)) + except Exception as e: + logger.error(str(e)) + return False + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py new file mode 100644 index 000000000..162f01680 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py @@ -0,0 +1,558 @@ +# -*- coding: utf-8 -*- + +PSU_FAN_AIRFLOW = { + "CSU550AP-3-300": "F2B", + "AS-40FAN-01-F-RJ": "F2B", + "CSU550AP-3-500": "F2B", + "DPS-550AB-39 A": "F2B", + "DPS-1300AB-6 S": "F2B", + "FSP1200-20ERM": "F2B", + "CSU800AP-3-300": "F2B", + "CSU550AP-3-501": "B2F", + "DPS-550AB-40 A": "B2F", +} + +FAN_AIRFLOW = { + "AS-80FAN-01-F-RJ": "F2B", + "AS-40FAN-01-F-RJ": "F2B", + "AS-80FAN-01-R-RJ": "B2F", + "AS-40FAN-01-R-RJ": "B2F", +} + +psutypedecode = { + 0x00: "N/A", + 0x01: "AC", + 0x02: "DC", +} + + +class Unit: + Temperature = "C" + Voltage = "V" + Current = "A" + Power = "W" + Speed = "RPM" + + +class Threshold: + PSU_TEMP_MIN = -10 * 1000 + PSU_TEMP_MAX = 60 * 1000 + + PSU_FAN_SPEED_MIN = 2000 + PSU_FAN_SPEED_MAX = 28000 + + PSU_OUTPUT_VOLTAGE_MIN = 11 * 1000 + PSU_OUTPUT_VOLTAGE_MAX = 14 * 1000 + + PSU_AC_INPUT_VOLTAGE_MIN = 200 * 1000 + PSU_AC_INPUT_VOLTAGE_MAX = 240 * 1000 + + PSU_DC_INPUT_VOLTAGE_MIN = 190 * 1000 + PSU_DC_INPUT_VOLTAGE_MAX = 290 * 1000 + + ERR_VALUE = -9999999 + + PSU_OUTPUT_POWER_MIN = 10 * 1000 + PSU_OUTPUT_POWER_MAX = 1300 * 1000 + + PSU_INPUT_POWER_MIN = 10 * 1000 + PSU_INPUT_POWER_MAX = 1444 * 1000 + + PSU_OUTPUT_CURRENT_MIN = 2 * 1000 + PSU_OUTPUT_CURRENT_MAX = 107 * 1000 + + PSU_INPUT_CURRENT_MIN = 0.2 * 1000 + PSU_INPUT_CURRENT_MAX = 7 * 1000 + + FAN_SPEED_MAX = 23000 + FAN_SPEED_MIN = 500 + + +class DecodeFormat: + TEXT = 0 + DECIMAL = 1 + ONE_BIT_HEX = 2 + HUNDREDTH = 3 + THOUSANDTH = 4 + MILLIONTH = 5 + AND = 6 + JOIN = 7 + + +class DecodeMethod: + SYSFS = 0 + I2C = 1 + I2C_WORD = 2 + DEVMEM = 3 + SDK = 4 + + +class Description: + CPLD = "Used for managing IO modules, SFP+ modules and system LEDs" + BIOS = "Performs initialization of hardware components during booting" + FPGA = "Platform management controller for on-board temperature monitoring, in-chassis power, Fan and LED control" + + +FAN_LED_COLORS = { + "green": 0b1001, + "red": 0b1010, + "amber": 0b0011, +} + + +DEVICE_CONF = { + "eeprom": {"bus": 2, "loc": "0057"}, + "components": [ + { + "name": "CPLD1 (MAC Board A)", + "firmware_version": { + "bus": 2, + "addr": 0x33, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 0, + }, + { + "name": "CPLD2 (MAC Board B)", + "firmware_version": { + "bus": 2, + "addr": 0x35, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 0, + }, + { + "name": "CPLD3 (CONNECT Board A)", + "firmware_version": { + "bus": 2, + "addr": 0x37, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 0, + }, + { + "name": "CPLD4 (CPU Board)", + "firmware_version": { + "bus": 0, + "addr": 0x0D, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 1, + }, + ], + "thermals": [ + { + "name": "INLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": None, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "OUTLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": None, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "BOARD TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": None, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "PHYSICAL ID 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp2_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 1", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp3_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 2", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp4_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 3", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp5_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + ], + "fans": [ + { + "name": "fan1", + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 0, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 0, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/3-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/3-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan0_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan1_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + { + "name": "fan2", + "e2loc": {"bus": 4, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/4-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/4-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan1_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan2_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + { + "name": "fan3", + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 2, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 2, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/5-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/5-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan2_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan3_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + { + "name": "fan4", + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 3, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 3, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/6-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/6-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan3_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan4_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + ], + "psus": [ + { + "name": "psu1", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 0, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "sn": {"loc": "/sys/bus/i2c/devices/7-0050/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/7-0050/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/7-0050/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_fault", + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_input" + }, + "speed_max": Threshold.PSU_FAN_SPEED_MAX, + } + ], + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power1_input", + "format": DecodeFormat.MILLIONTH, + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power2_input", + "format": DecodeFormat.MILLIONTH, + }, + }, + { + "name": "psu2", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 4, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 5, + }, + "sn": {"loc": "/sys/bus/i2c/devices/8-0053/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/8-0053/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/8-0053/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_fault", + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 5, + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_input" + }, + "speed_max": Threshold.PSU_FAN_SPEED_MAX, + } + ], + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power1_input", + "format": DecodeFormat.MILLIONTH, + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power2_input", + "format": DecodeFormat.MILLIONTH, + }, + }, + ], +} diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py new file mode 100644 index 000000000..5fe0561f6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- + +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains platform specific implementation of SONiC Platform +# Base API and provides the EEPROMs' information. +# +# The different EEPROMs available are as follows: +# - System EEPROM : Contains Serial number, Service tag, Base MA +# address, etc. in ONIE TlvInfo EEPROM format. +# - PSU EEPROM : Contains Serial number, Part number, Service Tag, +# PSU type, Revision. +# - Fan EEPROM : Contains Serial number, Part number, Service Tag, +# Fan type, Number of Fans in Fantray, Revision. +######################################################################## + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self, bus=2, loc="0057", config=None, iom_eeprom=False): + self.is_module = iom_eeprom + + if config: + bus = config.get("bus") + loc = config.get("loc") + + if bus and loc: + self.eeprom_path = "/sys/bus/i2c/devices/{}-{}/eeprom".format(bus, loc) + else: + raise ValueError( + "Eeprom location error, bus: {}, loc: {}, config: {}".format( + bus, loc, config + ) + ) + + super(Eeprom, self).__init__(self.eeprom_path, 0, "", True) + self.eeprom_tlv_dict = dict() + + try: + if self.is_module: + # TODO + pass + # self.write_eeprom("\x00\x00") + # self.eeprom_data = self.read_eeprom_bytes(256) + else: + self.eeprom_data = self.read_eeprom() + except Exception: + self.eeprom_data = "N/A" + if not self.is_module: + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index : tlv_index + 2 + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str( + (tlv[2] << 24) + | (tlv[3] << 16) + | (tlv[4] << 8) + | tlv[5] + ) + value += str(tlv[6 : 6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index + 1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER + ) + if not is_valid: + return "N/A" + + return results[2] + + def base_mac_addr(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE + ) + if not is_valid or results[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([hex(T) for T in results[2]]) + + def modelstr(self): + if self.is_module: + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PLATFORM_NAME + ) + else: + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME + ) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER + ) + if not is_valid: + return "N/A" + + return results[2] + + def serial_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG + ) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION + ) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py new file mode 100644 index 000000000..173c05294 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- + +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_base import FanBase + from sonic_platform.regutil import Reg + from sonic_platform.rotor import Rotor + from sonic_platform.logger import logger + from math import ceil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Fan(FanBase): + """Ruijie Platform-specific Fan class""" + + MAX_SPEED_CODE = 255 + + def __init__(self, index, config=None, hal_fan=None, is_psu_fan=False): + self.index = index + self.is_psu_fan = is_psu_fan + if config: + if self.is_psu_fan: + self.name = "Psu{}-{}".format(self.index, config.get("name")) + else: + self.name = config.get("name") + self.__reg_sn = Reg(config.get("sn")) + self.__reg_present = Reg(config.get("present")) + self.__reg_status = Reg(config.get("status")) + self.__reg_led = Reg(config.get("led")) + self.__reg_pn = Reg(config.get("pn")) + self.__led_colors = config.get("led_colors") + + # rotors + rotors = config.get("rotors") + if isinstance(rotors, list): + self.__rotors = [] + for rotor in rotors: + self.__rotors.append(Rotor(rotor)) + + self._hal_fan = hal_fan + + def _reg_setter(self, target, val): + if isinstance(val, dict): + target = Reg(val) + elif isinstance(val, Reg): + target = val + else: + raise ValueError + return target + + @property + def reg_sn(self): + return self.__reg_sn + + @reg_sn.setter + def reg_sn(self, val): + self._reg_setter(self.__reg_sn, val) + + @property + def reg_present(self): + return self.__reg_present + + @reg_present.setter + def reg_present(self, val): + self._reg_setter(self.__reg_present, val) + + @property + def reg_status(self): + return self.__reg_status + + @reg_status.setter + def reg_status(self, val): + self._reg_setter(self.__reg_status, val) + + @property + def reg_led(self): + return self.__reg_led + + @reg_led.setter + def reg_led(self, val): + self._reg_setter(self.__reg_led, val) + + def get_name(self): + """ + Retrieves the fan name + Returns: + string: The name of the device + """ + return self.name + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + string: Part number of FAN + """ + if self._hal_fan: + return self._hal_fan.pn() + + try: + if isinstance(self.__reg_pn, Reg): + return self.__reg_pn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + string: Serial number of FAN + """ + if self._hal_fan: + return self._hal_fan.sn() + + try: + if isinstance(self.__reg_sn, Reg): + return self.__reg_sn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + + # print self.fan_presence_reg.decode() + # return True if self.fan_presence_reg.decode() == 0 else False + if self._hal_fan: + return self._hal_fan.get_presence() + + try: + if isinstance(self.__reg_present, Reg): + present = self.__reg_present.decode() + if present == 0 or present == "0": + return True + except Exception as e: + logger.error(str(e)) + + return False + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + + # return True if self.fan_status_reg.decode() == 1 else False + if self._hal_fan: + return self._hal_fan.get_status() + + try: + if isinstance(self.__reg_status, Reg): + status = self.__reg_status.decode() + if status == 1 or status == "1": + return True + except Exception as e: + pass + + return False + + def get_direction(self): + """ + Retrieves the fan airflow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + + # TODO + return self.FAN_DIRECTION_EXHAUST + + def get_speed(self): + """ + Retrieves the speed of fan + Returns: + int: percentage of the max fan speed + """ + if self.get_presence(): + maxspeed = 0 + for r in self.__rotors: + speed = r.get_speed_percentage() + if speed > maxspeed: + maxspeed = speed + return maxspeed + else: + return 0 + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + # TODO + return 0 + + def set_speed(self, speed): + """ + Set fan speed to expected value + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + bool: True if set success, False if fail. + """ + if self.__rotors: + speed_code = hex(int(ceil(float(self.MAX_SPEED_CODE) / 100 * speed))) + return self.__rotors[0].set_speed(speed_code) + + return False + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # TODO + if self.is_psu_fan: + # No LED available for PSU Fan + return False + try: + if color not in self.__led_colors: + logger.error("color:%s not defined." % color) + return False + val = hex(self.__led_colors[color]) + if isinstance(self.__reg_led, Reg): + return self.__reg_led.encode(val) + return ret + except Exception as e: + logger.error(str(e)) + return False + + + def get_status_led(self): + """ + Gets the state of the Fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + # TODO + if self.is_psu_fan: + # No LED available for PSU Fan + return None + else: + try: + if isinstance(self.__reg_led, Reg) : + led_color = self.__reg_led.decode() + for color, code in self.__led_colors.items(): + if code ^ led_color == 0: + return color + except Exception as e: + logger.error(str(e)) + + return None + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + # TODO + return 0 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py new file mode 100644 index 000000000..692819a04 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py @@ -0,0 +1,71 @@ +# +# fan_drawer_base.py +# +# Abstract base class for implementing a platform-specific class with which +# to interact with a fan drawer module in SONiC +# + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(FanDrawerBase): + """ + Abstract base class for interfacing with a fan drawer + """ + # Device type definition. Note, this is a constant. + DEVICE_TYPE = "fan_drawer" + + def __init__(self, index, fan_list): + FanDrawerBase.__init__(self) + + self._fan_list = fan_list + self._index = index + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + + return "fan {}".format(self._index) + + def get_num_fans(self): + """ + Retrieves the number of fans available on this fan drawer + Returns: + An integer, the number of fan modules available on this fan drawer + """ + return len(self._fan_list) + + def get_all_fans(self): + """ + Retrieves all fan modules available on this fan drawer + Returns: + A list of objects derived from FanBase representing all fan + modules available on this fan drawer + """ + return self._fan_list + + def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + Args: + color: A string representing the color with which to set the + fan drawer status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + return self._fan_list[self._index].set_status_led(color) + + def get_status_led(self, color): + """ + Gets the state of the fan drawer LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._fan_list[self._index].get_status_led(color) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py new file mode 100644 index 000000000..5969781bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +import logging + + +def _init_logger(): + formatter = logging.Formatter( + "%(asctime)s %(levelname)s %(filename)s[%(funcName)s][%(lineno)s]: %(message)s" + ) + handler = logging.FileHandler("/var/log/syslog") + handler.setFormatter(formatter) + + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(handler) + return logger + + +logger = _init_logger() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py new file mode 100644 index 000000000..5a66997d3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py @@ -0,0 +1,43 @@ +# +# pcie_base.py +# +# Abstract base class for implementing platform-specific +# PCIE functionality for SONiC +# + +try: + import abc + from sonic_pcie import PcieUtil +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +class PcieBase(object): + def __init__(self, path): + """ + Constructor + Args: + pcieutil file and config file path + """ + self.pcie_util = PcieUtil(path) + + + @abc.abstractmethod + def get_pcie_device(self): + """ + get current device pcie info + + Returns: + A list including pcie device info + """ + return self.pcie_util.get_pcie_device() + + + @abc.abstractmethod + def get_pcie_check(self): + """ + Check Pcie device with config file + Returns: + A list including pcie device and test result info + """ + return self.pcie_util.get_pcie_check() + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py new file mode 100644 index 000000000..3aa7fe3f2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py @@ -0,0 +1,22 @@ +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + Ruijie Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py new file mode 100644 index 000000000..65e27bc1c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- + +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """Ruijie Platform-specific PSU class""" + + # HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + # HWMON_NODE = os.listdir(HWMON_DIR)[0] + # MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, index, config=None, hal_psu=None): + """ + "psus": [ + { + "name": "psu1", + "present": {"loc": "2-0037/psu_status", "format": DecodeFormat.ONE_BIT_HEX, "bit": 0}, + "status": {"loc": "2-0037/psu_status", "format": DecodeFormat.ONE_BIT_HEX, "bit": 1}, + "sn": {"loc": "7-0050/psu_sn"}, + "in_current": {"loc": "7-0058/hwmon/*/curr1_input", "format": DecodeFormat.THOUSANDTH}, + "in_voltage": {"loc": "7-0058/hwmon/*/in1_input", "format": DecodeFormat.THOUSANDTH}, + "out_voltage": {"loc": "7-0058/hwmon/*/in2_input", "format": DecodeFormat.THOUSANDTH}, + "out_current": {"loc": "7-0058/hwmon/*/curr2_input", "format": DecodeFormat.THOUSANDTH}, + "temperature": {"loc": "7-0058/hwmon/*/temp1_input", "format": DecodeFormat.THOUSANDTH}, + "hw_version": {"loc": "7-0050/psu_hw"}, + "psu_type": {"loc": "7-0050/psu_type"}, + "fans": [ + { + "rotor": { + "speed": {"loc": "7-0058/hwmon/*/fan1_input"}, + "speed_max": xx + } + } + ], + "in_power": {"loc": "7-0058/hwmon/*/power1_input", "format": DecodeFormat.MILLIONTH}, + "out_power": {"loc": "7-0058/hwmon/*/power2_input", "format": DecodeFormat.MILLIONTH}, + } + ] + """ + self._fan_list = [] + self.PSU_TEMP_MAX = 60 * 1000 + self.PSU_OUTPUT_POWER_MAX = 1300 * 1000 + self.PSU_OUTPUT_VOLTAGE_MIN = 11 * 1000 + self.PSU_OUTPUT_VOLTAGE_MAX = 14 * 1000 + self.index = index + if config is not None: + self.name = config.get("name") + self.__reg_sn = Reg(config.get("sn")) + self.__reg_present = Reg(config.get("present")) + self.__reg_status = Reg(config.get("status")) + self.__reg_out_vol = Reg(config.get("out_voltage")) + self.__reg_out_cur = Reg(config.get("out_current")) + self.__reg_out_pow = Reg(config.get("out_power")) + self.__reg_pn = Reg(config.get("pn")) + self.__reg_temperature = Reg(config.get("temperature")) + self._fan_list = config.get("fans") + self._psu_fan_parser(config.get("fans")) + + self._hal_psu = hal_psu + + def _psu_fan_parser(self, fans): + if not isinstance(fans, list): + raise TypeError("fan type error fans: {}".format(fans)) + for index in range(0,len(fans)): + if not isinstance(fans[index], dict): + raise TypeError("fan type must be a dict") + self._fan_list.append(Fan(index, config=fans[index], is_psu_fan=True)) + + def _reg_setter(self, target, val): + if isinstance(val, dict): + target = Reg(val) + elif isinstance(val, Reg): + target = val + else: + raise ValueError + return target + + @property + def reg_sn(self): + return self.__reg_sn + + @reg_sn.setter + def reg_sn(self, val): + self._reg_setter(self.__reg_sn, val) + + @property + def reg_present(self): + return self.__reg_present + + @reg_present.setter + def reg_present(self, val): + self._reg_setter(self.__reg_present, val) + + @property + def reg_status(self): + return self.__reg_status + + @reg_status.setter + def reg_status(self, val): + self._reg_setter(self.__reg_status, val) + + @property + def reg_out_vol(self): + return self.__reg_out_vol + + @reg_out_vol.setter + def reg_out_vol(self, val): + self._reg_setter(self.__reg_out_vol, val) + + @property + def reg_out_cur(self): + return self.__reg_out_cur + + @reg_out_cur.setter + def reg_out_cur(self, val): + self._reg_setter(self.__reg_out_cur, val) + + @property + def reg_out_pow(self): + return self.__reg_out_pow + + @reg_out_pow.setter + def reg_out_pow(self, val): + self._reg_setter(self.__reg_out_pow, val) + + def get_all_fans(self): + return self._fan_list + + def get_num_fans(self): + return len(self._fan_list) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.name + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_present, Reg): + psu_presence = self.__reg_present.decode() + if psu_presence == 0 or psu_presence == "0": + return True + except Exception as e: + logger.error(str(e)) + + return False + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + + if self._hal_psu: + return self._hal_psu.pn() + + try: + if isinstance(self.__reg_pn, Reg): + return self.__reg_pn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + if self._hal_psu: + return self._hal_psu.sn() + + try: + if isinstance(self.__reg_sn, Reg): + return self.__reg_sn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + # status = False + # psu_status = self._get_pmc_register(self.psu_presence_reg) + # if (psu_status != 'ERR'): + # psu_status = int(psu_status, 16) + # # Checking whether both bit 3 and bit 2 are not set + # if (~psu_status & 0b1000) and (~psu_status & 0b0100): + # status = True + + if self._hal_psu: + return self._hal_psu.get_status() + + try: + if isinstance(self.reg_status, Reg): + psu_status = self.reg_status.decode() + if psu_status == 1 or psu_status == "1": + return True + elif psu_status == 0 or psu_status == "0": + return False + except Exception as e: + logger.error(str(e)) + + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + # psu_voltage = self._get_pmc_register(self.psu_voltage_reg) + # if (psu_voltage != 'ERR') and self.get_presence(): + # # Converting the value returned by driver which is in + # # millivolts to volts + # psu_voltage = float(psu_voltage) / 1000 + # else: + # psu_voltage = 0.0 + + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_out_vol, Reg): + return self.__reg_out_vol.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + # psu_current = self._get_pmc_register(self.psu_current_reg) + # if (psu_current != 'ERR') and self.get_presence(): + # # Converting the value returned by driver which is in + # # milliamperes to amperes + # psu_current = float(psu_current) / 1000 + # else: + # psu_current = 0.0 + + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_out_cur, Reg): + return self.__reg_out_cur.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_out_pow, Reg): + return self.__reg_out_pow.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + if self._hal_psu: + pass + else: + if self.get_status() and self.get_presence(): + return True + + return False + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + # TODO + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_RED + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if + not + """ + # not supported + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_temperature, Reg): + return self.__reg_temperature.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return float(self.PSU_TEMP_MAX/1000) + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return float(self.PSU_OUTPUT_VOLTAGE_MAX/1000) + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return float(self.PSU_OUTPUT_VOLTAGE_MIN/1000) + + def get_maximum_supplied_power(self): + """ + Retrieves the maximum supplied power by PSU + Returns: + A float number, the maximum power output in Watts. + e.g. 1200.1 + """ + return float(self.PSU_OUTPUT_POWER_MAX/1000) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py new file mode 100644 index 000000000..d216da930 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +from glob import glob +from plat_hal.osutil import osutil + +try: + from sonic_platform.config import DecodeFormat, DecodeMethod + + DECODE_FORMAT = DecodeFormat + DECODE_METHOD = DecodeMethod +except ImportError: + raise ImportError(str(e) + "- required module not found") + +ERR_CODE = "ERR" + + +class Reg(object): + """ + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c"} + "value": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/hwmon*/temp1_input", + "way": "sysfs", + + "InputsStatus": { + "bus": 8, + "addr": 0x5B, + "offset": 0x79, + "way": "i2cword", + "mask": 0x0200, + }, + """ + + def __new__(cls, *args): + if args[0] is None or not isinstance(args[0], dict): + return None + return super(Reg, cls).__new__(cls) + + def __init__(self, data): + + self.loc = None + self.way = DECODE_METHOD.SYSFS + self.addr = None + self.bus = None + self.offset = None + self.size = 1 + self.bit = None + self.mask = None + self.digit = None + self.sdk_type = None + self.sep = None + self.format = DECODE_FORMAT.TEXT + self.__dict__.update(data) + + def _read_reg_val(self): + ret = None + try: + if self.way == DECODE_METHOD.SYSFS: + ret = self.get_sysfs() + elif self.way == DECODE_METHOD.I2C: + ret = self.get_i2c() + elif self.way == DECODE_METHOD.I2C_WORD: + ret = self.get_i2cword() + elif self.way == DECODE_METHOD.DEVMEM: + ret = self.get_devmem() + elif self.way == DECODE_METHOD.SDK: + # TODO + pass + else: + pass + except Exception as e: + raise e + + return ret + + def _write_reg_val(self, val): + try: + if self.way == DECODE_METHOD.SYSFS: + return self._write_sysfs(val) + except Exception as e: + raise e + + return False + + def _write_sysfs(self, val): + try: + with open(glob(self.loc)[0], "w") as f: + f.write(val) + f.flush() + return True + except Exception as e: + raise e + + def _format_val(self, val): + try: + if isinstance(val, str): + val = val.strip() + if self.format == DECODE_FORMAT.THOUSANDTH: + return float("%.1f" % (float(val) / 1000)) + elif self.format == DECODE_FORMAT.HUNDREDTH: + return float("%.1f" % (float(val) / 100)) + elif self.format == DECODE_FORMAT.ONE_BIT_HEX: + return (int(val, 16) & (1 << self.bit)) >> self.bit + elif self.format == DECODE_FORMAT.DECIMAL: + return int(val, 10) + elif self.format == DECODE_FORMAT.MILLIONTH: + return float("%.1f" % (float(val) / 1000 / 1000)) + elif self.format == DECODE_FORMAT.AND: + return (int(val, 16)) & self.mask + elif isinstance(val, list): + if self.format == DECODE_FORMAT.JOIN: + return self.sep.join(val) + except Exception as e: + raise e + else: + return val + + def decode(self): + """ + get value by config way + way i2c/sysfs/lpc + """ + if self.way is None: + raise ValueError("cannot found way to deal") + + ret = self._read_reg_val() + + ret = self._format_val(ret) + return ret + + def encode(self, val): + if self.way is None: + raise ValueError("cannot found way to deal") + + return self._write_reg_val(val) + + def get_sdk(self): + # TODO + pass + + def get_sysfs(self): + if self.loc is None: + raise ValueError("Not Enough Attr: loc: {}".format(self.loc)) + + ret, val = osutil.readsysfs(self.loc) + + if not ret: + raise IOError(val) + + return val + + def get_devmem(self): + if self.addr is None or self.digit is None or self.mask is None: + raise ValueError( + "Not Enough Attr: addr: {}, digit: {}, mask: {}".format( + self.addr, self.digit, self.mask + ) + ) + + ret, val = osutil.getdevmem(self.addr, self.digit, self.mask) + + if not ret: + raise IOError(val) + + return val + + def get_i2cword(self): + if self.bus is None or self.addr is None or self.offset is None: + raise ValueError( + "Not Enough Attr: bus: {}, addr: {}, offset: {}".format( + self.bus, self.addr, self.offset + ) + ) + + ret, val = osutil.geti2cword(self.bus, self.addr, self.offset) + + if not ret: + raise IOError(val) + + return val + + def get_i2c(self): + if ( + self.bus is None + or self.addr is None + or self.offset is None + or self.size is None + ): + raise ValueError( + "Not Enough Attr: bus: {}, addr: {}, offset: {}".format( + self.bus, self.addr, self.offset + ) + ) + + value = [] + for i in range(self.size): + ofs = self.offset + i + ret, val = osutil.rji2cget(self.bus, self.addr, ofs) + + if not ret: + raise IOError(val) + else: + value.append(repr(chr(val)).translate(None, r"\\x").replace("'", "")) + + return value + + def set_i2cword(self, bus, addr, offset, byte): + return self.seti2cword(bus, addr, offset, byte) + + def seti2cword(self, bus, addr, offset, byte): + return osutil.seti2cword(bus, addr, offset, byte) + + def set_i2c(self, bus, addr, offset, byte): + return self.seti2c(bus, addr, offset, byte) + + def seti2c(self, bus, addr, offset, byte): + ret, val = osutil.rji2cset(bus, addr, offset, byte) + return ret, val + + def getbcmtemp(self): + try: + sta, ret = osutil.getmactemp() + if sta == True: + mac_aver = float(ret.get("average", self.__error_ret)) + #mac_max = float(ret.get("maximum", self.__error_ret)) + mac_aver = mac_aver * 1000 + #mac_max = mac_max * 1000 + else: + return False, ret + except AttributeError as e: + return False, str(e) + return True, mac_aver + + def getbcmreg(self, reg): + ret, val = osutil.getsdkreg(reg) + return ret, val + + def logger_debug(self, msg): + baseutil.logger_debug(msg) + + def command(self, cmd): + ret, output = osutil.command(cmd) + return ret, output + + def set_val(self, val): + # TODO + pass diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py new file mode 100644 index 000000000..3e5bcc5b9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +try: + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError: + raise ImportError(str(e) + "- required module not found") + +class Rotor: + def __init__(self, config): + if config is not None and isinstance(config, dict): + self.__reg_speed_getter = Reg(config.get("speed_getter")) + self.__reg_speed_setter = Reg(config.get("speed_setter")) + self.__speed_max = config.get("speed_max") + else: + raise ValueError("init rotor Error: {}".format(config)) + + def get_speed(self): + try: + return int(self.__reg_speed_getter.decode()) + except Exception as e: + logger.error(str(e)) + + return 0 + + def set_speed(self, speed): + try: + return self.__reg_speed_setter.encode(speed) + except Exception as e: + logger.error(str(e)) + + return False + + def get_speed_percentage(self): + try: + speed = self.get_speed() + return (100 * speed) / self.__speed_max + except Exception as e: + logger.error(str(e)) + + return 0 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py new file mode 100644 index 000000000..41c2b63c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py @@ -0,0 +1,1566 @@ +# -*- coding: utf-8 -* + +############################################################################# +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + from ctypes import create_string_buffer + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +############################################################################# +# Ruijie B6510-48VS8CQ +PORT_START = 0 +PORT_END = 55 +PORTS_IN_BLOCK = 56 + +PORT_QSFP_START = 48 +PORT_QSFP_END = 56 + +EEPROM_OFFSET = 11 +############################################################################# + +IDENTITY_EEPROM_ADDR = 0x50 + +INFO_OFFSET = 128 +DOM_OFFSET = 0 +DOM_OFFSET1 = 384 + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWERMODE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_MODULE_UPPER_PAGE3_START = 384 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 24 + +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + + SFP_DEVICE_TYPE = "optoe2" + QSFP_DEVICE_TYPE = "optoe1" + port_to_i2cbus_mapping = {} + def __init__(self, index): + self.index = index + self.port_num = self.index + PORT_START + self.sfp_type = self.__get_sfp_info() + self.dom_supported = False + for x in range(PORT_START, PORTS_IN_BLOCK): + self.port_to_i2cbus_mapping[x] = (x + EEPROM_OFFSET) + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'lp_mode', 'tx_disable', 'tx_disabled_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + self.__dom_capability_detect() + + @property + def qsfp_ports(self): + return range(PORT_QSFP_START, PORT_QSFP_END) + + def get_presence(self): + # Check for invalid self.port_num + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + + if self.port_num <= 7: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence1" + elif self.port_num >= 8 and self.port_num <= 15: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence2" + elif self.port_num >= 16 and self.port_num <= 23: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence3" + elif self.port_num >= 24 and self.port_num <= 31: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence4" + elif self.port_num >= 32 and self.port_num <= 39: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence5" + elif self.port_num >= 40 and self.port_num <= 47: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence6" + elif self.port_num >= 48 and self.port_num <= 55: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence7" + else: + return False + + try: + data = open(presence_path, "rb") + except IOError: + return False + + presence_data = data.read(2) + if presence_data == "": + return False + result = int(presence_data, 16) + data.close() + + # ModPrsL is active low + if result & (1 << (self.port_num % 8)) == 0: + return True + + return False + + def __get_sfp_info(self): + if PORT_START <= self.port_num <= PORT_END: + if self.port_num in self.qsfp_ports: + sfp_type = QSFP_TYPE + else: + sfp_type = SFP_TYPE + else: + return "port range error" + return sfp_type + + def __dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.qsfp_page3_available = False + self.calibration = 0 + return + + if self.sfp_type == "QSFP": + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) + qsfp_version_compliance = int( + qsfp_version_compliance_raw[0], 16) + dom_capability = sfpi_obj.parse_qsfp_dom_capability( + qsfp_dom_capability_raw, 0) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' + self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = dom_capability['data']['Tx_power_support']['value'] == 'On' + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = True + + self.dom_supported = True + self.calibration = 1 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + qsfp_option_value_raw = self.__read_eeprom_specific_bytes( + QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + optional_capability = sfpd_obj.parse_option_params( + qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = optional_capability[ + 'data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator( + qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.qsfp_page3_available = False + + elif self.sfp_type == "SFP": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = ( + int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def __add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): + try: + sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path + + # Write device address to new_device file + nd_file = open(sysfs_nd_path, "w") + nd_str = "%s %s" % (devtype, hex(devaddr)) + nd_file.write(nd_str) + nd_file.close() + + except Exception as err: + print("Error writing to new device file: %s" % str(err)) + return 1 + else: + return 0 + + def __get_port_eeprom_path(self, port_num, devid): + if self.get_presence() is False: + print("port %d Not present" % port_num) + return None + + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050' + i2c_path = '/sys/bus/i2c/devices/i2c-{0}' + sysfs_sfp_i2c_client_path = eeprom_path.format(self.port_to_i2cbus_mapping[port_num]) + sysfs_sfp_i2c_adapter_path= i2c_path.format(self.port_to_i2cbus_mapping[port_num]) + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + if port_num in self.qsfp_ports: + ret = self.__add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) + else: + ret = self.__add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + + return sysfs_sfp_i2c_client_eeprom_path + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + if sysfs_sfp_i2c_client_eeprom_path is None: + return eeprom_raw + try: + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except IOError: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + ''' + if not self.get_presence(): + return transceiver_info_dict + ''' + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + #port_eeprom_path = self.sfputilbase.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + if self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_interface_bulk_raw[start: end], 0) + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + self.__dom_capability_detect() + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + offset = 128 + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + self.dom_supported = True + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_DOM_BULK_DATA_START), QSFP_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_TEMPE_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + temp = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_VOLT_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + volt = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + start = QSFP_CHANNL_MON_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_data_raw[start: end], 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value']) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX4Power']['value']) + + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + if sfpd_obj._calibration_type == 1: + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw[start: end], 0) + else: + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset), offset + 256) + dom_temperature_data = sfpd_obj.parse_temperature(dom_data_raw, 0) + + dom_voltage_data = sfpd_obj.parse_voltage(dom_data_raw, 0) + + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_data_raw, 0) + + transceiver_dom_info_dict['temperature'] = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + transceiver_dom_info_dict['voltage'] = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value']) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disabled_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + self.__dom_capability_detect() + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported or not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = QSFP_MODULE_UPPER_PAGE3_START + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values( + dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values( + dom_channel_threshold_raw, 0) + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + + else: + offset = SFP_MODULE_ADDRA2_OFFSET + + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + sfpd_obj._calibration_type = self.calibration + + if sfpd_obj._calibration_type == 1: + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + SFP_MODULE_THRESHOLD_OFFSET), + SFP_MODULE_THRESHOLD_WIDTH) + else: + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (offset), offset + 256) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold( + dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data[ + 'data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + return transceiver_dom_threshold_info_dict + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + if transceiver_bulk_status is not None: + return transceiver_bulk_status.get("temperature", "N/A") + else: + return None + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + if transceiver_bulk_status is not None: + return transceiver_bulk_status.get("voltage", "N/A") + else: + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + tx_bias_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_channel_monitor_raw, 0) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Bias']['value'])) + else: + return None + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value'])) + else: + return None + else: + return None + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + rx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_channel_monitor_raw, 0) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + tx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_channel_monitor_raw, 0) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + + return tx_power_list + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + if not self.dom_supported: + return None + + rx_los_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + if not self.dom_supported: + return None + tx_fault_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + # Check for invalid self.port_num + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + if not self.dom_supported: + return None + + tx_disable_list = [] + + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + else: + if self.port_num <= 7: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis1" + elif self.port_num >= 8 and self.port_num <= 15: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis2" + elif self.port_num >= 16 and self.port_num <= 23: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis3" + elif self.port_num >= 24 and self.port_num <= 31: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis4" + elif self.port_num >= 32 and self.port_num <= 39: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis5" + elif self.port_num >= 40 and self.port_num <= 47: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis6" + else: + return None + try: + data = open(txdis_path, "rb") + except IOError: + return None + + txdis_data = data.read(2) + if txdis_data == "": + return None + result = int(txdis_data, 16) + data.close() + + # ModPrsL is active low + tx_disable_list.append(result & (1 << (self.port_num % 8)) != 0) + + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + ''' + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + ''' + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + offset + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + lpmode = ('On' == dom_control_data['data']['PowerSet']['value']) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + if lpmode == power_override == True: + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + offset + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + return power_override + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + if self.port_num >= 48 and self.port_num <= 55: + reset_path = "/sys/bus/i2c/devices/1-0036/qsfp_reset" + else: + return False + try: + data = open(reset_path, "rb") + except IOError: + return None + + reset_data = data.read(2) + if reset_data == "": + return None + result = int(reset_data, 16) + data.close() + reset_status = result & (1 << (self.port_num % 8)) == 0 + return reset_status + + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + elif self.sfp_type == SFP_TYPE: + if self.port_num <= 7: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis1" + elif self.port_num >= 8 and self.port_num <= 15: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis2" + elif self.port_num >= 16 and self.port_num <= 23: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis3" + elif self.port_num >= 24 and self.port_num <= 31: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis4" + elif self.port_num >= 32 and self.port_num <= 39: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis5" + elif self.port_num >= 40 and self.port_num <= 47: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis6" + else: + return False + try: + data = open(txdis_path, "r+") + txdis_data = data.read(2) + if txdis_data == "": + return False + result = int(txdis_data, 16) + if tx_disable: + result = result | (1 << (self.port_num % 8)) + else: + result = result & (~(1 << (self.port_num % 8))) + data.seek(0) + sres = hex(result)[2:] + data.write(sres) + data.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + if 0 <= channel <= 15: + try: + channel_state = self.get_tx_disable_channel() + if disable: + tx_disable_ctl = channel_state | channel + else: + tx_disable_ctl = channel_state & (~channel) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + ''' + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + ''' + if lpmode: + return self.set_power_override(True, lpmode) + else: + return self.set_power_override(False, lpmode) + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + QSFP_POWERMODE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def reset(self, reset): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + if self.port_num >= 48 and self.port_num <= 55: + reset_path = "/sys/bus/i2c/devices/1-0036/qsfp_reset" + else: + return False + try: + data = open(reset_path, "r+") + reset_data = data.read(2) + if reset_data == "": + return False + result = int(reset_data, 16) + if reset: + result = result & (~(1 << (self.port_num % 8))) + else: + result = result | (1 << (self.port_num % 8)) + data.seek(0) + sres = hex(result)[2:] + data.write(sres) + data.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def read_eeprom(self, offset, num_bytes): + """ + read eeprom specfic bytes beginning from a random offset with size as num_bytes + Args: + offset : + Integer, the offset from which the read transaction will start + num_bytes: + Integer, the number of bytes to be read + Returns: + bytearray, if raw sequence of bytes are read correctly from the offset of size num_bytes + None, if the read_eeprom fails + """ + raise NotImplementedError + + def write_eeprom(self, offset, num_bytes, write_buffer): + """ + write eeprom specfic bytes beginning from a random offset with size as num_bytes + and write_buffer as the required bytes + Args: + offset : + Integer, the offset from which the read transaction will start + num_bytes: + Integer, the number of bytes to be written + write_buffer: + bytearray, raw bytes buffer which is to be written beginning at the offset + Returns: + a Boolean, true if the write succeeded and false if it did not succeed. + """ + raise NotImplementedError + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py new file mode 100644 index 000000000..49beb8e16 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py @@ -0,0 +1,217 @@ +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + def __init__(self, index, config=None, hal_thermal=None): + self.index = index + if config: + self.name = config.get("name") + self.__reg_low_threshold = Reg(config.get("low")) + self.__reg_high_thresnold = Reg(config.get("high")) + self.__reg_crit_low_threshold = Reg(config.get("crit_low")) + self.__reg_crit_high_thresnold = Reg(config.get("crit_high")) + self.__reg_temperature = Reg(config.get("temperature")) + self.minimum_thermal = self.get_temperature() + self.maximum_thermal = self.get_temperature() + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.name + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return "NA" + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return "NA" + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + if self.get_temperature() == 0.0: + return False + + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_temperature, Reg): + return self.__reg_temperature.decode() + except Exception as e: + logger.error(str(e)) + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_high_thresnold, Reg): + return float(self.__reg_high_thresnold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_low_threshold, Reg): + return float(self.__reg_low_threshold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + try: + if isinstance(self.__reg_high_thresnold, Reg): + temp_val = str(int(temperature * 1000)) + return self.__reg_high_thresnold.encode(temp_val) + except Exception as e: + logger.error(str(e)) + + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + # not supported + return False + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_crit_high_thresnold, Reg): + return float(self.__reg_crit_high_thresnold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_crit_low_threshold, Reg): + return float(self.__reg_crit_low_threshold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def get_minimum_recorded(self): + """ + Retrieves the minimum recorded temperature of thermal + Returns: + A float number, the minimum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + tmp = self.get_temperature() + if tmp < self.minimum_thermal: + self.minimum_thermal = tmp + raise self.minimum_thermal + + def get_maximum_recorded(self): + """ + Retrieves the maximum recorded temperature of thermal + Returns: + A float number, the maximum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + tmp = self.get_temperature() + if tmp > self.maximum_thermal: + self.maximum_thermal = tmp + raise self.maximum_thermal + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py new file mode 100644 index 000000000..6c3939c5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py @@ -0,0 +1,70 @@ +######################################################################## +# +# Ruijie B6510-48VS8CQ +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + def __init__(self): + print("INFO: Watchdog __init__") + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* available + value. + + Returns: + An integer specifying the *actual* number of seconds the watchdog + was armed with. On failure returns -1. + """ + print("ERROR: Platform did not implement arm()") + raise NotImplementedError + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + print("ERROR: Platform did not implement disarm()") + raise NotImplementedError + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + print("ERROR: Platform did not implement is_armed()") + raise NotImplementedError + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on thei + watchdog timer. If the watchdog is not armed, returns -1. + """ + print("ERROR: Platform did not implement get_remaining_time()") + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service new file mode 100644 index 000000000..3b0e8a000 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service @@ -0,0 +1,13 @@ +[Unit] +Description=b6510-48vs8cq platform modules +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/b6510-48vs8cq_platform.sh init +ExecStop=/usr/local/bin/b6510-48vs8cq_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/common/Makefile new file mode 100755 index 000000000..205a32578 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/Makefile @@ -0,0 +1,37 @@ +PWD = $(shell pwd) +CC ?=gcc +INSTALL_MOD_DIR ?=extra +KVERSION ?= $(shell uname -r) +KERNEL_SRC ?= /lib/modules/$(KVERSION) +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +SUB_BUILD_DIR = $(PWD)/build +DIR_KERNEL_SRC = $(PWD)/modules +SCRIPT_DIR = $(PWD)/script +SERVICE_DIR = $(PWD)/service + +KBUILD_EXTRA_SYMBOLS += $(DIR_KERNEL_SRC)/Module.symvers +export KBUILD_EXTRA_SYMBOLS + +INSTALL_MODULE_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) +INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin +INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system +INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3.7/dist-packages + +all: + $(MAKE) -C $(KERNEL_SRC)/build M=$(DIR_KERNEL_SRC) modules + @if [ ! -d ${INSTALL_MODULE_DIR} ]; then mkdir -p ${INSTALL_MODULE_DIR} ;fi + @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi + @if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi + @if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi + @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi + @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR2} ;fi + cp -r $(DIR_KERNEL_SRC)/*.ko $(INSTALL_MODULE_DIR) + cp -r $(SCRIPT_DIR)/* $(INSTALL_SCRIPT_DIR) + cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR) + @if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi +clean: + rm -f ${DIR_KERNEL_SRC}/*.o ${DIR_KERNEL_SRC}/*.ko ${DIR_KERNEL_SRC}/*.mod.c ${DIR_KERNEL_SRC}/.*.cmd + rm -f ${DIR_KERNEL_SRC}/Module.markers ${DIR_KERNEL_SRC}/Module.symvers ${DIR_KERNEL_SRC}/modules.order + rm -rf ${DIR_KERNEL_SRC}/.tmp_versions + rm -rf $(SUB_BUILD_DIR) diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py new file mode 100644 index 000000000..2d434d1ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py @@ -0,0 +1,212 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +class FantlvException(Exception): + def __init__(self, message='fantlverror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + +class fan_tlv(object): + HEAD_INFO = "\x01\x7e\x01\xf1" + VERSION = 0x01 # E2PROM file init version is 0x01 + FLAG = 0x7E #new version E2PROM mark as 0x7E + HW_VER = 0X01 # consists of master version and revised version + TYPE = 0xf1 # hardware type define + TLV_LEN = 00 # vaild data length(16bit) + _FAN_TLV_HDR_LEN = 6 + _FAN_TLV_CRC_LEN = 2 + + _FAN_TLV_TYPE_NAME = 0x02 + _FAN_TLV_TYPE_SN = 0x03 + _FAN_TLV_TYPE_HW_INFO = 0x05 + _FAN_TLV_TYPE_DEV_TYPE = 0x06 + + _fandecodetime = 0 + + @property + def dstatus(self): + return self._dstatus + + @property + def typename(self): + return self._typename + + @property + def typesn(self): + return self._typesn + + @property + def typehwinfo(self): + return self._typehwinfo + + @property + def typedevtype(self): + return self._typedevtype + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + @property + def fandecodetime(self): + return self._fandecodetime + + def __init__(self): + self._typename = "" + self._typesn = "" + self._typehwinfo = "" + self._typedevtype = "" + self._dstatus = 0 + + def strtoarr(self, str): + s = [] + if str is not None: + for index in range(len(str)): + s.append(str[index]) + return s + + def str_to_hex(self,rest_v): + value = 0 + for index in range(len(rest_v)): + value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8) + return value + + def hex_to_str(self,s): + len_t = len(s) + if len_t % 2 != 0: + return 0 + ret = "" + for t in range(0, int(len_t / 2)): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + return ret + + def generate_fan_value(self): + bin_buffer = [chr(0xff)] * 256 + bin_buffer[0] = chr(self.VERSION) + bin_buffer[1] = chr(self.FLAG) + bin_buffer[2] = chr(self.HW_VER) + bin_buffer[3] = chr(self.TYPE) + + temp_t = "%08x" % self.typedevtype # handle devtype first + typedevtype_t = self.hex_to_str(temp_t) + total_len = len(self.typename) + len(self.typesn) + \ + len(self.typehwinfo) + len(typedevtype_t) + 8 + + bin_buffer[4] = chr(total_len >> 8) + bin_buffer[5] = chr(total_len & 0x00FF) + + index_start = 6 + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME) + bin_buffer[index_start + 1] = chr(len(self.typename)) + bin_buffer[index_start + 2: index_start + 2 + + len(self.typename)] = self.strtoarr(self.typename) + index_start = index_start + 2 + len(self.typename) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN) + bin_buffer[index_start + 1] = chr(len(self.typesn)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typesn)] = self.strtoarr(self.typesn) + index_start = index_start + 2 + len(self.typesn) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO) + bin_buffer[index_start + 1] = chr(len(self.typehwinfo)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typehwinfo)] = self.strtoarr(self.typehwinfo) + index_start = index_start + 2 + len(self.typehwinfo) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE) + bin_buffer[index_start + 1] = chr(len(typedevtype_t)) + bin_buffer[index_start + 2:index_start + 2 + + len(typedevtype_t)] = self.strtoarr(typedevtype_t) + index_start = index_start + 2 + len(typedevtype_t) + + crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # 2bytes checking + bin_buffer[index_start] = chr(crcs >> 8) + bin_buffer[index_start + 1] = chr(crcs & 0x00ff) + # printvalue(bin_buffer) + return bin_buffer + + def decode(self, e2): + if e2[0:4] != self.HEAD_INFO: + raise FantlvException("Fan tlv head info error,not fan tlv type", -10) + ret = [] + self.VERSION = ord(e2[0]) + self.FLAG = ord(e2[1]) + self.HW_VER = ord(e2[2]) + self.TYPE = ord(e2[3]) + self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5]) + + tlv_index = self._FAN_TLV_HDR_LEN + tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN + + # check sum + if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2: + raise FantlvException("Fan tlv eeprom len error!", -2) + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN] + ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1]) + if sumcrc != readcrc: + raise FantlvException("Fan tlv eeprom checksum error!", -1) + else: + self._dstatus = 0 + while (tlv_index + 2) < len(e2) and tlv_index < tlv_end: + s = self.decoder( + e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])]) + tlv_index += ord(e2[tlv_index + 1]) + 2 + ret.append(s) + + return ret + + @staticmethod + def fancrc(t): + sum = 0 + for index in range(len(t)): + sum += ord(t[index]) + return sum + + def decoder(self, t): + try: + name = "" + value = "" + if ord(t[0]) == self._FAN_TLV_TYPE_NAME: + name = "Product Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typename = value + elif ord(t[0]) == self._FAN_TLV_TYPE_SN: + name = "serial Number" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typesn = value + elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO: + name = "hardware info" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typehwinfo = value + elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE: + name = "dev type" + _len = ord(t[1]) + value = "0x" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + self._typedevtype = int(value,16) + except Exception as e: + print(e) + return {"name": name, "code": ord(t[0]), "value": value,"lens": _len} + + def __str__(self): + formatstr = "VERSION : 0x%02x \n" \ + " FLAG : 0x%02x \n" \ + " HW_VER : 0x%02x \n" \ + " TYPE : 0x%02x \n" \ + "typename : %s \n" \ + "typesn : %s \n" \ + "typehwinfo : %s \n" + return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo) + + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py new file mode 100644 index 000000000..892d06194 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py @@ -0,0 +1,954 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +import collections +from bitarray import bitarray +from datetime import datetime, timedelta +import sys + +__all__ = ["FruException", "FruUtil", "BaseArea", "BoardInfoArea", "ProductInfoArea", + "MultiRecordArea", "Field", "ipmifru"] + +__DEBUG__ = "N" + + +class FruException(Exception): + def __init__(self, message='fruerror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + + +def e_print(err): + print("ERROR: " + err) + + +def d_print(debug_info): + if(__DEBUG__ == "Y"): + print(debug_info) + + +class FruUtil(): + @staticmethod + def decodeLength(value): + a = bitarray(8) + a.setall(True) + a[0:1] = 0 + a[1:2] = 0 + x = ord(a.tobytes()) + return x & ord(value) + + @staticmethod + def minToData(): + starttime = datetime(1996, 1, 1, 0, 0, 0) + endtime = datetime.now() + seconds = (endtime - starttime).total_seconds() + mins = seconds / 60 + m = int(round(mins)) + return m + + @staticmethod + def getTimeFormat(): + return datetime.now().strftime('%Y-%m-%d') + + @staticmethod + def getTypeLength(value): + if value is None: + return 0 + a = bitarray(8) + a.setall(False) + a[0:1] = 1 + a[1:2] = 1 + x = ord(a.tobytes()) + return x | len(value) + + @staticmethod + def checksum(b): + result = 0 + for i in range(len(b)): + result += ord(b[i]) + return (0x100 - (result & 0xff)) & 0xff + + +class BaseArea(object): + SUGGESTED_SIZE_COMMON_HEADER = 8 + SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 + SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 + SUGGESTED_SIZE_BOARD_INFO_AREA = 80 + SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 + + INITVALUE = b'\x00' + resultvalue = INITVALUE * 256 + COMMON_HEAD_VERSION = b'\x01' + __childList = None + + def __init__(self, name="", size=0, offset=0): + self.__childList = [] + self._offset = offset + self.name = name + self._size = size + self._isPresent = False + self._data = b'\x00' * size + self.__dataoffset = 0 + + @property + def childList(self): + return self.__childList + + @childList.setter + def childList(self, value): + self.__childList = value + + @property + def offset(self): + return self._offset + + @offset.setter + def offset(self, value): + self._offset = value + + @property + def size(self): + return self._size + + @size.setter + def size(self, value): + self._size = value + + @property + def data(self): + return self._data + + @data.setter + def data(self, value): + self._data = value + + @property + def isPresent(self): + return self._isPresent + + @isPresent.setter + def isPresent(self, value): + self._isPresent = value + + +class InternalUseArea(BaseArea): + pass + + +class ChassisInfoArea(BaseArea): + pass + + +class BoardInfoArea(BaseArea): + _boardTime = None + _fields = None + _mfg_date = None + + def __str__(self): + formatstr = "version : %x\n" \ + "length : %d \n" \ + "language : %x \n" \ + "mfg_date : %s \n" \ + "boardManufacturer : %s \n" \ + "boardProductName : %s \n" \ + "boardSerialNumber : %s \n" \ + "boardPartNumber : %s \n" \ + "fruFileId : %s \n" + + tmpstr = formatstr % (ord(self.boardversion), self.size, + self.language, self.getMfgRealData(), + self.boardManufacturer, self.boardProductName, + self.boardSerialNumber, self.boardPartNumber, + self.fruFileId) + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + tmpstr += "boardextra%d : %s \n" % (i, valtmpval) + else: + break + + return tmpstr + + def todict(self): + dic = collections.OrderedDict() + dic["boardversion"] = ord(self.boardversion) + dic["boardlength"] = self.size + dic["boardlanguage"] = self.language + dic["boardmfg_date"] = self.getMfgRealData() + dic["boardManufacturer"] = self.boardManufacturer + dic["boardProductName"] = self.boardProductName + dic["boardSerialNumber"] = self.boardSerialNumber + dic["boardPartNumber"] = self.boardPartNumber + dic["boardfruFileId"] = self.fruFileId + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + dic[valtmp] = valtmpval + else: + break + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] + index += 1 + d_print("decode length :%d class size:%d" % + ((ord(self.data[index]) * 8), self.size)) + index += 2 + + timetmp = self.data[index: index + 3] + self.mfg_date = ord(timetmp[0]) | ( + ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) + d_print("decode getMfgRealData :%s" % self.getMfgRealData()) + index += 3 + + templen = FruUtil.decodeLength(self.data[index]) + self.boardManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardManufacturer:%s" % self.boardManufacturer) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardProductName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardProductName:%s" % self.boardProductName) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardPartNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardPartNumber:%s" % self.boardPartNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + + for i in range(1, 11): + valtmp = "boardextra%d" % i + if self.data[index] != chr(0xc1): + templen = FruUtil.decodeLength(self.data[index]) + tmpval = self.data[index + 1: index + templen + 1] + setattr(self, valtmp, tmpval) + index += templen + 1 + d_print("decode boardextra%d:%s" % (i, tmpval)) + else: + break + + def recalcute(self): + d_print("boardInfoArea version:%x" % ord(self.boardversion)) + d_print("boardInfoArea length:%d" % self.size) + d_print("boardInfoArea language:%x" % self.language) + self.mfg_date = FruUtil.minToData() + d_print("boardInfoArea mfg_date:%x" % self.mfg_date) + + self.data = chr(ord(self.boardversion)) + \ + chr(self.size / 8) + chr(self.language) + + self.data += chr(self.mfg_date & 0xFF) + self.data += chr((self.mfg_date >> 8) & 0xFF) + self.data += chr((self.mfg_date >> 16) & 0xFF) + + d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) + typelength = FruUtil.getTypeLength(self.boardManufacturer) + self.data += chr(typelength) + self.data += self.boardManufacturer + + d_print("boardInfoArea boardProductName:%s" % self.boardProductName) + self.data += chr(FruUtil.getTypeLength(self.boardProductName)) + self.data += self.boardProductName + + d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) + self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) + self.data += self.boardSerialNumber + + d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) + self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) + self.data += self.boardPartNumber + + d_print("boardInfoArea fruFileId:%s" % self.fruFileId) + self.data += chr(FruUtil.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) + self.data += chr(FruUtil.getTypeLength(valtmpval)) + if valtmpval is None: + pass + else: + self.data += valtmpval + else: + break + + self.data += chr(0xc1) + + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + + self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:] + d_print("self data:%d" % len(self.data)) + d_print("self size:%d" % self.size) + d_print("adjust size:%d" % (self.size - len(self.data) - 1)) + self.data = self.data.ljust((self.size - 1), self.INITVALUE) + + # checksum + checksum = FruUtil.checksum(self.data) + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + def getMfgRealData(self): + starttime = datetime(1996, 1, 1, 0, 0, 0) + mactime = starttime + timedelta(minutes=self.mfg_date) + return mactime + + @property + def language(self): + self._language = 25 + return self._language + + @property + def mfg_date(self): + return self._mfg_date + + @mfg_date.setter + def mfg_date(self, val): + self._mfg_date = val + + @property + def boardversion(self): + self._boardversion = self.COMMON_HEAD_VERSION + return self._boardversion + + @property + def fruFileId(self): + return self._FRUFileID + + @fruFileId.setter + def fruFileId(self, val): + self._FRUFileID = val + + @property + def boardPartNumber(self): + return self._boardPartNumber + + @boardPartNumber.setter + def boardPartNumber(self, val): + self._boardPartNumber = val + + @property + def boardSerialNumber(self): + return self._boardSerialNumber + + @boardSerialNumber.setter + def boardSerialNumber(self, val): + self._boardSerialNumber = val + + @property + def boardProductName(self): + return self._boradProductName + + @boardProductName.setter + def boardProductName(self, val): + self._boradProductName = val + + @property + def boardManufacturer(self): + return self._boardManufacturer + + @boardManufacturer.setter + def boardManufacturer(self, val): + self._boardManufacturer = val + + @property + def boardTime(self): + return self._boardTime + + @boardTime.setter + def boardTime(self, val): + self._boardTime = val + + @property + def fields(self): + return self._fields + + @fields.setter + def fields(self, val): + self._fields = val + + +class ProductInfoArea(BaseArea): + _productManufacturer = None + _productAssetTag = None + _FRUFileID = None + + def __str__(self): + formatstr = "version : %x\n" \ + "length : %d \n" \ + "language : %x \n" \ + "productManufacturer : %s \n" \ + "productName : %s \n" \ + "productPartModelName: %s \n" \ + "productVersion : %s \n" \ + "productSerialNumber : %s \n" \ + "productAssetTag : %s \n" \ + "fruFileId : %s \n" + + tmpstr = formatstr % (ord(self.areaversion), self.size, + self.language, self.productManufacturer, + self.productName, self.productPartModelName, + self.productVersion, self.productSerialNumber, + self.productAssetTag, self.fruFileId) + + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + tmpstr += "productextra%d : %s \n" % (i, valtmpval) + else: + break + + return tmpstr + + def todict(self): + dic = collections.OrderedDict() + dic["productversion"] = ord(self.areaversion) + dic["productlength"] = self.size + dic["productlanguage"] = self.language + dic["productManufacturer"] = self.productManufacturer + dic["productName"] = self.productName + dic["productPartModelName"] = self.productPartModelName + dic["productVersion"] = int(self.productVersion, 16) + dic["productSerialNumber"] = self.productSerialNumber + dic["productAssetTag"] = self.productAssetTag + dic["productfruFileId"] = self.fruFileId + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + dic[valtmp] = valtmpval + else: + break + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] # 0 + index += 1 + d_print("decode length %d" % (ord(self.data[index]) * 8)) + d_print("class size %d" % self.size) + index += 2 + + templen = FruUtil.decodeLength(self.data[index]) + self.productManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productManufacturer:%s" % self.productManufacturer) + + templen = FruUtil.decodeLength(self.data[index]) + self.productName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productName:%s" % self.productName) + + templen = FruUtil.decodeLength(self.data[index]) + self.productPartModelName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productPartModelName:%s" % self.productPartModelName) + + templen = FruUtil.decodeLength(self.data[index]) + self.productVersion = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productVersion:%s" % self.productVersion) + + templen = FruUtil.decodeLength(self.data[index]) + self.productSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productSerialNumber:%s" % self.productSerialNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.productAssetTag = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productAssetTag:%s" % self.productAssetTag) + + templen = FruUtil.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + for i in range(1, 11): + valtmp = "productextra%d" % i + if self.data[index] != chr(0xc1) and index < self.size - 1: + templen = FruUtil.decodeLength(self.data[index]) + if templen == 0: + break + tmpval = self.data[index + 1: index + templen + 1] + d_print("decode boardextra%d:%s" % (i, tmpval)) + setattr(self, valtmp, tmpval) + index += templen + 1 + else: + break + + @property + def productVersion(self): + return self._productVersion + + @productVersion.setter + def productVersion(self, name): + self._productVersion = name + + @property + def areaversion(self): + self._areaversion = self.COMMON_HEAD_VERSION + return self._areaversion + + @areaversion.setter + def areaversion(self, name): + self._areaversion = name + + @property + def language(self): + self._language = 25 + return self._language + + @property + def productManufacturer(self): + return self._productManufacturer + + @productManufacturer.setter + def productManufacturer(self, name): + self._productManufacturer = name + + @property + def productName(self): + return self._productName + + @productName.setter + def productName(self, name): + self._productName = name + + @property + def productPartModelName(self): + return self._productPartModelName + + @productPartModelName.setter + def productPartModelName(self, name): + self._productPartModelName = name + + @property + def productSerialNumber(self): + return self._productSerialNumber + + @productSerialNumber.setter + def productSerialNumber(self, name): + self._productSerialNumber = name + + @property + def productAssetTag(self): + return self._productAssetTag + + @productAssetTag.setter + def productAssetTag(self, name): + self._productAssetTag = name + + @property + def fruFileId(self): + return self._FRUFileID + + @fruFileId.setter + def fruFileId(self, name): + self._FRUFileID = name + + def recalcute(self): + d_print("product version:%x" % ord(self.areaversion)) + d_print("product length:%d" % self.size) + d_print("product language:%x" % self.language) + self.data = chr(ord(self.areaversion)) + \ + chr(self.size / 8) + chr(self.language) + + typelength = FruUtil.getTypeLength(self.productManufacturer) + self.data += chr(typelength) + self.data += self.productManufacturer + + self.data += chr(FruUtil.getTypeLength(self.productName)) + self.data += self.productName + + self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) + self.data += self.productPartModelName + + self.data += chr(FruUtil.getTypeLength(self.productVersion)) + self.data += self.productVersion + + self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) + self.data += self.productSerialNumber + + self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) + if self.productAssetTag is not None: + self.data += self.productAssetTag + + self.data += chr(FruUtil.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + # 判断拓展字段是否存在, 拓展字段必须按顺序来 + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) + self.data += chr(FruUtil.getTypeLength(valtmpval)) + if valtmpval is None: + pass + else: + self.data += valtmpval + else: + break + + self.data += chr(0xc1) + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + d_print("self.data:%d" % len(self.data)) + d_print("self.size:%d" % self.size) + + self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:] + self.data = self.data.ljust((self.size - 1), self.INITVALUE) + checksum = FruUtil.checksum(self.data) + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + +class MultiRecordArea(BaseArea): + pass + + +class Field(object): + + def __init__(self, fieldType="ASCII", fieldData=""): + self.fieldData = fieldData + self.fieldType = fieldType + + @property + def data(self): + return self._data + + @property + def fieldType(self): + return self._fieldType + + @property + def fieldData(self): + return self._fieldData + + +class ipmifru(BaseArea): + _BoardInfoArea = None + _ProductInfoArea = None + _InternalUseArea = None + _ChassisInfoArea = None + _multiRecordArea = None + _productinfoAreaOffset = BaseArea.INITVALUE + _boardInfoAreaOffset = BaseArea.INITVALUE + _internalUserAreaOffset = BaseArea.INITVALUE + _chassicInfoAreaOffset = BaseArea.INITVALUE + _multiRecordAreaOffset = BaseArea.INITVALUE + _bindata = None + _bodybin = None + _version = BaseArea.COMMON_HEAD_VERSION + _zeroCheckSum = None + + def __str__(self): + tmpstr = "" + if self.boardInfoArea.isPresent: + tmpstr += "\nboardinfoarea: \n" + tmpstr += self.boardInfoArea.__str__() + if self.productInfoArea.isPresent: + tmpstr += "\nproductinfoarea: \n" + tmpstr += self.productInfoArea.__str__() + return tmpstr + + def decodeBin(self, eeprom): + commonHead = eeprom[0:8] + d_print("decode version %x" % ord(commonHead[0])) + if self.COMMON_HEAD_VERSION != commonHead[0]: + raise FruException("HEAD VERSION error,not Fru format!", -10) + if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): + strtemp = "check header checksum error [cal:%02x data:%02x]" % ( + FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) + raise FruException(strtemp, -3) + if commonHead[1] != self.INITVALUE: + d_print("Internal Use Area is present") + self.internalUseArea = InternalUseArea( + name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) + self.internalUseArea.isPresent = True + self.internalUserAreaOffset = ord(commonHead[1]) + self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( + self.internalUserAreaOffset * 8 + self.internalUseArea.size)] + if commonHead[2] != self.INITVALUE: + d_print("Chassis Info Area is present") + self.chassisInfoArea = ChassisInfoArea( + name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) + self.chassisInfoArea.isPresent = True + self.chassicInfoAreaOffset = ord(commonHead[2]) + self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( + self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] + if commonHead[3] != self.INITVALUE: + self.boardInfoArea = BoardInfoArea( + name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) + self.boardInfoArea.isPresent = True + self.boardInfoAreaOffset = ord(commonHead[3]) + self.boardInfoArea.size = ord( + eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 + d_print("Board Info Area is present size:%d" % + (self.boardInfoArea.size)) + self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( + self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] + if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): + print("check boardInfoArea checksum error[cal:%02x data:%02x]" % \ + (FruUtil.checksum( + self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:]))) + sys.exit(-1) + self.boardInfoArea.decodedata() + if commonHead[4] != self.INITVALUE: + d_print("Product Info Area is present") + self.productInfoArea = ProductInfoArea( + name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) + self.productInfoArea.isPresent = True + self.productinfoAreaOffset = ord(commonHead[4]) + d_print("length offset value: %02x" % + ord(eeprom[self.productinfoAreaOffset * 8 + 1])) + self.productInfoArea.size = ord( + eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 + d_print("Product Info Area is present size:%d" % + (self.productInfoArea.size)) + + self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( + self.productinfoAreaOffset * 8 + self.productInfoArea.size)] + if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): + strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( + FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) + raise FruException(strtmp, -3) + self.productInfoArea.decodedata() + if commonHead[5] != self.INITVALUE: + self.multiRecordArea = MultiRecordArea( + name="MultiRecord record Area ") + d_print("MultiRecord record present") + self.multiRecordArea.isPresent = True + self.multiRecordAreaOffset = ord(commonHead[5]) + self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( + self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] + + def initDefault(self): + self.version = self.COMMON_HEAD_VERSION + self.internalUserAreaOffset = self.INITVALUE + self.chassicInfoAreaOffset = self.INITVALUE + self.boardInfoAreaOffset = self.INITVALUE + self.productinfoAreaOffset = self.INITVALUE + self.multiRecordAreaOffset = self.INITVALUE + self.PAD = self.INITVALUE + self.zeroCheckSum = self.INITVALUE + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + self.productInfoArea = None + self.internalUseArea = None + self.boardInfoArea = None + self.chassisInfoArea = None + self.multiRecordArea = None + # self.recalcute() + + @property + def version(self): + return self._version + + @version.setter + def version(self, name): + self._version = name + + @property + def internalUserAreaOffset(self): + return self._internalUserAreaOffset + + @internalUserAreaOffset.setter + def internalUserAreaOffset(self, obj): + self._internalUserAreaOffset = obj + + @property + def chassicInfoAreaOffset(self): + return self._chassicInfoAreaOffset + + @chassicInfoAreaOffset.setter + def chassicInfoAreaOffset(self, obj): + self._chassicInfoAreaOffset = obj + + @property + def productinfoAreaOffset(self): + return self._productinfoAreaOffset + + @productinfoAreaOffset.setter + def productinfoAreaOffset(self, obj): + self._productinfoAreaOffset = obj + + @property + def boardInfoAreaOffset(self): + return self._boardInfoAreaOffset + + @boardInfoAreaOffset.setter + def boardInfoAreaOffset(self, obj): + self._boardInfoAreaOffset = obj + + @property + def multiRecordAreaOffset(self): + return self._multiRecordAreaOffset + + @multiRecordAreaOffset.setter + def multiRecordAreaOffset(self, obj): + self._multiRecordAreaOffset = obj + + @property + def zeroCheckSum(self): + return self._zeroCheckSum + + @zeroCheckSum.setter + def zeroCheckSum(self, obj): + self._zeroCheckSum = obj + + @property + def productInfoArea(self): + return self._ProductInfoArea + + @productInfoArea.setter + def productInfoArea(self, obj): + self._ProductInfoArea = obj + + @property + def internalUseArea(self): + return self._InternalUseArea + + @internalUseArea.setter + def internalUseArea(self, obj): + self.internalUseArea = obj + + @property + def boardInfoArea(self): + return self._BoardInfoArea + + @boardInfoArea.setter + def boardInfoArea(self, obj): + self._BoardInfoArea = obj + + @property + def chassisInfoArea(self): + return self._ChassisInfoArea + + @chassisInfoArea.setter + def chassisInfoArea(self, obj): + self._ChassisInfoArea = obj + + @property + def multiRecordArea(self): + return self._multiRecordArea + + @multiRecordArea.setter + def multiRecordArea(self, obj): + self._multiRecordArea = obj + + @property + def bindata(self): + return self._bindata + + @bindata.setter + def bindata(self, obj): + self._bindata = obj + + @property + def bodybin(self): + return self._bodybin + + @bodybin.setter + def bodybin(self, obj): + self._bodybin = obj + + def recalcuteCommonHead(self): + self.bindata = "" + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + d_print("common Header %d" % self.offset) + if self.internalUseArea is not None and self.internalUseArea.isPresent: + self.internalUserAreaOffset = self.offset / 8 + self.offset += self.internalUseArea.size + d_print("internalUseArea is present offset:%d" % self.offset) + + if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: + self.chassicInfoAreaOffset = self.offset / 8 + self.offset += self.chassisInfoArea.size + d_print("chassisInfoArea is present offset:%d" % self.offset) + + if self.boardInfoArea is not None and self.boardInfoArea.isPresent: + self.boardInfoAreaOffset = self.offset / 8 + self.offset += self.boardInfoArea.size + d_print("boardInfoArea is present offset:%d" % self.offset) + d_print("boardInfoArea is present size:%d" % + self.boardInfoArea.size) + + if self.productInfoArea is not None and self.productInfoArea.isPresent: + self.productinfoAreaOffset = self.offset / 8 + self.offset += self.productInfoArea.size + d_print("productInfoArea is present offset:%d" % self.offset) + + if self.multiRecordArea is not None and self.multiRecordArea.isPresent: + self.multiRecordAreaOffset = self.offset / 8 + d_print("multiRecordArea is present offset:%d" % self.offset) + + if self.internalUserAreaOffset == self.INITVALUE: + self.internalUserAreaOffset = 0 + if self.productinfoAreaOffset == self.INITVALUE: + self.productinfoAreaOffset = 0 + if self.chassicInfoAreaOffset == self.INITVALUE: + self.chassicInfoAreaOffset = 0 + if self.boardInfoAreaOffset == self.INITVALUE: + self.boardInfoAreaOffset = 0 + if self.multiRecordAreaOffset == self.INITVALUE: + self.multiRecordAreaOffset = 0 + + self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset + - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff + d_print("zerochecksum:%x" % self.zeroCheckSum) + self.data = self.version + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( + self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + self.INITVALUE + chr(self.zeroCheckSum) + + self.bindata = self.data + self.bodybin + totallen = len(self.bindata) + d_print("totallen %d" % totallen) + if (totallen < 256): + self.bindata = self.bindata.ljust(256, self.INITVALUE) + else: + raise FruException('bin data more than 256', -2) + + def recalcutebin(self): + self.bodybin = "" + if self.internalUseArea is not None and self.internalUseArea.isPresent: + d_print("internalUseArea present") + self.bodybin += self.internalUseArea.data + if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: + d_print("chassisInfoArea present") + self.bodybin += self.chassisInfoArea.data + if self.boardInfoArea is not None and self.boardInfoArea.isPresent: + d_print("boardInfoArea present") + self.boardInfoArea.recalcute() + self.bodybin += self.boardInfoArea.data + if self.productInfoArea is not None and self.productInfoArea.isPresent: + d_print("productInfoAreapresent") + self.productInfoArea.recalcute() + self.bodybin += self.productInfoArea.data + if self.multiRecordArea is not None and self.multiRecordArea.isPresent: + d_print("multiRecordArea present") + self.bodybin += self.productInfoArea.data + + def recalcute(self): + self.recalcutebin() + self.recalcuteCommonHead() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py @@ -0,0 +1 @@ + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py new file mode 100644 index 000000000..46f3089bb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py @@ -0,0 +1,222 @@ +####################################################### +# +# osutil.py +# Python implementation of the Class osutil +# Original author: sonic_rd@ruijie.com.cn +# +####################################################### + +import subprocess +import time +import glob +import re +#import chardet +from rjutil.smbus import SMBus +import time +from functools import wraps + + +def retry(maxretry =6, delay = 0.01): + ''' + maxretry: max retry times + delay : interval after last retry + ''' + def decorator(f): + @wraps(f) + def wrapper(*args, **kwargs): + time_retry = maxretry + time_delay = delay + result_msg = "" + while time_retry: + try: + val , result_msg = f(*args, **kwargs) + if val is False: + time_retry -=1 + time.sleep(time_delay) + continue + else: + return val, result_msg + except Exception as e: + time_retry -= 1 + result_msg = str(e) + time.sleep(time_delay) + return False, "max time retry last errmsg is {}".format(result_msg) + return wrapper + return decorator + +class osutil(object): + """ + osutil + """ + + @staticmethod + @retry(maxretry = 6) + def rji2cget_python(bus, addr, reg): + with SMBus(bus) as y: + val , ind = y.read_byte_data(addr, reg, True) + return val , ind + + + @staticmethod + @retry(maxretry = 6) + def rji2cset_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_byte_data(addr, reg, value, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2cgetword_python(bus, addr, reg): + with SMBus(bus) as y: + val , ind = y.read_word_data(addr, reg, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2csetword_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_word_data(addr, reg, value, True) + return val , ind + + @staticmethod + def command(cmdstr): + retcode, output = subprocess.getstatusoutput(cmdstr) + return retcode, output + + + @staticmethod + def geti2cword_i2ctool(bus, addr, offset): + command_line = "i2cget -f -y %d 0x%02x 0x%02x wp" % (bus, addr, offset) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, int(ret_t, 16) + time.sleep(0.1) + return False, ret_t + + + @staticmethod + def seti2cword_i2ctool(bus, addr, offset, val): + command_line = "i2cset -f -y %d 0x%02x 0x%0x 0x%04x wp" % (bus, addr, offset, val) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + @staticmethod + def rji2cget_i2ctool(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, int(ret_t, 16) + time.sleep(0.1) + return False, ret_t + + @staticmethod + def rji2cset_i2ctool(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + @staticmethod + def geti2cword(bus, addr, offset): + return osutil.rji2cgetword_python(bus, addr, offset) + @staticmethod + def seti2cword(bus, addr, offset, val): + return osutil.rji2csetword_python(bus, addr, offset, val) + @staticmethod + def rji2cget(bus, devno, address): + return osutil.rji2cget_python(bus, devno, address) + @staticmethod + def rji2cset(bus, devno, address, byte): + return osutil.rji2cset_python(bus, devno, address, byte) + + @staticmethod + def byteTostr(val): + strtmp = '' + for i in range(len(val)): + strtmp += chr(val[i]) + return strtmp + + @staticmethod + def readsysfs(location): + try: + locations = glob.glob(location) + with open(locations[0], 'rb') as fd1: + retval = fd1.read() + retval = retval.strip() + except Exception as e: + return False, (str(e)+" location[%s]" % location) + return True, retval.decode("utf-8", "ignore") + + @staticmethod + def getdevmem(addr, digit, mask): + command_line = "devmem 0x%02x %d" %(addr, digit) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + if mask != None: + ret_t = str(int(ret_t, 16) & mask) + return True, ret_t + return False, ret_t + + @staticmethod + def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + + @staticmethod + def getsdkreg(reg): + try: + cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg + ret, result = osutil.rj_os_system(cmd) + result_t = result.strip().replace("\r", "").replace("\n", "") + if ret != 0 or "Error:" in result_t: + return False, result + patt = r"%s.(.*):(.*)>drivshell" % reg + rt = re.findall(patt, result_t, re.S) + test = re.findall("=(.*)", rt[0][0])[0] + except Exception as e: + return False, 'get sdk register error' + return True, test + + @staticmethod + def getmactemp(): + try: + result = {} + #waitForDocker() + #need to exec twice + osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + ret, log = osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + if ret: + return False, result + else: + logs = log.splitlines() + for line in logs: + if "average" in line: + b = re.findall(r'\d+.\d+', line) + result["average"] = b[0] + elif "maximum" in line: + b = re.findall(r'\d+.\d+', line) + result["maximum"] = b[0] + except Exception as e: + return False, str(e) + return True, result + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/__init__.py new file mode 100755 index 000000000..e69de29bb diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py new file mode 100644 index 000000000..1cf74d32d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py @@ -0,0 +1,23 @@ +# -*- coding: UTF-8 -*- +import os + +def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_platform_info(machine_info): + if machine_info != None: + if 'onie_platform' in machine_info: + return machine_info['onie_platform'] + elif 'aboot_platform' in machine_info: + return machine_info['aboot_platform'] + return None + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py new file mode 100644 index 000000000..f3651fe59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py @@ -0,0 +1,705 @@ +"""smbus2 - A drop-in replacement for smbus-cffi/smbus-python""" +# The MIT License (MIT) +# Copyright (c) 2017 Karl-Petter Lindegaard +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +import sys +from fcntl import ioctl +from ctypes import c_uint32, c_uint8, c_uint16, c_char, POINTER, Structure, Array, Union, create_string_buffer, string_at + + +# Commands from uapi/linux/i2c-dev.h +I2C_SLAVE = 0x0703 # Use this slave address +I2C_SLAVE_FORCE = 0x0706 # Use this slave address, even if it is already in use by a driver! +I2C_FUNCS = 0x0705 # Get the adapter functionality mask +I2C_RDWR = 0x0707 # Combined R/W transfer (one STOP only) +I2C_SMBUS = 0x0720 # SMBus transfer. Takes pointer to i2c_smbus_ioctl_data + +# SMBus transfer read or write markers from uapi/linux/i2c.h +I2C_SMBUS_WRITE = 0 +I2C_SMBUS_READ = 1 + +# Size identifiers uapi/linux/i2c.h +I2C_SMBUS_QUICK = 0 +I2C_SMBUS_BYTE = 1 +I2C_SMBUS_BYTE_DATA = 2 +I2C_SMBUS_WORD_DATA = 3 +I2C_SMBUS_PROC_CALL = 4 +I2C_SMBUS_BLOCK_DATA = 5 # This isn't supported by Pure-I2C drivers with SMBUS emulation, like those in RaspberryPi, OrangePi, etc :( +I2C_SMBUS_BLOCK_PROC_CALL = 7 # Like I2C_SMBUS_BLOCK_DATA, it isn't supported by Pure-I2C drivers either. +I2C_SMBUS_I2C_BLOCK_DATA = 8 +I2C_SMBUS_BLOCK_MAX = 32 + +# To determine what functionality is present (uapi/linux/i2c.h) +try: + from enum import IntFlag +except ImportError: + IntFlag = int + + +class I2cFunc(IntFlag): + """ + These flags identify the operations supported by an I2C/SMBus device. + + You can test these flags on your `smbus.funcs` + + On newer python versions, I2cFunc is an IntFlag enum, but it + falls back to class with a bunch of int constants on older releases. + """ + I2C = 0x00000001 + ADDR_10BIT = 0x00000002 + PROTOCOL_MANGLING = 0x00000004 # I2C_M_IGNORE_NAK etc. + SMBUS_PEC = 0x00000008 + NOSTART = 0x00000010 # I2C_M_NOSTART + SLAVE = 0x00000020 + SMBUS_BLOCK_PROC_CALL = 0x00008000 # SMBus 2.0 + SMBUS_QUICK = 0x00010000 + SMBUS_READ_BYTE = 0x00020000 + SMBUS_WRITE_BYTE = 0x00040000 + SMBUS_READ_BYTE_DATA = 0x00080000 + SMBUS_WRITE_BYTE_DATA = 0x00100000 + SMBUS_READ_WORD_DATA = 0x00200000 + SMBUS_WRITE_WORD_DATA = 0x00400000 + SMBUS_PROC_CALL = 0x00800000 + SMBUS_READ_BLOCK_DATA = 0x01000000 + SMBUS_WRITE_BLOCK_DATA = 0x02000000 + SMBUS_READ_I2C_BLOCK = 0x04000000 # I2C-like block xfer + SMBUS_WRITE_I2C_BLOCK = 0x08000000 # w/ 1-byte reg. addr. + SMBUS_HOST_NOTIFY = 0x10000000 + + SMBUS_BYTE = 0x00060000 + SMBUS_BYTE_DATA = 0x00180000 + SMBUS_WORD_DATA = 0x00600000 + SMBUS_BLOCK_DATA = 0x03000000 + SMBUS_I2C_BLOCK = 0x0c000000 + SMBUS_EMUL = 0x0eff0008 + + +# i2c_msg flags from uapi/linux/i2c.h +I2C_M_RD = 0x0001 + +# Pointer definitions +LP_c_uint8 = POINTER(c_uint8) +LP_c_uint16 = POINTER(c_uint16) +LP_c_uint32 = POINTER(c_uint32) + + +############################################################# +# Type definitions as in i2c.h + + +class i2c_smbus_data(Array): + """ + Adaptation of the i2c_smbus_data union in ``i2c.h``. + + Data for SMBus messages. + """ + _length_ = I2C_SMBUS_BLOCK_MAX + 2 + _type_ = c_uint8 + + +class union_i2c_smbus_data(Union): + _fields_ = [ + ("byte", c_uint8), + ("word", c_uint16), + ("block", i2c_smbus_data) + ] + + +union_pointer_type = POINTER(union_i2c_smbus_data) + + +class i2c_smbus_ioctl_data(Structure): + """ + As defined in ``i2c-dev.h``. + """ + _fields_ = [ + ('read_write', c_uint8), + ('command', c_uint8), + ('size', c_uint32), + ('data', union_pointer_type)] + __slots__ = [name for name, type in _fields_] + + @staticmethod + def create(read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE_DATA): + u = union_i2c_smbus_data() + return i2c_smbus_ioctl_data( + read_write=read_write, command=command, size=size, + data=union_pointer_type(u)) + + +############################################################# +# Type definitions for i2c_rdwr combined transactions + + +class i2c_msg(Structure): + """ + As defined in ``i2c.h``. + """ + _fields_ = [ + ('addr', c_uint16), + ('flags', c_uint16), + ('len', c_uint16), + ('buf', POINTER(c_char))] + + def __iter__(self): + """ Iterator / Generator + + :return: iterates over :py:attr:`buf` + :rtype: :py:class:`generator` which returns int values + """ + idx = 0 + while idx < self.len: + yield ord(self.buf[idx]) + idx += 1 + + def __len__(self): + return self.len + + def __bytes__(self): + return string_at(self.buf, self.len) + + def __repr__(self): + return 'i2c_msg(%d,%d,%r)' % (self.addr, self.flags, self.__bytes__()) + + def __str__(self): + s = self.__bytes__() + if sys.version_info.major >= 3: + s = ''.join(map(chr, s)) + return s + + @staticmethod + def read(address, length): + """ + Prepares an i2c read transaction. + + :param address: Slave address. + :type: address: int + :param length: Number of bytes to read. + :type: length: int + :return: New :py:class:`i2c_msg` instance for read operation. + :rtype: :py:class:`i2c_msg` + """ + arr = create_string_buffer(length) + return i2c_msg( + addr=address, flags=I2C_M_RD, len=length, + buf=arr) + + @staticmethod + def write(address, buf): + """ + Prepares an i2c write transaction. + + :param address: Slave address. + :type address: int + :param buf: Bytes to write. Either list of values or str. + :type buf: list + :return: New :py:class:`i2c_msg` instance for write operation. + :rtype: :py:class:`i2c_msg` + """ + if sys.version_info.major >= 3: + if type(buf) is str: + buf = bytes(map(ord, buf)) + else: + buf = bytes(buf) + else: + if type(buf) is not str: + buf = ''.join([chr(x) for x in buf]) + arr = create_string_buffer(buf, len(buf)) + return i2c_msg( + addr=address, flags=0, len=len(arr), + buf=arr) + + +class i2c_rdwr_ioctl_data(Structure): + """ + As defined in ``i2c-dev.h``. + """ + _fields_ = [ + ('msgs', POINTER(i2c_msg)), + ('nmsgs', c_uint32) + ] + __slots__ = [name for name, type in _fields_] + + @staticmethod + def create(*i2c_msg_instances): + """ + Factory method for creating a i2c_rdwr_ioctl_data struct that can + be called with ``ioctl(fd, I2C_RDWR, data)``. + + :param i2c_msg_instances: Up to 42 i2c_msg instances + :rtype: i2c_rdwr_ioctl_data + """ + n_msg = len(i2c_msg_instances) + msg_array = (i2c_msg * n_msg)(*i2c_msg_instances) + return i2c_rdwr_ioctl_data( + msgs=msg_array, + nmsgs=n_msg + ) + + +############################################################# + + +class SMBus(object): + + def __init__(self, bus=None, force=False): + """ + Initialize and (optionally) open an i2c bus connection. + + :param bus: i2c bus number (e.g. 0 or 1) + or an absolute file path (e.g. `/dev/i2c-42`). + If not given, a subsequent call to ``open()`` is required. + :type bus: int or str + :param force: force using the slave address even when driver is + already using it. + :type force: boolean + """ + self.fd = None + self.funcs = I2cFunc(0) + if bus is not None: + self.open(bus) + self.address = None + self.force = force + self._force_last = None + + def __enter__(self): + """Enter handler.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Exit handler.""" + self.close() + + def open(self, bus): + """ + Open a given i2c bus. + + :param bus: i2c bus number (e.g. 0 or 1) + or an absolute file path (e.g. '/dev/i2c-42'). + :type bus: int or str + :raise TypeError: if type(bus) is not in (int, str) + """ + if isinstance(bus, int): + filepath = "/dev/i2c-{}".format(bus) + elif isinstance(bus, str): + filepath = bus + else: + raise TypeError("Unexpected type(bus)={}".format(type(bus))) + + self.fd = os.open(filepath, os.O_RDWR) + self.funcs = self._get_funcs() + + def close(self): + """ + Close the i2c connection. + """ + if self.fd: + os.close(self.fd) + self.fd = None + + def _set_address(self, address, force=None): + """ + Set i2c slave address to use for subsequent calls. + + :param address: + :type address: int + :param force: + :type force: Boolean + """ + force = force if force is not None else self.force + if self.address != address or self._force_last != force: + if force is True: + ioctl(self.fd, I2C_SLAVE_FORCE, address) + else: + ioctl(self.fd, I2C_SLAVE, address) + self.address = address + self._force_last = force + + def _get_funcs(self): + """ + Returns a 32-bit value stating supported I2C functions. + + :rtype: int + """ + f = c_uint32() + ioctl(self.fd, I2C_FUNCS, f) + return f.value + + def write_quick(self, i2c_addr, force=None): + """ + Perform quick transaction. Throws IOError if unsuccessful. + :param i2c_addr: i2c address + :type i2c_addr: int + :param force: + :type force: Boolean + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=0, size=I2C_SMBUS_QUICK) + ioctl(self.fd, I2C_SMBUS, msg) + + def read_byte(self, i2c_addr, force=None): + """ + Read a single byte from a device. + + :rtype: int + :param i2c_addr: i2c address + :type i2c_addr: int + :param force: + :type force: Boolean + :return: Read byte value + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE + ) + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.byte + + def write_byte(self, i2c_addr, value, force=None): + """ + Write a single byte to a device. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param value: value to write + :type value: int + :param force: + :type force: Boolean + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=value, size=I2C_SMBUS_BYTE + ) + ioctl(self.fd, I2C_SMBUS, msg) + + def read_byte_data(self, i2c_addr, register, force=None): + """ + Read a single byte from a designated register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read + :type register: int + :param force: + :type force: Boolean + :return: Read byte value + :rtype: int + """ + val_t = -1 + returnmsg="" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BYTE_DATA + ) + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + self.close() + returnmsg = str(e) + if val_t < 0: + return False, returnmsg + else: + return True, msg.data.contents.byte + + def write_byte_data(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Byte value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA + ) + msg.data.contents.byte = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def read_word_data(self, i2c_addr, register, force=None): + """ + Read a single word (2 bytes) from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read + :type register: int + :param force: + :type force: Boolean + :return: 2-byte word + :rtype: int + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_WORD_DATA + ) + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, msg.data.contents.word + + def write_word_data(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA + ) + msg.data.contents.word = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def process_call(self, i2c_addr, register, value, force=None): + """ + Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read/write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: int + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_PROC_CALL + ) + msg.data.contents.word = value + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.word + + def read_block_data(self, i2c_addr, register, force=None): + """ + Read a block of up to 32-bytes from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BLOCK_DATA + ) + ioctl(self.fd, I2C_SMBUS, msg) + length = msg.data.contents.block[0] + return msg.data.contents.block[1:length + 1] + + def write_block_data(self, i2c_addr, register, data, force=None): + """ + Write a block of byte data to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :rtype: None + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_DATA + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + + def block_process_call(self, i2c_addr, register, data, force=None): + """ + Executes a SMBus Block Process Call, sending a variable-size data + block and receiving another variable-size response + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read/write to + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_PROC_CALL + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + length = msg.data.contents.block[0] + return msg.data.contents.block[1:length + 1] + + def read_i2c_block_data(self, i2c_addr, register, length, force=None): + """ + Read a block of byte data from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param length: Desired block length + :type length: int + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Desired block length over %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA + ) + msg.data.contents.byte = length + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.block[1:length + 1] + + def write_i2c_block_data(self, i2c_addr, register, data, force=None): + """ + Write a block of byte data to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :rtype: None + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + + def i2c_rdwr(self, *i2c_msgs): + """ + Combine a series of i2c read and write operations in a single + transaction (with repeated start bits but no stop bits in between). + + This method takes i2c_msg instances as input, which must be created + first with :py:meth:`i2c_msg.read` or :py:meth:`i2c_msg.write`. + + :param i2c_msgs: One or more i2c_msg class instances. + :type i2c_msgs: i2c_msg + :rtype: None + """ + ioctl_data = i2c_rdwr_ioctl_data.create(*i2c_msgs) + ioctl(self.fd, I2C_RDWR, ioctl_data) + + +class SMBusWrapper: + """ + Wrapper class around the SMBus. + Deprecated as of version 0.3.0. Please replace with :py:class:`SMBus`. + + Enables the user to wrap access to the :py:class:`SMBus` class in a + "with" statement. If auto_cleanup is True (default), the + :py:class:`SMBus` handle will be automatically closed + upon exit of the ``with`` block. + """ + def __init__(self, bus_number=0, auto_cleanup=True, force=False): + """ + :param auto_cleanup: Close bus when leaving scope. + :type auto_cleanup: Boolean + :param force: Force using the slave address even when driver is already using it. + :type force: Boolean + """ + self.bus_number = bus_number + self.auto_cleanup = auto_cleanup + self.force = force + + def __enter__(self): + self.bus = SMBus(bus=self.bus_number, force=self.force) + return self.bus + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.auto_cleanup: + self.bus.close() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile new file mode 100755 index 000000000..373027a26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile @@ -0,0 +1,7 @@ +obj-m := rg-gpio-xeon.o +obj-m += rg_fan.o +obj-m += rg_psu.o +obj-m += ruijie_platform.o +obj-m += i2c-mux-pca9641.o +obj-m += i2c-mux-pca954x.o +obj-m += csu550.o diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c new file mode 100755 index 000000000..bb6a15889 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c @@ -0,0 +1,209 @@ +/* + * csu550.c - A driver for pmbus + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + + +/* + * Find sensor groups and status registers on each page. + */ +static void pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* Sensors detected on page 0 only */ + if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page) < 0) + break; + } + pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* Try to find sensor groups */ + pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +static int pmbus_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + struct pmbus_platform_data *pdata = NULL; + struct device *dev = &client->dev; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (!strncmp(id->name, "dps460", sizeof("dps460")) || + !strncmp(id->name, "fsp1200", sizeof("fsp1200")) || !strncmp(id->name, "dps550", sizeof("dps550"))) { + pdata = kzalloc(sizeof(struct pmbus_platform_data), GFP_KERNEL); + if (!pdata) { + kfree(info); + return -ENOMEM; + } + pdata->flags = PMBUS_SKIP_STATUS_CHECK; + } + + info->pages = id->driver_data; + info->identify = pmbus_identify; + dev->platform_data = pdata; + + return pmbus_do_probe(client, id, info); +} + +static const struct i2c_device_id pmbus_id[] = { + {"csu550", 0}, + {"csu800", 1}, + {"fsp1200", 1}, + {"dps550", 1}, + {} +}; +MODULE_DEVICE_TABLE(i2c, pmbus_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver pmbus_driver = { + .probe = pmbus_probe, + .remove = pmbus_do_remove, + .id_table = pmbus_id, + .driver = { + .name = "pmbus", + }, +}; + +module_i2c_driver(pmbus_driver); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie psupmbus driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c new file mode 100755 index 000000000..cc2d12c8b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c @@ -0,0 +1,1763 @@ +/* + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * Copyright (c) 2019 + * + * I2C multiplexer + * + * This module supports the PCA954x series of I2C multiplexer/switch chips + * made by Philips Semiconductors. + * This includes the: + * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 + * and PCA9548. + * + * These chips are all controlled via the I2C bus itself, and all have a + * single 8-bit register. The upstream "parent" bus fans out to two, + * four, or eight downstream busses or channels; which of these + * are selected is determined by the chip type and register contents. A + * mux can select only one sub-bus at a time; a switch can select any + * combination simultaneously. + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PCA954X_MAX_NCHANS 8 + +#define PCA954X_IRQ_OFFSET 4 + +extern int pca9641_setmuxflag(int nr, int flag); + +int force_create_bus = 0; +module_param(force_create_bus, int, S_IRUGO | S_IWUSR); + +enum pca_type { + pca_9540, + pca_9542, + pca_9543, + pca_9544, + pca_9545, + pca_9546, + pca_9547, + pca_9548, +}; + +struct chip_desc { + u8 nchans; + u8 enable; /* used for muxes only */ + u8 has_irq; + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi + } muxtype; +}; + + + + +struct pca954x { + const struct chip_desc *chip; + + u8 last_chan; /* last register value */ + u8 deselect; + struct i2c_client *client; + + struct irq_domain *irq; + unsigned int irq_mask; + raw_spinlock_t lock; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [pca_9540] = { + .nchans = 2, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9542] = { + .nchans = 2, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + }, + [pca_9543] = { + .nchans = 2, + .has_irq = 1, + .muxtype = pca954x_isswi, + }, + [pca_9544] = { + .nchans = 4, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + }, + [pca_9545] = { + .nchans = 4, + .has_irq = 1, + .muxtype = pca954x_isswi, + }, + [pca_9546] = { + .nchans = 4, + .muxtype = pca954x_isswi, + }, + [pca_9547] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + }, + [pca_9548] = { + .nchans = 8, + .muxtype = pca954x_isswi, + }, +}; + +static const struct i2c_device_id pca954x_id[] = { + { "pca9540", pca_9540 }, + { "pca9542", pca_9542 }, + { "pca9543", pca_9543 }, + { "pca9544", pca_9544 }, + { "pca9545", pca_9545 }, + { "pca9546", pca_9546 }, + { "pca9547", pca_9547 }, + { "pca9548", pca_9548 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca954x_of_match[] = { + { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, + { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, + { .compatible = "nxp,pca9543", .data = &chips[pca_9543] }, + { .compatible = "nxp,pca9544", .data = &chips[pca_9544] }, + { .compatible = "nxp,pca9545", .data = &chips[pca_9545] }, + { .compatible = "nxp,pca9546", .data = &chips[pca_9546] }, + { .compatible = "nxp,pca9547", .data = &chips[pca_9547] }, + { .compatible = "nxp,pca9548", .data = &chips[pca_9548] }, + {} +}; +MODULE_DEVICE_TABLE(of, pca954x_of_match); +#endif + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int pca954x_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + int ret = -ENODEV; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[1]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + buf[0] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + + if (ret >= 0 && ret != 1) + ret = -EREMOTEIO; + } else { + union i2c_smbus_data data; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + val, I2C_SMBUS_BYTE, &data); + } + + return ret; +} + + static int pca954x_setmuxflag(struct i2c_client *client, int flag) + { + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + pca9641_setmuxflag(adap->nr, flag); + return 0; + } + +static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + const struct chip_desc *chip = data->chip; + u8 regval; + int ret = 0; + + /* we make switches look like muxes, not sure how to be smarter */ + if (chip->muxtype == pca954x_ismux) + regval = chan | chip->enable; + else + regval = 1 << chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + pca954x_setmuxflag(client, 0); + ret = pca954x_reg_write(muxc->parent, client, regval); + data->last_chan = ret < 0 ? 0 : regval; + } + + return ret; +} + + +typedef void (*pca954x_hw_do_reset_func_t)(int busid, int addr); +pca954x_hw_do_reset_func_t g_notify_to_do_reset = NULL; + +void pca954x_hw_do_reset_func_register(void* func) +{ + if (func == NULL) { + return ; + } + g_notify_to_do_reset = func; + return; +} +EXPORT_SYMBOL(pca954x_hw_do_reset_func_register); + +static int pca954x_hw_do_reset(int busid, int addr) +{ + if (g_notify_to_do_reset != NULL) { + (*g_notify_to_do_reset)(busid, addr); + return 0; + } + + return 0; +} +/***************************************9548 reset*****************************************/ +#define DEV_TYPE 0x4040 /* BT2575 */ +#define PCA9548_MAX_CPLD_NUM (32) /* PCA9548 max number */ +#define PCA9548_MAX_CPLD_LAYER (8) /* PCA9548 max layer */ +#define DFD_PID_BUF_LEN (32) +#define DFD_PRODUCT_ID_LENGTH (8) +#define CPLD_PCA9548_RESET 0x023500b0 /* bus:2, addr:0x35, offset:0xb0 */ +#define B6510_32CQ_CPLD_PCA9548_RESET 0x060d0060 /* bus:6, addr:0x0d, offset:0x60 */ + +#define DFD_PUB_CARDTYPE_FILE "/sys/module/ruijie_common/parameters/dfd_my_type" +#define DFD_MAX_PRODUCT_NUM (32) + + +#define I2C_RETRY_TIMES 5 +#define I2C_RETRY_WAIT_TIMES 10 /*delay 10ms*/ + +#define PCA9548_I2C_GET_BUS(addr) (((addr) >> 24) & 0x00ff) +#define PCA9548_I2C_GET_CLIENT(addr) (((addr) >> 16) & 0x00ff) +#define PCA9548_I2C_GET_OFFSET(addr) (addr & 0xffff) + +typedef enum pca9548_reset_type { + PCA9548_RESET_FUNC = 0, + PCA9548_RESET_GPIO = 1, +} pca9548_reset_type_t; + +typedef void (*pca954x_hw_do_reset_func_t_new)(int io_port, u8 value); +typedef u8 (*pca954x_get_umask_func_t)(int io_port); + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value); +u8 pca954x_get_umask_by_i2c(int addr); +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value); +u8 pca954x_get_umask_by_lpc(int io_port); + + +typedef struct func_attr_s { + int cfg_offset[PCA9548_MAX_CPLD_LAYER]; + int umask[PCA9548_MAX_CPLD_LAYER]; + pca954x_hw_do_reset_func_t_new reset_func; /* 9548 reset function */ + pca954x_get_umask_func_t get_umask_func; /* get reset mask */ +} func_attr_t; + +typedef struct gpio_attr_s { + int gpio; + int gpio_init; + u8 reset_on; + u8 reset_off; +} gpio_attr_t; + +typedef struct pca9548_cfg_info_s { + int pca9548_reset_type; + int pca9548_bus; + int pca9548_addr; + int rst_delay_b; /* delay time before reset(us) */ + int rst_delay; /* reset time(us) */ + int rst_delay_a; /* delay time after reset(us) */ + union { + func_attr_t func_attr; + gpio_attr_t gpio_attr; + } attr; +} pca9548_cfg_info_t; + +typedef struct fpga_pcie_card_info_s { + int dev_type[DFD_MAX_PRODUCT_NUM]; /* dev type */ + pca9548_cfg_info_t pca9548_cfg_info[PCA9548_MAX_CPLD_NUM]; +} pca9548_card_info_t; + +static pca9548_card_info_t g_pca9548_card_info[] = { + { + .dev_type = {0x4040,0x4061,0x4071}, /*B6510,BT2575,TCS81*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4041}, /*B6520*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + /* sff8 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4044,0x4072,0x4048}, /*B6920,TCS83,BS100R0*/ + .pca9548_cfg_info = { + /* һ��9548 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x936, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* �װ� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 8, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* �ӿ�1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 9, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* �ӿ�2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 12, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* �ӿ�3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 11, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* �ӿ�4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 7, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* ����A */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 14, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* ����B */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 13, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + /* �ӿ�1 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* �ӿ�2 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* �ӿ�3 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* �ӿ�4 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4058,0x4073}, /* B6510-32CQ, TCS82 */ + .pca9548_cfg_info = { + /* psu */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* fan */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + }, + }, +}; +int g_pca954x_debug = 0; +module_param(g_pca954x_debug, int, S_IRUGO | S_IWUSR); + +#define PCA954X_DEBUG(fmt, args...) do { \ + if (g_pca954x_debug) { \ + printk(KERN_ERR "[PCA95x][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +/* x86�豸��ȡ�忨���ͷ��� */ +static int dfd_get_my_dev_type_by_file(void) +{ + struct file *fp; + /* mm_segment_t fs;*/ + loff_t pos; + static int card_type; + char buf[DFD_PID_BUF_LEN]; + + if (card_type != 0) { + return card_type; + } + + fp= filp_open(DFD_PUB_CARDTYPE_FILE, O_RDONLY, 0); + if (IS_ERR(fp)) { + PCA954X_DEBUG("open file fail!\r\n"); + return -1; + } + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + memset(buf, 0, DFD_PID_BUF_LEN); + pos = 0; + kernel_read(fp, pos, buf, DFD_PRODUCT_ID_LENGTH + 1 ); + if (pos < 0) { + PCA954X_DEBUG("read file fail!\r\n"); + goto exit; + } + + card_type = simple_strtoul(buf, NULL, 10); + PCA954X_DEBUG("card_type 0x%x.\n", card_type); + +exit: + /* set_fs(fs); */ + filp_close(fp, NULL); + return card_type; +} + +static int drv_get_my_dev_type(void) +{ + static int type = -1; + + if (type > 0) { + return type; + } + type = dfd_get_my_dev_type_by_file(); + PCA954X_DEBUG("ko board type %d\r\n", type); + + return type; +} + +pca9548_card_info_t* pca9548_get_card_info(int dev_type) +{ + int i, j; + int size; + + size = ARRAY_SIZE(g_pca9548_card_info); + + PCA954X_DEBUG("Enter dev_type 0x%x size %d.\n", dev_type, size); + for (i = 0; i < size; i++) { + for(j = 0; j < DFD_MAX_PRODUCT_NUM; j++) { + if (g_pca9548_card_info[i].dev_type[j] == dev_type) { + PCA954X_DEBUG("match dev_type 0x%x.\n", dev_type); + return &g_pca9548_card_info[i]; + } + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x.\n", dev_type); + return NULL; +} + +pca9548_cfg_info_t* get_pca9548_cfg_info(int bus, int addr) +{ + int dev_type; + pca9548_card_info_t *info; + pca9548_cfg_info_t *pca9548_cfg_info; + int i; + int size; + + dev_type = drv_get_my_dev_type(); + if (dev_type < 0) { + PCA954X_DEBUG("drv_get_my_dev_type failed ret %d.\n", dev_type); + return NULL; + } + + info = pca9548_get_card_info(dev_type); + if (info == NULL) { + PCA954X_DEBUG("fpga_pcie_get_card_info dev_type %d failed.\n", dev_type); + return NULL; + } + + size = PCA9548_MAX_CPLD_NUM; + for (i = 0; i < size; i++) { + pca9548_cfg_info = &(info->pca9548_cfg_info[i]); + if ((pca9548_cfg_info->pca9548_bus == bus) && (pca9548_cfg_info->pca9548_addr == addr)) { + PCA954X_DEBUG("match dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return pca9548_cfg_info; + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return NULL; +} + +static void pca9548_gpio_init(gpio_attr_t *gpio_attr) +{ + if (gpio_attr->gpio_init == 0) { + PCA954X_DEBUG("gpio%d init.\n", gpio_attr->gpio); + gpio_request(gpio_attr->gpio, "pca9548_reset"); + gpio_direction_output(gpio_attr->gpio, gpio_attr->reset_off); + gpio_attr->gpio_init = 1; + } +} + +static void pca9548_gpio_free(gpio_attr_t *gpio_attr) +{ + if (gpio_attr == NULL) { + PCA954X_DEBUG("pca9548_gpio_free,params error\n"); + return ; + } + if (gpio_attr->gpio_init == 1) { + PCA954X_DEBUG("gpio%d release.\n", gpio_attr->gpio); + gpio_free(gpio_attr->gpio); + gpio_attr->gpio_init = 0; + } +} + +static int pca954x_do_gpio_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret = -1; + gpio_attr_t *tmp_gpio_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + tmp_gpio_attr = &(cfg_info->attr.gpio_attr); + timeout = cfg_info->rst_delay_a; + + pca9548_gpio_init(tmp_gpio_attr); + udelay(cfg_info->rst_delay_b); + /* reset on */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + udelay(cfg_info->rst_delay); + /* reset off */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + + while (timeout > 0) { + udelay(1); + val = __gpio_get_value(tmp_gpio_attr->gpio); + if (val == tmp_gpio_attr->reset_off) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_gpio_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_gpio_reset failed.\n"); + } + pca9548_gpio_free(&(cfg_info->attr.gpio_attr)); + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_gpio_reset failed.\n"); + } + + return ret; +} + +static int pca954x_do_func_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret = -1; + func_attr_t *tmp_func_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + int i; + u8 old_value; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + tmp_func_attr = &(cfg_info->attr.func_attr); + timeout = cfg_info->rst_delay_a; + + if ((tmp_func_attr->reset_func == NULL) || (tmp_func_attr->get_umask_func == NULL)) { + PCA954X_DEBUG("pca954x hw do reset func or get umask func is null.\n"); + return ret; + } + + for(i = 0; (i < PCA9548_MAX_CPLD_LAYER) && (tmp_func_attr->cfg_offset[i] != -1) + && (tmp_func_attr->umask[i] != -1); i++) { + old_value = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i]); + PCA954X_DEBUG("cfg info: offset:0x%x umask:0x%x, old_value:0x%x\n", + tmp_func_attr->cfg_offset[i], tmp_func_attr->umask[i],old_value); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value & ~tmp_func_attr->umask[i]); + udelay(cfg_info->rst_delay); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value | tmp_func_attr->umask[i]); + } + + while (timeout > 0) { + udelay(1); + val = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i - 1]); + val &= (tmp_func_attr->umask[i - 1]); + if (val == tmp_func_attr->umask[i - 1]) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_func_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_func_reset failed.\n"); + } + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_func_reset failed.\n"); + } + + return ret; +} + +static int pca9548_reset_ctrl(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + int ret = -1; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + ret = pca954x_do_func_reset(cfg_info, adap, client, chan); + } else if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + ret = pca954x_do_gpio_reset(cfg_info, adap, client, chan); + } + + if (ret < 0) { + PCA954X_DEBUG("pca9548_reset_ctrl failed.\n"); + } + return ret; +} + +static int pca954x_reset_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset_addr, + unsigned char *buf, uint32_t size) +{ + struct file *fp; + /* mm_segment_t fs; */ + struct i2c_client client; + char i2c_path[32]; + int i ,j ; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = addr; + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + for (j = 0 ;j < size ;j++){ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_read_byte_data(&client, (offset_addr + j)); + if (rv < 0) { + PCA954X_DEBUG("i2c read failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + *(buf + j) = (unsigned char)rv; + break; + } + } +out: + filp_close(fp, NULL); + /* set_fs(fs); */ + return rv; +} + +static int pca954x_reset_i2c_write(uint32_t bus, uint32_t dev_addr, uint32_t offset_addr, + uint8_t write_buf) +{ + struct file *fp; + /* mm_segment_t fs; */ + struct i2c_client client; + char i2c_path[32]; + int i; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = dev_addr; + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_write_byte_data(&client, offset_addr, write_buf); + if (rv < 0) { + PCA954X_DEBUG("i2c write failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + break; + } +out: + filp_close(fp, NULL); + /* set_fs(fs); */ + return rv; +} + +int pca954x_reset_reg_i2c_read_byte(int addr, u8 *value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_read(bus, client_addr, offset, value, 1); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x read fail\r\n", addr); + goto end; + } +end: + return ret; +} + +int pca954x_reset_reg_i2c_write_byte(int addr, u8 value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_write(bus, client_addr, offset, value); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x write fail\r\n", addr); + goto end; + } +end: + return ret; +} + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value) +{ + int ret; + + PCA954X_DEBUG("write i2c cpld[0x%x], value[%d]\n", addr, value); + ret = pca954x_reset_reg_i2c_write_byte(addr, value); + if (ret < 0) { + PCA954X_DEBUG("write cpld pca9548 reset reg failed, ret = %d \n", ret); + } +} + +u8 pca954x_get_umask_by_i2c(int addr) +{ + u8 value = 0xFF; + int ret; + + ret = pca954x_reset_reg_i2c_read_byte(addr, &value); + PCA954X_DEBUG("read i2c cpld[0x%x], value[%d], ret = %d\n", addr, value, ret); + + return value; +} + +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value) +{ + PCA954X_DEBUG("write lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + outb(value, (u16)io_port); +} + +u8 pca954x_get_umask_by_lpc(int io_port) +{ + u8 value; + + value = inb(io_port); + PCA954X_DEBUG("read lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + + return value; +} + +int pca954x_hw_do_reset_new(struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + pca9548_cfg_info_t *cfg_info; + int ret = -1; + + cfg_info = get_pca9548_cfg_info(adap->nr, client->addr); + if (cfg_info == NULL && g_notify_to_do_reset == NULL) { + PCA954X_DEBUG("fpga_do_pca954x_reset_func do nothing.\n"); + return ret; + } + if(cfg_info != NULL) { + ret = pca9548_reset_ctrl(cfg_info, adap, client, chan); + } else { + ret = pca954x_hw_do_reset(adap->nr, client->addr); + } + if (ret < 0) { + PCA954X_DEBUG("pca954x_hw_do_reset failed.\n"); + } + return ret; +} +/******************************end 9548 reset***********************************/ + +static int pca954x_do_reset(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct i2c_client *new_client; + int ret = -1; + + PCA954X_DEBUG("do pca954x reset x86\n"); + new_client =(struct i2c_client *) client; + ret = pca954x_hw_do_reset_new(adap, new_client, chan); + if (ret < 0) { + PCA954X_DEBUG("pca954x_do_reset failed.\n"); + return ret; + } + + PCA954X_DEBUG("pca954x_do_reset success.\n"); + ret = 0; + return ret; +} +static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret, rv; + struct i2c_client * new_client; + + /* Deselect active channel */ + data->last_chan = 0; + + ret = pca954x_reg_write(muxc->parent, client, data->last_chan); + if (ret < 0) { + /* ʹ��i2c��ʽ�ر�ͨ��ʧ�ܣ�����ʹ��reset��ʽ */ + new_client =(struct i2c_client *) client; + dev_warn(&new_client->dev, "pca954x close chn failed, do reset.\n"); + rv = pca954x_do_reset(client->adapter, client, chan); + if (rv == 0) { + ret = 0; + } + + } + /*9641Ȩ����Ҫ��9548��λ֮���ͷţ����¹�һ��ͨ��ȷ��9641Ȩ�������ͷ�*/ + pca954x_setmuxflag(client, 1); + (void)pca954x_reg_write(muxc->parent, client, data->last_chan); + + return ret; + +} + +static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) +{ + struct pca954x *data = dev_id; + unsigned int child_irq; + int ret, i, handled = 0; + + ret = i2c_smbus_read_byte(data->client); + if (ret < 0) + return IRQ_NONE; + + for (i = 0; i < data->chip->nchans; i++) { + if (ret & BIT(PCA954X_IRQ_OFFSET + i)) { + child_irq = irq_linear_revmap(data->irq, i); + handle_nested_irq(child_irq); + handled++; + } + } + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static void pca954x_irq_mask(struct irq_data *idata) +{ + struct pca954x *data = irq_data_get_irq_chip_data(idata); + unsigned int pos = idata->hwirq; + unsigned long flags; + + raw_spin_lock_irqsave(&data->lock, flags); + + data->irq_mask &= ~BIT(pos); + if (!data->irq_mask) + disable_irq(data->client->irq); + + raw_spin_unlock_irqrestore(&data->lock, flags); +} + +static void pca954x_irq_unmask(struct irq_data *idata) +{ + struct pca954x *data = irq_data_get_irq_chip_data(idata); + unsigned int pos = idata->hwirq; + unsigned long flags; + + raw_spin_lock_irqsave(&data->lock, flags); + + if (!data->irq_mask) + enable_irq(data->client->irq); + data->irq_mask |= BIT(pos); + + raw_spin_unlock_irqrestore(&data->lock, flags); +} + +static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) +{ + if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + return 0; +} + +static struct irq_chip pca954x_irq_chip = { + .name = "i2c-mux-pca954x", + .irq_mask = pca954x_irq_mask, + .irq_unmask = pca954x_irq_unmask, + .irq_set_type = pca954x_irq_set_type, +}; + +static int pca954x_irq_setup(struct i2c_mux_core *muxc) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int c, err, irq; + + if (!data->chip->has_irq || client->irq <= 0) + return 0; + + raw_spin_lock_init(&data->lock); + + data->irq = irq_domain_add_linear(client->dev.of_node, + data->chip->nchans, + &irq_domain_simple_ops, data); + if (!data->irq) + return -ENODEV; + + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_create_mapping(data->irq, c); + irq_set_chip_data(irq, data); + irq_set_chip_and_handler(irq, &pca954x_irq_chip, + handle_simple_irq); + } + + err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL, + pca954x_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, + "pca954x", data); + if (err) + goto err_req_irq; + + disable_irq(data->client->irq); + + return 0; +err_req_irq: + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_find_mapping(data->irq, c); + irq_dispose_mapping(irq); + } + irq_domain_remove(data->irq); + + return err; +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct device_node *of_node = client->dev.of_node; + bool idle_disconnect_dt; + struct gpio_desc *gpio; + int num, force, class; + struct i2c_mux_core *muxc; + struct pca954x *data; + const struct of_device_id *match; + int ret; + + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + PCA954X_MAX_NCHANS, sizeof(*data), 0, + pca954x_select_chan, pca954x_deselect_mux); + if (!muxc) + return -ENOMEM; + data = i2c_mux_priv(muxc); + + i2c_set_clientdata(client, muxc); + data->client = client; + + /* Get the mux out of reset if a reset GPIO is specified. */ + gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + + /* Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to disconnected state. + */ + if ((i2c_smbus_write_byte(client, 0) < 0) && (force_create_bus == 0)) { + dev_warn(&client->dev, "probe failed\n"); + return -ENODEV; + } + + match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); + if (match) + data->chip = of_device_get_match_data(&client->dev); + else + data->chip = &chips[id->driver_data]; + + data->last_chan = 0; /* force the first selection */ + + idle_disconnect_dt = of_node && + of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); + + ret = pca954x_irq_setup(muxc); + if (ret) + goto fail_del_adapters; + + /* Now create an adapter for each channel */ + for (num = 0; num < data->chip->nchans; num++) { + bool idle_disconnect_pd = false; + + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + if (pdata) { + if (num < pdata->num_modes) { + /* force static number */ + force = pdata->modes[num].adap_id; + class = pdata->modes[num].class; + } else + /* discard unconfigured channels */ + break; + idle_disconnect_pd = pdata->modes[num].deselect_on_exit; + } + data->deselect |= (idle_disconnect_pd || + idle_disconnect_dt) << num; + + ret = i2c_mux_add_adapter(muxc, force, num, class); + if (ret) + goto fail_del_adapters; + } + + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s %s\n", + num, data->chip->muxtype == pca954x_ismux + ? "mux" : "switch", client->name); + + return 0; + +fail_del_adapters: + i2c_mux_del_adapters(muxc); + return ret; +} + +static int pca954x_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int c, irq; + + if (data->irq) { + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_find_mapping(data->irq, c); + irq_dispose_mapping(irq); + } + irq_domain_remove(data->irq); + } + + i2c_mux_del_adapters(muxc); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pca954x_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + + data->last_chan = 0; + return i2c_smbus_write_byte(client, 0); +} +#endif + +static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume); + +static struct i2c_driver pca954x_driver = { + .driver = { + .name = "pca954x", + .pm = &pca954x_pm, + .of_match_table = of_match_ptr(pca954x_of_match), + }, + .probe = pca954x_probe, + .remove = pca954x_remove, + .id_table = pca954x_id, +}; + +module_i2c_driver(pca954x_driver); + +MODULE_AUTHOR("sonic_rd sonic_rd@ruijie.com.cn"); +MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c new file mode 100755 index 000000000..bb2af837d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c @@ -0,0 +1,645 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * Copyright (c) 2019 + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) +#define PCA9641_ID 0x00 +#define PCA9641_ID_MAGIC 0x38 +#define PCA9641_CONTROL 0x01 +#define PCA9641_STATUS 0x02 +#define PCA9641_TIME 0x03 +#define PCA9641_CTL_LOCK_REQ BIT(0) +#define PCA9641_CTL_LOCK_GRANT BIT(1) +#define PCA9641_CTL_BUS_CONNECT BIT(2) +#define PCA9641_CTL_BUS_INIT BIT(3) +#define PCA9641_CTL_SMBUS_SWRST BIT(4) +#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5) +#define PCA9641_CTL_SMBUS_DIS BIT(6) +#define PCA9641_CTL_PRIORITY BIT(7) +#define PCA9641_STS_OTHER_LOCK BIT(0) +#define PCA9641_STS_BUS_INIT_FAIL BIT(1) +#define PCA9641_STS_BUS_HUNG BIT(2) +#define PCA9641_STS_MBOX_EMPTY BIT(3) +#define PCA9641_STS_MBOX_FULL BIT(4) +#define PCA9641_STS_TEST_INT BIT(5) +#define PCA9641_STS_SCL_IO BIT(6) +#define PCA9641_STS_SDA_IO BIT(7) +#define PCA9641_RES_TIME 0x03 +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) +#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \ + !((y) & PCA9641_STS_OTHER_LOCK)) +#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK) +#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT) + +#define PCA9641_RETRY_TIME 8 + +typedef struct i2c_muxs_struct_flag +{ + int nr; + char name[48]; + struct mutex update_lock; + int flag; +}i2c_mux_flag; + +i2c_mux_flag pca_flag = { + .flag = -1, +}; + +int pca9641_setmuxflag(int nr, int flag) +{ + if (pca_flag.nr == nr) { + pca_flag.flag = flag; + } + return 0; +} +EXPORT_SYMBOL(pca9641_setmuxflag); + +int g_debug = 0; +module_param(g_debug, int, S_IRUGO | S_IWUSR); + +#define PCA_DEBUG(fmt, args...) do { \ + if (g_debug) { \ + printk(KERN_ERR "[pca9641][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_client *client; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {"pca9641", 1}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + { .compatible = "nxp,pca9641" }, + {} +}; +MODULE_DEVICE_TABLE(of, pca9541_of_match); +#endif + + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = __i2c_transfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + pca9541_release_bus(client); + return 0; +} + +/* +* Arbitration management functions +*/ +static void pca9641_release_bus(struct i2c_client *client) +{ + pca9541_reg_write(client, PCA9641_CONTROL, 0x80); //master 0x80 +} + +/* +* Channel arbitration +* +* Return values: +* <0: error +* 0 : bus not acquired +* 1 : bus acquired +*/ +static int pca9641_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg_ctl, reg_sts; + + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + if (reg_ctl < 0) + return reg_ctl; + reg_sts = pca9541_reg_read(client, PCA9641_STATUS); + + if (BUSOFF(reg_ctl, reg_sts)) { + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + + if (lock_grant(reg_ctl)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT + | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + data->select_timeout = SELECT_DELAY_SHORT; + + return 1; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (lock_grant(reg_ctl)) { + /* + * Bus is on, and we own it. We are done with acquisition. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + + return 1; + } else if (other_lock(reg_sts)) { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + } + return 0; +} + + +int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + int result; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + for (result = 0 ; result < PCA9641_RETRY_TIME ; result ++) { + do { + ret = pca9641_arbitrate(client); + if (ret == 1) { + return 0; + } + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + timeout = jiffies + ARB2_TIMEOUT; + } + return -ETIMEDOUT; +} +EXPORT_SYMBOL(pca9641_select_chan); + +static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + if (pca_flag.flag) { + pca9641_release_bus(client); + } + return 0; +} + +static int pca9641_detect_id(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9641_ID); + if (reg == PCA9641_ID_MAGIC) + return 1; + else + return 0; +} + +/** + ** �޶�: 20180827 ֧��һ��PCA9641 + **/ +static int pca9641_recordflag(struct i2c_adapter *adap) { + if (pca_flag.flag != -1) { + pr_err(" %s %d has init already!!!", __func__, __LINE__); + return -1 ; + } + pca_flag.nr = adap->nr; + PCA_DEBUG(" adap->nr:%d\n", adap->nr); + snprintf(pca_flag.name, sizeof(pca_flag.name),adap->name); + return 0; +} + +static void i2c_lock_adapter(struct i2c_adapter *adapter){ + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + if (parent) + i2c_lock_adapter(parent); + else + rt_mutex_lock(&adapter->bus_lock); +} + +void i2c_unlock_adapter(struct i2c_adapter *adapter) +{ + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_unlock_adapter(parent); + else + rt_mutex_unlock(&adapter->bus_lock); +} +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; + struct pca9541 *data; + int force; + int ret = -ENODEV; + int detect_id; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + detect_id = pca9641_detect_id(client); + + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + if (detect_id == 0) { + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + } else { + i2c_lock_adapter(adap); + pca9641_release_bus(client); + i2c_unlock_adapter(adap); + } + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + + if (detect_id == 0) { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9541_select_chan, pca9541_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) + return ret; + } else { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9641_select_chan, pca9641_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) + return ret; + } + pca9641_recordflag(muxc->adapter[0]); + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; + +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + i2c_mux_del_adapters(muxc); + return 0; +} + +static struct i2c_driver pca9641_driver = { + .driver = { + .name = "pca9641", + .of_match_table = of_match_ptr(pca9541_of_match), + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9641_driver); + +MODULE_AUTHOR("sonic_rd sonic_rd@ruijie.com.cn"); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h new file mode 100755 index 000000000..869a8d155 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h @@ -0,0 +1,424 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +#include +#include + +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT BIT(4) +#define PB_CAPABILITY_ERROR_CHECK BIT(7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1)) +#define PB_FAN_2_RPM BIT(2) +#define PB_FAN_2_INSTALLED BIT(3) +#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5)) +#define PB_FAN_1_RPM BIT(6) +#define PB_FAN_1_INSTALLED BIT(7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE BIT(0) +#define PB_STATUS_CML BIT(1) +#define PB_STATUS_TEMPERATURE BIT(2) +#define PB_STATUS_VIN_UV BIT(3) +#define PB_STATUS_IOUT_OC BIT(4) +#define PB_STATUS_VOUT_OV BIT(5) +#define PB_STATUS_OFF BIT(6) +#define PB_STATUS_BUSY BIT(7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN BIT(8) +#define PB_STATUS_OTHER BIT(9) +#define PB_STATUS_FANS BIT(10) +#define PB_STATUS_POWER_GOOD_N BIT(11) +#define PB_STATUS_WORD_MFR BIT(12) +#define PB_STATUS_INPUT BIT(13) +#define PB_STATUS_IOUT_POUT BIT(14) +#define PB_STATUS_VOUT BIT(15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING BIT(0) +#define PB_POUT_OP_FAULT BIT(1) +#define PB_POWER_LIMITING BIT(2) +#define PB_CURRENT_SHARE_FAULT BIT(3) +#define PB_IOUT_UC_FAULT BIT(4) +#define PB_IOUT_OC_WARNING BIT(5) +#define PB_IOUT_OC_LV_FAULT BIT(6) +#define PB_IOUT_OC_FAULT BIT(7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT BIT(4) +#define PB_VOLTAGE_UV_WARNING BIT(5) +#define PB_VOLTAGE_OV_WARNING BIT(6) +#define PB_VOLTAGE_OV_FAULT BIT(7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING BIT(0) +#define PB_IIN_OC_WARNING BIT(1) +#define PB_IIN_OC_FAULT BIT(2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT BIT(4) +#define PB_TEMP_UT_WARNING BIT(5) +#define PB_TEMP_OT_WARNING BIT(6) +#define PB_TEMP_OT_FAULT BIT(7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING BIT(0) +#define PB_FAN_AIRFLOW_FAULT BIT(1) +#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2) +#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3) +#define PB_FAN_FAN2_WARNING BIT(4) +#define PB_FAN_FAN1_WARNING BIT(5) +#define PB_FAN_FAN2_FAULT BIT(6) +#define PB_FAN_FAN1_FAULT BIT(7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) +#define PB_CML_FAULT_OTHER_COMM BIT(1) +#define PB_CML_FAULT_PROCESSOR BIT(3) +#define PB_CML_FAULT_MEMORY BIT(4) +#define PB_CML_FAULT_PACKET_ERROR BIT(5) +#define PB_CML_FAULT_INVALID_DATA BIT(6) +#define PB_CML_FAULT_INVALID_COMMAND BIT(7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version[PMBUS_PAGES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +/* Regulator ops */ + +extern const struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, + u8 value); +int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, + u8 mask, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c new file mode 100644 index 000000000..89043f377 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c @@ -0,0 +1,357 @@ +/* + * GPIO interface for XEON Super I/O chip + * + * Author: sonic_rd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_NAME "xeon-gpio" +#define GPIO_IOSIZE 7 +#define GPIO_BASE 0x500 + +#define GPIO_USE_SEL GPIO_BASE +#define GP_IO_SEL (GPIO_BASE+0x4) +#define GP_LVL (GPIO_BASE+0xC) + +#define GPIO_USE_SEL2 (GPIO_BASE+0x30) +#define GP_IO_SEL2 (GPIO_BASE+0x34) +#define GP_LVL2 (GPIO_BASE+0x38) + +#define GPIO_USE_SEL3 (GPIO_BASE+0x40) +#define GP_IO_SEL3 (GPIO_BASE+0x44) +#define GP_LVL3 (GPIO_BASE+0x48) + + +#define GPIO_BASE_ID 0 +#define BANKSIZE 32 + +#define GPIO_SDA 17 +#define GPIO_SCL 1 + +#define GPIO_XEON_SPIN_LOCK(lock, flags) spin_lock_irqsave(&(lock), (flags)) +#define GPIO_XEON_SPIN_UNLOCK(lock, flags) spin_unlock_irqrestore(&(lock), (flags)) +static DEFINE_SPINLOCK(sio_lock); + +/****************** i2c adapter with gpio ***********************/ + +static struct i2c_gpio_platform_data i2c_pdata = { + .timeout = 200, + .udelay = 10, + .scl_is_output_only = 0, + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, +}; + +static struct gpiod_lookup_table rg_gpio_lookup_table = { + .dev_id = "i2c-gpio", + .table = { + GPIO_LOOKUP(GPIO_NAME, GPIO_SDA, "sda", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP(GPIO_NAME, GPIO_SCL, "scl", + GPIO_ACTIVE_HIGH), + }, +}; + +static void i2c_gpio_release(struct device *dev) +{ + return; +} + +static struct platform_device i2c_gpio = { + .name = "i2c-gpio", + .num_resources = 0, + .id = -1, + + .dev = { + .platform_data = &i2c_pdata, + .release = i2c_gpio_release, + } +}; + +static int xeon_gpio_get(struct gpio_chip *gc, unsigned gpio_num) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + data = 0; + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_LVL) & (1 << offset); + if (data) { + data = 1; + } + } else if (bank == 1) { + data = inl(GP_LVL2) & (1 << offset); + if (data) { + data = 1; + } + } else if (bank == 2) { + data = inl(GP_LVL3) & (1 << offset); + if (data) { + data = 1; + } + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + + return data; +} + +static int xeon_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_IO_SEL); + data = data | (1 << offset); + outl(data, GP_IO_SEL); + } else if (bank == 1) { + data = inl(GP_IO_SEL2); + data = data | (1 << offset); + outl(data, GP_IO_SEL2); + } else if (bank == 2) { + data = inl(GP_IO_SEL3); + data = data | (1 << offset); + outl(data, GP_IO_SEL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + + return 0; +} + +static void xeon_gpio_set(struct gpio_chip *gc, + unsigned gpio_num, int val) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_LVL); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL); + } else if (bank == 1) { + data = inl(GP_LVL2); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL2); + } else if (bank == 2) { + data = inl(GP_LVL3); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); +} + +static int xeon_gpio_direction_out(struct gpio_chip *gc, + unsigned gpio_num, int val) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_IO_SEL); + data = data & ~(1 << offset); + outl(data, GP_IO_SEL); + + data = inl(GP_LVL); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL); + } else if (bank == 1) { + data = inl(GP_IO_SEL2); + data = data & ~(1 << offset); + outl(data, GP_IO_SEL2); + + data = inl(GP_LVL2); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL2); + } else if (bank == 2) { + data = inl(GP_IO_SEL3); + data = data & ~(1 << offset); + outl(data, GP_IO_SEL3); + + data = inl(GP_LVL3); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + + return 0; +} + +static int xeon_gpio_request(struct gpio_chip *chip, unsigned int offset) +{ + unsigned int data; + unsigned int bank, tmp_offset; + unsigned long flags; + + bank = offset / BANKSIZE; + tmp_offset = offset % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GPIO_USE_SEL); + data = data | (1 << tmp_offset); + outl(data, GPIO_USE_SEL); + } else if (bank == 1) { + data = inl(GPIO_USE_SEL2); + data = data | (1 << tmp_offset); + outl(data, GPIO_USE_SEL2); + } else if (bank == 2) { + data = inl(GPIO_USE_SEL3); + data = data | (1 << tmp_offset); + outl(data, GPIO_USE_SEL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + return 0; +} + +static void xeon_gpio_free(struct gpio_chip *chip, unsigned int offset) +{ + unsigned int data; + unsigned int bank, tmp_offset; + unsigned long flags; + + bank = offset / BANKSIZE; + tmp_offset = offset % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GPIO_USE_SEL); + data = data & ~(1 << tmp_offset); + outl(data, GPIO_USE_SEL); + } else if (bank == 1) { + data = inl(GPIO_USE_SEL2); + data = data & ~(1 << tmp_offset); + outl(data, GPIO_USE_SEL2); + } else if (bank == 2) { + data = inl(GPIO_USE_SEL3); + data = data & ~(1 << tmp_offset); + outl(data, GPIO_USE_SEL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); +} + +static struct gpio_chip xeon_gpio_chip = { + .label = GPIO_NAME, + .owner = THIS_MODULE, + .get = xeon_gpio_get, + .direction_input = xeon_gpio_direction_in, + .set = xeon_gpio_set, + .direction_output = xeon_gpio_direction_out, + .request = xeon_gpio_request, + .free = xeon_gpio_free, +}; + +static int __init xeon_gpio_init(void) +{ + int err; + if (!request_region(GPIO_BASE, GPIO_IOSIZE, GPIO_NAME)) + return -EBUSY; + + xeon_gpio_chip.base = GPIO_BASE_ID; + xeon_gpio_chip.ngpio = 96; + + err = gpiochip_add_data(&xeon_gpio_chip, NULL); + if (err < 0) + goto gpiochip_add_err; + gpiod_add_lookup_table(&rg_gpio_lookup_table); + err = platform_device_register(&i2c_gpio); + if (err < 0) { + goto i2c_get_adapter_err; + } + return 0; + +i2c_get_adapter_err: + gpiod_remove_lookup_table(&rg_gpio_lookup_table); + platform_device_unregister(&i2c_gpio); + gpiochip_remove(&xeon_gpio_chip); + +gpiochip_add_err: + release_region(GPIO_BASE, GPIO_IOSIZE); + return -1; +} + +static void __exit xeon_gpio_exit(void) +{ + gpiod_remove_lookup_table(&rg_gpio_lookup_table); + platform_device_unregister(&i2c_gpio); + mdelay(100); + gpiochip_remove(&xeon_gpio_chip); + release_region(GPIO_BASE, GPIO_IOSIZE); +} + +module_init(xeon_gpio_init); +module_exit(xeon_gpio_exit); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("GPIO interface for XEON Super I/O chip"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c new file mode 100755 index 000000000..45c9e4ab4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c @@ -0,0 +1,266 @@ +/* + * rg_fan.c - A driver for control rg_fan base on rg_fan.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAN_SIZE (256) +#define SYS_FAN_BUF_LEN (64) + +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; + +#define DBG_DEBUG(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:" fmt, \ + __FUNCTION__, __LINE__, ##arg); \ + } else if (debuglevel >= DBG_ERROR) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } else { \ + } \ + } while (0) + +#define DBG_ERROR(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } \ + } while (0) + +extern s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command); +extern s32 platform_i2c_smbus_read_i2c_block_data( + const struct i2c_client *client, u8 command, u8 length, u8 *values); +extern s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command); + +typedef enum dfd_dev_info_type_e { + DFD_DEV_INFO_TYPE_MAC = 1, + DFD_DEV_INFO_TYPE_NAME = 2, + DFD_DEV_INFO_TYPE_SN = 3, + DFD_DEV_INFO_TYPE_PWR_CONS = 4, + DFD_DEV_INFO_TYPE_HW_INFO = 5, + DFD_DEV_INFO_TYPE_DEV_TYPE = 6, +} dfd_dev_tlv_type_t; + +typedef struct dfd_dev_head_info_s { + uint8_t ver; /* define E2PROM version,default is 0x01 */ + uint8_t flag; /* flag is 0x7E in new version E2PROM */ + uint8_t hw_ver; /* consists of main version and revise version */ + uint8_t type; /* HW type */ + int16_t tlv_len; /* 16 bits */ +} dfd_dev_head_info_t; + +typedef struct dfd_dev_tlv_info_s { + uint8_t type; + uint8_t len; + uint8_t data[0]; +} dfd_dev_tlv_info_t; + +struct fan_data { + struct i2c_client *client; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated[8]; /* In jiffies */ + u8 data[FAN_SIZE]; /* Register value */ +}; + +static ssize_t show_fan_sysfs_tlv_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct fan_data *data = i2c_get_clientdata(client); + + dfd_dev_head_info_t info; + uint8_t tmp_tlv_len[sizeof(uint16_t)]; + uint8_t *tlv_data; + dfd_dev_tlv_info_t *tlv; + int type; + int buf_len = SYS_FAN_BUF_LEN - 1; + u8 sysfs_buf[SYS_FAN_BUF_LEN]; + int i; + int ret = 0; + + mutex_lock(&data->update_lock); + memset(sysfs_buf, 0, SYS_FAN_BUF_LEN); + ret = platform_i2c_smbus_read_i2c_block_data( + client, 0, sizeof(dfd_dev_head_info_t), (uint8_t *)&info); + if (ret != sizeof(dfd_dev_head_info_t)) { + DBG_ERROR("fan maybe not set mac or not present0"); + goto exit; + } + + /* transform TLV_LEN */ + memcpy(tmp_tlv_len, (uint8_t *)&info.tlv_len, sizeof(int16_t)); + info.tlv_len = (tmp_tlv_len[0] << 8) + tmp_tlv_len[1]; + + if ((info.tlv_len <= 0) || (info.tlv_len > 0xFF)) { + DBG_ERROR("fan maybe not set mac or not present1"); + goto exit; + } + + type = attr->index; + tlv_data = (uint8_t *)kmalloc(info.tlv_len, GFP_KERNEL); + memset(tlv_data, 0, info.tlv_len); + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = 0; i < info.tlv_len; i += 32) + if (platform_i2c_smbus_read_i2c_block_data(client, + sizeof(dfd_dev_head_info_t) + i, + 32, tlv_data + i) != 32) + break; + } + + DBG_DEBUG("TLV Len:%d\n", (int)sizeof(dfd_dev_tlv_info_t)); + for (tlv = (dfd_dev_tlv_info_t *)tlv_data; + (ulong)tlv < (ulong)tlv_data + info.tlv_len;) { + DBG_DEBUG( + "tlv: %p, tlv->type: 0x%x, tlv->len: 0x%x info->tlv_len: 0x%x\n", + tlv, tlv->type, tlv->len, info.tlv_len); + if (tlv->type == type && buf_len >= tlv->len) { + memcpy((uint8_t *)sysfs_buf, (uint8_t *)tlv->data, + tlv->len); + buf_len = (uint32_t)tlv->len; + break; + } + tlv = (dfd_dev_tlv_info_t *)((uint8_t *)tlv + + sizeof(dfd_dev_tlv_info_t) + + tlv->len); + } + + kfree(tlv_data); + DBG_DEBUG("value: %s \n", sysfs_buf); +exit: + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", sysfs_buf); +} + +static ssize_t show_fan_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct fan_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = 0; i < FAN_SIZE; i += 32) { + if (platform_i2c_smbus_read_i2c_block_data( + client, i, 32, data->data + i) != 32) + goto exit; + } + } else { + for (i = 0; i < FAN_SIZE; i += 2) { + int word = platform_i2c_smbus_read_word_data(client, i); + if (word < 0) + goto exit; + data->data[i] = word & 0xff; + data->data[i + 1] = word >> 8; + } + } + memcpy(buf, &data->data[0], FAN_SIZE); +exit: + mutex_unlock(&data->update_lock); + return FAN_SIZE; +} + +static SENSOR_DEVICE_ATTR(fan_hw_version, S_IRUGO, show_fan_sysfs_tlv_value, NULL, DFD_DEV_INFO_TYPE_HW_INFO); +static SENSOR_DEVICE_ATTR(fan_sn, S_IRUGO, show_fan_sysfs_tlv_value, NULL, DFD_DEV_INFO_TYPE_SN); +static SENSOR_DEVICE_ATTR(fan_type, S_IRUGO, show_fan_sysfs_tlv_value, NULL, DFD_DEV_INFO_TYPE_NAME); +static SENSOR_DEVICE_ATTR(fan, S_IRUGO, show_fan_value, NULL, 0); + +static struct attribute *fan_sysfs_attrs[] = { + &sensor_dev_attr_fan_hw_version.dev_attr.attr, + &sensor_dev_attr_fan_sn.dev_attr.attr, + &sensor_dev_attr_fan_type.dev_attr.attr, + &sensor_dev_attr_fan.dev_attr.attr, + NULL +}; + +static const struct attribute_group fan_sysfs_group = { + .attrs = fan_sysfs_attrs, +}; + +static int fan_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct fan_data *data; + int status; + + status = -1; + DBG_DEBUG("fan_probe(0x%02x)\n", client->addr); + data = devm_kzalloc(&client->dev, sizeof(struct fan_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = sysfs_create_group(&client->dev.kobj, &fan_sysfs_group); + if (status != 0) { + DBG_ERROR(" sysfs_create_group err\n"); + return status; + } + return 0; +} + +static int fan_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &fan_sysfs_group); + return 0; +} + +static const struct i2c_device_id fan_id[] = { { "rg_fan", 0 }, {} }; +MODULE_DEVICE_TABLE(i2c, fan_id); + +static struct i2c_driver rg_fan_driver = { + .driver = { + .name = "rg_fan", + }, + .probe = fan_probe, + .remove = fan_remove, + .id_table = fan_id, +}; + +module_i2c_driver(rg_fan_driver); +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie fan driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c new file mode 100755 index 000000000..4b58a5102 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c @@ -0,0 +1,340 @@ +/* + * rg_cpld.c - A driver for pmbus psu + * + * Copyright (c) 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAGIC_PSU_RATE (0xA7) +#define MAGIC_PSU_OUT_CURRENT (0x8C) +#define MAGIC_PSU_OUT_VOLTAGE (0x8B) +#define MAGIC_PSU_IN_VOLTAGE (0x88) +#define MAGIC_PSU_IN_CURRENT (0x89) +#define MAGIC_PSU_TEMP (0x8D) +#define MAGIC_PSU_TYPE (0x25) +#define MAGIC_PSU_SN (0x38) +#define MAGIC_PSU_HW (0x35) +#define PSU_SIZE (256) + +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; + +#define DBG_DEBUG(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:" fmt, \ + __FUNCTION__, __LINE__, ##arg); \ + } else if (debuglevel >= DBG_ERROR) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } else { \ + } \ + } while (0) + +#define DBG_INFO(fmt, arg...) \ + do { \ + if (debuglevel > DBG_KEY) { \ + printk(KERN_INFO "[INFO]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } \ + } while (0) + +#define DBG_ERROR(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } \ + } while (0) + +static const unsigned short rg_i2c_psu[] = { 0x50, 0x53, 0x58, 0x5b, I2C_CLIENT_END }; + +extern s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command); +extern s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values); + +struct psu_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[PSU_SIZE]; /* Register value */ +}; + +static ssize_t show_psu_sysfs_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_sysfs_15_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_psu_value(struct device *dev, struct device_attribute *da, char *buf); + +static SENSOR_DEVICE_ATTR(psu_rate, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_RATE); +static SENSOR_DEVICE_ATTR(psu_out_current, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_OUT_CURRENT); +static SENSOR_DEVICE_ATTR(psu_out_voltage, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_OUT_VOLTAGE); +static SENSOR_DEVICE_ATTR(psu_in_voltage, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_IN_VOLTAGE); +static SENSOR_DEVICE_ATTR(psu_in_current, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_IN_CURRENT); +static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_TEMP); +static SENSOR_DEVICE_ATTR(psu_type, S_IRUGO, show_sysfs_15_value, NULL, MAGIC_PSU_TYPE); +static SENSOR_DEVICE_ATTR(psu_sn, S_IRUGO, show_sysfs_15_value, NULL, MAGIC_PSU_SN); +static SENSOR_DEVICE_ATTR(psu_hw, S_IRUGO, show_psu_value, NULL, MAGIC_PSU_HW); + +static struct attribute *psu_pmbus_sysfs_attrs[] = { + &sensor_dev_attr_psu_rate.dev_attr.attr, + &sensor_dev_attr_psu_out_current.dev_attr.attr, + &sensor_dev_attr_psu_out_voltage.dev_attr.attr, + &sensor_dev_attr_psu_in_voltage.dev_attr.attr, + &sensor_dev_attr_psu_in_current.dev_attr.attr, + &sensor_dev_attr_psu_temp.dev_attr.attr, + NULL +}; + +static struct attribute *psu_fru_sysfs_attrs[] = { + &sensor_dev_attr_psu_type.dev_attr.attr, + &sensor_dev_attr_psu_sn.dev_attr.attr, + &sensor_dev_attr_psu_hw.dev_attr.attr, + NULL +}; + +static const struct attribute_group psu_pmbus_sysfs_attrs_group = { + .attrs = psu_pmbus_sysfs_attrs, +}; + +static const struct attribute_group psu_fru_sysfs_attrs_group = { + .attrs = psu_fru_sysfs_attrs, +}; + +static ssize_t show_psu_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + char psu_buf[PSU_SIZE]; + memset(psu_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 2, psu_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu\n"); + } + DBG_DEBUG("cpld reg pos:0x%x value:0x%02x\n", attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + return snprintf(buf, 3, "%s\n", psu_buf); +} + +static int linear_to_value(short reg, bool v_out) +{ + short exponent; + int mantissa; + long val; + + if (v_out) { + exponent = -9; + mantissa = reg; + } else { + exponent = reg >> 11; + mantissa = (((reg & 0x7ff) << 5)) >> 5; + } + val = mantissa; + val = val * 1000L; + if (exponent >= 0) { + val <<= exponent; + } else { + val >>= -exponent; + } + + return val; +} + +static ssize_t show_psu_sysfs_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + u8 smbud_buf[PSU_SIZE]; + uint16_t value; + int result; + + ret = -1; + memset(smbud_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + DBG_DEBUG("ret:%d", ret); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 2, smbud_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu \n"); + } + value = smbud_buf[1]; + value = value << 8; + value |= smbud_buf[0]; + + if (attr->index == 0x8b) { + result = linear_to_value(value, true); + } else { + result = linear_to_value(value, false); + } + mutex_unlock(&data->update_lock); + return snprintf(buf, PSU_SIZE, "%d\n", result); +} + +static ssize_t show_sysfs_15_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + u8 smbud_buf[PSU_SIZE]; + + memset(smbud_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 15, smbud_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu\n"); + } + mutex_unlock(&data->update_lock); + return snprintf(buf, PSU_SIZE, "%s\n", smbud_buf); +} + +static ssize_t show_sysfs_13_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + u8 smbud_buf[PSU_SIZE]; + + memset(smbud_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 13, smbud_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu \n"); + } + mutex_unlock(&data->update_lock); + return snprintf(buf, PSU_SIZE, "%s\n", smbud_buf); +} + +static int psu_detect(struct i2c_client *new_client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + conf = platform_i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + +static int psu_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct psu_data *data; + int status; + + status = -1; + data = devm_kzalloc(&client->dev, sizeof(struct psu_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + switch (client->addr) { + case 0x50: + case 0x53: + status = sysfs_create_group(&client->dev.kobj, + &psu_fru_sysfs_attrs_group); + if (status != 0) { + DBG_ERROR("%s %d sysfs_create_group err\n", __func__, __LINE__); + } + break; + case 0x58: + case 0x5b: + status = sysfs_create_group(&client->dev.kobj, + &psu_pmbus_sysfs_attrs_group); + if (status != 0) { + DBG_ERROR("%s %d sysfs_create_group err\n", __func__, __LINE__); + break; + } + break; + default: + break; + } + + return status; +} + +static int psu_remove(struct i2c_client *client) +{ + switch (client->addr) { + case 0x50: + case 0x53: + sysfs_remove_group(&client->dev.kobj, &psu_fru_sysfs_attrs_group); + break; + case 0x58: + case 0x5b: + sysfs_remove_group(&client->dev.kobj, &psu_pmbus_sysfs_attrs_group); + break; + default: + break; + } + return 0; +} + +static const struct i2c_device_id psu_id[] = { + { "rg_psu", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, psu_id); + +static struct i2c_driver rg_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "rg_psu", + }, + .probe = psu_probe, + .remove = psu_remove, + .id_table = psu_id, + .detect = psu_detect, + .address_list = rg_i2c_psu, +}; + +module_i2c_driver(rg_psu_driver); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie pmbus psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c new file mode 100755 index 000000000..105e6f1d2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c @@ -0,0 +1,97 @@ +/* + * ruijie_platform.c - A driver for ruijie platform module + * + * Copyright (c) 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLATFORM_I2C_RETRY_TIMES (3) + +s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try ++) { + if ((ret = i2c_smbus_read_byte_data(client, command)) >= 0) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_byte_data); + +s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try ; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try ++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values)) >= 0) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_i2c_block_data); + +s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try ++) { + if ((ret = i2c_smbus_read_word_data(client, command)) >= 0) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_word_data); + +static int __init ruijie_platform_init(void) +{ + return 0; +} + +static void __exit ruijie_platform_exit(void) +{ + return; +} + +module_init(ruijie_platform_init); +module_exit(ruijie_platform_exit); + +MODULE_DESCRIPTION("ruijie Platform Support"); +MODULE_AUTHOR("sonic_rd "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py new file mode 100755 index 000000000..c3461d7fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +import click +import time +import syslog +import traceback +from ruijieutil import waitForDocker, STARTMODULE, AVSUTIL +try: + from rest.rest import BMCMessage +except ImportError: + pass + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def avswarninglog(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def avscriticallog(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def avserror(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def avsinfo(s): + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_INFO,s) + +def doAvsCtrol(): + index = 0 + url = "/xyz/openbmc_project/hostchannel/attr/MacRov" + while True: + if "avscontrol_restful" in STARTMODULE and STARTMODULE['avscontrol_restful'] == 1: + try: + #for alibmc rest.py has define get_macrov_value function + get_macrov_value = getattr(BMCMessage(), "get_macrov_value", None) + if callable(get_macrov_value): + macrov_value = int(get_macrov_value()) + else: + macrov_value = int(BMCMessage().getBmcValue(url)) + if macrov_value >= 0: + break + except Exception as e: + time.sleep(2) + continue + else: + if AVSUTIL.mac_adj(): + break + + index += 1 + if index >= 10: + avserror("%%DEV_MONITOR-AVS: MAC Voltage adjust failed.") + exit(-1) + avsinfo("%%AVSCONTROL success") + exit(0) + +def run(interval): + while True: + try: + if waitForDocker(timeout = 0) == True: + time.sleep(10) # w10s + doAvsCtrol() + time.sleep(interval) + except Exception as e: + traceback.print_exc() + print(e) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start AVS control''' + avsinfo("%%AVSCONTROL start") + interval = 5 + run(interval) + +##device_i2c operation +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py new file mode 100755 index 000000000..35bca09c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py @@ -0,0 +1,336 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- + +import click +import os +import subprocess +import time +from ruijieconfig import GLOBALCONFIG, GLOBALINITPARAM, GLOBALINITCOMMAND, MAC_LED_RESET, STARTMODULE, i2ccheck_params + +from ruijieutil import rjpciwr + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def log_os_system(cmd): + u'''execute shell command''' + status, output = subprocess.getstatusoutput(cmd) + if status: + print(output) + return status, output + +def write_sysfs_value(reg_name, value): + u'''write sysfs file''' + mb_reg_file = "/sys/bus/i2c/devices/" + reg_name + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return False + try: + with open(mb_reg_file, 'w') as fd: + fd.write(value) + except Exception as error: + return False + return True + +def check_driver(): + u'''whether there is driver start with rg''' + status, output = log_os_system("lsmod | grep rg | wc -l") + #System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def i2c_getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='r') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def startAvscontrol(): + cmd = "nohup avscontrol.py start >/dev/null 2>&1 &" + rets = i2c_getPid("avscontrol.py") + if len(rets) == 0: + os.system(cmd) + +def startFanctrol(): + if STARTMODULE['fancontrol'] == 1: + cmd = "nohup fancontrol.py start >/dev/null 2>&1 &" + rets = i2c_getPid("fancontrol.py") + if len(rets) == 0: + os.system(cmd) + +def starthal_fanctrl(): + if STARTMODULE.get('hal_fanctrl',0) == 1: + cmd = "nohup hal_fanctrl.py start >/dev/null 2>&1 &" + rets = i2c_getPid("hal_fanctrl.py") + if len(rets) == 0: + os.system(cmd) + +def starthal_ledctrl(): + if STARTMODULE.get('hal_ledctrl',0) == 1: + cmd = "nohup hal_ledctrl.py start >/dev/null 2>&1 &" + rets = i2c_getPid("hal_ledctrl.py") + if len(rets) == 0: + os.system(cmd) + +def startDevmonitor(): + if STARTMODULE.get('dev_monitor',0) == 1: + cmd = "nohup dev_monitor.py start >/dev/null 2>&1 &" + rets = i2c_getPid("dev_monitor.py") + if len(rets) == 0: + os.system(cmd) + +def startSlotmonitor(): + if STARTMODULE.get('slot_monitor',0) == 1: + cmd = "nohup slot_monitor.py start >/dev/null 2>&1 &" + rets = i2c_getPid("slot_monitor.py") + if len(rets) == 0: + os.system(cmd) + +def stopFanctrol(): + u'''disable fan timer service''' + if STARTMODULE['fancontrol'] == 1: + rets = i2c_getPid("fancontrol.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def stophal_ledctrl(): + if STARTMODULE.get('hal_ledctrl',0) == 1: + rets = i2c_getPid("hal_ledctrl.py") + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + + +def stopDevmonitor(): + u'''disable the fan timer service''' + if STARTMODULE.get('dev_monitor',0) == 1: + rets = i2c_getPid("dev_monitor.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def stopSlotmonitor(): + u'''disable slot timer service''' + if STARTMODULE.get('slot_monitor',0) == 1: + rets = i2c_getPid("slot_monitor.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def removeDev(bus, loc): + cmd = "echo 0x%02x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath): + log_os_system(cmd) + +def addDev(name, bus, loc): + if name == "lm75": + time.sleep(0.1) + pdevpath = "/sys/bus/i2c/devices/i2c-%d/" % (bus) + for i in range(1, 100):#wait for mother-bus generation,maximum wait time is 10s + if os.path.exists(pdevpath) == True: + break + time.sleep(0.1) + if i % 10 == 0: + click.echo("%%DEVICE_I2C-INIT: %s not found, wait 0.1 second ! i %d " % (pdevpath,i)) + + cmd = "echo %s 0x%02x > /sys/bus/i2c/devices/i2c-%d/new_device" % (name, loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath) == False: + os.system(cmd) + +def removedevs(): + devs = GLOBALCONFIG["DEVS"] + for index in range(len(devs)-1, -1, -1 ): + removeDev(devs[index]["bus"] , devs[index]["loc"]) + +def adddevs(): + devs = GLOBALCONFIG["DEVS"] + for dev in range(0, devs.__len__()): + addDev(devs[dev]["name"], devs[dev]["bus"] , devs[dev]["loc"]) + +def checksignaldriver(name): + modisexistcmd = "lsmod | grep %s | wc -l" % name + status, output = log_os_system(modisexistcmd) + #System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def adddriver(name, delay): + cmd = "modprobe %s" % name + if delay != 0: + time.sleep(delay) + if checksignaldriver(name) != True: + log_os_system(cmd) + +def removedriver(name, delay): + realname = name.lstrip().split(" ")[0]; + cmd = "rmmod -f %s" % realname + if checksignaldriver(realname): + log_os_system(cmd) + +def removedrivers(): + u'''remove all drivers''' + if GLOBALCONFIG is None: + click.echo("%%DEVICE_I2C-INIT: load global config failed.") + return + drivers = GLOBALCONFIG.get("DRIVERLISTS", None) + if drivers is None: + click.echo("%%DEVICE_I2C-INIT: load driver list failed.") + return + for index in range(len(drivers)-1, -1, -1 ): + delay = 0 + name = "" + if type(drivers[index]) == dict and "delay" in drivers[index]: + name = drivers[index].get("name") + delay = drivers[index]["delay"] + else: + name = drivers[index] + removedriver(name, delay) + +def adddrivers(): + u'''add drivers''' + if GLOBALCONFIG is None: + click.echo("%%DEVICE_I2C-INIT: load global config failed.") + return + drivers = GLOBALCONFIG.get("DRIVERLISTS", None) + if drivers is None: + click.echo("%%DEVICE_I2C-INIT: load driver list failed.") + return + for index in range(0 ,len(drivers)): + delay = 0 + name = "" + if type(drivers[index]) == dict and "delay" in drivers[index]: + name = drivers[index].get("name") + delay = drivers[index]["delay"] + else: + name = drivers[index] + adddriver(name, delay) + +def otherinit(): + for index in GLOBALINITPARAM: + write_sysfs_value(index["loc"], index["value"]) + + for index in GLOBALINITCOMMAND: + log_os_system(index) + +def unload_driver(): + u'''remove devices and drivers''' + stopDevmonitor() # disable removable device driver monitors + stopFanctrol() # disable fan-control service + removedevs() # remove other devices + removedrivers() # remove drivers + +def reload_driver(): + u'''reload devices and drivers''' + removedevs() # remove other devices + removedrivers() # remove drivers + time.sleep(1) + adddrivers() + adddevs() + + +def i2c_check(bus,retrytime = 6): + try: + i2cpath = "/sys/bus/i2c/devices/" + bus + while retrytime and not os.path.exists(i2cpath): + click.echo("%%DEVICE_I2C-HA: i2c bus abnormal, last bus %s is not exist." % i2cpath) + reload_driver() + retrytime -= 1 + time.sleep(1) + except Exception as e: + click.echo("%%DEVICE_I2C-HA: %s" % str(e)) + return + +def MacLedSet(data): + '''write pci register''' + pcibus = MAC_LED_RESET.get("pcibus") + slot = MAC_LED_RESET.get("slot") + fn = MAC_LED_RESET.get("fn") + bar = MAC_LED_RESET.get("bar") + offset = MAC_LED_RESET.get("offset") + val = MAC_LED_RESET.get(data, None) + if val is None: + click.echo("%%DEVICE_I2C-INIT: MacLedSet wrong input") + return + rjpciwr(pcibus, slot, fn, bar, offset, val) + +def load_driver(): + u'''load devices and drivers''' + adddrivers() + adddevs() + if STARTMODULE.get("i2ccheck",0) == 1: #i2c HA + busend = i2ccheck_params.get("busend") + retrytime = i2ccheck_params.get("retrytime") + i2c_check(busend,retrytime) + startFanctrol() # enable fan + starthal_fanctrl() # enable fan control + starthal_ledctrl() # enable LED control + if STARTMODULE['avscontrol'] == 1: + startAvscontrol() # avs voltage-adjustment + startDevmonitor() # enable removable device driver monitors + startSlotmonitor() # slot insertion and removal initialization monitor + otherinit(); # other initialization, QSFP initialization + if STARTMODULE.get("macledreset",0) == 1: + MacLedSet("reset") + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + + +@main.command() +def start(): + '''load device ''' + if check_driver(): + unload_driver() + load_driver() + +@main.command() +def stop(): + '''stop device ''' + unload_driver() + +@main.command() +def restart(): + '''restart device''' + unload_driver() + load_driver() + +if __name__ == '__main__': + u'''device_i2c operation''' + main() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py new file mode 100755 index 000000000..87fb01e5f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py @@ -0,0 +1,838 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +import click +import os +import time +import syslog +from ruijieconfig import MONITOR_CONST, FANCTROLDEBUG, MONITOR_FANS_LED, DEV_LEDS, MONITOR_PSU_STATUS, \ + MONITOR_SYS_PSU_LED, MONITOR_DEV_STATUS, MONITOR_FAN_STATUS, MONITOR_DEV_STATUS_DECODE, \ + MONITOR_SYS_FAN_LED, MONITOR_SYS_LED, fanloc + +from ruijieutil import rji2cget, getMacTemp_sysfs, write_sysfs_value, get_sysfs_value, strtoint, \ + rji2cset + +import traceback +import glob + + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +DEBUG_COMMON = 0x01 +DEBUG_LEDCONTROL = 0x02 +DEBUG_FANCONTROL = 0x04 + + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def fanwarninglog(s): + #s = s.decode('utf-8').encode('gb2312') + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def fancriticallog(s): + #s = s.decode('utf-8').encode('gb2312') + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def fanerror(s): + #s = s.decode('utf-8').encode('gb2312') + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def fanwarningdebuglog(debuglevel,s): + #s = s.decode('utf-8').encode('gb2312') + if FANCTROLDEBUG & debuglevel: + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG,s) + + +class FanControl(object): + critnum = 0 + def __init__(self): + self._fanOKNum = 0 + self._psuOKNum = 0 + self._intemp = -100.0 + self._mac_aver = -100.0 + self._mac_max = -100.0 + self._preIntemp = -1000 # previous temperature + self._outtemp = -100 + self._boardtemp = -100 + self._cputemp = -1000 + + @property + def fanOKNum(self): + return self._fanOKNum; + + @property + def psuOKNum(self): + return self._psuOKNum; + + @property + def cputemp(self): + return self._cputemp; + + @property + def intemp(self): + return self._intemp; + + @property + def outtemp(self): + return self._outtemp; + + @property + def boardtemp(self): + return self._boardtemp; + + @property + def mac_aver(self): + return self._mac_aver; + + @property + def preIntemp(self): + return self._preIntemp; + + @property + def mac_max(self): + return self._mac_max; + + def sortCallback(self, element): + return element['id'] + + def gettemp(self,ret): + u'''get inlet, outlet, hot-point and cpu temperature''' + temp_conf = MONITOR_DEV_STATUS.get('temperature', None) + + if temp_conf is None: + fanerror("gettemp: config error") + return False + for item_temp in temp_conf: + try: + retval = "" + rval = None + name = item_temp.get('name') + location = item_temp.get('location') + if name == "cpu": + L=[] + for dirpath, dirnames, filenames in os.walk(location): + for file in filenames : + if file.endswith("input"): + L.append(os.path.join(dirpath, file)) + L =sorted(L,reverse=False) + for i in range(len(L)): + nameloc = "%s/temp%d_label"%(location,i+1) + valloc = "%s/temp%d_input"%(location,i+1) + with open(nameloc, 'r') as fd1: + retval2 = fd1.read() + with open(valloc, 'r') as fd2: + retval3 = fd2.read() + ret_t ={} + ret_t["name"] = retval2.strip() + ret_t["value"] = float(retval3)/1000 + ret.append(ret_t) + fanwarningdebuglog(DEBUG_COMMON,"gettemp %s : %f" % (ret_t["name"],ret_t["value"])) + else: + locations = glob.glob(location) + with open(locations[0], 'r') as fd1: + retval = fd1.read() + rval = float(retval)/1000 + ret_t ={} + ret_t["name"] = name + ret_t["value"] = rval + ret.append(ret_t) + fanwarningdebuglog(DEBUG_COMMON,"gettemp %s : %f" % (ret_t["name"],ret_t["value"])) + except Exception as e: + fanerror("gettemp error:name:%s" % name) + fanerror(str(e)) + return True + + def checkslot(self,ret): + u'''get slot present status''' + slots_conf = MONITOR_DEV_STATUS.get('slots', None) + slotpresent = MONITOR_DEV_STATUS_DECODE.get('slotpresent',None) + + if slots_conf is None or slotpresent is None: + return False + for item_slot in slots_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_slot.get('name') + ret_t["status"] = "" + gettype = item_slot.get('gettype') + presentbit = item_slot.get('presentbit') + if gettype == "io": + io_addr = item_slot.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_slot.get('name'), "lpc read failed")) + else: + bus = item_slot.get('bus') + loc = item_slot.get('loc') + offset = item_slot.get('offset') + ind, val = rji2cget(bus, loc,offset) + if ind == True: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_slot.get('name'), "i2c read failed")) + if totalerr < 0 : + ret_t["status"] = "NOT OK" + ret.append(ret_t) + continue + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + fanwarningdebuglog(DEBUG_COMMON,"%s present:%s" % (item_slot.get('name'),slotpresent.get(val_t))) + if val_t != slotpresent.get('okval'): + ret_t["status"] = "ABSENT" + else: + ret_t["status"] = "PRESENT" + except Exception as e: + ret_t["status"] = "NOT OK" + totalerr -= 1 + fanerror("checkslot error") + fanerror(str(e)) + ret.append(ret_t) + return True + + def checkpsu(self,ret): + u'''get psu status present, output and warning''' + psus_conf = MONITOR_DEV_STATUS.get('psus', None) + psupresent = MONITOR_DEV_STATUS_DECODE.get('psupresent',None) + psuoutput = MONITOR_DEV_STATUS_DECODE.get('psuoutput',None) + psualert = MONITOR_DEV_STATUS_DECODE.get('psualert',None) + + if psus_conf is None or psupresent is None or psuoutput is None: + fanerror("checkpsu: config error") + return False + for item_psu in psus_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_psu.get('name') + ret_t["status"] = "" + gettype = item_psu.get('gettype') + presentbit = item_psu.get('presentbit') + statusbit = item_psu.get('statusbit') + alertbit = item_psu.get('alertbit') + if gettype == "io": + io_addr = item_psu.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_psu.get('name'), "lpc read failed")) + else: + bus = item_psu.get('bus') + loc = item_psu.get('loc') + offset = item_psu.get('offset') + ind, val = rji2cget(bus, loc,offset) + if ind == True: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_psu.get('name'), "i2c read failed")) + if totalerr < 0 : + ret_t["status"] = "NOT OK" + ret.append(ret_t) + continue + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + val_status = (int(retval,16) & (1<< statusbit)) >> statusbit + val_alert = (int(retval,16) & (1<< alertbit)) >> alertbit + fanwarningdebuglog(DEBUG_COMMON,"%s present:%s output:%s alert:%s" % (item_psu.get('name'),psupresent.get(val_t),psuoutput.get(val_status),psualert.get(val_alert))) + if val_t != psupresent.get('okval') or val_status != psuoutput.get('okval') or val_alert != psualert.get('okval'): + totalerr -=1 + except Exception as e: + totalerr -= 1 + fanerror("checkpsu error") + fanerror(str(e)) + if totalerr < 0: + ret_t["status"] = "NOT OK" + else: + ret_t["status"] = "OK" + ret.append(ret_t) + return True + + def checkfan(self,ret): + u'''get fan status present and roll''' + fans_conf = MONITOR_DEV_STATUS.get('fans', None) + fanpresent = MONITOR_DEV_STATUS_DECODE.get('fanpresent',None) + fanroll = MONITOR_DEV_STATUS_DECODE.get('fanroll',None) + + if fans_conf is None or fanpresent is None or fanroll is None: + fanerror("checkfan: config error") + return False + for item_fan in fans_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_fan.get('name') + ret_t["status"] = "" + presentstatus = item_fan.get('presentstatus') + presentbus = presentstatus.get('bus') + presentloc = presentstatus.get('loc') + presentaddr = presentstatus.get('offset') + presentbit = presentstatus.get('bit') + ind, val = rji2cget(presentbus, presentloc,presentaddr) + if ind == True: + val_t = (int(val,16) & (1<< presentbit)) >> presentbit + fanwarningdebuglog(DEBUG_COMMON,"checkfan:%s present status:%s" % (item_fan.get('name'),fanpresent.get(val_t))) + if val_t != fanpresent.get('okval'): + ret_t["status"] = "ABSENT" + ret.append(ret_t) + continue + else: + fanerror("checkfan: %s get present status error." % item_fan.get('name')) + motors = item_fan.get("rollstatus") + for motor in motors: + statusbus = motor.get('bus', None) + statusloc = motor.get('loc', None) + statusaddr = motor.get('offset', None) + statusbit = motor.get('bit', None) + ind, val = rji2cget(statusbus, statusloc, statusaddr) + if ind == True: + val_t = (int(val,16) & (1<< statusbit)) >> statusbit + fanwarningdebuglog(DEBUG_COMMON,"checkfan:%s roll status:%s" % (motor.get('name'),fanroll.get(val_t))) + if val_t != fanroll.get('okval'): + totalerr -= 1 + else: + totalerr -= 1 + fanerror("checkfan: %s " % item_fan.get('name')) + fanerror("get %s status error." % motor["name"]) + except Exception as e: + totalerr -= 1 + fanerror("checkfan error") + fanerror(str(e)) + if totalerr < 0: + ret_t["status"] = "NOT OK" + else: + ret_t["status"] = "OK" + ret.append(ret_t) + return True + + def getCurrentSpeed(self): + try: + loc = fanloc[0].get("location","") + sped = get_sysfs_value(loc) + value = strtoint(sped) + return value + except Exception as e: + fanerror("%%policy: get current speedlevel error") + fanerror(str(e)) + return None + + # guarantee the speed is lowest when speed lower than lowest value after speed-adjustment + def checkCurrentSpeedSet(self): + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy: guarantee the lowest speed after speed-adjustment") + value = self.getCurrentSpeed() + if value is None or value == 0: + raise Exception("%%policy: getCurrentSpeed None") + elif value < MONITOR_CONST.MIN_SPEED: + self.fanSpeedSet(MONITOR_CONST.MIN_SPEED) + + + def fanSpeedSet(self, level): + if level >= MONITOR_CONST.MAX_SPEED: + level = MONITOR_CONST.MAX_SPEED + for item in fanloc: + try: + loc = item.get("location","") + write_sysfs_value(loc, "0x%02x"% level ) + except Exception as e: + fanerror(str(e)) + fanerror("%%policy: config fan runlevel error") + self.checkCurrentSpeedSet() # guaranteed minimum + + def fanSpeedSetMax(self): + try: + self.fanSpeedSet(MONITOR_CONST.MAX_SPEED) + except Exception as e: + fanerror("%%policy:fanSpeedSetMax failed") + fanerror(str(e)) + + def fanStatusCheck(self): # fan status check , max speed if fan error + if self.fanOKNum < MONITOR_CONST.FAN_TOTAL_NUM: + fanwarninglog("%%DEV_MONITOR-FAN: Normal fan number: %d" % (self.fanOKNum)) + self.fanSpeedSetMax() + return False + return True + + def setFanAttr(self,val): + u'''set status of each fan''' + for item in val: + fanid = item.get("id") + fanattr = fanid + "status" + fanstatus = item.get("status") + setattr(FanControl,fanattr,fanstatus) + fanwarningdebuglog(DEBUG_COMMON,"fanattr:%s,fanstatus:%s"% (fanattr,fanstatus)) + + def getFanPresentNum(self,curFanStatus): + fanoknum = 0; + for item in curFanStatus: + if item["status"] == "OK": + fanoknum += 1 + self._fanOKNum = fanoknum + fanwarningdebuglog(DEBUG_COMMON,"fanOKNum = %d"% self._fanOKNum) + + def getFanStatus(self): + try: + curFanStatus = [] + ret = self.checkfan(curFanStatus) + if ret == True: + self.setFanAttr(curFanStatus) + self.getFanPresentNum(curFanStatus) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getFanStatus success" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + except Exception as e: + fanerror(str(e)) + return -1 + + def getPsuOkNum(self,curPsuStatus): + psuoknum = 0; + for item in curPsuStatus: + if item.get("status") == "OK": + psuoknum += 1 + self._psuOKNum = psuoknum + fanwarningdebuglog(DEBUG_COMMON,"psuOKNum = %d"% self._psuOKNum) + + def getPsuStatus(self): + try: + curPsuStatus = [] + ret = self.checkpsu(curPsuStatus) + if ret == True: + self.getPsuOkNum(curPsuStatus) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getPsuStatus success" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + except Exception as e: + fanerror(str(e)) + return -1 + + def getMonitorTemp(self, temp): + for item in temp: + if item.get('name') == "lm75in": + self._intemp = item.get('value',self._intemp) + if item.get('name') == "lm75out": + self._outtemp = item.get('value',self._outtemp) + if item.get('name') == "lm75hot": + self._boardtemp = item.get('value',self._boardtemp) + if item.get('name') == "Physical id 0": + self._cputemp = item.get('value',self._cputemp) + fanwarningdebuglog(DEBUG_COMMON,"intemp:%f, outtemp:%f, boadrtemp:%f, cputemp:%f"% (self._intemp,self._outtemp,self._boardtemp,self._cputemp)) + + def getTempStatus(self): + try: + monitortemp =[] + ret = self.gettemp(monitortemp) + if ret == True: + self.getMonitorTemp(monitortemp) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getTempStatus success" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + except Exception as e: + fanerror(str(e)) + return -1 + + def getMacStatus_bcmcmd(self): + try: + if waitForDocker(timeout = 0) == True : + sta, ret = getMacTemp() + if sta == True: + self._mac_aver = float(ret.get("average",self._mac_aver)) + self._mac_max = float(ret.get("maximum",self._mac_max)) + fanwarningdebuglog(DEBUG_COMMON,"mac_aver:%f, mac_max:%f" % (self.mac_aver,self._mac_max)) + else: + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getMacStatus_bcmcmd failed" ) + else: + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getMacStatus_bcmcmd SDK not OK" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + return -1 + + def getMacStatus_sysfs(self,conf): + try: + sta, ret = getMacTemp_sysfs(conf) + if sta == True: + self._mac_aver = float(ret) / 1000 + self._mac_max = float(ret) / 1000 + fanwarningdebuglog(DEBUG_COMMON,"mac_aver:%f, mac_max:%f" % (self.mac_aver,self._mac_max)) + elif conf.get("try_bcmcmd", 0) == 1: + fanwarningdebuglog(DEBUG_COMMON,"get sysfs mac temp failed.try to use bcmcmd") + self.getMacStatus_bcmcmd() + else: + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getMacStatus_sysfs failed" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + return -1 + + def getMacStatus(self): + try: + mactempconf = MONITOR_DEV_STATUS.get('mac_temp', None) + if mactempconf is not None: + self.getMacStatus_sysfs(mactempconf) + else: + self.getMacStatus_bcmcmd() + return 0 + except AttributeError as e: + fanerror(str(e)) + return -1 + + def settSlotAttr(self,val): + u'''set each slot present status attribute''' + for item in val: + slotid = item.get("id") + slotattr = slotid + "status" + slotstatus = item.get("status") + setattr(FanControl,slotattr,slotstatus) + fanwarningdebuglog(DEBUG_COMMON,"slotattr:%s,slotstatus:%s"% (slotattr,slotstatus)) + + def getSlotStatus(self): + try: + curSlotStatus = [] + ret = self.checkslot(curSlotStatus) + if ret == True: + self.settSlotAttr(curSlotStatus) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getSlotStatus success" ) + except AttributeError as e: + fanerror(str(e)) + return 0 + + def fanctrol(self): #fan speed-adjustment + try: + if self.preIntemp <= -1000: + self.preIntemp = self.intemp + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:previous temperature[%.2f] , current temperature[%.2f]" % (self.preIntemp,self.intemp)) + if self.intemp < MONITOR_CONST.TEMP_MIN: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:inlet %.2f minimum temperature: %.2f" %(self.intemp,MONITOR_CONST.TEMP_MIN)) + self.fanSpeedSet(MONITOR_CONST.DEFAULT_SPEED) # default level + elif self.intemp >= MONITOR_CONST.TEMP_MIN and self.intemp > self.preIntemp: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:increase temperature") + self.policySpeed(self.intemp) + elif self.intemp >= MONITOR_CONST.TEMP_MIN and (self.preIntemp - self.intemp) > MONITOR_CONST.MONITOR_FALL_TEMP: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:temperature reduce over %d degree" % MONITOR_CONST.MONITOR_FALL_TEMP) + self.policySpeed(self.intemp) + else: + speed = self.getCurrentSpeed()# set according to current speed, prevent fan watch-dog + if speed is not None: + self.fanSpeedSet(speed) + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:change nothing") + except Exception as e: + fanerror("%%policy: fancontrol error") + + # start speed-adjustment + def startFanCtrol(self): + self.checkCrit() + if self.critnum == 0 and self.checkWarning() == False and self.fanStatusCheck() ==True: + self.fanctrol() + self.checkDevError() + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy: speed after speed-adjustment is %0x" % (self.getCurrentSpeed())) + + def policySpeed(self, temp): # fan speed-adjustment algorithm + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:fan speed-adjustment algorithm") + sped_level = MONITOR_CONST.DEFAULT_SPEED + MONITOR_CONST.K * (temp - MONITOR_CONST.TEMP_MIN) + self.fanSpeedSet(sped_level) + self.preIntemp = self.intemp + + def getBoardMonitorMsg(self,ledcontrol = False): + ret_t = 0 + try: + ret_t += self.getFanStatus() # get fan status, get number of fan which status is OK + ret_t += self.getTempStatus() # get inlet, outlet, hot-point temperature, CPU temperature + ret_t += self.getMacStatus() # get MAC highest and average temperature + if ledcontrol == True: + ret_t += self.getSlotStatus() # get slot present status + ret_t += self.getPsuStatus() # get psu status + if ret_t == 0: + return True + except Exception as e: + fanerror(str(e)) + return False + + # device error algorithm Tmac-Tin≥50℃, or Tmac-Tin≤-50℃ + def checkDevError(self): + try: + if (self.mac_aver - self.intemp) >= MONITOR_CONST.MAC_UP_TEMP or (self.mac_aver - self.intemp) <= MONITOR_CONST.MAC_LOWER_TEMP: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%DEV_MONITOR-TEMP: MAC temp get failed.") + value = self.getCurrentSpeed() + if MONITOR_CONST.MAC_ERROR_SPEED >= value: + self.fanSpeedSet(MONITOR_CONST.MAC_ERROR_SPEED) + else: + self.fanSpeedSetMax() + else: + pass + except Exception as e: + fanerror("%%policy:checkDevError failed") + fanerror(str(e)) + + def checkTempWarning(self): + u'''check whether temperature above the normal alarm value''' + try: + if self._mac_aver >= MONITOR_CONST.MAC_WARNING_THRESHOLD \ + or self._outtemp >= MONITOR_CONST.OUTTEMP_WARNING_THRESHOLD \ + or self._boardtemp >= MONITOR_CONST.BOARDTEMP_WARNING_THRESHOLD \ + or self._cputemp>=MONITOR_CONST.CPUTEMP_WARNING_THRESHOLD \ + or self._intemp >=MONITOR_CONST.INTEMP_WARNING_THRESHOLD: + fanwarningdebuglog(DEBUG_COMMON,"check whether temperature above the normal alarm value") + return True + except Exception as e: + fanerror("%%policy: checkTempWarning failed") + fanerror(str(e)) + return False + + def checkTempCrit(self): + u'''check whether temperature above the critical alarm value''' + try: + if self._mac_aver >= MONITOR_CONST.MAC_CRITICAL_THRESHOLD \ + or ( self._outtemp >= MONITOR_CONST.OUTTEMP_CRITICAL_THRESHOLD \ + and self._boardtemp >= MONITOR_CONST.BOARDTEMP_CRITICAL_THRESHOLD \ + and self._cputemp>= MONITOR_CONST.CPUTEMP_CRITICAL_THRESHOLD \ + and self._intemp >= MONITOR_CONST.INTEMP_CRITICAL_THRESHOLD): + fanwarningdebuglog(DEBUG_COMMON,"temperature above the critical alarm value") + return True + except Exception as e: + fanerror("%%policy: checkTempCrit failed") + fanerror(str(e)) + return False + + def checkFanStatus(self): + u'''check fan status''' + for item in MONITOR_FAN_STATUS: + maxoknum = item.get('maxOkNum') + minoknum = item.get('minOkNum') + status = item.get('status') + if self.fanOKNum >= minoknum and self.fanOKNum <= maxoknum : + fanwarningdebuglog(DEBUG_COMMON,"checkFanStatus:fanOKNum:%d,status:%s" % (self.fanOKNum,status)) + return status + fanwarningdebuglog(DEBUG_COMMON,"checkFanStatus Error:fanOKNum:%d" % (self.fanOKNum)) + return None + + def checkPsuStatus(self): + u'''check psu status''' + for item in MONITOR_PSU_STATUS: + maxoknum = item.get('maxOkNum') + minoknum = item.get('minOkNum') + status = item.get('status') + if self.psuOKNum >= minoknum and self.psuOKNum <= maxoknum : + fanwarningdebuglog(DEBUG_COMMON,"checkPsuStatus:psuOKNum:%d,status:%s" % (self.psuOKNum,status)) + return status + fanwarningdebuglog(DEBUG_COMMON,"checkPsuStatus Error:psuOKNum:%d" % (self.psuOKNum)) + return None + + def dealSysLedStatus(self): + u'''set up SYSLED according to temperature, fan and psu status''' + try: + fanstatus = self.checkFanStatus() + psustatus = self.checkPsuStatus() + if self.checkTempCrit() == True or fanstatus == "red" or psustatus == "red": + status = "red" + elif self.checkTempWarning() == True or fanstatus == "yellow" or psustatus == "yellow": + status = "yellow" + else: + status = "green" + self.setSysLed(status) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealSysLedStatus success, status:%s," % status) + except Exception as e: + fanerror(str(e)) + + def dealSysFanLedStatus(self): + u'''light panel fan led according to status''' + try: + status = self.checkFanStatus() + if status is not None: + self.setSysFanLed(status) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealSysFanLedStatus success, status:%s," % status) + except Exception as e: + fanerror("%%ledcontrol:dealSysLedStatus error") + fanerror(str(e)) + + def dealPsuLedStatus(self): + u'''set up PSU-LED according to psu status''' + try: + status = self.checkPsuStatus() + if status is not None: + self.setSysPsuLed(status) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealPsuLedStatus success, status:%s," % status) + except Exception as e: + fanerror("%%ledcontrol:dealPsuLedStatus error") + fanerror(str(e)) + + def dealLocFanLedStatus(self): + u'''light fan led according to fan status''' + for item in MONITOR_FANS_LED: + try: + index = MONITOR_FANS_LED.index(item) + 1 + fanattr = "fan%dstatus" % index + val_t = getattr(FanControl,fanattr,None) + if val_t == "NOT OK": + rji2cset(item["bus"],item["devno"],item["addr"], item["red"]) + elif val_t == "OK": + rji2cset(item["bus"],item["devno"],item["addr"], item["green"]) + else: + pass + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealLocFanLed success.fanattr:%s, status:%s"% (fanattr,val_t)) + except Exception as e: + fanerror("%%ledcontrol:dealLocFanLedStatus error") + fanerror(str(e)) + + def dealSlotLedStatus(self): + u'''light slot status led according to slot present status''' + slotLedList = DEV_LEDS.get("SLOTLED",[]) + for item in slotLedList: + try: + index = slotLedList.index(item) + 1 + slotattr = "slot%dstatus" % index + val_t = getattr(FanControl,slotattr,None) + if val_t == "PRESENT": + rji2cset(item["bus"],item["devno"],item["addr"], item["green"]) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealSlotLedStatus success.slotattr:%s, status:%s"% (slotattr,val_t)) + except Exception as e: + fanerror("%%ledcontrol:dealSlotLedStatus error") + fanerror(str(e)) + + def dealBmcLedstatus(self,val): + pass + + def dealLctLedstatus(self,val): + pass + + def setled(self, item, color): + if item.get('type', 'i2c') == 'sysfs': + rjsysset(item["cmdstr"], item.get(color)) + else : + mask = item.get('mask', 0xff) + ind, val = rji2cget(item["bus"], item["devno"], item["addr"]) + if ind == True: + setval = (int(val,16) & ~mask) | item.get(color) + rji2cset(item["bus"], item["devno"], item["addr"], setval) + else: + fanerror("led %s" % "i2c read failed") + + def setSysLed(self,color): + for item in MONITOR_SYS_LED: + self.setled(item, color) + + def setSysFanLed(self,color): + for item in MONITOR_SYS_FAN_LED: + self.setled(item, color) + + def setSysPsuLed(self,color): + for item in MONITOR_SYS_PSU_LED: + self.setled(item, color) + + def checkWarning(self): + try: + if self.checkTempWarning() == True: + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake start") + time.sleep(MONITOR_CONST.SHAKE_TIME) + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake end") + self.getBoardMonitorMsg()# re-read + if self.checkTempWarning() == True: + fanwarninglog("%%DEV_MONITOR-TEMP:The temperature of device is over warning value.") + self.fanSpeedSetMax() # fan full speed + return True + except Exception as e: + fanerror("%%policy: checkWarning failed") + fanerror(str(e)) + return False + + def checkCrit(self): + try: + if self.checkTempCrit() == True: + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake start") + time.sleep(MONITOR_CONST.SHAKE_TIME) + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake end") + self.getBoardMonitorMsg()# re-read + if self.checkTempCrit() == True: + fancriticallog("%%DEV_MONITOR-TEMP:The temperature of device is over critical value.") + self.fanSpeedSetMax() # fan full speed + self.critnum += 1 # anti-shake + if self.critnum >= MONITOR_CONST.CRITICAL_NUM: + os.system("reboot") + fanwarningdebuglog(DEBUG_FANCONTROL,"crit次数:%d" % self.critnum) + else: + self.critnum = 0 + else: + self.critnum = 0 + except Exception as e: + fanerror("%%policy: checkCrit failed") + fanerror(str(e)) + + +def callback(): + pass + +def doFanCtrol(fanCtrol): + ret = fanCtrol.getBoardMonitorMsg() + if ret==True: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:startFanCtrol") + fanCtrol.startFanCtrol() + else: + fanCtrol.fanSpeedSetMax() + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:getBoardMonitorMsg error") + +def doLedCtrol(fanCtrol): + fanCtrol.getBoardMonitorMsg(ledcontrol = True) # get status + fanCtrol.dealSysLedStatus() # light system led + fanCtrol.dealSysFanLedStatus() # light panel fan led + fanCtrol.dealLocFanLedStatus() # light fan led + fanCtrol.dealPsuLedStatus() # light psu led + fanCtrol.dealSlotLedStatus() # light slot status led + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:doLedCtrol success") + +def run(interval, fanCtrol): + loop = 0 + # waitForDocker() + while True: + try: + if loop % MONITOR_CONST.MONITOR_INTERVAL ==0: # fan speed-adjustment + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:fanCtrol") + doFanCtrol(fanCtrol) + else: + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:start ledctrol")# LED control + doLedCtrol(fanCtrol) + time.sleep(interval) + loop += interval + except Exception as e: + traceback.print_exc() + fanerror(str(e)) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start fan control''' + fanwarninglog("FANCTROL start") + fanCtrol = FanControl() + interval = MONITOR_CONST.MONITOR_INTERVAL /30 + run(interval, fanCtrol) + +@main.command() +def stop(): + '''stop fan control ''' + fanwarninglog("stop") + +##device_i2c operation +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py new file mode 100755 index 000000000..53eac5ce1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py @@ -0,0 +1,717 @@ +# -*- coding: UTF-8 -*- +#------------------------------------------------------------------------------- +# Name: Ruijie python common module +# Purpose: called by other modules +# +# Author: rd +# +# Created: 02/07/2018 +# Copyright: (c) rd 2018 +#------------------------------------------------------------------------------- + +################################driver-load-adaption####################################################### +# need to export interface +################################################################################################### + +__all__ = ["fancontrol_loc", "fancontrol_config_loc", "GLOBALCONFIG", "MONITOR_CONST", + "RUIJIE_PART_NUMBER", "RUIJIE_LABEL_REVISION", "RUIJIE_ONIE_VERSION", "RUIJIE_MAC_SIZE", + "RUIJIE_MANUF_NAME", "RUIJIE_MANUF_COUNTRY", "RUIJIE_VENDOR_NAME", "RUIJIE_DIAG_VERSION", + "RUIJIE_SERVICE_TAG", "DEV_LEDS", "MEM_SLOTS", "LOCAL_LED_CONTROL", "FIRMWARE_TOOLS", + "STARTMODULE", "i2ccheck_params", "FANS_DEF", "factest_module", "MONITOR_TEMP_MIN", + "MONITOR_K", "MONITOR_MAC_IN", "MONITOR_DEFAULT_SPEED", "MONITOR_MAX_SPEED", + "MONITOR_MIN_SPEED", "MONITOR_MAC_ERROR_SPEED","MONITOR_FAN_TOTAL_NUM", + "MONITOR_MAC_UP_TEMP", "MONITOR_MAC_LOWER_TEMP","MONITOR_MAC_MAX_TEMP", + "MONITOR_FALL_TEMP","MONITOR_MAC_WARNING_THRESHOLD", "MONITOR_OUTTEMP_WARNING_THRESHOLD", + "MONITOR_BOARDTEMP_WARNING_THRESHOLD", "MONITOR_CPUTEMP_WARNING_THRESHOLD", + "MONITOR_INTEMP_WARNING_THRESHOLD", "MONITOR_MAC_CRITICAL_THRESHOLD", + "MONITOR_OUTTEMP_CRITICAL_THRESHOLD", "MONITOR_BOARDTEMP_CRITICAL_THRESHOLD", + "MONITOR_CPUTEMP_CRITICAL_THRESHOLD", "MONITOR_INTEMP_CRITICAL_THRESHOLD", + "MONITOR_CRITICAL_NUM", "MONITOR_SHAKE_TIME", "MONITOR_INTERVAL", + "MONITOR_MAC_SOURCE_SYSFS", "MONITOR_MAC_SOURCE_PATH", "MAC_AVS_PARAM", + "MAC_DEFAULT_PARAM", "MONITOR_SYS_LED", "MONITOR_SYS_FAN_LED", "MONITOR_FANS_LED", + "MONITOR_SYS_PSU_LED", "MONITOR_FAN_STATUS", "MONITOR_PSU_STATUS", "MONITOR_DEV_STATUS", + "MONITOR_DEV_STATUS_DECODE", "DEV_MONITOR_PARAM", "SLOT_MONITOR_PARAM", "fanloc", + "PCA9548START", "PCA9548BUSEND", "RUIJIE_CARDID", "RUIJIE_PRODUCTNAME", "FAN_PROTECT", + "rg_eeprom", "E2_LOC", "E2_PROTECT", "MAC_LED_RESET", "INIT_PARAM", "INIT_COMMAND", + "CPLDVERSIONS", "DRIVERLISTS", "DEVICE", "E2TYPE", "FRULISTS", "fanlevel_6510", + "fanlevel_6520", "fanlevel", "TEMPIDCHANGE", "FACTESTMODULE", "item1", + "test_sys_reload_item", "test_sys_item", "test_temp_item", "test_mem_item", + "test_hd_item", "test_rtc_item", "test_i2c_item", "test_cpld_item", + "test_portframe_item", "test_sysled_item", "test_fan_item", "test_power_item", + "test_usb_item", "test_prbs_item", "test_portbroadcast_item", "test_debug_level", + "test_log_level", "test_setmac", "test_setrtc", "log_level_critical", "log_level_debug", + "log_level_error", "log_level_info", "log_level_notset", "log_level_warning", + "test_e2_setmac_item", "test_bmc_setmac_item", "test_fan_setmac_item", "alltest", + "looptest", "diagtestall", "menuList", "TESTCASE", "PCIe_DEV_LIST", "PCIe_SPEED_ITEM"] + +fancontrol_loc = "/usr/local/bin" +fancontrol_config_loc = "/usr/local/bin" + +GLOBALCONFIG = "GLOBALCONFIG" +MONITOR_CONST = "MONITOR_CONST" + +RUIJIE_PART_NUMBER = "RJ000001" +RUIJIE_LABEL_REVISION = "R01" +RUIJIE_ONIE_VERSION = "2018.02" +RUIJIE_MAC_SIZE = 3 +RUIJIE_MANUF_NAME = "Ruijie" +RUIJIE_MANUF_COUNTRY = "CHN" +RUIJIE_VENDOR_NAME = "Ruijie" +RUIJIE_DIAG_VERSION = "0.1.0.15" +RUIJIE_SERVICE_TAG = "www.ruijie.com.cn" + +DEV_LEDS = {} +MEM_SLOTS = [] + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +FIRMWARE_TOOLS = {} +#start-up module +STARTMODULE = { + "fancontrol":1, + "avscontrol":1 + } + +i2ccheck_params = {"busend":"i2c-66","retrytime":6} + +################################################################################################### +##### fan board ID reference +################################################################################################### +FANS_DEF = { + 0x8100:"M6500-FAN-F", + 0x8101:"M6510-FAN-F", + 0x8102:"M6520-FAN-F", + 0x8103:"M6510-FAN-R" +} + +factest_module = { + "sysinfo_showfanmsg":1, + "sysinfo_showPsumsg":1, + "sysinfo_showrestfanmsg":0, + "sysinfo_showrestpsumsg":0 +} + +#################fan adjustment parameters ############################## +MONITOR_TEMP_MIN = 38 # temperature before speed-adjustment +MONITOR_K = 11 # adjustment algorithm +MONITOR_MAC_IN = 35 # temperature difference between mac and chip(backup) +MONITOR_DEFAULT_SPEED = 0x60 # default speed +MONITOR_MAX_SPEED = 0xFF # maximum speed +MONITOR_MIN_SPEED = 0x33 # minimum speed +MONITOR_MAC_ERROR_SPEED = 0XBB # MAC abnormal speed +MONITOR_FAN_TOTAL_NUM = 4 # 3+1 redundancy design, report to syslog if there is a error +MONITOR_MAC_UP_TEMP = 50 # MAC compared with inlet up +MONITOR_MAC_LOWER_TEMP = -50 # MAC compared with outlet down +MONITOR_MAC_MAX_TEMP = 100 # + +MONITOR_FALL_TEMP = 4 # adjustment reduced temperature +MONITOR_MAC_WARNING_THRESHOLD = 100 #100 +MONITOR_OUTTEMP_WARNING_THRESHOLD = 85 +MONITOR_BOARDTEMP_WARNING_THRESHOLD = 85 +MONITOR_CPUTEMP_WARNING_THRESHOLD = 85 +MONITOR_INTEMP_WARNING_THRESHOLD = 70 #70 + +MONITOR_MAC_CRITICAL_THRESHOLD = 105 #105 +MONITOR_OUTTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_BOARDTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_CPUTEMP_CRITICAL_THRESHOLD = 100 #100 +MONITOR_INTEMP_CRITICAL_THRESHOLD = 80 # 80 +MONITOR_CRITICAL_NUM = 3 #retry times +MONITOR_SHAKE_TIME = 20 #anti-shake times +MONITOR_INTERVAL = 60 + +MONITOR_MAC_SOURCE_SYSFS = 0 #1 get mac temperature from sysfs ,0 get mac temperature from bcmcmd +MONITOR_MAC_SOURCE_PATH = None #sysfs path + +################################################################### + + +#####################MAC调压parameters (B6510)#################################### +MAC_AVS_PARAM ={ + 0x72:0x0384 , + 0x73:0x037e , + 0x74:0x0378 , + 0x75:0x0372 , + 0x76:0x036b , + 0x77:0x0365 , + 0x78:0x035f , + 0x79:0x0359 , + 0x7a:0x0352 , + 0x7b:0x034c , + 0x7c:0x0346 , + 0x7d:0x0340 , + 0x7e:0x0339 , + 0x7f:0x0333 , + 0x80:0x032d , + 0x81:0x0327 , + 0x82:0x0320 , + 0x83:0x031a , + 0x84:0x0314 , + 0x85:0x030e , + 0x86:0x0307 , + 0x87:0x0301 , + 0x88:0x02fb , + 0x89:0x02f5 , + 0x8A:0x02ee +} + +# default 6520 configuration +MAC_DEFAULT_PARAM = { + "type": 1, # type 1 represents default if out of range / 0 represents no voltage-adjustment if out of range + "default":0x74, # should be used with type + "loopaddr":0x00, # AVS loop address + "loop":0x00, # AVS loop value + "open":0x00, # diasble write-protection value + "close":0x40, # enable write-protection value + "bus":2, # AVSI2C bus address + "devno":0x60, # AVS address + "addr":0x21, # AVS voltage-adjustment address + "protectaddr":0x10, # AVS write-protection address + "sdkreg":"DMU_PCU_OTP_CONFIG_8", # SDK register name + "sdktype": 1, # type 0 represents no shift operation / 1 represents shift operation + "macregloc":24 , # shift operation + "mask": 0xff # mask after shift +} + +MONITOR_SYS_LED = [ + {"bus":2,"devno":0x33, "addr":0xb2, "yellow":0x06, "red":0x02,"green":0x04}, + {"bus":2,"devno":0x32, "addr":0x72, "yellow":0x06, "red":0x02,"green":0x04}] + +MONITOR_SYS_FAN_LED =[ + {"bus":2,"devno":0x33, "addr":0xb4, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FANS_LED = [ + {"bus":2,"devno":0x32, "addr":0x23, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x24, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x25, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x26, "green":0x09, "red":0x0a}] + + +MONITOR_SYS_PSU_LED =[ + {"bus":2,"devno":0x33, "addr":0xb3, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FAN_STATUS = [ + {'status':'green' , 'minOkNum':4,'maxOkNum':4}, + {'status':'yellow', 'minOkNum':3,'maxOkNum':3}, + {'status':'red' , 'minOkNum':0,'maxOkNum':2}, + ] + +MONITOR_PSU_STATUS = [ + {'status':'green' , 'minOkNum':2,'maxOkNum':2}, + {'status':'yellow', 'minOkNum':1,'maxOkNum':1}, + {'status':'red' , 'minOkNum':0,'maxOkNum':0}, + ] + +MONITOR_DEV_STATUS = {} +MONITOR_DEV_STATUS_DECODE = {} +DEV_MONITOR_PARAM = {} +SLOT_MONITOR_PARAM = {} + + +fanloc = {"name":"fanset","location":"0-0032/fan_speed_set"} +#####################MAC-Voltage-Adjustment-Parameters#################################### + + +####================================Adaption-Area================================ +#### RUIJIE_COMMON common configuration head +#### “platform” specific configuration head +#### +PCA9548START = 11 +PCA9548BUSEND = 74 + +RUIJIE_CARDID = 0x00004040 +RUIJIE_PRODUCTNAME = "ruijie_b6510" + +FAN_PROTECT = {"bus":0, "devno":0x32, "addr":0x19, "open":0x00, "close":0x0f} +rg_eeprom = "2-0057/eeprom" +E2_LOC = {"bus":2, "devno":0x57} +E2_PROTECT ={"bus":2, "devno":0x33, "addr":0xb0, "open":0, "close":1} +MAC_LED_RESET = {"pcibus":8, "slot":0, "fn":0, "bar":0, "offset":64, "reset":0x98} + +INIT_PARAM = [ + {"loc":"1-0034/sfp_enable","value": "01"}, + {"loc":"2-0035/sfp_enable2","value":"ff"}, + {"loc":"2-0033/mac_led", "value":"ff"}, + {"loc":"1-0034/sfp_txdis1","value":"00"}, + {"loc":"1-0034/sfp_txdis2","value":"00"}, + {"loc":"1-0034/sfp_txdis3","value":"00"}, + {"loc":"1-0036/sfp_txdis4","value":"00"}, + {"loc":"1-0036/sfp_txdis5","value":"00"}, + {"loc":"1-0036/sfp_txdis6","value":"00"}, + {"loc":fanloc["location"], "value":"80"} +] + +INIT_COMMAND = [ +] + +CPLDVERSIONS = [ + {"loc":"2-0033/cpld_version","des":"MAC Board 上CPLDA"}, + {"loc":"2-0035/cpld_version","des":"MAC Board 上CPLDB"}, + {"loc":"2-0037/cpld_version","des":"CPU Board 上cpld"} +] + +## Driver List +## +DRIVERLISTS = [ + "i2c_dev", + "i2c_algo_bit", + "i2c_gpio", + "i2c_mux", + "i2c_mux_pca9641", + "i2c_mux_pca954x", # force_deselect_on_exit=1 + "eeprom", + "at24", + "ruijie_platform", + "rg_cpld", + "rg_fan", + "rg_psu", + "csu550", + "rg_gpio_xeon", + #IPMIdriver + "ipmi_msghandler", + "ipmi_devintf", + "ipmi_si", +] + +DEVICE = [ + {"name":"pca9641","bus":0 ,"loc":0x10 }, + {"name":"pca9548","bus":2 ,"loc":0x70 }, + {"name":"lm75","bus": 2, "loc":0x48 }, + {"name":"lm75","bus": 2, "loc":0x49 }, + {"name":"lm75","bus": 2, "loc":0x4a }, + {"name":"24c02","bus":2 , "loc":0x57 }, + {"name":"rg_cpld","bus":2 ,"loc":0x33 }, + {"name":"rg_cpld","bus":2 ,"loc":0x35 }, + {"name":"rg_cpld","bus":2 ,"loc":0x37 }, + {"name":"pca9548","bus":1,"loc":0x70 }, + {"name":"pca9548","bus":1,"loc":0x71 }, + {"name":"pca9548","bus":1,"loc":0x72 }, + {"name":"pca9548","bus":1,"loc":0x73 }, + {"name":"pca9548","bus":1,"loc":0x74 }, + {"name":"pca9548","bus":1,"loc":0x75 }, + {"name":"pca9548","bus":1,"loc":0x76 }, + {"name":"pca9548","bus":1,"loc":0x77 }, + {"name":"rg_fan","bus":3,"loc":0x53 }, + {"name":"rg_fan","bus":4,"loc":0x53 }, + {"name":"rg_fan","bus":5,"loc":0x53 }, + #{"name":"rg_fan","bus":6,"loc":0x53 }, #specific fan + {"name":"rg_psu","bus":7 ,"loc":0x50 }, + {"name":"csu550","bus":7 ,"loc":0x58 }, + {"name":"rg_psu","bus":8 ,"loc":0x53 }, + {"name":"csu550","bus":8 ,"loc":0x5b }, +] + +#####################FRU-Info-Adaption################################# +E2TYPE = {"1": "tlveeprom", + "2": "x86cpueeprom", + "3": "bmceeprom", + "4": "cpueeprom", + "5": "maceeprom", + "6": "sloteeprom", + "7": "fanconnecteeprom", + "8": "M1HFANI-F", + "9": "M1HFANI-R", + "A": "M2HFANI-F", + "B": "M2HFANI-R", + "C": "psu"} +FRULISTS = [] +################################Manufacturing-Test-Adaption-Area####################################################### +# need to export interface +fanlevel_6510 = { + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanlevel_6520 = { + "level":[75,150,255], + "low_speed":[750,4250,6750], + "high_speed":[4500,7500,10000] +} + +fanlevel = fanlevel_6520 + +TEMPIDCHANGE = { + "lm75in":"inlet", + "lm75out":"outlet", + "lm75hot":"hot-point", + "inlet":"lm75in", + "outlet":"lm75out", + "hot-point":"lm75hot", +} + +# Manufacturing-Test module +FACTESTMODULE = { } + +##################################Manufacturing-Test-Menu +item1 = {"name":"Single Test", "deal" :"test_signal", "childid":1} +test_sys_reload_item = {"name":"reset-system", "deal" :"test_sys_reload"} + +test_sys_item = { "name":"Product information test", "deal" :"test_sysinfo"} +test_temp_item = { "name":"temperature test", "deal" :"test_tempinfo"} +test_mem_item = { "name":"Memory test", "deal" :"test_cpumemoryinfo"} +test_hd_item = { "name":"Hard disk test", "deal" :"test_hard"} +test_rtc_item = { "name":"RTC test ", "deal" :"test_rtc"} +test_i2c_item = { "name":"I2c test ", "deal" :"test_i2c"} +test_cpld_item = { "name":"CPLD test", "deal" :"test_cpld"} +test_portframe_item = { "name":"Port transmit-receive frame test", "deal" :"test_portframe"} +test_sysled_item = { "name":"System led test", "deal" :"test_led"} +test_fan_item = { "name":"Fan status test", "deal" :"test_fan"} +test_power_item = { "name":"PSU status test", "deal" :"test_power"} +test_usb_item = { "name":"USB test", "deal" :"test_usb"} +test_prbs_item = { "name":"PRBS test", "deal" :"test_prbs"} +test_portbroadcast_item = { "name":"Port broadcast", "deal" :"test_portbroadcast"} + +test_debug_level = {"name":"Change debug level", "deal" :"test_setdebug"} +test_log_level = {"name":"Log output level", "deal" :"test_loginfolevel"} +test_setmac = {"name":"setmac", "deal" :"test_setmac"} +test_setrtc = {"name":"Set RTC", "deal" :"test_set_rtc"} + +log_level_critical = {"name":"CRITICAL", "deal" :"test_log_critical"} +log_level_debug = {"name":"DEBUG", "deal" :"test_log_debug"} +log_level_error = {"name":"ERROR", "deal" :"test_log_error"} +log_level_info = {"name":"INFO", "deal" :"test_log_info"} +log_level_notset = {"name":"NOTSET", "deal" :"test_log_notset"} +log_level_warning = {"name":"WARNING", "deal" :"test_log_warning"} + + +test_e2_setmac_item = {"name":"E2SETMAC", "deal" :"test_e2_setmac"} +test_bmc_setmac_item = {"name":"BMCSETMAC", "deal" :"test_bmc_setmac"} +test_fan_setmac_item = {"name":"fan SETMAC", "deal" :"test_fan_setmac"} + +alltest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_sysled_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item + ] + +looptest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item , +] + +diagtestall = [ +] + +menuList =[ + { + "menuid":0, "value":[ + {"name":"Single test", "deal" :"test_signal", "childid":1}, + {"name":"All test", "deal" :"test_all"}, + {"name":"Loop test", "deal" :"test_loop"}, + #{"name":"Check loop-test result", "deal" :"test_loop_read"}, + #{"name":"Delete loop-test result", "deal" :"test_loop_delete"}, +# {"name":"Load configuration", "deal" :"test_config"}, + test_sys_reload_item, + {"name":"System Configuration", "deal" :"test_sysconfig","childid":2}, + ] + }, + { + "menuid":1, "parentid":0, "value":[ + test_sys_item , + test_temp_item , + test_mem_item , + test_hd_item , + test_rtc_item , + test_i2c_item , + test_cpld_item , + test_portframe_item , + test_sysled_item , + test_fan_item , + test_power_item , + test_usb_item , + test_prbs_item , + test_portbroadcast_item , + ]}, + { + "menuid":2, "parentid":0, "value":[ + test_debug_level, + test_log_level , + test_setmac , + test_setrtc , + ]}, + { + "menuid":3, "parentid":2, "value":[ + log_level_critical , + log_level_debug , + log_level_error , + log_level_info , + log_level_notset , + log_level_warning , + ]}, + { + "menuid":4, "parentid":2, "value":[ + test_e2_setmac_item , + test_bmc_setmac_item, + test_fan_setmac_item, + ]}, +] + + +TESTCASE={ + "CPLD":[ + {"name":"CONNECT BOARD CPLD-A" ,"cases":[ + {"name":"cpld32", "cmd":"grtd_test.py cpld_check 0 0x32 0xAA"}, + {"name":"cpld37", "cmd":"grtd_test.py cpld_check 2 0x37 0xAC"}, + ] + }, + {"name":"MAC BOARD CPLD-A" ,"cases":[ + {"name":"cpld33", "cmd":"grtd_test.py cpld_check 2 0x33 0xAB"}, + {"name":"cpld34", "cmd":"grtd_test.py cpld_check 1 0x34 0xAA"}, + ] + }, + {"name":"MAC BOARD CPLD-B" ,"cases":[ + {"name":"cpld36", "cmd":"grtd_test.py cpld_check 1 0x36 0xAA"}, + {"name":"cpld35", "cmd":"grtd_test.py cpld_check 2 0x35 0xAB"}, + ] + }, + ], + "TEMPERATURE":[ + { + "name":"-->temperature test" , "cases":[ + {"name":"inlet","cmd":"grtd_test.py temp 2-0048/hwmon/hwmon1/temp1_input"}, + {"name":"outlet","cmd":"grtd_test.py temp 2-0049/hwmon/hwmon2/temp1_input"}, + {"name":"hot-point","cmd":"grtd_test.py temp 2-004a/hwmon/hwmon3/temp1_input"}, + ] + } + ], + "MEMTORY":{ + "cases":[ + {"name":"->memory test 1M","cmd":"memtester 1M 1"}, + {"name":"->memory test 2M","cmd":"memtester 2M 1"}, + {"name":"->memory test 8M","cmd":"memtester 8M 1"}, +# {"name":"->memory test 16M","cmd":"memtester 16M 1"}, +# {"name":"->memory test 256M","cmd":"memtester 256M 1"}, + ] + }, + "SMARTCTLCMDS":{ + "cases":[ + {"name":"->Check Hard Disk Info", "cmd":"smartctl -i /dev/sda"}, + {"name":"->Check Hard Disk Monitor Status", "cmd":"smartctl -H /dev/sda"}, + ] + }, + "LED":[ + {"name":"Light Port Led test","cases":[ + {"name":"-> Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Red Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + + {"name":"-> Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Yellow Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + ] + }, + {"name":"fan 1 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + ] + }, + {"name":"fan 2 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + ] + }, + {"name":"fan 3 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + ] + }, + {"name":"Front panel CPU Led", "cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x00"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x02"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x03"}, + {"name":"-> Green Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x11"}, + {"name":"-> Green Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x21"}, + {"name":"-> Green Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x41"}, + {"name":"-> Green Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x81"}, + {"name":"-> Red Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x12"}, + {"name":"-> Red Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x22"}, + {"name":"-> Red Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x42"}, + {"name":"-> Red Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x82"}, + {"name":"-> Yellow Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x13"}, + {"name":"-> Yellow Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x23"}, + {"name":"-> Yellow Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x43"}, + {"name":"-> Yellow Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x83"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + ] + }, + {"name":"Front panel BMC Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + ] + }, + {"name":"Front panel location Led" , "cases":[ + {"name":"-> LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + {"name":"-> LedOn","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xfe"}, + {"name":"->Recovery LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + ] + }, + + {"name":"Front panel pwr Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + ] + }, + {"name":"Front panel fan Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + ] + }, + + ], + "I2C":[ + ####type 1 represents value obtained compated with value + ####type 2 represents return True or False + {"name":"I2C device test" ,"cases":[ + {"name":" PCA9641 test", "cmd":"grtd_test.py dev_rd 0 10 0","deal_type":2}, + {"name":" cpld32 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld33 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld34 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld35 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld36 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld37 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" inlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" outlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" hot-point LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" EEPROM", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" Port 1", "cmd":"grtd_test.py dev_rd 11 0050 0","deal_type":2}, + {"name":" Port 2", "cmd":"grtd_test.py dev_rd 12 0050 0","deal_type":2}, + {"name":" Port 3", "cmd":"grtd_test.py dev_rd 13 0050 0","deal_type":2}, + {"name":" Port 4", "cmd":"grtd_test.py dev_rd 14 0050 0","deal_type":2}, + {"name":" Port 5", "cmd":"grtd_test.py dev_rd 15 0050 0","deal_type":2}, + {"name":" Port 6", "cmd":"grtd_test.py dev_rd 16 0050 0","deal_type":2}, + {"name":" Port 7", "cmd":"grtd_test.py dev_rd 17 0050 0","deal_type":2}, + {"name":" Port 8", "cmd":"grtd_test.py dev_rd 18 0050 0","deal_type":2}, + {"name":" Port 9", "cmd":"grtd_test.py dev_rd 19 0050 0","deal_type":2}, + {"name":" Port 10", "cmd":"grtd_test.py dev_rd 20 0050 0","deal_type":2}, + {"name":" Port 11", "cmd":"grtd_test.py dev_rd 21 0050 0","deal_type":2}, + {"name":" Port 12", "cmd":"grtd_test.py dev_rd 22 0050 0","deal_type":2}, + {"name":" Port 13", "cmd":"grtd_test.py dev_rd 23 0050 0","deal_type":2}, + {"name":" Port 14", "cmd":"grtd_test.py dev_rd 24 0050 0","deal_type":2}, + {"name":" Port 15", "cmd":"grtd_test.py dev_rd 25 0050 0","deal_type":2}, + {"name":" Port 16", "cmd":"grtd_test.py dev_rd 26 0050 0","deal_type":2}, + {"name":" Port 17", "cmd":"grtd_test.py dev_rd 27 0050 0","deal_type":2}, + {"name":" Port 18", "cmd":"grtd_test.py dev_rd 28 0050 0","deal_type":2}, + {"name":" Port 19", "cmd":"grtd_test.py dev_rd 29 0050 0","deal_type":2}, + {"name":" Port 20", "cmd":"grtd_test.py dev_rd 30 0050 0","deal_type":2}, + {"name":" Port 21", "cmd":"grtd_test.py dev_rd 31 0050 0","deal_type":2}, + {"name":" Port 22", "cmd":"grtd_test.py dev_rd 32 0050 0","deal_type":2}, + {"name":" Port 23", "cmd":"grtd_test.py dev_rd 33 0050 0","deal_type":2}, + {"name":" Port 24", "cmd":"grtd_test.py dev_rd 34 0050 0","deal_type":2}, + {"name":" Port 25", "cmd":"grtd_test.py dev_rd 35 0050 0","deal_type":2}, + {"name":" Port 26", "cmd":"grtd_test.py dev_rd 36 0050 0","deal_type":2}, + {"name":" Port 27", "cmd":"grtd_test.py dev_rd 37 0050 0","deal_type":2}, + {"name":" Port 28", "cmd":"grtd_test.py dev_rd 38 0050 0","deal_type":2}, + {"name":" Port 29", "cmd":"grtd_test.py dev_rd 39 0050 0","deal_type":2}, + {"name":" Port 30", "cmd":"grtd_test.py dev_rd 40 0050 0","deal_type":2}, + {"name":" Port 31", "cmd":"grtd_test.py dev_rd 41 0050 0","deal_type":2}, + {"name":" Port 32", "cmd":"grtd_test.py dev_rd 42 0050 0","deal_type":2}, + {"name":" Port 33", "cmd":"grtd_test.py dev_rd 43 0050 0","deal_type":2}, + {"name":" Port 34", "cmd":"grtd_test.py dev_rd 44 0050 0","deal_type":2}, + {"name":" Port 35", "cmd":"grtd_test.py dev_rd 45 0050 0","deal_type":2}, + {"name":" Port 36", "cmd":"grtd_test.py dev_rd 46 0050 0","deal_type":2}, + {"name":" Port 37", "cmd":"grtd_test.py dev_rd 47 0050 0","deal_type":2}, + {"name":" Port 38", "cmd":"grtd_test.py dev_rd 48 0050 0","deal_type":2}, + {"name":" Port 39", "cmd":"grtd_test.py dev_rd 49 0050 0","deal_type":2}, + {"name":" Port 40", "cmd":"grtd_test.py dev_rd 50 0050 0","deal_type":2}, + {"name":" Port 41", "cmd":"grtd_test.py dev_rd 51 0050 0","deal_type":2}, + {"name":" Port 42", "cmd":"grtd_test.py dev_rd 52 0050 0","deal_type":2}, + {"name":" Port 43", "cmd":"grtd_test.py dev_rd 53 0050 0","deal_type":2}, + {"name":" Port 44", "cmd":"grtd_test.py dev_rd 54 0050 0","deal_type":2}, + {"name":" Port 45", "cmd":"grtd_test.py dev_rd 55 0050 0","deal_type":2}, + {"name":" Port 46", "cmd":"grtd_test.py dev_rd 56 0050 0","deal_type":2}, + {"name":" Port 47", "cmd":"grtd_test.py dev_rd 57 0050 0","deal_type":2}, + {"name":" Port 48", "cmd":"grtd_test.py dev_rd 58 0050 0","deal_type":2}, + {"name":" Port 49", "cmd":"grtd_test.py dev_rd 59 0050 0","deal_type":2}, + {"name":" Port 50", "cmd":"grtd_test.py dev_rd 60 0050 0","deal_type":2}, + {"name":" Port 51", "cmd":"grtd_test.py dev_rd 61 0050 0","deal_type":2}, + {"name":" Port 52", "cmd":"grtd_test.py dev_rd 62 0050 0","deal_type":2}, + {"name":" Port 53", "cmd":"grtd_test.py dev_rd 63 0050 0","deal_type":2}, + {"name":" Port 54", "cmd":"grtd_test.py dev_rd 64 0050 0","deal_type":2}, + {"name":" Port 55", "cmd":"grtd_test.py dev_rd 65 0050 0","deal_type":2}, + {"name":" Port 56", "cmd":"grtd_test.py dev_rd 66 0050 0","deal_type":2}, + {"name":" Port 57", "cmd":"grtd_test.py dev_rd 67 0050 0","deal_type":2}, + {"name":" Port 58", "cmd":"grtd_test.py dev_rd 68 0050 0","deal_type":2}, + {"name":" Port 59", "cmd":"grtd_test.py dev_rd 69 0050 0","deal_type":2}, + {"name":" Port 60", "cmd":"grtd_test.py dev_rd 70 0050 0","deal_type":2}, + {"name":" Port 61", "cmd":"grtd_test.py dev_rd 71 0050 0","deal_type":2}, + {"name":" Port 62", "cmd":"grtd_test.py dev_rd 72 0050 0","deal_type":2}, + {"name":" Port 63", "cmd":"grtd_test.py dev_rd 73 0050 0","deal_type":2}, + {"name":" Port 64", "cmd":"grtd_test.py dev_rd 74 0050 0","deal_type":2}, + ] + }, + ], +} + +PCIe_DEV_LIST = [] +PCIe_SPEED_ITEM = [] + +################################Manufacturing-Test-Adaption-Area####################################################### + + + + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py new file mode 100755 index 000000000..297e5af6d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py @@ -0,0 +1,186 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- +#------------------------------------------------------------------------------- +# Name: ruijieconfig.py +# Purpose: block the difference between various product/onie version for other module +# +# Author: rd +# +# Created: 02/07/2018 +# Copyright: (c) rd 2018 +#------------------------------------------------------------------------------- +import sys +import os +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info + +__all__ = ["getdeviceplatform", "get_rjconfig_info", "MONITOR_CONST", "MAILBOX_DIR", "DEVICE", + "GLOBALCONFIG", "GLOBALINITPARAM", "GLOBALINITCOMMAND", "MAC_LED_RESET", "STARTMODULE", + "fanloc", "RUIJIE_CARDID", "RUIJIE_PRODUCTNAME", "RUIJIE_PART_NUMBER", + "RUIJIE_LABEL_REVISION", "RUIJIE_MAC_SIZE", "RUIJIE_MANUF_NAME", "RUIJIE_MANUF_COUNTRY", + "RUIJIE_VENDOR_NAME", "RUIJIE_DIAG_VERSION", "RUIJIE_SERVICE_TAG", "E2_PROTECT", + "E2_LOC", "FAN_PROTECT", "FANS_DEF", "MONITOR_FANS_LED", "MONITOR_SYS_FAN_LED", + "MONITOR_SYS_PSU_LED", "MONITOR_FAN_STATUS", "MONITOR_PSU_STATUS", "MONITOR_DEV_STATUS", + "MONITOR_DEV_STATUS_DECODE", "DEV_LEDS", "MAC_AVS_PARAM", "MAC_DEFAULT_PARAM", + "FRULISTS", "rg_eeprom", "i2ccheck_params", "FANCTROLDEBUG", "DEVMONITORDEBUG"] + +def getdeviceplatform(): + x = get_platform_info(get_machine_info()) + if x != None: + filepath = "/usr/share/sonic/device/" + x + return filepath + + +platform = get_platform_info(get_machine_info()) # platform get platform info x86_64-ruijie_b6520-64cq-r0 +platformpath = getdeviceplatform() # platformpath get mappable docker contents /usr/share/sonic/device/x86_64-ruijie_b6520-64cq-r0 +MAILBOX_DIR = "/sys/bus/i2c/devices/" # sysfs top contents +grtd_productfile = (platform + "_config").replace("-","_") +common_productfile = "ruijiecommon" +configfile_pre = "/usr/local/bin/" # py's contents, use /usr/local/bin temporarily + +sys.path.append(platformpath) +sys.path.append(configfile_pre) + +def get_rjconfig_info(attr_key): + rjconf_filename = platformpath + "/plugins" + "/rj.conf" + if not os.path.isfile(rjconf_filename): + return None + with open(rjconf_filename) as rjconf_file: + for line in rjconf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == attr_key: + return tokens[1].strip() + return None + +#####BMC-Password### +OPENBMC_PASSWORD = get_rjconfig_info("OPENBMC_PASSWORD") +OPENBMC_PASSWORD = OPENBMC_PASSWORD if(OPENBMC_PASSWORD != None) else "0penBmc" + +############################################################################################ +## if there is no specific file, use common file +module_product = None +if os.path.exists(configfile_pre + grtd_productfile + ".py"): + module_product = __import__(grtd_productfile, globals(), locals(), [], 0) +elif os.path.exists(configfile_pre + common_productfile + ".py"): + module_product = __import__(common_productfile, globals(), locals(), [], 0) +else: + print("No Configuration existed, quit") + exit(-1) +############################################################################################ + +DEVICE = module_product.DEVICE + +##########Driver loading needs parameters +#get different product configuration +RUIJIE_GLOBALCONFIG ={ + "DRIVERLISTS":module_product.DRIVERLISTS, + "QSFP": {"startbus":module_product.PCA9548START, "endbus":module_product.PCA9548BUSEND}, + "DEVS": DEVICE +} +GLOBALCONFIG = RUIJIE_GLOBALCONFIG +GLOBALINITPARAM = module_product.INIT_PARAM +GLOBALINITCOMMAND = module_product.INIT_COMMAND + +fancontrol_loc = module_product.fancontrol_loc +fancontrol_config_loc = module_product.fancontrol_config_loc +MAC_LED_RESET = module_product.MAC_LED_RESET +###########Stat-up module parameters +STARTMODULE = module_product.STARTMODULE +FIRMWARE_TOOLS = module_product.FIRMWARE_TOOLS + + +##########Manufacturing-Test need parameters +FACTESTMODULE = module_product.FACTESTMODULE +TESTCASE = module_product.TESTCASE +menuList = module_product.menuList +alltest = module_product.alltest +diagtestall = module_product.diagtestall +looptest = module_product.looptest +fanloc = module_product.fanloc +fanlevel = module_product.fanlevel # fan adjustment level +TEMPIDCHANGE = module_product.TEMPIDCHANGE +CPLDVERSIONS = module_product.CPLDVERSIONS +RUIJIE_CARDID = module_product.RUIJIE_CARDID +RUIJIE_PRODUCTNAME = module_product.RUIJIE_PRODUCTNAME + +RUIJIE_PART_NUMBER = module_product.RUIJIE_PART_NUMBER +RUIJIE_LABEL_REVISION = module_product.RUIJIE_LABEL_REVISION +RUIJIE_ONIE_VERSION = module_product.RUIJIE_ONIE_VERSION +RUIJIE_MAC_SIZE = module_product.RUIJIE_MAC_SIZE +RUIJIE_MANUF_NAME = module_product.RUIJIE_MANUF_NAME +RUIJIE_MANUF_COUNTRY = module_product.RUIJIE_MANUF_COUNTRY +RUIJIE_VENDOR_NAME = module_product.RUIJIE_VENDOR_NAME +RUIJIE_DIAG_VERSION = module_product.RUIJIE_DIAG_VERSION +RUIJIE_SERVICE_TAG = module_product.RUIJIE_SERVICE_TAG + +E2_PROTECT = module_product.E2_PROTECT +E2_LOC = module_product.E2_LOC +FAN_PROTECT = module_product.FAN_PROTECT + +FANS_DEF = module_product.FANS_DEF +MONITOR_SYS_LED = module_product.MONITOR_SYS_LED +MONITOR_FANS_LED = module_product.MONITOR_FANS_LED +MONITOR_SYS_FAN_LED = module_product.MONITOR_SYS_FAN_LED +MONITOR_SYS_PSU_LED = module_product.MONITOR_SYS_PSU_LED +MONITOR_FAN_STATUS = module_product.MONITOR_FAN_STATUS +MONITOR_PSU_STATUS = module_product.MONITOR_PSU_STATUS +MONITOR_DEV_STATUS = module_product.MONITOR_DEV_STATUS +MONITOR_DEV_STATUS_DECODE = module_product.MONITOR_DEV_STATUS_DECODE +DEV_MONITOR_PARAM = module_product.DEV_MONITOR_PARAM +SLOT_MONITOR_PARAM = module_product.SLOT_MONITOR_PARAM + + +DEV_LEDS = module_product.DEV_LEDS +MEM_SLOTS = module_product.MEM_SLOTS + +MAC_AVS_PARAM = module_product.MAC_AVS_PARAM +MAC_DEFAULT_PARAM = module_product.MAC_DEFAULT_PARAM +E2TYPE = module_product.E2TYPE +FRULISTS = module_product.FRULISTS +rg_eeprom = "%d-%04x/eeprom" % (E2_LOC["bus"], E2_LOC["devno"]) +factest_module = module_product.factest_module + +LOCAL_LED_CONTROL = module_product.LOCAL_LED_CONTROL + +PCIe_DEV_LIST = module_product.PCIe_DEV_LIST +PCIe_SPEED_ITEM = module_product.PCIe_SPEED_ITEM +i2ccheck_params = module_product.i2ccheck_params + + +class MONITOR_CONST: + TEMP_MIN = module_product.MONITOR_TEMP_MIN + K =module_product.MONITOR_K + MAC_IN =module_product.MONITOR_MAC_IN + DEFAULT_SPEED =module_product.MONITOR_DEFAULT_SPEED + MAX_SPEED =module_product.MONITOR_MAX_SPEED + MIN_SPEED =module_product.MONITOR_MIN_SPEED + MAC_ERROR_SPEED =module_product.MONITOR_MAC_ERROR_SPEED + FAN_TOTAL_NUM =module_product.MONITOR_FAN_TOTAL_NUM + MAC_UP_TEMP =module_product.MONITOR_MAC_UP_TEMP + MAC_LOWER_TEMP =module_product.MONITOR_MAC_LOWER_TEMP + MAC_MAX_TEMP = module_product.MONITOR_MAC_MAX_TEMP + + MAC_WARNING_THRESHOLD = module_product.MONITOR_MAC_WARNING_THRESHOLD + OUTTEMP_WARNING_THRESHOLD = module_product.MONITOR_OUTTEMP_WARNING_THRESHOLD + BOARDTEMP_WARNING_THRESHOLD = module_product.MONITOR_BOARDTEMP_WARNING_THRESHOLD + CPUTEMP_WARNING_THRESHOLD = module_product.MONITOR_CPUTEMP_WARNING_THRESHOLD + INTEMP_WARNING_THRESHOLD = module_product.MONITOR_INTEMP_WARNING_THRESHOLD + + MAC_CRITICAL_THRESHOLD = module_product.MONITOR_MAC_CRITICAL_THRESHOLD + OUTTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_OUTTEMP_CRITICAL_THRESHOLD + BOARDTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_BOARDTEMP_CRITICAL_THRESHOLD + CPUTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_CPUTEMP_CRITICAL_THRESHOLD + INTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_INTEMP_CRITICAL_THRESHOLD + CRITICAL_NUM = module_product.MONITOR_CRITICAL_NUM + SHAKE_TIME = module_product.MONITOR_SHAKE_TIME + MONITOR_INTERVAL= module_product.MONITOR_INTERVAL + MONITOR_FALL_TEMP = module_product.MONITOR_FALL_TEMP + + MONITOR_MAC_SOURCE_SYSFS = module_product.MONITOR_MAC_SOURCE_SYSFS + MONITOR_MAC_SOURCE_PATH = module_product.MONITOR_MAC_SOURCE_PATH + +FANCTROLDEBUG = 0 # 1 means enable +DEVMONITORDEBUG = 0 # 1 means enable + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py new file mode 100755 index 000000000..ff594b72e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py @@ -0,0 +1,1828 @@ +# -*- coding: UTF-8 -*- +#------------------------------------------------------------------------- +# Name: ruijieutil +# Purpose: common configuration and api +# +# Author: rd +# +# Created: 02/07/2018 +# Copyright: (c) rd 2018 +#------------------------------------------------------------------------- +import sys +import os +import re +import subprocess +import syslog +import time +import binascii +import tty +import termios +import threading +import click +import mmap +from ruijieconfig import rg_eeprom, FRULISTS, MAC_DEFAULT_PARAM, MAC_AVS_PARAM, FANS_DEF, \ + FAN_PROTECT, E2_LOC, E2_PROTECT, RUIJIE_SERVICE_TAG, RUIJIE_DIAG_VERSION, \ + STARTMODULE, RUIJIE_CARDID, RUIJIE_PRODUCTNAME, RUIJIE_PART_NUMBER, \ + RUIJIE_LABEL_REVISION, RUIJIE_MAC_SIZE, RUIJIE_MANUF_NAME, RUIJIE_MANUF_COUNTRY, \ + RUIJIE_VENDOR_NAME, MAILBOX_DIR + +try: + from eepromutil.fru import ipmifru + +except Exception or SystemExit: + pass + +import logging.handlers +import shutil +import gzip +import glob + +__all__ = ["MENUID", "MENUPARENT", "MENUVALUE", "CHILDID", "MENUITEMNAME", "MENUITEMDEAL", + "GOBACK", "GOQUIT", "file_name", "CRITICAL", "FATAL", "ERROR", "WARNING", "WARN", + "INFO", "DEBUG", "NOTSET", "levelNames", "TLV_INFO_ID_STRING", "TLV_INFO_VERSION", + "TLV_INFO_LENGTH", "TLV_INFO_LENGTH_VALUE", "TLV_CODE_PRODUCT_NAME", + "TLV_CODE_PART_NUMBER", "TLV_CODE_SERIAL_NUMBER", "TLV_CODE_MAC_BASE", + "TLV_CODE_MANUF_DATE", "TLV_CODE_DEVICE_VERSION", "TLV_CODE_LABEL_REVISION", + "TLV_CODE_PLATFORM_NAME", "TLV_CODE_ONIE_VERSION", "TLV_CODE_MAC_SIZE", + "TLV_CODE_MANUF_NAME", "TLV_CODE_MANUF_COUNTRY", "TLV_CODE_VENDOR_NAME", + "TLV_CODE_DIAG_VERSION", "TLV_CODE_SERVICE_TAG", "TLV_CODE_VENDOR_EXT", + "TLV_CODE_CRC_32", "_TLV_DISPLAY_VENDOR_EXT", "TLV_CODE_RJ_CARID", + "_TLV_INFO_HDR_LEN", "SYSLOG_IDENTIFIER", "log_info", "log_debug", "log_warning", + "log_error", "CompressedRotatingFileHandler", "SETMACException", "checkinput", + "checkinputproduct", "getInputSetmac", "fan_tlv", "AVSUTIL", "I2CUTIL", "BMC", + "getSdkReg", "getfilevalue", "get_sysfs_value", "write_sysfs_value", + "RJPRINTERR", "strtoint", "inttostr", "str_to_hex", "hex_to_str", "str_to_bin", + "bin_to_str", "getMacTemp", "getMacTemp_sysfs", "restartDockerService", + "waitForDhcp", "waitForSdk", "waitForDocker", "getTLV_BODY", "_crc32", + "printvalue", "generate_value", "getsyseeprombyId", "fac_init_cardidcheck", + "isValidMac", "util_setmac", "getInputCheck", "getrawch", "upper_input", + "changeTypeValue", "astrcmp", "generate_ext", "rji2cget", "rji2cset", "rjpcird", + "rjpciwr", "rjsysset", "rji2cgetWord", "rji2csetWord", "fan_setmac", "checkfansninput", + "checkfanhwinput", "util_show_fanse2", "get_fane2_sysfs", "util_show_fane2", "getPid", + "fac_fans_setmac_tlv", "fac_fan_setmac_fru", "fac_fans_setmac", "fac_fan_setmac", + "writeToEEprom", "get_local_eth0_mac", "getonieversion", "createbmcMac", + "fac_board_setmac", "ipmi_set_mac", "getInputValue", "bmc_setmac", "closeProtocol", + "checkSdkMem", "getch", "get_raw_input", "getsysvalue", "get_pmc_register", "decoder", + "decode_eeprom", "get_sys_eeprom", "getCardId", "getsysmeminfo", "getsysmeminfo_detail", + "getDmiSysByType", "gethwsys", "getsysbios", "searchDirByName", "getUsbLocation", + "getusbinfo", "get_cpu_info", "get_version_config_info", "io_rd", "io_wr"] + +MENUID = "menuid" +MENUPARENT = "parentid" +MENUVALUE = "value" +CHILDID = "childid" +MENUITEMNAME = "name" +MENUITEMDEAL = "deal" +GOBACK = "goBack" +GOQUIT = "quit" + +file_name = "/etc/init.d/opennsl-modules-3.16.0-5-amd64" +########################################################################## +# ERROR LOG LEVEL +########################################################################## +CRITICAL = 50 +FATAL = CRITICAL +ERROR = 40 +WARNING = 30 +WARN = WARNING +INFO = 20 +DEBUG = 10 +NOTSET = 0 + +levelNames = { + CRITICAL: 'CRITICAL', + ERROR: 'ERROR', + WARNING: 'WARNING', + INFO: 'INFO', + DEBUG: 'DEBUG', + NOTSET: 'NOTSET', + 'CRITICAL': CRITICAL, + 'ERROR': ERROR, + 'WARN': WARNING, + 'WARNING': WARNING, + 'INFO': INFO, + 'DEBUG': DEBUG, + 'NOTSET': NOTSET, +} + +TLV_INFO_ID_STRING = "TlvInfo\x00" +TLV_INFO_VERSION = 0x01 +TLV_INFO_LENGTH = 0x00 +TLV_INFO_LENGTH_VALUE = 0xba + +########################################################################## +# eeprom info +########################################################################## +TLV_CODE_PRODUCT_NAME = 0x21 +TLV_CODE_PART_NUMBER = 0x22 +TLV_CODE_SERIAL_NUMBER = 0x23 +TLV_CODE_MAC_BASE = 0x24 +TLV_CODE_MANUF_DATE = 0x25 +TLV_CODE_DEVICE_VERSION = 0x26 +TLV_CODE_LABEL_REVISION = 0x27 +TLV_CODE_PLATFORM_NAME = 0x28 +TLV_CODE_ONIE_VERSION = 0x29 +TLV_CODE_MAC_SIZE = 0x2A +TLV_CODE_MANUF_NAME = 0x2B +TLV_CODE_MANUF_COUNTRY = 0x2C +TLV_CODE_VENDOR_NAME = 0x2D +TLV_CODE_DIAG_VERSION = 0x2E +TLV_CODE_SERVICE_TAG = 0x2F +TLV_CODE_VENDOR_EXT = 0xFD +TLV_CODE_CRC_32 = 0xFE +_TLV_DISPLAY_VENDOR_EXT = 1 +TLV_CODE_RJ_CARID = 0x01 +_TLV_INFO_HDR_LEN = 11 + + +SYSLOG_IDENTIFIER = "UTILTOOL" + +# ========================== Syslog wrappers ========================== + +def log_info(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_debug(msg, also_print_to_console=False): + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + + +def log_warning(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_WARNING, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + + +def log_error(msg, also_print_to_console=False): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + +class CompressedRotatingFileHandler(logging.handlers.RotatingFileHandler): + def doRollover(self): + """ + Do a rollover, as described in __init__(). + """ + if self.stream: + self.stream.close() + self.stream = None + if self.backupCount > 0: + for i in range(self.backupCount - 1, 0, -1): + sfn = "%s.%d.gz" % (self.baseFilename, i) + dfn = "%s.%d.gz" % (self.baseFilename, i + 1) + if os.path.exists(sfn): + if os.path.exists(dfn): + os.remove(dfn) + os.rename(sfn, dfn) + dfn = self.baseFilename + ".1.gz" + if os.path.exists(dfn): + os.remove(dfn) + # These two lines below are the only new lines. I commented out the os.rename(self.baseFilename, dfn) and + # replaced it with these two lines. + with open(self.baseFilename, 'rb') as f_in, gzip.open(dfn, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + self.mode = 'w' + self.stream = self._open() + + +class SETMACException(Exception): + def __init__(self, param='ERROR', errno="-1"): + err = "Setmac fail[%s]: %s" % (errno, param) + Exception.__init__(self, err) + self.param = param + self.errno = errno + +def checkinput(b): + if b.isdigit() == False: + raise Exception("Ivalid Number") + if int(b) > 0xff or int(b) < 0: + raise Exception("Out of area") + +def checkinputproduct(b): + if b.isalnum() ==False: + raise Exception("Invalid string") + +def getInputSetmac(val): + bia = val.boardInfoArea + pia = val.productInfoArea + if bia != None: + a = raw_input("[Board Card]Product Serial Number:") + if len(a) != 13: + raise Exception("Invalid Serial Number length") + checkinputproduct(a) + bia.boardSerialNumber = a + b = raw_input("[Board Card]Product Version:(from 1-255)") + checkinput(b) + b = "%0x" % int(b) + bia.boardextra1 = b.upper() + if pia != None: + a = raw_input("[Product Area]Product Serial Number:") + if len(a) != 13: + raise Exception("Invalid Serial Number") + checkinputproduct(a) + pia.productSerialNumber = a + b = raw_input("[Product Area]Product Version:(from 1-255)") + checkinput(b) + b = "%0x" % int(b) + pia.productVersion = b.upper() + return val + +class fan_tlv(object): + VERSION = 0x01 # E2PROM Version,start from 0x01 + FLAG = 0x7E # New E2PROM version flag is 0x7E + HW_VER = 0X01 # compose by master version and fixed version + TYPE = 0xf1 # hw type defination + TLV_LEN = 00 # data length (16bit) + _FAN_TLV_HDR_LEN = 6 + _FAN_TLV_CRC_LEN = 2 + + _FAN_TLV_TYPE_NAME = 0x02 + _FAN_TLV_TYPE_SN = 0x03 + _FAN_TLV_TYPE_HW_INFO = 0x05 + _FAN_TLV_TYPE_DEV_TYPE = 0x06 + + _fandecodetime = 0 + + @property + def dstatus(self): + return self._dstatus + + @property + def typename(self): + return self._typename + + @property + def typesn(self): + return self._typesn + + @property + def typehwinfo(self): + return self._typehwinfo + + @property + def typedevtype(self): + return self._typedevtype + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + @property + def fandecodetime(self): + return self._fandecodetime + + def __init__(self): + self._typename = "" + self._typesn = "" + self._typehwinfo = "" + self._typedevtype = "" + self._dstatus = 0 + + def strtoarr(self, str): + s = [] + if str is not None: + for index in range(len(str)): + s.append(str[index]) + return s + + def generate_fan_value(self): + bin_buffer = [chr(0xff)] * 256 + bin_buffer[0] = chr(self.VERSION) + bin_buffer[1] = chr(self.FLAG) + bin_buffer[2] = chr(self.HW_VER) + bin_buffer[3] = chr(self.TYPE) + + temp_t = "%08x" % self.typedevtype # handle devtype first + typedevtype_t = hex_to_str(temp_t) + total_len = len(self.typename) + len(self.typesn) + \ + len(self.typehwinfo) + len(typedevtype_t) + 8 + + bin_buffer[4] = chr(total_len >> 8) + bin_buffer[5] = chr(total_len & 0x00FF) + + index_start = 6 + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME) + bin_buffer[index_start + 1] = chr(len(self.typename)) + bin_buffer[index_start + 2: index_start + 2 + + len(self.typename)] = self.strtoarr(self.typename) + index_start = index_start + 2 + len(self.typename) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN) + bin_buffer[index_start + 1] = chr(len(self.typesn)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typesn)] = self.strtoarr(self.typesn) + index_start = index_start + 2 + len(self.typesn) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO) + bin_buffer[index_start + 1] = chr(len(self.typehwinfo)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typehwinfo)] = self.strtoarr(self.typehwinfo) + index_start = index_start + 2 + len(self.typehwinfo) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE) + bin_buffer[index_start + 1] = chr(len(typedevtype_t)) + bin_buffer[index_start + 2:index_start + 2 + + len(typedevtype_t)] = self.strtoarr(typedevtype_t) + index_start = index_start + 2 + len(typedevtype_t) + + crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # check 2bytes + bin_buffer[index_start] = chr(crcs >> 8) + bin_buffer[index_start + 1] = chr(crcs & 0x00ff) + return bin_buffer + + def decode(self, e2): + ret = [] + self.VERSION = ord(e2[0]) + self.FLAG = ord(e2[1]) + self.HW_VER = ord(e2[2]) + self.TYPE = ord(e2[3]) + self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5]) + + tlv_index = self._FAN_TLV_HDR_LEN + tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN + + # check checksum + if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2: + self._dstatus = -2 + return ret + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN] + ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1]) + if sumcrc != readcrc: + self._dstatus = -1 + return ret + else: + self._dstatus = 0 + while (tlv_index + 2) < len(e2) and tlv_index < tlv_end: + s = self.decoder( + e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])]) + tlv_index += ord(e2[tlv_index + 1]) + 2 + ret.append(s) + + return ret + + @staticmethod + def fancrc(t): + sum = 0 + for index in range(len(t)): + sum += ord(t[index]) + return sum + + def decoder(self, t): + try: + name = "" + value = "" + if ord(t[0]) == self._FAN_TLV_TYPE_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + self._typename = value + elif ord(t[0]) == self._FAN_TLV_TYPE_SN: + name = "serial Number" + value = str(t[2:2 + ord(t[1])]) + self._typesn = value + elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO: + name = "hardware info" + value = str(t[2:2 + ord(t[1])]) + self._typehwinfo = value + elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE: + name = "dev type" + value = str(t[2:2 + ord(t[1])]) + value = str_to_hex(value) + self._typedevtype = value + value = "0x08%x" % value + except Exception as e: + print(e) + return {"name": name, "code": ord(t[0]), "value": value} + + def __str__(self): + formatstr = "VERSION : 0x%02x \n" \ + " FLAG : 0x%02x \n" \ + " HW_VER : 0x%02x \n" \ + " TYPE : 0x%02x \n" \ + "typename : %s \n" \ + "typesn : %s \n" \ + "typehwinfo : %s \n" + return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo) + + +class AVSUTIL(): + @staticmethod + def mac_avs_chip(bus, devno, loc, open, close, loop, protectaddr, level, loopaddr): + # disable protection + rji2cset(bus, devno, protectaddr, open) + rji2cset(bus, devno, loopaddr, loop) + rji2csetWord(bus, devno, loc, level) + ret, value = rji2cgetWord(bus, devno, loc) + if strtoint(value) == level: + ret = 0 + # enable protection + rji2cset(bus, devno, protectaddr, close) + if ret == 0: + return True + return False + + @staticmethod + def macPressure_adj(macavs, avs_param, mac_def_param): + # check whether it within range + max_adj = max(avs_param.keys()) + min_adj = min(avs_param.keys()) + type = mac_def_param["type"] + level = 0 + if type == 0: + if macavs not in range(min_adj, max_adj + 1): + return False + else: + level = macavs + else: + if macavs not in range(min_adj, max_adj + 1): + level = mac_def_param["default"] + else: + level = macavs + ret = AVSUTIL.mac_avs_chip(mac_def_param["bus"], mac_def_param["devno"], mac_def_param["addr"], mac_def_param["open"], + mac_def_param["close"], mac_def_param["loop"], mac_def_param["protectaddr"], avs_param[level], mac_def_param["loopaddr"]) + return ret + + @staticmethod + def mac_adj(): + macavs = 0 + name = MAC_DEFAULT_PARAM["sdkreg"] + ret, status = getSdkReg(name) + if ret == False: + return False + status = strtoint(status) + # shift operation + if MAC_DEFAULT_PARAM["sdktype"] != 0: + status = ( + status >> MAC_DEFAULT_PARAM["macregloc"]) & MAC_DEFAULT_PARAM["mask"] + macavs = status + ret = AVSUTIL.macPressure_adj(macavs, MAC_AVS_PARAM, MAC_DEFAULT_PARAM) + return ret + + +class I2CUTIL(): + @staticmethod + def getvaluefromdevice(name): + ret = [] + for item in DEVICE: + if item["name"] == name: + ret.append(item) + return ret + + @staticmethod + def openFanE2Protect(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + + @staticmethod + def closeFanE2Protect(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + + @staticmethod + def writeToFanE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def writeToE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def getE2File(bus, loc): + return "/sys/bus/i2c/devices/%d-00%02x/eeprom" % (bus, loc) + + +class BMC(): + _instance_lock = threading.Lock() + + def __init__(self): + pass + + def __new__(cls, *args, **kwargs): + if not hasattr(Singleton, "_instance"): + with Singleton._instance_lock: + if not hasattr(Singleton, "_instance"): + Singleton._instance = object.__new__(cls) + return Singleton._instance + +# Internal interface + + +def getSdkReg(reg): + try: + cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg + ret, result = rj_os_system(cmd) + result_t = result.strip().replace("\r", "").replace("\n", "") + if ret != 0 or "Error:" in result_t: + return False, result + patt = r"%s.(.*):(.*)>drivshell" % reg + rt = re.findall(patt, result_t, re.S) + test = re.findall("=(.*)", rt[0][0])[0] + except Exception as e: + return False, 'getsdk register error' + return True, test + + +def getfilevalue(location): + try: + with open(location, 'r') as fd: + value = fd.read() + return True, value.strip() + except Exception as e: + return False, "error" + + +def get_sysfs_value(location): + pos_t = str(location) + name = get_pmc_register(pos_t) + return name + + +def write_sysfs_value(reg_name, value): + fileLoc = MAILBOX_DIR + reg_name + try: + if not os.path.isfile(fileLoc): + print(fileLoc, 'not found !') + return False + with open(fileLoc, 'w') as fd: + fd.write(value) + except Exception as error: + log_error("Unable to open " + fileLoc + "file !") + return False + return True + + +def RJPRINTERR(str): + print("\033[0;31m%s\033[0m" % str) + + +def strtoint(str): # convert Hex string to int such as "4040"/"0x4040"/"0X4040" = 16448 + value = 0 + rest_v = str.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + print(rest_v[index]) + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + +def inttostr(vl,len): # convert int to string such as 0x3030 = 00 + if type(vl) != int: + raise Exception(" type error") + index = 0 + ret_t = "" + while index < len: + ret = 0xff & (vl >> index * 8) + ret_t += chr(ret) + index += 1; + return ret_t + +def str_to_hex(rest_v): + value = 0 + for index in range(len(rest_v)): + value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8) + return value + + +def hex_to_str(s): + len_t = len(s) + if len_t % 2 != 0: + return 0 + ret = "" + for t in range(0, int(len_t / 2)): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + return ret + + +def str_to_bin(s): + return ' '.join([bin(ord(c)).replace('0b', '') for c in s]) + + +def bin_to_str(s): + return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]]) + + +def getMacTemp(): + result = {} + #waitForDocker() + # exec twice, get the second result + rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + ret, log = rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + if ret: + return False, result + else: + # decode obtained info + logs = log.splitlines() + for line in logs: + if "average" in line: + b = re.findall(r'\d+.\d+', line) + result["average"] = b[0] + elif "maximum" in line: + b = re.findall(r'\d+.\d+', line) + result["maximum"] = b[0] + return True, result + +def getMacTemp_sysfs(mactempconf): + try: + temp = -1000000 + temp_list = [] + mac_temp_loc = mactempconf.get("loc", []) + mac_temp_flag = mactempconf.get("flag",None) + if mac_temp_flag is not None: # check mac temperature vaild flag + gettype = mac_temp_flag.get('gettype') + okbit = mac_temp_flag.get('okbit') + okval = mac_temp_flag.get('okval') + if gettype == "io": + io_addr = mac_temp_flag.get('io_addr') + val = io_rd(io_addr) + if val is None: + raise Exception("get mac_flag by io failed.") + else: + bus = mac_temp_flag.get('bus') + loc = mac_temp_flag.get('loc') + offset = mac_temp_flag.get('offset') + ind, val = rji2cget(bus, loc, offset) + if ind is not True: + raise Exception("get mac_flag by i2c failed.") + val_t = (int(val,16) & (1<< okbit)) >> okbit + if val_t != okval: + raise Exception("mac_flag invalid, val_t:%d." % val_t) + for loc in mac_temp_loc: + temp_s = get_sysfs_value(loc) + if isinstance(temp_s, str) and temp_s.startswith("ERR"): + raise Exception("get mac temp error. loc:%s" % loc) + temp_t = int(temp_s) + if temp_t == -1000000: + raise Exception("mac temp invalid.loc:%s" % loc) + temp_list.append(temp_t) + temp_list.sort(reverse=True) + temp = temp_list[0] + except Exception as e: + return False, temp + return True, temp + +def restartDockerService(force=False): + container_name = ["database","snmp","syncd","swss","dhcp_relay","radv","teamd","pmon"] + ret, status = rj_os_system("docker ps") + if ret == 0 : + for tmpname in container_name: + if (tmpname not in status): + if (force == True): + rj_os_system("docker restart %s"%tmpname) + else: + rj_os_system("systemctl restart %s"%tmpname) + + +def waitForDhcp(timeout): + time_cnt = 0 + while True: + try: + ret, status = rj_os_system("systemctl status dhcp_relay.service") + if (ret == 0 and "running" in status) or "SUCCESS" in status: + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + if time_cnt > timeout: + raise Exception("waitForDhcp timeout") + time.sleep(1) + except Exception as e: + return False + return True + +def waitForSdk(sdk_fpath ,timeout): + time_cnt = 0 + while True: + try: + if os.path.exists(sdk_fpath): + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + if time_cnt > timeout: + raise Exception("waitForSdk timeout") + time.sleep(1) + except Exception as e: + return False + return True + +def waitForDocker(need_restart=False,timeout=180): + sdkcheck_params = STARTMODULE.get("sdkcheck",{}) + if sdkcheck_params.get("checktype") == "file": # pass file check + sdk_fpath = sdkcheck_params.get("sdk_fpath") + return waitForSdk(sdk_fpath,timeout) + return waitForDhcp(timeout) + + +def getTLV_BODY(type, productname): + x = [] + temp_t = "" + if type == TLV_CODE_MAC_BASE: + arr = productname.split(':') + for tt in arr: + temp_t += chr(int(tt, 16)) + elif type == TLV_CODE_DEVICE_VERSION: + temp_t = chr(productname) + elif type == TLV_CODE_MAC_SIZE: + temp_t = chr(productname >> 8) + chr(productname & 0x00ff) + else: + temp_t = productname + x.append(chr(type)) + x.append(chr(len(temp_t))) + for i in temp_t: + x.append(i) + return x + + +def _crc32(v): + return '0x%08x' % (binascii.crc32(v) & 0xffffffff) # get 8 bytes of crc32 %x return hex + + +def printvalue(b): + index = 0 + for i in range(0, len(b)): + if index % 16 == 0: + print(" ") + print("%02x " % ord(b[i])) + index += 1 + print("\n") + + +def generate_value(_t): + ret = [] + for i in TLV_INFO_ID_STRING: + ret.append(i) + ret.append(chr(TLV_INFO_VERSION)) + ret.append(chr(TLV_INFO_LENGTH)) + ret.append(chr(TLV_INFO_LENGTH_VALUE)) + + total_len = 0 + for key in _t: + x = getTLV_BODY(key, _t[key]) + ret += x + total_len += len(x) + ret[10] = chr(total_len + 6) + + ret.append(chr(0xFE)) + ret.append(chr(0x04)) + s = _crc32(''.join(ret)) + for t in range(0, 4): + ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) + totallen = len(ret) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + ret.append(chr(0x00)) + return (ret, True) + + +def getsyseeprombyId(id): + ret = get_sys_eeprom() + for item in ret: + if item["code"] == id: + return item + return None + + +def fac_init_cardidcheck(): + rest = getsyseeprombyId(TLV_CODE_RJ_CARID) # check cardId same or not + if rest is None: + print("need to program write bin file") + return False + else: + rest_v = rest['value'] + value = strtoint(rest_v) + if value == RUIJIE_CARDID: + log_debug("check card ID pass") + else: + log_debug("check card ID error") + return False + return True + + +def isValidMac(mac): + if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac): + return True + return False + +# Internet cardsetmac + + +def util_setmac(eth, mac): + rulefile = "/etc/udev/rules.d/70-persistent-net.rules" + if isValidMac(mac) == False: + return False, "MAC invaild" + cmd = "ethtool -e %s | grep 0x0010 | awk '{print \"0x\"$13$12$15$14}'" % eth + ret, log = rj_os_system(cmd) + log_debug(log) + magic = "" + if ret == 0 and len(log): + magic = log + macs = mac.upper().split(":") + + # chage ETH0 to value after setmac + ifconfigcmd = "ifconfig eth0 hw ether %s" % mac + log_debug(ifconfigcmd) + ret, status = rj_os_system(ifconfigcmd) + if ret: + raise SETMACException("software set Internet cardMAC error") + index = 0 + for item in macs: + cmd = "ethtool -E %s magic %s offset %d value 0x%s" % ( + eth, magic, index, item) + log_debug(cmd) + index += 1 + ret, log = rj_os_system(cmd) + if ret != 0: + raise SETMACException(" set hardware Internet card MAC error") + # get value after setting + cmd_t = "ethtool -e eth0 offset 0 length 6" + ret, log = rj_os_system(cmd_t) + m = re.split(':', log)[-1].strip().upper() + mac_result = m.upper().split(" ") + + for ind, s in enumerate(macs): + if s != mac_result[ind]: + RJPRINTERR("MAC comparison error") + if os.path.exists(rulefile): + os.remove(rulefile) + print("MGMT MAC[%s]" % mac) + return True + + +def getInputCheck(tips): + str = raw_input(tips) + if astrcmp(str, "y") or astrcmp(str, "ye") or astrcmp(str, "yes") or astrcmp(str, ""): + return True + else: + return False + +def getrawch(): + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + +def upper_input(tips): + sys.stdout.write(tips) + sys.stdout.flush() + passwd = [] + while True: + ch = getrawch().upper() + if ch == "\r" or ch == "\n": + return "".join(passwd) + elif ch == '\b' or ord(ch) == 127: + if passwd: + del passwd[-1] + sys.stdout.write('\b \b') + else: + sys.stdout.write(ch) + passwd.append(ch) + +def changeTypeValue(_value, type1, tips, example): + if type1 == TLV_CODE_PRODUCT_NAME: + while True: + print("please check (1)air from forward to backward/(2)air from backward to forward:") + option = raw_input() + if option == "1": + _value[type1] = example + "-F-RJ" + print("check Product is air from forward to backward device,Product Name:%s"%_value[type1]) + break + elif option == "2": + _value[type1] = example + "-R-RJ" + print("check Product is air from backward to forward device,Product Name:%s"%_value[type1]) + break + else: + print("input incorrect, check please") + return True + print("Please input[%s]such as(%s):" % (tips, example)) + name = upper_input("") + if type1 == TLV_CODE_MAC_BASE: + if len(name) != 12: + raise SETMACException("MAC address length incorrect, check please") + release_mac = "" + for i in range(int(len(name) / 2)): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + _value[type1] = release_mac + else: + raise SETMACException("MAC address invaild, check please") + elif type1 == TLV_CODE_DEVICE_VERSION: + if name.isdigit(): + _value[type1] = int(name) + else: + raise SETMACException("Version is not number, check please") + elif type1 == TLV_CODE_MAC_SIZE: + if name.isdigit(): + _value[type1] = int(name, 16) + else: + raise SETMACException("Version is not number, check please") + elif type1 == TLV_CODE_SERIAL_NUMBER: + if name.isalnum() == False: + raise SETMACException("Serial Number invaild string, check please") + elif len(name) != 13: + raise SETMACException("Serial Number length incorrect, check please") + else: + _value[type1] = name + elif type1 == TLV_CODE_VENDOR_EXT: + _value[type1] = name + else: + _value[type1] = name + return True + + +def astrcmp(str1, str2): + return str1.lower() == str2.lower() + + +def generate_ext(cardid): + s = "%08x" % cardid + ret = "" + for t in range(0, 4): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + ret = chr(0x01) + chr(len(ret)) + ret + return ret + + +def rji2cget(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + +def rji2cset(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + +def rjpcird(pcibus , slot , fn, bar, offset): + '''read pci register''' + if offset % 4 != 0: + return + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + file = open(filename, "r+") + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + return "0x%08x" % val + + +def rjpciwr(pcibus , slot ,fn, bar, offset, data): + '''write pci register''' + ret = inttostr(data, 4) + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + file = open(filename, "r+") + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + data[offset: offset + 4] = ret + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + +def rjsysset(location, value): + command_line = "echo 0x%02x > %s" % (value, location) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2cgetWord(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x w" % (bus, devno, address) + retrytime = 3 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2csetWord(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%x w" % ( + bus, devno, address, byte) + rj_os_system(command_line) + + +def fan_setmac(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + + +def checkfansninput(fan_sn, fansntemp): + if fan_sn in fansntemp: + RJPRINTERR("exist same Serial Number,please input again") + return False + if(len(fan_sn) != 13): + RJPRINTERR("Serial Number length incorrect,please input again") + return False + return True + +# check 输入的hardware version + + +def checkfanhwinput(hw): + if len(hw) != 4: + RJPRINTERR("hardware version length incorrect, please input again") + return False + if hw.find(".") != 1: + RJPRINTERR("hardware version incorrect, please input again") + return False + return True + + +def util_show_fanse2(fans): + formatstr = "%-8s %-20s %-20s %-20s %-20s" + print(formatstr % ("id", "Name", "hardware version", "Serial Number", "Time")) + print(formatstr % ("------", "---------------", "---------------", "---------------", "----")) + for fan in fans: + # print fan.dstatus + if fan.dstatus < 0: + print("%-8s" % ("FAN%d" % (fans.index(fan) + 1))) + RJPRINTERR(" decode e2 error") + else: + print(formatstr % ("FAN%d" % (fans.index(fan) + 1), fan.typename.replace(chr(0x00), ""), + fan.typehwinfo.replace(chr(0x00), ""), fan.typesn.replace(chr(0x00), ""), fan.fandecodetime)) + + +def get_fane2_sysfs(bus, loc): + rg_fan_e2 = "%d-%04x/fan" % (bus, loc) + eeprom = get_sysfs_value(rg_fan_e2) + return eeprom + + +def util_show_fane2(): + ret = sorted(I2CUTIL.getvaluefromdevice("rg_fan")) + if len(ret) <=0: + return None + fans = [] + for index in range(len(ret)): + t1 = (int(round(time.time() * 1000))) + eeprom = get_fane2_sysfs(ret[index]["bus"], ret[index]["loc"]) + t2 = (int(round(time.time() * 1000))) + fane2 = fan_tlv() + fane2.fandecodetime = t2 - t1 + fane2.decode(eeprom) + fans.append(fane2) + util_show_fanse2(fans) + + +def getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def fac_fans_setmac_tlv(ret): + if len(ret) <=0: + return None + fans = [] + fansntemp = [] + for index in range(len(ret)): + item = ret[index] + log_debug(item) + eeprom = get_fane2_sysfs(item["bus"], item["loc"]) + fane2 = fan_tlv() + fane2.decode(eeprom) + fane2.fanbus = item["bus"] + fane2.fanloc = item["loc"] + log_debug("decode eeprom success") + + print("Fan[%d]-[%s]setmac" % ((index + 1), FANS_DEF[fane2.typedevtype])) + while True: + print("Please input[%s]:" % "Serial Number") + fan_sn = raw_input() + if checkfansninput(fan_sn, fansntemp) == False: + continue + fansntemp.append(fan_sn) + fan_sn = fan_sn + chr(0x00) + fane2.typesn = fan_sn + chr(0x00) + break + while True: + print("Please input[%s]:" % "hardware version") + hwinfo = raw_input() + if checkfanhwinput(hwinfo) == False: + continue + fan_hwinfo = hwinfo + chr(0x00) + fane2.typehwinfo = fan_hwinfo + chr(0x00) + break + log_debug(fane2.typedevtype) + fane2.typename = FANS_DEF[fane2.typedevtype] + chr(0x00) + fans.append(fane2) + print("\n") + print("\n*******************************\n") + + util_show_fanse2(fans) + if getInputCheck("check input correctly or not(Yes/No):") == True: + for fan in fans: + log_debug("ouput fan") + fac_fan_setmac(fan) + else: + print("setmac quit") + return False + + +def fac_fan_setmac_fru(ret): + fans = FRULISTS.get('fans') + + fanfrus = {} + newfrus = {} + + #getmsg + try: + for fan in fans: + print("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + fanfrus[fan.get('name')] = fru + except Exception as e: + print(str(e)) + return False + + #setmsg + for fan in fans: + print("===============%s ================setmac" % fan.get('name')) + fruold = fanfrus.get(fan.get('name')) + newfru = getInputSetmac(fruold) + newfru.recalcute() + newfrus[fan.get('name')] = newfru + #writemsg + for fan in fans: + print("===============%s ================writeToE2" % fan.get('name')) + ret_t = newfrus.get(fan.get('name')) + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(fan.get('bus'), fan.get('loc'), ret_t.bindata) + I2CUTIL.closeFanE2Protect() + #check + try: + for fan in fans: + print("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + except Exception as e: + print(str(e)) + return False + return True + +def fac_fans_setmac(): + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return fac_fans_setmac_tlv(ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans)>0: + return fac_fan_setmac_fru(ret) + return False + +def fac_fan_setmac(item): + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(item.fanbus, item.fanloc, item.generate_fan_value()) + I2CUTIL.closeFanE2Protect() + +def writeToEEprom(rst_arr): + dealtype = E2_PROTECT.get('gettype',None) + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["open"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["open"]) + index = 0 + for item in rst_arr: + rji2cset(E2_LOC["bus"], E2_LOC["devno"], index, ord(item)) + index += 1 + + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["close"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["close"]) + # deal last drivers + os.system("rmmod at24 ") + os.system("modprobe at24 ") + os.system("rm -f /var/cache/sonic/decode-syseeprom/syseeprom_cache") + + +def get_local_eth0_mac(): + cmd = "ifconfig eth0 |grep HWaddr" + print(rj_os_system(cmd)) + +def getonieversion(): + if not os.path.isfile('/host/machine.conf'): + return "" + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars.get("onie_version") + +def createbmcMac(cpumac , num = 2): + bcmvalue = strtoint(cpumac[cpumac.rindex(":")+ 1:len(cpumac)]) + num + # bmcmac = + t = cpumac.split(":") + t[5] = "%02x" % bcmvalue + bmcmac = ":".join(t) + return bmcmac.upper() + + +def fac_board_setmac(): + _value = {} + # default value + _value[TLV_CODE_VENDOR_EXT] = generate_ext(RUIJIE_CARDID) # generate id + _value[TLV_CODE_PRODUCT_NAME] = RUIJIE_PRODUCTNAME + _value[TLV_CODE_PART_NUMBER] = RUIJIE_PART_NUMBER + _value[TLV_CODE_LABEL_REVISION] = RUIJIE_LABEL_REVISION + _value[TLV_CODE_PLATFORM_NAME] = platform + _value[TLV_CODE_ONIE_VERSION] = getonieversion() + _value[TLV_CODE_MAC_SIZE] = RUIJIE_MAC_SIZE + _value[TLV_CODE_MANUF_NAME] = RUIJIE_MANUF_NAME + _value[TLV_CODE_MANUF_COUNTRY] = RUIJIE_MANUF_COUNTRY + _value[TLV_CODE_VENDOR_NAME] = RUIJIE_VENDOR_NAME + _value[TLV_CODE_DIAG_VERSION] = RUIJIE_DIAG_VERSION + _value[TLV_CODE_SERVICE_TAG] = RUIJIE_SERVICE_TAG + try: + if 0x00004052 == RUIJIE_CARDID: + _value[TLV_CODE_PRODUCT_NAME] = RUIJIE_PRODUCTNAME + "-RJ" + elif 0x00004051 == RUIJIE_CARDID or 0x00004050 == RUIJIE_CARDID: + changeTypeValue(_value, TLV_CODE_PRODUCT_NAME, + "Product name",RUIJIE_PRODUCTNAME) + + changeTypeValue(_value, TLV_CODE_SERIAL_NUMBER, + "SN", "0000000000000") # add serial number + changeTypeValue(_value, TLV_CODE_DEVICE_VERSION, + "hardware version", "101") # hardware version + changeTypeValue(_value, TLV_CODE_MAC_BASE, + "MAC address", "58696cfb2108") # MAC address + _value[TLV_CODE_MANUF_DATE] = time.strftime( + '%m/%d/%Y %H:%M:%S', time.localtime()) # add setmac time + rst, ret = generate_value(_value) + if util_setmac("eth0", _value[TLV_CODE_MAC_BASE]) == True: # set Internet cardIP + writeToEEprom(rst) # write to e2 + # set BMC MAC + if "bmcsetmac" in FACTESTMODULE and FACTESTMODULE['bmcsetmac'] == 1: + bmcmac = createbmcMac(_value[TLV_CODE_MAC_BASE]) + if ipmi_set_mac(bmcmac) == True: + print("BMC MAC[%s]"%bmcmac) + else: + print("SET BMC MAC FAILED") + return False + else: + return False + except SETMACException as e: + #print(e) + RJPRINTERR("\n\n%s\n\n" % e) + return False + except ValueError as e: + return False + return True + + +def ipmi_set_mac(mac): + macs = mac.split(":") + cmdinit = "ipmitool raw 0x0c 0x01 0x01 0xc2 0x00" + cmdset = "ipmitool raw 0x0c 0x01 0x01 0x05" + for ind in range(len(macs)): + cmdset += " 0x%02x" % int(macs[ind], 16) + rj_os_system(cmdinit) + ret, status = rj_os_system(cmdset) + if ret: + RJPRINTERR("\n\n%s\n\n" % status) + return False + return True + + +def getInputValue(title, tips): + print("Please input[%s]such as(%s):" % (title, tips)) + name = raw_input() + + return name + + +def bmc_setmac(): + tips = "BMC MAC" + print("Please input value you want to change[%s]:" % tips) + name = raw_input() + if len(name) != 12: + RJPRINTERR("\nMAC address invaild, try again\n") + return False + release_mac = "" + for i in range(int(len(name) / 2)): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + if ipmi_set_mac(release_mac) == True: + return True + else: + RJPRINTERR("\nMAC address invaild, try again\n") + return False + + +def closeProtocol(): + # disable LLDP + log_info("disable LLDP") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop lldp.service") + log_info("disable lldp service") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop bgp.service") + log_info("disable bgp service") + sys.stdout.write(".") + sys.stdout.flush() + #ret, status = rj_os_system('bcmcmd "port ce,xe stp=disable"') + +# check SDK memory must be 256M + + +def checkSdkMem(): + ind = 0 + file_data = "" + with open(file_name, "r") as f: + for line in f: + if "dmasize=16M" in line: + line = line.replace("dmasize=16M", "dmasize=256M") + ind = -1 + file_data += line + if ind == 0: + return + with open(file_name, "w") as f: + f.write(file_data) + print("change SDK memory to 256, reboot required") + rj_os_system("sync") + rj_os_system("reboot") + +########################################################################## +# receives a character setting +########################################################################## + + +def getch(msg): + ret = "" + fd = sys.stdin.fileno() + old_ttyinfo = termios.tcgetattr(fd) + new_ttyinfo = old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + sys.stdout.write(msg) + sys.stdout.flush() + try: + termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo) + ret = os.read(fd, 1) + finally: + # print "try to setting" + termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo) + return ret + +def get_raw_input(): + ret="" + fd=sys.stdin.fileno() + old_ttyinfo=termios.tcgetattr(fd) + new_ttyinfo=old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + try: + termios.tcsetattr(fd,termios.TCSANOW,new_ttyinfo) + ret=raw_input("") + except Exception as e: + print(e) + finally: + termios.tcsetattr(fd,termios.TCSANOW,old_ttyinfo) + return ret + + +def getsysvalue(location): + retval = None + mb_reg_file = location + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return retval + try: + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + #log_debug(retval) + return retval + +# get file value + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR + reg_name + filepath = glob.glob(mb_reg_file) + if(len(filepath) == 0): + return "%s %s notfound"% (retval , mb_reg_file) + mb_reg_file = filepath[0] + if (not os.path.isfile(mb_reg_file)): + return "%s %s notfound"% (retval , mb_reg_file) + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + pass + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +# decode EEPROM + + +def decoder(s, t): + if ord(t[0]) == TLV_CODE_PRODUCT_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + elif ord(t[0]) == TLV_CODE_PART_NUMBER: + name = "Part Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERIAL_NUMBER: + name = "Serial Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_BASE: + name = "Base MAC Address" + value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() + elif ord(t[0]) == TLV_CODE_MANUF_DATE: + name = "Manufacture Date" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DEVICE_VERSION: + name = "Device Version" + value = str(ord(t[2])) + elif ord(t[0]) == TLV_CODE_LABEL_REVISION: + name = "Label Revision" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_PLATFORM_NAME: + name = "Platform Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_ONIE_VERSION: + name = "ONIE Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_SIZE: + name = "MAC Addresses" + value = str((ord(t[2]) << 8) | ord(t[3])) + elif ord(t[0]) == TLV_CODE_MANUF_NAME: + name = "Manufacturer" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MANUF_COUNTRY: + name = "Manufacture Country" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_NAME: + name = "Vendor Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DIAG_VERSION: + name = "Diag Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERVICE_TAG: + name = "Service Tag" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_EXT: + name = "Vendor Extension" + value = "" + if _TLV_DISPLAY_VENDOR_EXT: + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_CRC_32 and len(t) == 6: + name = "CRC-32" + value = "0x%08X" % (((ord(t[2]) << 24) | ( + ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) + elif ord(t[0]) == TLV_CODE_RJ_CARID: + name = "rj_cardid" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + else: + name = "Unknown" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "0x%02X " % (ord(c),) + return {"name": name, "code": ord(t[0]), "value": value} + + +def decode_eeprom(e): + total_len = (ord(e[9]) << 8) | ord(e[10]) + tlv_index = _TLV_INFO_HDR_LEN + tlv_end = _TLV_INFO_HDR_LEN + total_len + ret = [] + while (tlv_index + 2) < len(e) and tlv_index < tlv_end: + rt = decoder(None, e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) + ret.append(rt) + if ord(e[tlv_index]) == TLV_CODE_CRC_32: + break + tlv_index += ord(e[tlv_index + 1]) + 2 + for item in ret: + if item['code'] == TLV_CODE_VENDOR_EXT: + rt = decoder(None, item["value"] + [0: 0 + 2 + ord(item["value"][0 + 1])]) + ret.append(rt) + return ret + + +def get_sys_eeprom(): + eeprom = get_sysfs_value(rg_eeprom) + return decode_eeprom(eeprom) + +# get card ID +def getCardId(): + ret = get_sys_eeprom() + for item in ret: + if item['code'] == TLV_CODE_RJ_CARID: + return item.get('value',None) + return None + +# ==================================== +# execute shell command +# ==================================== +def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + +########################################### +# get memory slot and number via DMI command +########################################### +def getsysmeminfo(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + "|grep -P -A5 \"Memory\s+Device\"|grep Size|grep -v Range" + # get total number first + result = [] + ret1, log1 = rj_os_system(cmd) + if ret1 == 0 and len(log1): + log1 = log1.lstrip() + arr = log1.split("\n") + #total = len(arr) # total slot number + for i in range(len(arr)): + val = re.sub("\D", "", arr[i]) + if val == "": + val = arr[i].lstrip() + val = re.sub('Size:', '', val).lstrip() + # print val + result.append({"slot": i + 1, "size": val}) + return True, result + return False, "error" + +########################################### +# get memory slot and number via DMI command +# return various arrays +########################################### +def getsysmeminfo_detail(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t 17 | grep -A21 \"Memory Device\"" # 17 + # get total number + ret1, log1 = rj_os_system(cmd) + if ret1 != 0 or len(log1) <= 0: + return False, "command execution error[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets + + +########################################### +# get BIOS info via DMI command +########################################### +def getDmiSysByType(type_t): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t %s" % type_t + # get total number + ret1, log1 = rj_os_system(cmd) + if ret1 != 0 or len(log1) <= 0: + return False, "command execution error[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + return True, ret + + +def gethwsys(): + return getDmiSysByType(1) + +########################################### +# get BIOS info via DMI command + + +def getsysbios(): + return getDmiSysByType(0) + + +def searchDirByName(name, dir): + result = [] + try: + files = os.listdir(dir) + for file in files: + if name in file: + result.append(os.path.join(dir, file)) + except Exception as e: + pass + return result + + +def getUsbLocation(): + dir = "/sys/block/" + spect = "sd" + usbpath = "" + result = searchDirByName(spect, dir) + if len(result) <= 0: + return False + for item in result: + with open(os.path.join(item, "removable"), 'r') as fd: + value = fd.read() + if value.strip() == "1": # U-Disk found + usbpath = item + break + if usbpath == "": # no U-Disk found + log_debug("no usb found") + return False, usbpath + return True, usbpath + +# judge USB file +def getusbinfo(): + ret, path = getUsbLocation() + if ret == False: + return False, "not usb exists" + str = os.path.join(path, "size") + ret, value = getfilevalue(str) + if ret == True: + return True, {"id": os.path.basename(path), "size": float(value) * 512 / 1024 / 1024 / 1024} + else: + return False, "Err" + +def get_cpu_info(): + cmd = "cat /proc/cpuinfo |grep processor -A18" # 17 + + ret, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "command execution error[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets +# read file +def get_version_config_info(attr_key, file_name=None): + if file_name is None: + version_conf_filename = "/root/version.json" + else: + version_conf_filename = file_name + if not os.path.isfile(version_conf_filename): + return None + with open(version_conf_filename) as rjconf_file: + for line in rjconf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == attr_key: + return tokens[1].strip() + return None + + +def io_rd(reg_addr, len =1): + u'''io read''' + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, len) + return "".join(["%02x"% ord(item) for item in str]) + except ValueError: + return None + except Exception as e: + print(e) + return None + finally: + os.close(fd) + + +def io_wr(reg_addr, reg_data): + u'''io write''' + try: + regdata = 0 + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + if type(reg_data) == int: + regdata = reg_data + else: + regdata = int(reg_data, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + os.write(fd, chr(regdata)) + return True + except ValueError as e: + print(e) + return False + except Exception as e: + print(e) + return False + finally: + os.close(fd) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service b/platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service new file mode 100755 index 000000000..8777a46b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service @@ -0,0 +1,15 @@ +[Unit] +Description= Ruijie Global Initialize I2c drivers. +After=local-fs.target +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/device_i2c.py start +ExecStop=/usr/local/bin/device_i2c.py stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/changelog b/platform/broadcom/sonic-platform-modules-ruijie/debian/changelog new file mode 100755 index 000000000..c987c3560 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/changelog @@ -0,0 +1,5 @@ +sonic-ruijie-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- sonic_rd Fri, 21 APR 2017 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/compat b/platform/broadcom/sonic-platform-modules-ruijie/debian/compat new file mode 100755 index 000000000..45a4fb75d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/control b/platform/broadcom/sonic-platform-modules-ruijie/debian/control new file mode 100755 index 000000000..369ad546e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/control @@ -0,0 +1,10 @@ +Source: sonic-ruijie-platform-modules +Section: main +Priority: extra +Maintainer: Ruijie Network +Standards-Version: 3.9.3 + +Package: platform-modules-ruijie-b6510-48vs8cq +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/copyright b/platform/broadcom/sonic-platform-modules-ruijie/debian/copyright new file mode 100755 index 000000000..c00a47507 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/copyright @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Ruijie Network Corporation + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init new file mode 100644 index 000000000..a2ff25881 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup B6510-48VS8CQ board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/b6510-48vs8cq_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/b6510-48vs8cq_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-b6510-48vs8cq.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install new file mode 100644 index 000000000..436896926 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install @@ -0,0 +1,3 @@ +b6510-48vs8cq/modules/sonic_platform-1.0-py3-none-any.whl /usr/share/sonic/device/x86_64-ruijie_b6510-48vs8cq-r0 +b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh /usr/local/bin +b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service /usr/lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst new file mode 100755 index 000000000..5edc53b1c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst @@ -0,0 +1,15 @@ +#!/bin/sh +# postinst + +kernel_version=$(uname -r) + +if [ -e /boot/System.map-${kernel_version} ]; then + depmod -a -F /boot/System.map-${kernel_version} ${kernel_version} || true +fi + +# Enable Ruijie-B6510-48VS8CQ-platform-service +depmod -a +systemctl enable platform-modules-b6510-48vs8cq.service +systemctl start platform-modules-b6510-48vs8cq.service + +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/rules b/platform/broadcom/sonic-platform-modules-ruijie/debian/rules new file mode 100755 index 000000000..a2b71bb5c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/rules @@ -0,0 +1,93 @@ +#!/usr/bin/make -f +CC=gcc +INSTALL_MOD_DIR:=extra +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +KBUILD_OUTPUT=$(KERNEL_SRC)/build + +LIB_DIR = usr/lib/python3.7/dist-packages +CUSTOM_RULES_DIR := $(shell pwd)/debian + +export INSTALL_MOD_DIR top_srcdir KVERSION KERNEL_SRC CC KBUILD_OUTPUT + +currentdir = $(shell pwd) +MODULE_DIRS := b6510-48vs8cq +export CUSTOMS_DIRS MODULE_DIRS + +#all product need common +COMPILE_DIRS = $(MODULE_DIRS) + +clean_dirs = $(MODULE_DIRS) +clean_dirs += common + +custom_clean_dirs := $(addprefix _clean_,$(clean_dirs) ) + + +%: + dh $@ +build: $(COMPILE_DIRS) + @echo "build success" + +$(custom_clean_dirs): + $(MAKE) -C $(patsubst _clean_%,%,$@) clean + +common_build : + $(MAKE) -C $(MOD_SRC_DIR)/common + +$(COMPILE_DIRS): common_build + $(MAKE) -C $(MOD_SRC_DIR)/$@ + dh_testdir + dh_installdirs + if [ $@ = "b6510-48vs8cq" ]; then \ + dh_installdirs -pplatform-modules-ruijie-$@ \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + fi; \ + cp -r $(MOD_SRC_DIR)/common/build/* debian/platform-modules-ruijie-$@/ + cp -r $(MOD_SRC_DIR)/$@/build/* debian/platform-modules-ruijie-$@/ + + @(for mod in $(MODULE_DIRS); do \ + cp -r $@/build/* $(MOD_SRC_DIR)/debian/platform-modules-ruijie-$${mod}/; \ + if [ $$mod = "b6510-48vs8cq" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + cp -r $(MOD_SRC_DIR)/common/lib/plat_hal $(MOD_SRC_DIR)/$${mod}/; \ + cp -r $(MOD_SRC_DIR)/common/lib/rjutil $(MOD_SRC_DIR)/$${mod}/; \ + cp -r $(MOD_SRC_DIR)/common/lib/eepromutil $(MOD_SRC_DIR)/$${mod}/; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/plat_hal; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/rjutil; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/eepromutil; \ + cd $(MOD_SRC_DIR); \ + fi; \ + done) + +binary: binary-indep + @echo "=======================================================" + +binary-indep: + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +override_dh_usrlocal: + +override_dh_pysupport: + +clean: $(custom_clean_dirs) + dh_testdir + dh_testroot + dh_clean + +.PHONY: build $(COMPILE_DIRS) binary binary-arch binary-indep clean