From 537f376fd0464f3dc3fb3a2dd3faba26766245fd Mon Sep 17 00:00:00 2001 From: Jemston Fernando Date: Thu, 4 Jul 2024 08:06:27 +0000 Subject: [PATCH] Add new and harden Celestica platforms - Add support for new platforms Seastone2, Questone2A, DS4000-v2, DS3000-v2, DS2000-v2 - Rename Belgite platform to DS1000 and harden --- .../CELESTICA-BELGITE/port_config.ini | 57 - .../CELESTICA-BELGITE/sai.profile | 1 - .../x86_64-cel_belgite-r0/custom_led.bin | Bin 220 -> 0 bytes .../x86_64-cel_belgite-r0/default_sku | 1 - .../pddf/pddf-device.json.original | 686 - .../platform_components.json | 10 - .../DS1000/ds1000.config.bcm} | 3 +- .../DS1000}/hwsku.json | 0 .../DS1000/port_config.ini | 57 + .../x86_64-cel_ds1000-r0/DS1000/sai.profile | 1 + .../DS1000/sai_postinit_cmd.soc | 6 + .../x86_64-cel_ds1000-r0/custom_led.bin | Bin 0 -> 272 bytes .../x86_64-cel_ds1000-r0/default_sku | 1 + .../installer.conf | 4 +- .../led-source-code/cmicx/Makefile | 1 - .../led-source-code/cmicx/custom_led.c | 87 +- .../led-source-code/cmicx/custom_led.lds | 0 .../x86_64-cel_ds1000-r0/led_proc_init.soc | 5 + .../media_settings.json | 1 - .../pcie.yaml | 108 +- .../pddf/pd-plugin.json | 8 +- .../pddf/pddf-device.json | 1367 +- .../pddf_support | 0 .../platform.json | 350 +- .../platform_asic | 0 .../platform_components.json | 12 + .../x86_64-cel_ds1000-r0/platform_reboot | 3 + .../plugins/eeprom.py | 0 .../plugins/psuutil.py | 0 .../plugins/sfputil.py | 0 .../pmon_daemon_control.json | 0 .../x86_64-cel_ds1000-r0/sensors.conf | 45 + .../system_health_monitoring_config.json | 4 +- .../DS2000/buffers.json.j2 | 3 + .../DS2000/buffers_defaults_def.j2 | 46 + .../DS2000/buffers_defaults_t0.j2 | 45 + .../DS2000/buffers_defaults_t1.j2 | 46 + .../x86_64-cel_ds2000-r0/DS2000/hwsku.json | 284 + .../x86_64-cel_ds2000-r0/DS2000/l2/config | 7 + .../x86_64-cel_ds2000-r0/DS2000/l3/config | 5 + .../DS2000/port_config.ini | 57 + .../x86_64-cel_ds2000-r0/DS2000/qos.json.j2 | 1 + .../DS2000/qos_config_t1.j2 | 175 + .../x86_64-cel_ds2000-r0/DS2000/sai.profile | 2 + .../DS2000/sai_postinit_cmd.soc | 2 + .../DS2000/td3-as13-48f8h-2a.config.bcm | 461 + .../x86_64-cel_ds2000-r0/custom_led.bin | Bin 0 -> 264 bytes .../x86_64-cel_ds2000-r0/default_sku | 1 + .../x86_64-cel_ds2000-r0/installer.conf | 4 + .../x86_64-cel_ds2000-r0/led_proc_init.soc | 8 + .../x86_64-cel_ds2000-r0/media_settings.json | 834 + .../x86_64-cel_ds2000-r0/pddf/pd-plugin.json | 145 + .../pddf/pddf-device-bmc.json | 2891 +++ .../pddf/pddf-device-nonbmc.json | 2889 +++ .../x86_64-cel_ds2000-r0/pddf_support | 0 .../x86_64-cel_ds2000-r0/platform.json | 404 + .../x86_64-cel_ds2000-r0/platform_asic | 1 + .../platform_components-bmc.json | 18 + .../platform_components-nonbmc.json | 15 + .../x86_64-cel_ds2000-r0/platform_reboot | 3 + .../x86_64-cel_ds2000-r0/plugins/eeprom.py | 23 + .../x86_64-cel_ds2000-r0/plugins/pcie.yaml | 22 + .../x86_64-cel_ds2000-r0/plugins/sfputil.py | 312 + .../pmon_daemon_control.json | 3 + .../system_health_monitoring_config.json | 16 + .../DS3000/buffers.json.j2 | 2 + .../DS3000/buffers_defaults_def.j2 | 46 + .../DS3000/buffers_defaults_t0.j2 | 45 + .../DS3000/buffers_defaults_t1.j2 | 46 + .../x86_64-cel_ds3000-r0/DS3000/hwsku.json | 169 + .../x86_64-cel_ds3000-r0/DS3000/l2/config | 3 + .../x86_64-cel_ds3000-r0/DS3000/l3/config | 3 + .../DS3000/pg_profile_lookup.ini | 17 + .../DS3000/port_config.ini | 34 + .../x86_64-cel_ds3000-r0/DS3000/qos.json.j2 | 1 + .../x86_64-cel_ds3000-r0/DS3000/sai.profile | 2 + .../DS3000/td3-ds3000-32x100G.config.bcm | 545 + .../x86_64-cel_ds3000-r0/custom_led.bin | Bin 0 -> 130 bytes .../x86_64-cel_ds3000-r0/default_sku | 1 + .../x86_64-cel_ds3000-r0/installer.conf | 4 + .../led_proc_init.soc | 3 +- .../x86_64-cel_ds3000-r0/media_settings.json | 408 + .../celestica/x86_64-cel_ds3000-r0/pcie.yaml | 165 + .../x86_64-cel_ds3000-r0/pddf/pd-plugin.json | 138 + .../pddf/pddf-device-bmc.json | 2123 ++ .../pddf/pddf-device-nonbmc.json | 2216 ++ .../x86_64-cel_ds3000-r0/pddf_support | 0 .../x86_64-cel_ds3000-r0/platform.json | 267 + .../x86_64-cel_ds3000-r0/platform_asic | 1 + .../platform_components.json | 18 + .../x86_64-cel_ds3000-r0/platform_reboot | 3 + .../pmon_daemon_control.json | 7 + .../x86_64-cel_ds3000-r0/sensors.conf | 87 + .../system_health_monitoring_config.json | 16 + .../x86_64-cel_ds3000-r0/thermal_policy.json | 136 + .../Questone_2/custom_led.bin | Bin 0 -> 248 bytes .../Questone_2/hwsku.json | 284 + .../Questone_2/platform.json | 396 + .../Questone_2/platform_components.json | 17 + .../Questone_2/port_config.ini | 57 + .../Questone_2/sai.profile | 1 + .../Questone_2/sai_postinit_cmd.soc | 2 + .../Questone_2/td3-as13-48f8h.config.bcm | 359 + .../Questone_2A/custom_led.bin | Bin 0 -> 308 bytes .../Questone_2A/hwsku.json | 284 + .../Questone_2A/platform.json | 396 + .../Questone_2A/platform_components.json | 17 + .../Questone_2A/port_config.ini | 57 + .../Questone_2A/sai.profile.j2 | 16 + .../Questone_2A/sai_postinit_cmd.soc | 2 + .../td3-as13-48f8h-vxlan.config.bcm | 423 + .../Questone_2A/td3-as13-48f8h.config.bcm | 414 + .../x86_64-cel_questone_2-r0/installer.conf | 4 + .../led_proc_init.soc | 8 + .../opennsl-postinit.cfg | 3 + .../x86_64-cel_questone_2-r0/pcie.yaml | 153 + .../x86_64-cel_questone_2-r0/platform_asic | 1 + .../x86_64-cel_questone_2-r0/platform_reboot | 6 + .../plugins/eeprom.py | 23 + .../plugins/sfputil.py | 312 + .../pmon_daemon_control.json | 5 + .../system_health_monitoring_config.json | 13 + .../warm-reboot_plugin | 4 + .../Seastone_2/buffers.json.j2 | 2 + .../Seastone_2/buffers_defaults_def.j2 | 46 + .../Seastone_2/buffers_defaults_t0.j2 | 45 + .../Seastone_2/buffers_defaults_t1.j2 | 46 + .../Seastone_2/hwsku.json | 169 + .../Seastone_2/l2/config | 3 + .../Seastone_2/l3/config | 3 + .../Seastone_2/pg_profile_lookup.ini | 17 + .../Seastone_2/port_config.ini | 68 +- .../Seastone_2/qos.json.j2 | 1 + .../Seastone_2/sai.profile | 2 - .../Seastone_2/sai.profile.j2 | 17 + .../td3-seastone_2-32x100G-vxlan.config.bcm | 576 + .../td3-seastone_2-32x100G.config.bcm | 131 +- .../{custom.bin => custom_led.bin} | Bin .../x86_64-cel_seastone_2-r0/installer.conf | 3 +- .../led_proc_init.soc | 5 +- .../x86_64-cel_seastone_2-r0/pcie.yaml | 153 + .../x86_64-cel_seastone_2-r0/platform.json | 235 + .../platform_components.json | 17 + .../x86_64-cel_seastone_2-r0/platform_reboot | 6 + .../pmon_daemon_control.json | 8 +- .../sonic_platform_config/chassis.json | 45 - .../sonic_platform_config/component.json | 62 - .../sonic_platform_config/event.py | 117 - .../sonic_platform_config/fan.json | 200 - .../sonic_platform_config/psu.json | 135 - .../sonic_platform_config/sfp.json | 143 - .../sonic_platform_config/thermal.json | 105 - .../sonic_platform_config/watchdog.py | 191 - .../system_health_monitoring_config.json | 13 + .../warm-reboot_plugin | 4 + .../th3-128x100G.config.bcm | 2 - .../Silverstone/hwsku.json | 164 + .../Silverstone/port_config.ini | 64 +- .../Silverstone/sai_postinit_cmd.soc | 2 + .../Silverstone/th3-32x400G.config.bcm | 70 +- .../x86_64-cel_silverstone-r0/pcie.yaml | 434 + .../x86_64-cel_silverstone-r0/platform.json | 484 + .../platform_components.json | 18 + .../x86_64-cel_silverstone-r0/platform_reboot | 6 + .../plugins/psuutil.py | 20 +- .../pmon_daemon_control.json | 4 +- .../sonic_platform/__init__.py | 2 - .../sonic_platform/chassis.py | 131 - .../sonic_platform/component.py | 118 - .../sonic_platform/eeprom.py | 117 - .../sonic_platform/helper.py | 111 - .../sonic_platform/psu.py | 236 - .../sonic_platform/sfp.py | 1467 -- .../system_health_monitoring_config.json | 13 + .../warm-reboot_plugin | 4 + .../Silverstone_v2/buffers.json.j2 | 3 + .../Silverstone_v2/buffers_defaults_def.j2 | 46 + .../Silverstone_v2/buffers_defaults_t0.j2 | 45 + .../Silverstone_v2/buffers_defaults_t1.j2 | 46 + .../Silverstone_v2/hwsku.json | 164 + .../Silverstone_v2/l2/config | 3 + .../Silverstone_v2/l3/config | 3 + .../Silverstone_v2/pg_profile_lookup.ini | 17 + .../Silverstone_v2/platform-def.json | 23 + .../Silverstone_v2/port_config.ini | 33 + .../Silverstone_v2/qos.json.j2 | 1 + .../Silverstone_v2/sai.profile | 2 + .../Silverstone_v2/sai_postinit_cmd.soc | 2 + .../Silverstone_v2/th3-32x400G.config.bcm | 231 + .../Silverstone_v2_128X100G/buffers.json.j2 | 3 + .../buffers_defaults_def.j2 | 46 + .../buffers_defaults_t0.j2 | 45 + .../buffers_defaults_t1.j2 | 46 + .../Silverstone_v2_128X100G/hwsku.json | 100 + .../Silverstone_v2_128X100G/l2/config | 3 + .../Silverstone_v2_128X100G/l3/config | 3 + .../pg_profile_lookup.ini | 17 + .../Silverstone_v2_128X100G/platform-def.json | 23 + .../Silverstone_v2_128X100G/port_config.ini | 129 + .../Silverstone_v2_128X100G/qos.json.j2 | 1 + .../Silverstone_v2_128X100G/sai.profile | 2 + .../th3-128x100G.config.bcm | 445 + .../custom_led.bin | Bin 0 -> 1580 bytes .../x86_64-cel_silverstone_v2-r0/default_sku | 1 + .../installer.conf | 3 + .../led_proc_init.soc | 3 + .../linkscan_led_fw.bin | Bin 0 -> 14248 bytes .../media_settings.json | 18024 ++++++++++++++++ .../x86_64-cel_silverstone_v2-r0/pcie.yaml | 35 + .../pddf/pd-plugin.json | 188 + .../pddf/pddf-device.json-bmc | 2114 ++ .../pddf/pddf-device.json-nonebmc | 2058 ++ .../x86_64-cel_silverstone_v2-r0/pddf_support | 0 .../platform.json | 914 + .../platform_asic | 1 + .../platform_components.json-bmc | 19 + .../platform_components.json-nonebmc | 18 + .../platform_env.conf | 0 .../platform_reboot | 3 + .../plugins/eeprom.py | 20 + .../plugins/psuutil.py | 85 + .../plugins/sfputil.py | 179 + .../plugins/ssd_util.py | 105 + .../pmon_daemon_control.json | 4 + .../system_health_monitoring_config.json | 16 + platform/broadcom/one-image.mk | 6 +- platform/broadcom/platform-modules-cel.mk | 42 +- .../belgite/pddf/sonic_platform/fan.py | 93 - .../belgite/pddf/sonic_platform/sfp.py | 15 - .../belgite/pddf/sonic_platform/thermal.py | 111 - .../scripts/pddf_post_device_create.sh | 13 - .../belgite/utils/belgite_pddf_monitor.py | 272 - .../debian/changelog | 9 + .../sonic-platform-modules-cel/debian/control | 22 +- .../debian/platform-modules-belgite.install | 7 - .../debian/platform-modules-ds1000.install | 8 + ...tinst => platform-modules-ds1000.postinst} | 4 +- .../debian/platform-modules-ds2000.install | 12 + .../debian/platform-modules-ds2000.postinst | 7 + .../debian/platform-modules-ds3000.install | 11 + .../debian/platform-modules-ds3000.postinst | 4 + .../debian/platform-modules-dx010.init | 8 +- .../debian/platform-modules-haliburton.init | 9 + .../debian/platform-modules-questone2.init | 97 + .../debian/platform-modules-questone2.install | 9 + .../platform-modules-questone2.postinst | 6 + .../debian/platform-modules-seastone2.init | 25 +- .../debian/platform-modules-seastone2.install | 3 + .../platform-modules-seastone2.postinst | 5 +- .../platform-modules-silverstone-v2.install | 13 + .../platform-modules-silverstone-v2.postinst | 6 + .../debian/platform-modules-silverstone.init | 87 +- .../platform-modules-silverstone.install | 1 + .../platform-modules-silverstone.postinst | 5 +- .../sonic-platform-modules-cel/debian/rules | 28 +- .../{belgite => ds1000}/modules/Makefile | 0 .../{belgite => ds1000}/modules/mc24lc64t.c | 0 .../modules/pddf_custom_psu.c | 0 .../ds1000/modules/pddf_custom_wdt.c | 734 + .../ds1000/pddf/setup.py | 27 + .../ds1000/pddf/sonic_platform/__init__.py | 2 + .../pddf/sonic_platform/chassis.py | 100 +- .../pddf/sonic_platform/component.py | 296 +- .../pddf/sonic_platform/eeprom.py | 15 +- .../ds1000/pddf/sonic_platform/fan.py | 153 + .../pddf/sonic_platform/fan_drawer.py | 9 +- .../ds1000/pddf/sonic_platform/pcie.py | 15 + .../pddf/sonic_platform/platform.py | 0 .../pddf/sonic_platform/psu.py | 39 +- .../ds1000/pddf/sonic_platform/sfp.py | 36 + .../ds1000/pddf/sonic_platform/thermal.py | 105 + .../pddf/sonic_platform/watchdog.py | 15 +- .../scripts/ds1000_platform_shutdown.sh | 26 + .../ds1000/scripts/pddf_post_device_create.sh | 22 + .../scripts/pddf_pre_driver_install.sh | 2 +- .../ds1000/service/ds1000-fan-control.service | 17 + .../ds1000/systemd/pddf-platform-init.service | 15 + .../ds1000/utils/ds1000_fanctld.py | 346 + .../ds2000/classes/__init__.py | 0 .../ds2000/modules/Makefile | 5 + .../ds2000/modules/lpc_basecpld.c | 720 + .../ds2000/modules/mc24lc64t.c | 171 + .../ds2000/modules/pddf_custom_fpga_algo.c | 631 + .../ds2000/modules/pddf_custom_fpga_extend.c | 372 + .../ds2000/modules/pmbus.h | 504 + .../ds2000/modules/psu_driver/pddf_psu_api.c | 478 + .../ds2000/modules/psu_driver/pddf_psu_api.h | 31 + .../ds2000/modules/psu_driver/pddf_psu_defs.h | 90 + .../modules/psu_driver/pddf_psu_driver.c | 398 + .../modules/psu_driver/pddf_psu_driver.h | 70 + .../{belgite => ds2000}/pddf/setup.py | 1 + .../pddf/sonic_platform/__init__.py | 4 +- .../ds2000/pddf/sonic_platform/chassis.py | 242 + .../ds2000/pddf/sonic_platform/component.py | 214 + .../pddf/sonic_platform/cpld_watchdog.py | 228 + .../ds2000/pddf/sonic_platform/eeprom.py | 78 + .../ds2000/pddf/sonic_platform/fan.py | 192 + .../ds2000/pddf/sonic_platform/fan_drawer.py | 17 + .../ds2000/pddf/sonic_platform/helper.py | 143 + .../ds2000/pddf/sonic_platform/platform.py | 23 + .../ds2000/pddf/sonic_platform/psu.py | 33 + .../ds2000/pddf/sonic_platform/sfp.py | 110 + .../ds2000/pddf/sonic_platform/thermal.py | 13 + .../ds2000/pddf/sonic_platform/watchdog.py | 15 + .../scripts/ds2000_platform_shutdown.sh | 42 + .../ds2000/scripts/pddf_post_device_create.sh | 26 + .../ds2000/scripts/pddf_pre_driver_install.sh | 14 + .../ds2000/scripts/platform_sensors.py | 178 + .../ds2000/scripts/pre_pddf_init.sh | 31 + .../ds2000/scripts/sensors | 11 + .../ds2000-pddf-platform-monitor.service | 17 + .../ds2000/systemd/pddf-platform-init.service | 15 + .../utils/FanControl/CPUPIDRegulation.py | 152 + .../ds2000/utils/FanControl/FanControl.py | 253 + .../utils/FanControl/FanLinearAdjustment.py | 195 + .../FanControl/SwitchInternalPIDRegulation.py | 162 + .../ds2000/utils/FanControl/__init__.py | 5 + .../utils/pddf_fan_control_sensor_refresh.py | 20 + .../ds3000/modules/Makefile | 8 + .../ds3000/modules/baseboard_cpld.c | 414 + .../modules/led_driver/pddf_custom_led_defs.h | 149 + .../led_driver/pddf_custom_led_module.c | 873 + .../ds3000/modules/mc24lc64t.c | 172 + .../ds3000/modules/pddf_custom_fpga_algo.c | 626 + .../ds3000/modules/pddf_custom_fpga_extend.c | 372 + .../ds3000/modules/psu_driver/pddf_psu_api.c | 478 + .../ds3000/modules/psu_driver/pddf_psu_api.h | 31 + .../ds3000/modules/psu_driver/pddf_psu_defs.h | 90 + .../modules/psu_driver/pddf_psu_driver.c | 398 + .../modules/psu_driver/pddf_psu_driver.h | 70 + .../modules/switchboard_fpga.c} | 991 +- .../ds3000/pddf/setup.py | 28 + .../ds3000/pddf/sonic_platform/__init__.py | 4 + .../ds3000/pddf/sonic_platform/chassis.py | 295 + .../ds3000/pddf/sonic_platform/component.py | 321 + .../pddf/sonic_platform/cpld_watchdog.py | 228 + .../ds3000/pddf/sonic_platform/eeprom.py | 84 + .../ds3000/pddf/sonic_platform/event.py | 52 + .../ds3000/pddf/sonic_platform/fan.py | 246 + .../ds3000/pddf/sonic_platform/fan_drawer.py | 28 + .../ds3000/pddf/sonic_platform/helper.py | 139 + .../ds3000/pddf/sonic_platform/pcie.py | 10 + .../ds3000/pddf/sonic_platform/platform.py | 23 + .../ds3000/pddf/sonic_platform/psu.py | 49 + .../ds3000/pddf/sonic_platform/sfp.py | 183 + .../ds3000/pddf/sonic_platform/thermal.py | 56 + .../pddf/sonic_platform/thermal_actions.py | 341 + .../pddf/sonic_platform/thermal_conditions.py | 121 + .../pddf/sonic_platform/thermal_infos.py | 362 + .../pddf/sonic_platform/thermal_manager.py | 21 + .../ds3000/pddf/sonic_platform/watchdog.py | 14 + .../ds3000/pddf/sonic_platform_setup.py | 28 + .../scripts/ds3000_platform_shutdown.sh | 39 + .../ds3000/scripts/pddf_post_device_create.sh | 37 + .../ds3000/scripts/pddf_pre_driver_install.sh | 11 + .../ds3000/scripts/platform_sensors.py | 179 + .../ds3000/scripts/pre_pddf_init.sh | 30 + .../ds3000/scripts/sensors | 11 + .../ds3000/systemd/pddf-platform-init.service | 16 + .../ds3000/utils/afulnx_64 | Bin 0 -> 1134256 bytes .../ds3000/utils/fpga_prog | Bin 0 -> 17536 bytes .../ds3000/utils/ispvm | Bin 0 -> 101752 bytes .../ds3000/utils/pddf_switch_svc.py | 83 + .../questone2/cfg/pid_config_questone2.ini | 19 + .../questone2/cfg/questone2-modprobe.conf | 1 + .../questone2/cfg/questone2-modules.conf | 16 + .../questone2/modules/Makefile | 1 + .../questone2/modules/mc24lc64t.c | 171 + .../modules/questone2_baseboard_cpld.c | 408 + .../questone2/modules/questone2_switchboard.c | 2211 ++ .../questone2/scripts/platform_sensors.py | 161 + .../scripts/questone2_platform_shutdown.sh | 26 + .../questone2/scripts/sensors | 11 + .../questone2/setup.py | 10 + .../questone2/sonic_platform/__init__.py | 2 + .../questone2/sonic_platform/chassis.py | 464 + .../questone2/sonic_platform/component.py | 156 + .../questone2/sonic_platform/eeprom.py | 128 + .../questone2/sonic_platform/fan.py | 345 + .../questone2/sonic_platform/fan_drawer.py | 82 + .../questone2/sonic_platform/helper.py | 191 + .../questone2/sonic_platform/pcie.py | 15 + .../questone2/sonic_platform/platform.py | 23 + .../questone2/sonic_platform/psu.py | 265 + .../questone2/sonic_platform/sfp.py | 197 + .../questone2}/sonic_platform/thermal.py | 132 +- .../questone2/sonic_platform/watchdog.py | 264 + .../platform-modules-questone2.service | 13 + .../seastone2/modules/baseboard_cpld.c | 2 +- .../seastone2/scripts/platform_sensors.py | 161 + .../scripts/seastone2_platform_shutdown.sh | 26 + .../seastone2/scripts/sensors | 11 + .../seastone2/setup.py | 31 + .../seastone2/sonic_platform/__init__.py | 2 + .../seastone2/sonic_platform/chassis.py | 457 + .../seastone2/sonic_platform/component.py | 156 + .../seastone2/sonic_platform/eeprom.py | 128 + .../seastone2/sonic_platform/fan.py | 345 + .../seastone2/sonic_platform/fan_drawer.py | 91 + .../seastone2/sonic_platform/helper.py | 191 + .../seastone2/sonic_platform/pcie.py | 15 + .../seastone2/sonic_platform/platform.py | 23 + .../seastone2/sonic_platform/psu.py | 273 + .../seastone2/sonic_platform/sfp.py | 198 + .../seastone2/sonic_platform/thermal.py | 204 + .../seastone2/sonic_platform/watchdog.py | 274 + .../silverstone-v2/modules/Makefile | 11 + .../modules/fan_driver/pddf_custom_fan_api.c | 656 + .../modules/fan_driver/pddf_custom_fan_defs.h | 93 + .../fan_driver/pddf_custom_fan_driver.c | 523 + .../fan_driver/pddf_custom_fan_driver.h | 117 + .../modules/fan_driver/readme.txt | 4 + .../modules/led_driver/pddf_custom_led_defs.h | 149 + .../led_driver/pddf_custom_led_module.c | 873 + .../modules/pddf_custom_fpga_algo.c | 634 + .../modules/pddf_custom_fpga_extend.c | 340 + .../modules/pddf_custom_lpc_basecpld.c | 441 + .../modules/pddf_custom_wdt.c | 150 +- .../silverstone-v2/modules/pmbus.h | 504 + .../modules/psu_driver/pddf_psu_api.c | 478 + .../modules/psu_driver/pddf_psu_api.h | 31 + .../modules/psu_driver/pddf_psu_defs.h | 90 + .../modules/psu_driver/pddf_psu_driver.c | 398 + .../modules/psu_driver/pddf_psu_driver.h | 70 + .../silverstone-v2/modules/tps536c7.c | 133 + .../silverstone-v2/pddf/setup.py | 27 + .../pddf/sonic_platform/__init__.py | 4 + .../pddf/sonic_platform/chassis.py | 234 + .../pddf/sonic_platform/component.py | 230 + .../pddf/sonic_platform/eeprom.py | 78 + .../silverstone-v2/pddf/sonic_platform/fan.py | 93 + .../pddf/sonic_platform/fan_drawer.py | 21 + .../pddf/sonic_platform/helper.py | 143 + .../pddf/sonic_platform/platform.py | 23 + .../silverstone-v2/pddf/sonic_platform/psu.py | 46 + .../pddf/sonic_platform/sensor_list_config.py | 11 + .../silverstone-v2/pddf/sonic_platform/sfp.py | 103 + .../pddf/sonic_platform/thermal.py | 68 + .../pddf/sonic_platform/watchdog.py | 208 + .../scripts/pddf_post_device_create.sh | 20 + .../scripts/pddf_pre_driver_install.sh | 14 + .../scripts/platform_sensors.py | 180 + .../silverstone-v2/scripts/pre_pddf_init.py | 100 + .../silverstone-v2/scripts/sensors | 11 + .../silverstone_v2_platform_shutdown.sh | 39 + ...verstone-v2-pddf-platform-monitor.service} | 6 +- .../systemd/pddf-platform-init.service | 1 + .../utils/FanControl/CPUPIDRegulation.py | 129 + .../utils/FanControl/FanControl.py | 207 + .../utils/FanControl/FanLinearAdjustment.py | 156 + .../FanControl/SwitchInternalPIDRegulation.py | 145 + .../utils/FanControl/__init__.py | 5 + .../utils/pddf_fan_control_sensor_refresh.py | 26 + .../utils/pddf_sensor_list_refresh.py | 39 + .../silverstone/cfg/silverstone-modules.conf | 4 +- .../silverstone/modules/Makefile | 2 +- .../silverstone/modules/baseboard-lpc.c | 4 +- .../silverstone/modules/cls-i2c-mux-pca954x.c | 578 + .../silverstone/modules/cls-pca954x.h | 44 + .../silverstone/modules/cls-switchboard.c | 542 + .../silverstone/modules/switch_cpld.c | 416 + .../silverstone/modules/xcvr-cls.c | 520 + .../silverstone/modules/xcvr-cls.h | 41 + .../silverstone/scripts/platform_sensors.py | 114 +- .../silverstone/scripts/sensors | 2 +- .../scripts/silverstone_platform_shutdown.sh | 26 + .../silverstone/setup.py | 5 +- .../silverstone/sonic_platform/__init__.py | 2 + .../silverstone/sonic_platform/chassis.py | 452 + .../silverstone/sonic_platform/component.py | 181 + .../silverstone/sonic_platform/eeprom.py | 123 + .../silverstone}/sonic_platform/fan.py | 238 +- .../silverstone/sonic_platform/fan_drawer.py | 108 + .../silverstone/sonic_platform/helper.py | 190 + .../silverstone/sonic_platform/pcie.py | 15 + .../silverstone}/sonic_platform/platform.py | 0 .../silverstone/sonic_platform/psu.py | 338 + .../silverstone/sonic_platform/sfp.py | 232 + .../silverstone/sonic_platform/thermal.py | 205 + .../silverstone/sonic_platform/watchdog.py | 247 + 480 files changed, 83159 insertions(+), 6570 deletions(-) delete mode 100644 device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/port_config.ini delete mode 100644 device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/sai.profile delete mode 100644 device/celestica/x86_64-cel_belgite-r0/custom_led.bin delete mode 100644 device/celestica/x86_64-cel_belgite-r0/default_sku delete mode 100644 device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json.original delete mode 100644 device/celestica/x86_64-cel_belgite-r0/platform_components.json rename device/celestica/{x86_64-cel_belgite-r0/CELESTICA-BELGITE/belgite.config.bcm => x86_64-cel_ds1000-r0/DS1000/ds1000.config.bcm} (98%) rename device/celestica/{x86_64-cel_belgite-r0/CELESTICA-BELGITE => x86_64-cel_ds1000-r0/DS1000}/hwsku.json (100%) create mode 100644 device/celestica/x86_64-cel_ds1000-r0/DS1000/port_config.ini create mode 100644 device/celestica/x86_64-cel_ds1000-r0/DS1000/sai.profile create mode 100644 device/celestica/x86_64-cel_ds1000-r0/DS1000/sai_postinit_cmd.soc create mode 100755 device/celestica/x86_64-cel_ds1000-r0/custom_led.bin create mode 100644 device/celestica/x86_64-cel_ds1000-r0/default_sku rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/installer.conf (83%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/led-source-code/cmicx/Makefile (99%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/led-source-code/cmicx/custom_led.c (79%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/led-source-code/cmicx/custom_led.lds (100%) create mode 100644 device/celestica/x86_64-cel_ds1000-r0/led_proc_init.soc rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/media_settings.json (99%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/pcie.yaml (56%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/pddf/pd-plugin.json (84%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/pddf/pddf-device.json (87%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/pddf_support (100%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/platform.json (62%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/platform_asic (100%) create mode 100644 device/celestica/x86_64-cel_ds1000-r0/platform_components.json create mode 100755 device/celestica/x86_64-cel_ds1000-r0/platform_reboot rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/plugins/eeprom.py (100%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/plugins/psuutil.py (100%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/plugins/sfputil.py (100%) rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/pmon_daemon_control.json (100%) create mode 100644 device/celestica/x86_64-cel_ds1000-r0/sensors.conf rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds1000-r0}/system_health_monitoring_config.json (86%) create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers.json.j2 create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_def.j2 create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t0.j2 create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t1.j2 create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/hwsku.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/l2/config create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/l3/config create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/port_config.ini create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/qos.json.j2 create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/qos_config_t1.j2 create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/sai.profile create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/sai_postinit_cmd.soc create mode 100644 device/celestica/x86_64-cel_ds2000-r0/DS2000/td3-as13-48f8h-2a.config.bcm create mode 100644 device/celestica/x86_64-cel_ds2000-r0/custom_led.bin create mode 100644 device/celestica/x86_64-cel_ds2000-r0/default_sku create mode 100644 device/celestica/x86_64-cel_ds2000-r0/installer.conf create mode 100644 device/celestica/x86_64-cel_ds2000-r0/led_proc_init.soc create mode 100644 device/celestica/x86_64-cel_ds2000-r0/media_settings.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/pddf/pd-plugin.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-bmc.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-nonbmc.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/pddf_support create mode 100644 device/celestica/x86_64-cel_ds2000-r0/platform.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/platform_asic create mode 100644 device/celestica/x86_64-cel_ds2000-r0/platform_components-bmc.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/platform_components-nonbmc.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/platform_reboot create mode 100644 device/celestica/x86_64-cel_ds2000-r0/plugins/eeprom.py create mode 100644 device/celestica/x86_64-cel_ds2000-r0/plugins/pcie.yaml create mode 100755 device/celestica/x86_64-cel_ds2000-r0/plugins/sfputil.py create mode 100644 device/celestica/x86_64-cel_ds2000-r0/pmon_daemon_control.json create mode 100644 device/celestica/x86_64-cel_ds2000-r0/system_health_monitoring_config.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers.json.j2 create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_def.j2 create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t0.j2 create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t1.j2 create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/hwsku.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/l2/config create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/l3/config create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/pg_profile_lookup.ini create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/port_config.ini create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/qos.json.j2 create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/sai.profile create mode 100644 device/celestica/x86_64-cel_ds3000-r0/DS3000/td3-ds3000-32x100G.config.bcm create mode 100644 device/celestica/x86_64-cel_ds3000-r0/custom_led.bin create mode 100644 device/celestica/x86_64-cel_ds3000-r0/default_sku create mode 100644 device/celestica/x86_64-cel_ds3000-r0/installer.conf rename device/celestica/{x86_64-cel_belgite-r0 => x86_64-cel_ds3000-r0}/led_proc_init.soc (71%) create mode 100644 device/celestica/x86_64-cel_ds3000-r0/media_settings.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/pcie.yaml create mode 100644 device/celestica/x86_64-cel_ds3000-r0/pddf/pd-plugin.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-bmc.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-nonbmc.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/pddf_support create mode 100644 device/celestica/x86_64-cel_ds3000-r0/platform.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/platform_asic create mode 100644 device/celestica/x86_64-cel_ds3000-r0/platform_components.json create mode 100755 device/celestica/x86_64-cel_ds3000-r0/platform_reboot create mode 100644 device/celestica/x86_64-cel_ds3000-r0/pmon_daemon_control.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/sensors.conf create mode 100644 device/celestica/x86_64-cel_ds3000-r0/system_health_monitoring_config.json create mode 100644 device/celestica/x86_64-cel_ds3000-r0/thermal_policy.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/custom_led.bin create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/hwsku.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform_components.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/port_config.ini create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai.profile create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai_postinit_cmd.soc create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2/td3-as13-48f8h.config.bcm create mode 100755 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/custom_led.bin create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/hwsku.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform_components.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/port_config.ini create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai.profile.j2 create mode 100644 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai_postinit_cmd.soc create mode 100755 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h-vxlan.config.bcm create mode 100755 device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h.config.bcm create mode 100644 device/celestica/x86_64-cel_questone_2-r0/installer.conf create mode 100644 device/celestica/x86_64-cel_questone_2-r0/led_proc_init.soc create mode 100644 device/celestica/x86_64-cel_questone_2-r0/opennsl-postinit.cfg create mode 100644 device/celestica/x86_64-cel_questone_2-r0/pcie.yaml create mode 100644 device/celestica/x86_64-cel_questone_2-r0/platform_asic create mode 100755 device/celestica/x86_64-cel_questone_2-r0/platform_reboot create mode 100644 device/celestica/x86_64-cel_questone_2-r0/plugins/eeprom.py create mode 100755 device/celestica/x86_64-cel_questone_2-r0/plugins/sfputil.py create mode 100644 device/celestica/x86_64-cel_questone_2-r0/pmon_daemon_control.json create mode 100644 device/celestica/x86_64-cel_questone_2-r0/system_health_monitoring_config.json create mode 100755 device/celestica/x86_64-cel_questone_2-r0/warm-reboot_plugin create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers.json.j2 create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_def.j2 create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t0.j2 create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t1.j2 create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/hwsku.json create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l2/config create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l3/config create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/pg_profile_lookup.ini create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/qos.json.j2 delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile.j2 create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G-vxlan.config.bcm rename device/celestica/x86_64-cel_seastone_2-r0/{custom.bin => custom_led.bin} (100%) create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/pcie.yaml create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/platform.json create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/platform_components.json create mode 100755 device/celestica/x86_64-cel_seastone_2-r0/platform_reboot delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json delete mode 100644 device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py create mode 100644 device/celestica/x86_64-cel_seastone_2-r0/system_health_monitoring_config.json create mode 100755 device/celestica/x86_64-cel_seastone_2-r0/warm-reboot_plugin create mode 100644 device/celestica/x86_64-cel_silverstone-r0/Silverstone/hwsku.json create mode 100644 device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai_postinit_cmd.soc create mode 100644 device/celestica/x86_64-cel_silverstone-r0/pcie.yaml create mode 100644 device/celestica/x86_64-cel_silverstone-r0/platform.json create mode 100644 device/celestica/x86_64-cel_silverstone-r0/platform_components.json create mode 100755 device/celestica/x86_64-cel_silverstone-r0/platform_reboot delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py delete mode 100644 device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py create mode 100644 device/celestica/x86_64-cel_silverstone-r0/system_health_monitoring_config.json create mode 100755 device/celestica/x86_64-cel_silverstone-r0/warm-reboot_plugin create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers.json.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_def.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t0.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t1.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/hwsku.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l2/config create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l3/config create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/pg_profile_lookup.ini create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/platform-def.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/port_config.ini create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/qos.json.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai.profile create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai_postinit_cmd.soc create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/th3-32x400G.config.bcm create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers.json.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_def.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t0.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t1.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/hwsku.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l2/config create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l3/config create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/pg_profile_lookup.ini create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/platform-def.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/port_config.ini create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/qos.json.j2 create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/sai.profile create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/th3-128x100G.config.bcm create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/custom_led.bin create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/default_sku create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/installer.conf create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/led_proc_init.soc create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/linkscan_led_fw.bin create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/media_settings.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/pcie.yaml create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pd-plugin.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-bmc create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-nonebmc create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/pddf_support create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/platform.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/platform_asic create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-bmc create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-nonebmc create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/platform_env.conf create mode 100755 device/celestica/x86_64-cel_silverstone_v2-r0/platform_reboot create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/plugins/eeprom.py create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/plugins/psuutil.py create mode 100755 device/celestica/x86_64-cel_silverstone_v2-r0/plugins/sfputil.py create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/plugins/ssd_util.py create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/pmon_daemon_control.json create mode 100644 device/celestica/x86_64-cel_silverstone_v2-r0/system_health_monitoring_config.json delete mode 100644 platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan.py delete mode 100644 platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/sfp.py delete mode 100644 platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/thermal.py delete mode 100755 platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_post_device_create.sh delete mode 100755 platform/broadcom/sonic-platform-modules-cel/belgite/utils/belgite_pddf_monitor.py delete mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.install create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.install rename platform/broadcom/sonic-platform-modules-cel/debian/{platform-modules-belgite.postinst => platform-modules-ds1000.postinst} (56%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.install create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.postinst create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.install create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.postinst create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.init create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.install create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.postinst create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.install create mode 100644 platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.postinst rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/modules/Makefile (100%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/modules/mc24lc64t.c (100%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/modules/pddf_custom_psu.c (100%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/modules/pddf_custom_wdt.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/__init__.py rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/chassis.py (71%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/component.py (52%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/eeprom.py (81%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan.py rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/fan_drawer.py (91%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/pcie.py rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/platform.py (100%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/psu.py (61%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/thermal.py rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/pddf/sonic_platform/watchdog.py (98%) create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/ds1000_platform_shutdown.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_post_device_create.sh rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds1000}/scripts/pddf_pre_driver_install.sh (70%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/service/ds1000-fan-control.service create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds1000/systemd/pddf-platform-init.service create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds1000/utils/ds1000_fanctld.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/classes/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/lpc_basecpld.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/mc24lc64t.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_algo.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_extend.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pmbus.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.h rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds2000}/pddf/setup.py (98%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => ds2000}/pddf/sonic_platform/__init__.py (63%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/cpld_watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/ds2000_platform_shutdown.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_post_device_create.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_pre_driver_install.sh create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/platform_sensors.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pre_pddf_init.sh create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/sensors create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/ds2000-pddf-platform-monitor.service create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/pddf-platform-init.service create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/CPUPIDRegulation.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanControl.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanLinearAdjustment.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/SwitchInternalPIDRegulation.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/__init__.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds2000/utils/pddf_fan_control_sensor_refresh.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/baseboard_cpld.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_module.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/mc24lc64t.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_algo.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_extend.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.h rename platform/broadcom/sonic-platform-modules-cel/{silverstone/modules/switchboard.c => ds3000/modules/switchboard_fpga.c} (67%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/cpld_watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/event.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/pcie.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_actions.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_conditions.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_infos.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_manager.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform_setup.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/ds3000_platform_shutdown.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_post_device_create.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_pre_driver_install.sh create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/platform_sensors.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pre_pddf_init.sh create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/sensors create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/systemd/pddf-platform-init.service create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/utils/afulnx_64 create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/utils/fpga_prog create mode 100755 platform/broadcom/sonic-platform-modules-cel/ds3000/utils/ispvm create mode 100644 platform/broadcom/sonic-platform-modules-cel/ds3000/utils/pddf_switch_svc.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/cfg/pid_config_questone2.ini create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modprobe.conf create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modules.conf create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/modules/mc24lc64t.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_baseboard_cpld.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_switchboard.c create mode 100755 platform/broadcom/sonic-platform-modules-cel/questone2/scripts/platform_sensors.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/questone2/scripts/questone2_platform_shutdown.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/questone2/scripts/sensors create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/pcie.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/sfp.py rename {device/celestica/x86_64-cel_silverstone-r0 => platform/broadcom/sonic-platform-modules-cel/questone2}/sonic_platform/thermal.py (50%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/questone2/systemd/platform-modules-questone2.service create mode 100755 platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/platform_sensors.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/seastone2_platform_shutdown.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/sensors create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/pcie.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_api.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/readme.txt create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_module.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_algo.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_extend.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_lpc_basecpld.c rename platform/broadcom/sonic-platform-modules-cel/{belgite => silverstone-v2}/modules/pddf_custom_wdt.c (85%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pmbus.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/tps536c7.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sensor_list_config.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/watchdog.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_post_device_create.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_pre_driver_install.sh create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/platform_sensors.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pre_pddf_init.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/sensors create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/silverstone_v2_platform_shutdown.sh rename platform/broadcom/sonic-platform-modules-cel/{belgite/service/belgite-pddf-platform-monitor.service => silverstone-v2/service/silverstone-v2-pddf-platform-monitor.service} (58%) rename platform/broadcom/sonic-platform-modules-cel/{belgite => silverstone-v2}/systemd/pddf-platform-init.service (89%) create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/CPUPIDRegulation.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanControl.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanLinearAdjustment.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/SwitchInternalPIDRegulation.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/__init__.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_fan_control_sensor_refresh.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_sensor_list_refresh.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-i2c-mux-pca954x.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-pca954x.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-switchboard.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switch_cpld.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.h create mode 100755 platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/silverstone_platform_shutdown.sh create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/eeprom.py rename {device/celestica/x86_64-cel_silverstone-r0 => platform/broadcom/sonic-platform-modules-cel/silverstone}/sonic_platform/fan.py (51%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/pcie.py rename {device/celestica/x86_64-cel_silverstone-r0 => platform/broadcom/sonic-platform-modules-cel/silverstone}/sonic_platform/platform.py (100%) create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/watchdog.py diff --git a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/port_config.ini b/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/port_config.ini deleted file mode 100644 index 90ecfa4859ad..000000000000 --- a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/port_config.ini +++ /dev/null @@ -1,57 +0,0 @@ -# name lanes alias index speed autoneg -Ethernet0 26 Ethernet1/0/1 1 1000 1 -Ethernet1 25 Ethernet1/0/2 2 1000 1 -Ethernet2 28 Ethernet1/0/3 3 1000 1 -Ethernet3 27 Ethernet1/0/4 4 1000 1 -Ethernet4 30 Ethernet1/0/5 5 1000 1 -Ethernet5 29 Ethernet1/0/6 6 1000 1 -Ethernet6 32 Ethernet1/0/7 7 1000 1 -Ethernet7 31 Ethernet1/0/8 8 1000 1 -Ethernet8 34 Ethernet1/0/9 9 1000 1 -Ethernet9 33 Ethernet1/0/10 10 1000 1 -Ethernet10 36 Ethernet1/0/11 11 1000 1 -Ethernet11 35 Ethernet1/0/12 12 1000 1 -Ethernet12 38 Ethernet1/0/13 13 1000 1 -Ethernet13 37 Ethernet1/0/14 14 1000 1 -Ethernet14 40 Ethernet1/0/15 15 1000 1 -Ethernet15 39 Ethernet1/0/16 16 1000 1 -Ethernet16 42 Ethernet1/0/17 17 1000 1 -Ethernet17 41 Ethernet1/0/18 18 1000 1 -Ethernet18 44 Ethernet1/0/19 19 1000 1 -Ethernet19 43 Ethernet1/0/20 20 1000 1 -Ethernet20 50 Ethernet1/0/21 21 1000 1 -Ethernet21 49 Ethernet1/0/22 22 1000 1 -Ethernet22 52 Ethernet1/0/23 23 1000 1 -Ethernet23 51 Ethernet1/0/24 24 1000 1 -Ethernet24 2 Ethernet1/0/25 25 1000 1 -Ethernet25 1 Ethernet1/0/26 26 1000 1 -Ethernet26 4 Ethernet1/0/27 27 1000 1 -Ethernet27 3 Ethernet1/0/28 28 1000 1 -Ethernet28 6 Ethernet1/0/29 29 1000 1 -Ethernet29 5 Ethernet1/0/30 30 1000 1 -Ethernet30 8 Ethernet1/0/31 31 1000 1 -Ethernet31 7 Ethernet1/0/32 32 1000 1 -Ethernet32 10 Ethernet1/0/33 33 1000 1 -Ethernet33 9 Ethernet1/0/34 34 1000 1 -Ethernet34 12 Ethernet1/0/35 35 1000 1 -Ethernet35 11 Ethernet1/0/36 36 1000 1 -Ethernet36 14 Ethernet1/0/37 37 1000 1 -Ethernet37 13 Ethernet1/0/38 38 1000 1 -Ethernet38 16 Ethernet1/0/39 39 1000 1 -Ethernet39 15 Ethernet1/0/40 40 1000 1 -Ethernet40 18 Ethernet1/0/41 41 1000 1 -Ethernet41 17 Ethernet1/0/42 42 1000 1 -Ethernet42 20 Ethernet1/0/43 43 1000 1 -Ethernet43 19 Ethernet1/0/44 44 1000 1 -Ethernet44 22 Ethernet1/0/45 45 1000 1 -Ethernet45 21 Ethernet1/0/46 46 1000 1 -Ethernet46 24 Ethernet1/0/47 47 1000 1 -Ethernet47 23 Ethernet1/0/48 48 1000 1 -Ethernet48 60 Ethernet1/0/49 49 10000 0 -Ethernet49 58 Ethernet1/0/50 50 10000 0 -Ethernet50 59 Ethernet1/0/51 51 10000 0 -Ethernet51 57 Ethernet1/0/52 52 10000 0 -Ethernet52 62 Ethernet1/0/53 53 10000 0 -Ethernet53 64 Ethernet1/0/54 54 10000 0 -Ethernet54 61 Ethernet1/0/55 55 10000 0 -Ethernet55 63 Ethernet1/0/56 56 10000 0 diff --git a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/sai.profile b/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/sai.profile deleted file mode 100644 index 2e5979fd112c..000000000000 --- a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/sai.profile +++ /dev/null @@ -1 +0,0 @@ -SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/belgite.config.bcm diff --git a/device/celestica/x86_64-cel_belgite-r0/custom_led.bin b/device/celestica/x86_64-cel_belgite-r0/custom_led.bin deleted file mode 100644 index c1b5e0e1b1d6df0a03d57ba312715b5ebb0b772e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmV~$yH3JT0D$4YEecYRn<6MEP>_oz1jHLvEG0RED-*D2F_FQ6Cm@80MK KSJbh%;g)~zw=1~- diff --git a/device/celestica/x86_64-cel_belgite-r0/default_sku b/device/celestica/x86_64-cel_belgite-r0/default_sku deleted file mode 100644 index 3eeb370889f9..000000000000 --- a/device/celestica/x86_64-cel_belgite-r0/default_sku +++ /dev/null @@ -1 +0,0 @@ -CELESTICA-BELGITE t1 diff --git a/device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json.original b/device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json.original deleted file mode 100644 index 8f43a3f6090d..000000000000 --- a/device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json.original +++ /dev/null @@ -1,686 +0,0 @@ -{ - "PLATFORM": - { - "num_psus":2, - "num_fantrays":3, - "num_fans_pertray":1, - "num_ports":56, - "num_temps":4, - "pddf_dev_types": - { - "description":"Belgite - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", - "CPLD": - [ - "i2c_cpld" - ], - "PSU": - [ - "psu_eeprom", - "psu_pmbus" - ], - "FAN": - [ - "fan_ctrl", - "fan_eeprom", - "fan_cpld" - ], - "PORT_MODULE": - [ - "pddf_xcvr" - ] - }, - "std_perm_kos": - [ - "i2c-ismt", - "i2c-i801" - ], - "std_kos": - [ - "i2c_dev", - "i2c_mux_pca954x", - "gpio_pca953x", - "mc24lc64t", - "optoe" - ], - "pddf_kos": - [ - "pddf_client_module", - "pddf_mux_module", - "pddf_psu_driver_module", - "pddf_psu_module", - "pddf_gpio_module", - "pddf_xcvr_module", - "pddf_xcvr_driver_module", - "pddf_led_module", - "pddf_fan_driver_module", - "pddf_fan_module", - "pddf_led_module" - ], - "custom_kos": - [ - "pddf_custom_psu" - ] - }, - "SYSTEM": - { - "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, - "i2c": - { - "CONTROLLERS": - [ - { "dev_name":"i2c-0", "dev":"SMBUS0" } - ] - } - }, - "SMBUS0": - { - "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, - "i2c": - { - "topo_info": {"dev_addr": "0x0"}, - "DEVICES": - [ - {"dev": "EEPROM1"}, - {"dev": "MUX1"} - ] - } - }, - "EEPROM1": - { - "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, - "i2c": - { - "topo_info": {"parent_bus": "0x0", "dev_addr": "0x52", "dev_type": "24lc64t"}, - "dev_attr": {"access_mode": "BLOCK"}, - "attr_list": - [ - {"attr_name": "eeprom"} - ] - } - }, - "MUX1": - { - "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"SMBUS0"}, - "i2c": - { - "topo_info": { "parent_bus":"0x0", "dev_addr":"0x70", "dev_type":"pca9548"}, - "dev_attr": { "virt_bus":"0x2"}, - "channel": - [ - {"chn":"0", "dev":"CPLD1" }, - {"chn":"0", "dev":"FAN-CTRL1" }, - {"chn":"2", "dev":"PSU1" }, - {"chn":"2", "dev":"PSU2" }, - {"chn":"3", "dev":"TEMP1"}, - {"chn":"3", "dev":"TEMP2"}, - {"chn":"4", "dev":"TEMP3"}, - {"chn":"4", "dev":"TEMP4"}, - {"chn":"7", "dev":"MUX2"} - ] - } - }, - "MUX2": - { - "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"MUX1"}, - "i2c": - { - "topo_info": { "parent_bus":"0x9", "dev_addr":"0x71", "dev_type":"pca9548"}, - "dev_attr": { "virt_bus":"0x10"}, - "channel": - [ - {"chn":"0", "dev":"PORT49"}, - {"chn":"1", "dev":"PORT50"}, - {"chn":"2", "dev":"PORT51"}, - {"chn":"3", "dev":"PORT52"}, - {"chn":"4", "dev":"PORT53"}, - {"chn":"5", "dev":"PORT54"}, - {"chn":"6", "dev":"PORT55"}, - {"chn":"7", "dev":"PORT56"} - ] - } - }, - "CPLD1": - { - "dev_info": {"device_type": "CPLD", "device_name": "CPLD1", "device_parent": "MUX1"}, - "i2c": - { - "topo_info": {"parent_bus": "0x2", "dev_addr": "0x32", "dev_type": "i2c_cpld"}, - "dev_attr": {} - } - }, - "PSU1": - { - "dev_info": { "device_type":"PSU", "device_name":"PSU1", "device_parent":"MUX1"}, - "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, - "i2c": - { - "interface": - [ - { "itf":"pmbus", "dev":"PSU1-PMBUS" } - ] - } - }, - "PSU1-PMBUS": - { - "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU1-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU1"}, - "i2c": - { - "topo_info":{ "parent_bus":"0x4", "dev_addr":"0x58", "dev_type":"psu_pmbus"}, - "attr_list": - [ - { "attr_name":"psu_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x10", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_power_good", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_model_name", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"16" }, - { "attr_name":"psu_mfr_id", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"7" }, - { "attr_name":"psu_serial_num", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"16" }, - { "attr_name":"psu_v_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_p_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_v_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_fan_dir", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xc5", "attr_mask":"0x18", "attr_cmpval":"0x08", "attr_len":"1"}, - { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} - ] - } - }, - "PSU2": - { - "dev_info": { "device_type":"PSU", "device_name":"PSU2", "device_parent":"MUX1" }, - "dev_attr": { "dev_idx":"2", "num_psu_fans":"1"}, - "i2c": - { - "interface": - [ - { "itf":"pmbus", "dev":"PSU2-PMBUS"} - ] - } - }, - "PSU2-PMBUS": - { - "dev_info": {"device_type":"PSU-PMBUS", "device_name":"PSU2-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU2"}, - "i2c": - { - "topo_info": { "parent_bus":"0x4", "dev_addr":"0x59", "dev_type":"psu_pmbus"}, - "attr_list": - [ - { "attr_name":"psu_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x20", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_power_good", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x8", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_model_name", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"16" }, - { "attr_name":"psu_mfr_id", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"7" }, - { "attr_name":"psu_serial_num", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"16" }, - { "attr_name":"psu_v_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_p_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_v_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_fan_dir", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xc5", "attr_mask":"0x18", "attr_cmpval":"0x08", "attr_len":"1"}, - { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} - ] - } - }, - "TEMP1": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U10"}, - "i2c": - { - "topo_info": { "parent_bus":"0x5", "dev_addr":"0x48", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "TEMP2": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U4"}, - "i2c": - { - "topo_info": { "parent_bus":"0x5", "dev_addr":"0x49", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "TEMP3": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U7"}, - "i2c": - { - "topo_info": { "parent_bus":"0x6", "dev_addr":"0x4a", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "TEMP4": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U60"}, - "i2c": - { - "topo_info": { "parent_bus":"0x6", "dev_addr":"0x49", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "PORT49": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT49", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"49"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT49-EEPROM" }, - { "itf":"control", "dev":"PORT49-CTRL" } - ] - } - }, - "PORT49-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT49-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT49"}, - "i2c": - { - "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT49-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT49-CTRL", "device_parent":"MUX2", "virt_parent":"PORT49"}, - "i2c": - { - "topo_info": { "parent_bus":"0x10", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"} - ] - } - }, - "PORT50": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT50", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"50"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT50-EEPROM" }, - { "itf":"control", "dev":"PORT50-CTRL" } - ] - } - }, - "PORT50-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT50-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT50"}, - "i2c": - { - "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT50-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT50-CTRL", "device_parent":"MUX2", "virt_parent":"PORT50"}, - "i2c": - { - "topo_info": { "parent_bus":"0x11", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"} - - ] - } - }, - "PORT51": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT51", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"51"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT51-EEPROM" }, - { "itf":"control", "dev":"PORT51-CTRL" } - ] - } - }, - "PORT51-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT51-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT51"}, - "i2c": - { - "topo_info": { "parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT51-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT51-CTRL", "device_parent":"MUX2", "virt_parent":"PORT51"}, - "i2c": - { - "topo_info": { "parent_bus":"0x12", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"} - ] - } - }, - "PORT52": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT52", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"52"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT52-EEPROM" }, - { "itf":"control", "dev":"PORT52-CTRL" } - ] - } - }, - "PORT52-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT52-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT52"}, - "i2c": - { - "topo_info": { "parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT52-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT52-CTRL", "device_parent":"MUX2", "virt_parent":"PORT52"}, - "i2c": - { - "topo_info": { "parent_bus":"0x13", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"} - - ] - } - }, - "PORT53": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT53", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"53"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT53-EEPROM" }, - { "itf":"control", "dev":"PORT53-CTRL" } - ] - } - }, - "PORT53-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT53-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT53"}, - "i2c": - { - "topo_info": { "parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT53-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT53-CTRL", "device_parent":"MUX2", "virt_parent":"PORT53"}, - "i2c": - { - "topo_info": { "parent_bus":"0x14", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} - - ] - } - }, - "PORT54": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT54", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"54"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT54-EEPROM" }, - { "itf":"control", "dev":"PORT54-CTRL" } - ] - } - }, - "PORT54-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT54-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT54"}, - "i2c": - { - "topo_info": { "parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT54-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT54-CTRL", "device_parent":"MUX2", "virt_parent":"PORT54"}, - "i2c": - { - "topo_info": { "parent_bus":"0x15", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"} - ] - } - }, - "PORT55": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT55", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"55"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT55-EEPROM" }, - { "itf":"control", "dev":"PORT55-CTRL" } - ] - } - }, - "PORT55-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT55-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT55"}, - "i2c": - { - "topo_info": { "parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT55-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT55-CTRL", "device_parent":"MUX2", "virt_parent":"PORT55"}, - "i2c": - { - "topo_info": { "parent_bus":"0x16", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} - ] - } - }, - "PORT56": - { - "dev_info": { "device_type":"SFP28", "device_name":"PORT56", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"56"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT56-EEPROM" }, - { "itf":"control", "dev":"PORT56-CTRL" } - ] - } - }, - "PORT56-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT56-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT56"}, - "i2c": - { - "topo_info": { "parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT56-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT56-CTRL", "device_parent":"MUX2", "virt_parent":"PORT56"}, - "i2c": - { - "topo_info": { "parent_bus":"0x17", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"} - ] - } - }, - "FAN-CTRL1": - { - "dev_info": { "device_type":"FAN", "device_name":"FAN-CTRL1", "device_parent":"MUX1"}, - "i2c": - { - "topo_info": { "parent_bus":"0x2", "dev_addr":"0x66", "dev_type":"fan_cpld"}, - "dev_attr": { "num_fantrays":"3"}, - "attr_list": - [ - { "attr_name":"fan1_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x32", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan2_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x36", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan3_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x3a", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan1_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan2_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan3_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x1", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan1_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x31", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, - { "attr_name":"fan2_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x35", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150" , "attr_is_divisor":0}, - { "attr_name":"fan3_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x39", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0} - ] - } - }, - "SYS_LED": - { - "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, - "dev_attr": { "index":"0", "flag": "rw"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"amber","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x1","swpld_addr_offset":"0x43"}, - {"attr_name":"green","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x2","swpld_addr_offset":"0x43"}, - {"attr_name":"off","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x0","swpld_addr_offset":"0x43"} - ] - } - }, - "FANTRAY1_LED": - { - "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, - "dev_attr": { "index":"0", "flag": "rw"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x33"}, - {"attr_name":"red","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x33"} - ] - } - }, - "FANTRAY2_LED": - { - "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, - "dev_attr": { "index":"1", "flag": "rw"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x37"}, - {"attr_name":"red","attr_devtype":"cpld","attr_devname":"CPLD1B","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x37"} - ] - } - }, - "FANTRAY3_LED": - { - "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, - "dev_attr": { "index":"2", "flag": "rw"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x3b"}, - {"attr_name":"red","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x3b"} - ] - } - } -} diff --git a/device/celestica/x86_64-cel_belgite-r0/platform_components.json b/device/celestica/x86_64-cel_belgite-r0/platform_components.json deleted file mode 100644 index 23a4ce41cd67..000000000000 --- a/device/celestica/x86_64-cel_belgite-r0/platform_components.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "chassis": { - "E1070": { - "component": { - "SWCPLD": {}, - "BIOS": {} - } - } - } -} diff --git a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/belgite.config.bcm b/device/celestica/x86_64-cel_ds1000-r0/DS1000/ds1000.config.bcm similarity index 98% rename from device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/belgite.config.bcm rename to device/celestica/x86_64-cel_ds1000-r0/DS1000/ds1000.config.bcm index a249804582c9..fd2ca27948be 100644 --- a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/belgite.config.bcm +++ b/device/celestica/x86_64-cel_ds1000-r0/DS1000/ds1000.config.bcm @@ -166,4 +166,5 @@ portmap_56=63:10 pbmp_xport_xe=0x01FFFFFFFFFFFFFE -# \ No newline at end of file +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc +# diff --git a/device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/hwsku.json b/device/celestica/x86_64-cel_ds1000-r0/DS1000/hwsku.json similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/CELESTICA-BELGITE/hwsku.json rename to device/celestica/x86_64-cel_ds1000-r0/DS1000/hwsku.json diff --git a/device/celestica/x86_64-cel_ds1000-r0/DS1000/port_config.ini b/device/celestica/x86_64-cel_ds1000-r0/DS1000/port_config.ini new file mode 100644 index 000000000000..123c4f10df22 --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/DS1000/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed autoneg +Ethernet0 26 Eth1/1 1 1000 1 +Ethernet1 25 Eth2/1 2 1000 1 +Ethernet2 28 Eth3/1 3 1000 1 +Ethernet3 27 Eth4/1 4 1000 1 +Ethernet4 30 Eth5/1 5 1000 1 +Ethernet5 29 Eth6/1 6 1000 1 +Ethernet6 32 Eth7/1 7 1000 1 +Ethernet7 31 Eth8/1 8 1000 1 +Ethernet8 34 Eth9/1 9 1000 1 +Ethernet9 33 Eth10/1 10 1000 1 +Ethernet10 36 Eth11/1 11 1000 1 +Ethernet11 35 Eth12/1 12 1000 1 +Ethernet12 38 Eth13/1 13 1000 1 +Ethernet13 37 Eth14/1 14 1000 1 +Ethernet14 40 Eth15/1 15 1000 1 +Ethernet15 39 Eth16/1 16 1000 1 +Ethernet16 42 Eth17/1 17 1000 1 +Ethernet17 41 Eth18/1 18 1000 1 +Ethernet18 44 Eth19/1 19 1000 1 +Ethernet19 43 Eth20/1 20 1000 1 +Ethernet20 50 Eth21/1 21 1000 1 +Ethernet21 49 Eth22/1 22 1000 1 +Ethernet22 52 Eth23/1 23 1000 1 +Ethernet23 51 Eth24/1 24 1000 1 +Ethernet24 2 Eth25/1 25 1000 1 +Ethernet25 1 Eth26/1 26 1000 1 +Ethernet26 4 Eth27/1 27 1000 1 +Ethernet27 3 Eth28/1 28 1000 1 +Ethernet28 6 Eth29/1 29 1000 1 +Ethernet29 5 Eth30/1 30 1000 1 +Ethernet30 8 Eth31/1 31 1000 1 +Ethernet31 7 Eth32/1 32 1000 1 +Ethernet32 10 Eth33/1 33 1000 1 +Ethernet33 9 Eth34/1 34 1000 1 +Ethernet34 12 Eth35/1 35 1000 1 +Ethernet35 11 Eth36/1 36 1000 1 +Ethernet36 14 Eth37/1 37 1000 1 +Ethernet37 13 Eth38/1 38 1000 1 +Ethernet38 16 Eth39/1 39 1000 1 +Ethernet39 15 Eth40/1 40 1000 1 +Ethernet40 18 Eth41/1 41 1000 1 +Ethernet41 17 Eth42/1 42 1000 1 +Ethernet42 20 Eth43/1 43 1000 1 +Ethernet43 19 Eth44/1 44 1000 1 +Ethernet44 22 Eth45/1 45 1000 1 +Ethernet45 21 Eth46/1 46 1000 1 +Ethernet46 24 Eth47/1 47 1000 1 +Ethernet47 23 Eth48/1 48 1000 1 +Ethernet48 60 Eth49/1 49 10000 0 +Ethernet49 58 Eth50/1 50 10000 0 +Ethernet50 59 Eth51/1 51 10000 0 +Ethernet51 57 Eth52/1 52 10000 0 +Ethernet52 62 Eth53/1 53 10000 0 +Ethernet53 64 Eth54/1 54 10000 0 +Ethernet54 61 Eth55/1 55 10000 0 +Ethernet55 63 Eth56/1 56 10000 0 diff --git a/device/celestica/x86_64-cel_ds1000-r0/DS1000/sai.profile b/device/celestica/x86_64-cel_ds1000-r0/DS1000/sai.profile new file mode 100644 index 000000000000..d58abd359c7f --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/DS1000/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/ds1000.config.bcm diff --git a/device/celestica/x86_64-cel_ds1000-r0/DS1000/sai_postinit_cmd.soc b/device/celestica/x86_64-cel_ds1000-r0/DS1000/sai_postinit_cmd.soc new file mode 100644 index 000000000000..0de17febfeaf --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/DS1000/sai_postinit_cmd.soc @@ -0,0 +1,6 @@ +modreg ING_MISC_CONFIG INPUT_PRI_TAGGED=1 +modreg ING_MISC_CONFIG INPUT_PRI_UNTAGGED=1 +modreg QTG_CHIP_CONFIG.qtgport0 PAUSE_PFC_SEL=1 +modreg QTG_CHIP_CONFIG.qtgport1 PAUSE_PFC_SEL=1 +modreg CHIP_CONFIG.pmqport0 PAUSE_PFC_SEL=1 +modreg CHIP_CONFIG.pmqport1 PAUSE_PFC_SEL=1 diff --git a/device/celestica/x86_64-cel_ds1000-r0/custom_led.bin b/device/celestica/x86_64-cel_ds1000-r0/custom_led.bin new file mode 100755 index 0000000000000000000000000000000000000000..1fe3d5abac5a44b16f6ae059e0811f236295265f GIT binary patch literal 272 zcmWN}J1;|V7{KA*zpdMG+^eW-PjBj2w3VVR)i$qz1zTgFBI)QO2nHi!kTUoPa*_^` zN@}vn!6cS0Qjtg+qlxDOJoVC(tjIwruoh-NLC_ge#)UYIGjSMN>QwaVVc}(KSG=iJ zDSFSXOd+@Fh`XlCY2EgpsN|JZL=`r2p7fU;Wm$-PKY!FP@ag_*InJtZBBUiRMO7cR zRrJ-u{I!*-*>1Hbk#!Y&w_N7WTcvy_w^F}<+);VSXXGgVS*ys+3=H69kRgT{VU#g^ z|Fxe0K|+KXC&C0KlS~mMMjV9$CoURjq={x)&}c=cpFTYF;--ggy6B{XcG{R{jwG`z Jl45}+{s5hIKs^8e literal 0 HcmV?d00001 diff --git a/device/celestica/x86_64-cel_ds1000-r0/default_sku b/device/celestica/x86_64-cel_ds1000-r0/default_sku new file mode 100644 index 000000000000..e83707dd8d95 --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/default_sku @@ -0,0 +1 @@ +DS1000 t1 diff --git a/device/celestica/x86_64-cel_belgite-r0/installer.conf b/device/celestica/x86_64-cel_ds1000-r0/installer.conf similarity index 83% rename from device/celestica/x86_64-cel_belgite-r0/installer.conf rename to device/celestica/x86_64-cel_ds1000-r0/installer.conf index 430473933330..fbc96da1773d 100644 --- a/device/celestica/x86_64-cel_belgite-r0/installer.conf +++ b/device/celestica/x86_64-cel_ds1000-r0/installer.conf @@ -1,4 +1,4 @@ -CONSOLE_PORT=0x3f8 +CONSOLE_PORT=0xe060 CONSOLE_DEV=0 -CONSOLE_SPEED=9600 +CONSOLE_SPEED=115200 ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off modprobe.blacklist=gpio_ich,i2c-ismt,i2c_ismt,i2c-i801,i2c_i801 crashkernel=0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M acpi_no_watchdog" diff --git a/device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/Makefile b/device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/Makefile similarity index 99% rename from device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/Makefile rename to device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/Makefile index ddc700bfb87e..21bd48d0ab3b 100755 --- a/device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/Makefile +++ b/device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/Makefile @@ -21,4 +21,3 @@ all: clean: rm -rf *.elf *.o *.map *.bin - diff --git a/device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/custom_led.c b/device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/custom_led.c similarity index 79% rename from device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/custom_led.c rename to device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/custom_led.c index 712b5503e34b..fea5bc581f16 100755 --- a/device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/custom_led.c +++ b/device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/custom_led.c @@ -82,31 +82,42 @@ This array would have port speed for each port, as per bit mapping defined in "soc_led_speed_t" in $SDK/include/shared/cmicfw/cmicx_led_public.h file. Here is an exception, please keep in mind: -1. For TH3, port status/speed of xe1 (physical port 258) is located in the +1. For TH3, port status/speed of xe1 (physical port 258) is located in the accumulation entry/speed array of physical port 259. ******************************************************************************/ #include #define ACTIVITY_TICKS 2 -#define READ_LED_ACCU_DATA(base, port) (*((uint16 *)(base + ((port - 1) * sizeof(uint32))))) -#define WRITE_LED_SEND_DATA(base, port, val) (*((uint16 *)(base + ((port - 1) * sizeof(uint32)))) = val) + +/*! Macro to calculate LED RAM address. */ +#define LED_HW_RAM_ADDR(base, port) \ + (base + (port * sizeof(uint32))) + +/*! Macro to read LED RAM. */ +#define LED_HW_RAM_READ16(base, port) \ + *((uint16 *) LED_HW_RAM_ADDR(base, port)) + +/*! Macro to write LED RAM. */ +#define LED_HW_RAM_WRITE16(base, port, val) \ + *((uint16 *) LED_HW_RAM_ADDR(base, port)) = (val) #define PORT_NUM_TOTAL 56 #define LED_GREEN_BICOLOR 0x2 //bit : 10 #define LED_AMBER_BICOLOR 0x1 //bit : 01 #define LED_OFF_BICOLOR 0x3 //bit : 11 - +#define LED_SW_LINK_UP 0x1 + unsigned short portmap[] = { 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 49, 50, 51, 52, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 24, 23, 22, 21, - 20, 19, 18, 17, 16, 15, 14, 13, + 20, 19, 18, 17, 16, 15, 14, 13, 60, 58, 59, 57, 62, 64, 61, 63 -}; +}; /* @@ -123,49 +134,59 @@ unsigned short portmap[] = { void custom_led_handler(soc_led_custom_handler_ctrl_t *ctrl, uint32 activity_count) { - unsigned short accu_val = 0, send_val = 0; - unsigned short port, physical_port; - + uint8 idx = 0; + uint16 accu_val = 0, send_val = 0; + uint16 uc_port = 0, physical_port = 0; + /* Physical port numbers to be used */ - for(port = 1; port <= PORT_NUM_TOTAL; port++) { + for(uc_port = 0; uc_port < PORT_NUM_TOTAL; uc_port++) { + + // change to zero-based + physical_port = portmap[uc_port] - 1; - physical_port = portmap[port-1]; - /* Read value from led_ram bank0 */ - accu_val = READ_LED_ACCU_DATA(ctrl->accu_ram_base, physical_port); + accu_val = LED_HW_RAM_READ16(ctrl->accu_ram_base, physical_port); - send_val = 0xff; - - if (((accu_val & LED_OUTPUT_RX) || (accu_val & LED_OUTPUT_TX)) && (activity_count & ACTIVITY_TICKS)) + send_val = LED_OFF_BICOLOR; + + if (((accu_val & LED_HW_RX) || (accu_val & LED_HW_TX)) && (activity_count & ACTIVITY_TICKS)) { send_val = LED_OFF_BICOLOR; } - else if ( accu_val & LED_OUTPUT_LINK_UP) + else if (ctrl->led_control_data[physical_port] & LED_SW_LINK_UP) { send_val = LED_GREEN_BICOLOR; } else { send_val = LED_OFF_BICOLOR; - } - + } + /* Write value to led_ram bank1 */ - WRITE_LED_SEND_DATA(ctrl->pat_ram_base, port, send_val); + LED_HW_RAM_WRITE16(ctrl->pat_ram_base, uc_port, send_val); } /* for */ - /* Send the pattern over LED interface 1 for ports 1 - 56*/ - ctrl->intf_ctrl[1].valid = 1; - ctrl->intf_ctrl[1].start_row = 0; - ctrl->intf_ctrl[1].end_row = 55; - ctrl->intf_ctrl[1].pat_width = 2; - - /* Invalidate rest of the interfaces */ - ctrl->intf_ctrl[0].valid = 0; - ctrl->intf_ctrl[2].valid = 0; - ctrl->intf_ctrl[3].valid = 0; - ctrl->intf_ctrl[4].valid = 0; + /* Configure LED HW interfaces based on board configuration */ + for (idx = 0; idx < LED_HW_INTF_MAX_NUM; idx++) { + soc_led_intf_ctrl_t *lic = &ctrl->intf_ctrl[idx]; + switch (idx) { + case 0: + lic->valid = 0; + break; + case 1: + lic->valid = 1; + lic->start_row = 0; + lic->end_row = 55; + lic->pat_width = 2; + break; + default: + + /* Invalidate rest of the interfaces */ + lic->valid = 0; + break; + } + } return; } - diff --git a/device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/custom_led.lds b/device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/custom_led.lds similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/led-source-code/cmicx/custom_led.lds rename to device/celestica/x86_64-cel_ds1000-r0/led-source-code/cmicx/custom_led.lds diff --git a/device/celestica/x86_64-cel_ds1000-r0/led_proc_init.soc b/device/celestica/x86_64-cel_ds1000-r0/led_proc_init.soc new file mode 100644 index 000000000000..7bd004f12b82 --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/led_proc_init.soc @@ -0,0 +1,5 @@ +linkscan off +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +sleep 3 +led auto on; led start +linkscan on diff --git a/device/celestica/x86_64-cel_belgite-r0/media_settings.json b/device/celestica/x86_64-cel_ds1000-r0/media_settings.json similarity index 99% rename from device/celestica/x86_64-cel_belgite-r0/media_settings.json rename to device/celestica/x86_64-cel_ds1000-r0/media_settings.json index 50f7c545f09e..fc52c39c7a60 100644 --- a/device/celestica/x86_64-cel_belgite-r0/media_settings.json +++ b/device/celestica/x86_64-cel_ds1000-r0/media_settings.json @@ -46,4 +46,3 @@ } } } - diff --git a/device/celestica/x86_64-cel_belgite-r0/pcie.yaml b/device/celestica/x86_64-cel_ds1000-r0/pcie.yaml similarity index 56% rename from device/celestica/x86_64-cel_belgite-r0/pcie.yaml rename to device/celestica/x86_64-cel_ds1000-r0/pcie.yaml index 46e202526716..47e5ecbead8f 100644 --- a/device/celestica/x86_64-cel_belgite-r0/pcie.yaml +++ b/device/celestica/x86_64-cel_ds1000-r0/pcie.yaml @@ -1,121 +1,143 @@ - bus: '00' dev: '00' fn: '0' - id: 1980 - name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent' + id: '1980' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev + 11)' - bus: '00' dev: '04' fn: '0' id: 19a1 - name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers + (rev 11)' - bus: '00' dev: '05' fn: '0' id: 19a2 - name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 Series Root Complex Event Collector' + name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 + Series Root Complex Event Collector (rev 11)' - bus: '00' dev: '06' fn: '0' - id: 19e2 - name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT Root Port' + id: 19a3 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT + Root Port (rev 11)' - bus: '00' - dev: '09' + dev: 09 fn: '0' - id: b277 - name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root Port' + id: 19a4 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #0 (rev 11)' - bus: '00' - dev: '0b' + dev: 0b fn: '0' - id: 1533 - name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root Port' + id: 19a6 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #2 (rev 11)' - bus: '00' - dev: '0e' + dev: 0e fn: '0' id: 19a8 - name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root Port' + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #4 (rev 11)' - bus: '00' dev: '12' fn: '0' id: 19ac - name: 'System peripheral: Intel Corporation DNV SMBus Contoller - Host' + name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller + - Host (rev 11)' - bus: '00' dev: '14' fn: '0' id: 19c2 - name: 'SATA controller: Intel Corporation DNV SATA Controller 1' + name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller + 1 (rev 11)' - bus: '00' dev: '15' fn: '0' id: 19d0 - name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI Controller' + name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI + Controller (rev 11)' - bus: '00' dev: '16' fn: '0' - id: 15ce - name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN Root Port' + id: 19d1 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #0 (rev 11)' - bus: '00' dev: '18' fn: '0' id: 19d3 - name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME HECI 1' + name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME + HECI 1 (rev 11)' - bus: '00' - dev: '1a' + dev: 1a fn: '0' id: 19d8 - name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller' + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' - bus: '00' - dev: '1a' + dev: 1a fn: '1' id: 19d8 - name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller' + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' - bus: '00' - dev: '1a' + dev: 1a fn: '2' id: 19d8 - name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller' + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' - bus: '00' - dev: '1f' + dev: 1f fn: '0' id: 19dc - name: 'ISA bridge: Intel Corporation DNV LPC or eSPI' + name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev + 11)' - bus: '00' - dev: '1f' + dev: 1f fn: '2' id: 19de - name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management Controller' + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management + Controller (rev 11)' - bus: '00' - dev: '1f' + dev: 1f fn: '4' id: 19df - name: 'SMBus: Intel Corporation DNV SMBus controller' + name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev + 11)' - bus: '00' - dev: '1f' + dev: 1f fn: '5' id: 19e0 - name: 'Serial bus controller [0c80]: Intel Corporation DNV SPI Controller' + name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series + SPI Controller (rev 11)' - bus: '01' dev: '00' fn: '0' id: 19e2 - name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology' + name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology + (rev 11)' - bus: '02' dev: '00' fn: '0' id: b277 - name: 'Ethernet controller: Broadcom Limited Device b277' + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b277 (rev 02)' - bus: '03' dev: '00' fn: '0' - id: 1533 - name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' - bus: '05' dev: '00' fn: '0' - id: 15ce - name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 10 GbE SFP+' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' - bus: '05' dev: '00' fn: '1' - id: 15ce - name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 10 GbE SFP+' - + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' diff --git a/device/celestica/x86_64-cel_belgite-r0/pddf/pd-plugin.json b/device/celestica/x86_64-cel_ds1000-r0/pddf/pd-plugin.json similarity index 84% rename from device/celestica/x86_64-cel_belgite-r0/pddf/pd-plugin.json rename to device/celestica/x86_64-cel_ds1000-r0/pddf/pd-plugin.json index 454afd239964..f0ce24dc6524 100644 --- a/device/celestica/x86_64-cel_belgite-r0/pddf/pd-plugin.json +++ b/device/celestica/x86_64-cel_ds1000-r0/pddf/pd-plugin.json @@ -11,14 +11,14 @@ }, "PSU": { - "psu_present": + "psu_present": { "i2c": { "valmap": { "1":true, "0":false } } }, - "psu_power_good": + "psu_power_good": { "i2c": { @@ -29,7 +29,7 @@ { "i2c": { - "valmap": { "0":"INTAKE", "1":"EXHAUST" } + "valmap": { "0":"intake", "1":"exhaust" } } }, "PSU_FAN_MAX_SPEED":"18000" @@ -40,7 +40,7 @@ { "i2c": { - "valmap": {"1":"EXHAUST", "0":"INTAKE"} + "valmap": {"1":"exhaust", "0":"intake"} } }, "present": diff --git a/device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json b/device/celestica/x86_64-cel_ds1000-r0/pddf/pddf-device.json similarity index 87% rename from device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json rename to device/celestica/x86_64-cel_ds1000-r0/pddf/pddf-device.json index a97102c1f4cb..02293634e7f7 100644 --- a/device/celestica/x86_64-cel_belgite-r0/pddf/pddf-device.json +++ b/device/celestica/x86_64-cel_ds1000-r0/pddf/pddf-device.json @@ -1,685 +1,682 @@ -{ - "PLATFORM": - { - "num_psus":2, - "num_fantrays":3, - "num_fans_pertray":1, - "num_ports":56, - "num_temps":4, - "pddf_dev_types": - { - "description":"Belgite - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", - "CPLD": - [ - "i2c_cpld" - ], - "PSU": - [ - "psu_eeprom", - "psu_pmbus" - ], - "FAN": - [ - "fan_ctrl", - "fan_eeprom", - "fan_cpld" - ], - "PORT_MODULE": - [ - "pddf_xcvr" - ] - }, - "std_perm_kos": - [ - "i2c-ismt", - "i2c-i801" - ], - "std_kos": - [ - "i2c_dev", - "i2c_mux_pca954x force_deselect_on_exit=1", - "gpio_pca953x", - "mc24lc64t", - "optoe" - ], - "pddf_kos": - [ - "pddf_client_module", - "pddf_mux_module", - "pddf_psu_driver_module", - "pddf_psu_module", - "pddf_gpio_module", - "pddf_xcvr_module", - "pddf_xcvr_driver_module", - "pddf_led_module", - "pddf_fan_driver_module", - "pddf_fan_module", - "pddf_led_module" - ], - "custom_kos": - [ - "pddf_custom_psu", - "pddf_custom_wdt" - ] - }, - "SYSTEM": - { - "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, - "i2c": - { - "CONTROLLERS": - [ - { "dev_name":"i2c-0", "dev":"SMBUS0" } - ] - } - }, - "SMBUS0": - { - "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, - "i2c": - { - "topo_info": {"dev_addr": "0x0"}, - "DEVICES": - [ - {"dev": "EEPROM1"}, - {"dev": "MUX1"} - ] - } - }, - "EEPROM1": - { - "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, - "i2c": - { - "topo_info": {"parent_bus": "0x0", "dev_addr": "0x52", "dev_type": "24lc64t"}, - "dev_attr": {"access_mode": "BLOCK"}, - "attr_list": - [ - {"attr_name": "eeprom"} - ] - } - }, - "MUX1": - { - "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"SMBUS0"}, - "i2c": - { - "topo_info": { "parent_bus":"0x0", "dev_addr":"0x70", "dev_type":"pca9548"}, - "dev_attr": { "virt_bus":"0x2"}, - "channel": - [ - {"chn":"0", "dev":"CPLD1" }, - {"chn":"0", "dev":"FAN-CTRL" }, - {"chn":"2", "dev":"PSU1" }, - {"chn":"2", "dev":"PSU2" }, - {"chn":"3", "dev":"TEMP1"}, - {"chn":"3", "dev":"TEMP2"}, - {"chn":"4", "dev":"TEMP3"}, - {"chn":"4", "dev":"TEMP4"}, - {"chn":"7", "dev":"MUX2"} - ] - } - }, - "MUX2": - { - "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"MUX1"}, - "i2c": - { - "topo_info": { "parent_bus":"0x9", "dev_addr":"0x71", "dev_type":"pca9548"}, - "dev_attr": { "virt_bus":"0xA"}, - "channel": - [ - {"chn":"0", "dev":"PORT49"}, - {"chn":"1", "dev":"PORT50"}, - {"chn":"2", "dev":"PORT51"}, - {"chn":"3", "dev":"PORT52"}, - {"chn":"4", "dev":"PORT53"}, - {"chn":"5", "dev":"PORT54"}, - {"chn":"6", "dev":"PORT55"}, - {"chn":"7", "dev":"PORT56"} - ] - } - }, - "CPLD1": - { - "dev_info": {"device_type": "CPLD", "device_name": "CPLD1", "device_parent": "MUX1"}, - "i2c": - { - "topo_info": {"parent_bus": "0x2", "dev_addr": "0x32", "dev_type": "i2c_cpld"}, - "dev_attr": {} - } - }, - "PSU1": - { - "dev_info": { "device_type":"PSU", "device_name":"PSU1", "device_parent":"MUX1"}, - "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, - "i2c": - { - "interface": - [ - { "itf":"pmbus", "dev":"PSU1-PMBUS" } - ] - } - }, - "PSU1-PMBUS": - { - "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU1-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU1"}, - "i2c": - { - "topo_info":{ "parent_bus":"0x4", "dev_addr":"0x58", "dev_type":"psu_pmbus"}, - "attr_list": - [ - { "attr_name":"psu_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x10", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_power_good", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_model_name", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13" }, - { "attr_name":"psu_mfr_id", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"11" }, - { "attr_name":"psu_serial_num", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"14" }, - { "attr_name":"psu_v_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_v_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_fan_dir", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x80", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"1"}, - { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} - ] - } - }, - "PSU2": - { - "dev_info": { "device_type":"PSU", "device_name":"PSU2", "device_parent":"MUX1" }, - "dev_attr": { "dev_idx":"2", "num_psu_fans":"1"}, - "i2c": - { - "interface": - [ - { "itf":"pmbus", "dev":"PSU2-PMBUS"} - ] - } - }, - "PSU2-PMBUS": - { - "dev_info": {"device_type":"PSU-PMBUS", "device_name":"PSU2-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU2"}, - "i2c": - { - "topo_info": { "parent_bus":"0x4", "dev_addr":"0x59", "dev_type":"psu_pmbus"}, - "attr_list": - [ - { "attr_name":"psu_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x20", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_power_good", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x8", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"psu_model_name", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13" }, - { "attr_name":"psu_mfr_id", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"11" }, - { "attr_name":"psu_serial_num", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"14" }, - { "attr_name":"psu_v_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_v_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_fan_dir", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x80", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"1"}, - { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} - ] - } - }, - "TEMP1": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U10"}, - "i2c": - { - "topo_info": { "parent_bus":"0x5", "dev_addr":"0x48", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "TEMP2": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U4"}, - "i2c": - { - "topo_info": { "parent_bus":"0x5", "dev_addr":"0x49", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "TEMP3": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U7"}, - "i2c": - { - "topo_info": { "parent_bus":"0x6", "dev_addr":"0x4a", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "TEMP4": - { - "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"MUX1"}, - "dev_attr": { "display_name":"LM75_U60"}, - "i2c": - { - "topo_info": { "parent_bus":"0x6", "dev_addr":"0x49", "dev_type":"lm75"}, - "attr_list": - [ - { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, - { "attr_name": "temp1_max_hyst"}, - { "attr_name": "temp1_input"} - ] - } - }, - "PORT49": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT49", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"49"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT49-EEPROM" }, - { "itf":"control", "dev":"PORT49-CTRL" } - ] - } - }, - "PORT49-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT49-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT49"}, - "i2c": - { - "topo_info": { "parent_bus":"0xA", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT49-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT49-CTRL", "device_parent":"MUX2", "virt_parent":"PORT49"}, - "i2c": - { - "topo_info": { "parent_bus":"0xA", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"} - ] - } - }, - "PORT50": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT50", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"50"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT50-EEPROM" }, - { "itf":"control", "dev":"PORT50-CTRL" } - ] - } - }, - "PORT50-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT50-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT50"}, - "i2c": - { - "topo_info": { "parent_bus":"0xB", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT50-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT50-CTRL", "device_parent":"MUX2", "virt_parent":"PORT50"}, - "i2c": - { - "topo_info": { "parent_bus":"0xB", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"} - - ] - } - }, - "PORT51": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT51", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"51"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT51-EEPROM" }, - { "itf":"control", "dev":"PORT51-CTRL" } - ] - } - }, - "PORT51-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT51-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT51"}, - "i2c": - { - "topo_info": { "parent_bus":"0xC", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT51-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT51-CTRL", "device_parent":"MUX2", "virt_parent":"PORT51"}, - "i2c": - { - "topo_info": { "parent_bus":"0xC", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"} - ] - } - }, - "PORT52": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT52", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"52"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT52-EEPROM" }, - { "itf":"control", "dev":"PORT52-CTRL" } - ] - } - }, - "PORT52-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT52-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT52"}, - "i2c": - { - "topo_info": { "parent_bus":"0xD", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT52-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT52-CTRL", "device_parent":"MUX2", "virt_parent":"PORT52"}, - "i2c": - { - "topo_info": { "parent_bus":"0xD", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"} - - ] - } - }, - "PORT53": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT53", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"53"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT53-EEPROM" }, - { "itf":"control", "dev":"PORT53-CTRL" } - ] - } - }, - "PORT53-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT53-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT53"}, - "i2c": - { - "topo_info": { "parent_bus":"0xE", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT53-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT53-CTRL", "device_parent":"MUX2", "virt_parent":"PORT53"}, - "i2c": - { - "topo_info": { "parent_bus":"0xE", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} - - ] - } - }, - "PORT54": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT54", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"54"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT54-EEPROM" }, - { "itf":"control", "dev":"PORT54-CTRL" } - ] - } - }, - "PORT54-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT54-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT54"}, - "i2c": - { - "topo_info": { "parent_bus":"0xF", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT54-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT54-CTRL", "device_parent":"MUX2", "virt_parent":"PORT54"}, - "i2c": - { - "topo_info": { "parent_bus":"0xF", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"} - ] - } - }, - "PORT55": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT55", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"55"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT55-EEPROM" }, - { "itf":"control", "dev":"PORT55-CTRL" } - ] - } - }, - "PORT55-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT55-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT55"}, - "i2c": - { - "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT55-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT55-CTRL", "device_parent":"MUX2", "virt_parent":"PORT55"}, - "i2c": - { - "topo_info": { "parent_bus":"0x10", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} - ] - } - }, - "PORT56": - { - "dev_info": { "device_type":"SFP+", "device_name":"PORT56", "device_parent":"MUX2"}, - "dev_attr": { "dev_idx":"56"}, - "i2c": - { - "interface": - [ - { "itf":"eeprom", "dev":"PORT56-EEPROM" }, - { "itf":"control", "dev":"PORT56-CTRL" } - ] - } - }, - "PORT56-EEPROM": - { - "dev_info": { "device_type":"", "device_name":"PORT56-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT56"}, - "i2c": - { - "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe2"}, - "attr_list": - [ - { "attr_name":"eeprom"} - ] - } - }, - "PORT56-CTRL": - { - "dev_info": { "device_type":"", "device_name":"PORT56-CTRL", "device_parent":"MUX2", "virt_parent":"PORT56"}, - "i2c": - { - "topo_info": { "parent_bus":"0x11", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, - "attr_list": - [ - { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, - { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"} - ] - } - }, - "FAN-CTRL": - { - "dev_info": { "device_type":"FAN", "device_name":"FAN-CTRL", "device_parent":"MUX1"}, - "i2c": - { - "topo_info": { "parent_bus":"0x2", "dev_addr":"0x66", "dev_type":"fan_cpld"}, - "dev_attr": { "num_fantrays":"3"}, - "attr_list": - [ - { "attr_name":"fan1_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x32", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan2_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x36", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan3_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x3a", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan1_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan2_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan3_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x1", "attr_cmpval":"0x0", "attr_len":"1"}, - { "attr_name":"fan1_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x31", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, - { "attr_name":"fan2_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x35", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150" , "attr_is_divisor":0}, - { "attr_name":"fan3_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x39", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0} - ] - } - }, - "SYS_LED": - { - "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, - "dev_attr": { "index":"0"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"STATUS_LED_COLOR_AMBER","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x1","swpld_addr_offset":"0x43"}, - {"attr_name":"STATUS_LED_COLOR_GREEN","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x2","swpld_addr_offset":"0x43"}, - {"attr_name":"STATUS_LED_COLOR_OFF","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x3","swpld_addr_offset":"0x43"} - ] - } - }, - "FANTRAY1_LED": - { - "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, - "dev_attr": { "index":"0"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"STATUS_LED_COLOR_GREEN","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x33"}, - {"attr_name":"STATUS_LED_COLOR_AMBER","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x33"} - ] - } - }, - "FANTRAY2_LED": - { - "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, - "dev_attr": { "index":"1"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"STATUS_LED_COLOR_GREEN","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x37"}, - {"attr_name":"STATUS_LED_COLOR_AMBER","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x37"} - ] - } - }, - "FANTRAY3_LED": - { - "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, - "dev_attr": { "index":"2"}, - "i2c" : { - "attr_list": - [ - {"attr_name":"STATUS_LED_COLOR_GREEN","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x3b"}, - {"attr_name":"STATUS_LED_COLOR_AMBER","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x3b"} - ] - } - } -} +{ + "PLATFORM": + { + "num_psus":2, + "num_fantrays":3, + "num_fans_pertray":1, + "num_ports":56, + "num_temps":4, + "pddf_dev_types": + { + "description":"DS1000 - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld" + ], + "PSU": + [ + "psu_eeprom", + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl", + "fan_eeprom", + "fan_cpld" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ] + }, + "std_perm_kos": + [ + "i2c-ismt", + "i2c-i801" + ], + "std_kos": + [ + "i2c_dev", + "i2c_mux_pca954x force_deselect_on_exit=1", + "gpio_pca953x", + "mc24lc64t", + "optoe" + ], + "pddf_kos": + [ + "pddf_client_module", + "pddf_mux_module", + "pddf_psu_driver_module", + "pddf_psu_module", + "pddf_gpio_module", + "pddf_xcvr_module", + "pddf_xcvr_driver_module", + "pddf_led_module", + "pddf_fan_driver_module", + "pddf_fan_module", + "pddf_led_module" + ], + "custom_kos": + [ + "pddf_custom_psu", + "pddf_custom_wdt" + ] + }, + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + { "dev_name":"i2c-0", "dev":"SMBUS0" } + ] + } + }, + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"}, + {"dev": "MUX1"} + ] + } + }, + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x52", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": + [ + {"attr_name": "eeprom"} + ] + } + }, + "MUX1": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"SMBUS0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x0", "dev_addr":"0x70", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2"}, + "channel": + [ + {"chn":"0", "dev":"CPLD1" }, + {"chn":"0", "dev":"FAN-CTRL" }, + {"chn":"2", "dev":"PSU1" }, + {"chn":"2", "dev":"PSU2" }, + {"chn":"3", "dev":"TEMP1"}, + {"chn":"3", "dev":"TEMP2"}, + {"chn":"4", "dev":"TEMP3"}, + {"chn":"4", "dev":"TEMP4"}, + {"chn":"7", "dev":"MUX2"} + ] + } + }, + "MUX2": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"MUX1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x71", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0xA"}, + "channel": + [ + {"chn":"0", "dev":"PORT49"}, + {"chn":"1", "dev":"PORT50"}, + {"chn":"2", "dev":"PORT51"}, + {"chn":"3", "dev":"PORT52"}, + {"chn":"4", "dev":"PORT53"}, + {"chn":"5", "dev":"PORT54"}, + {"chn":"6", "dev":"PORT55"}, + {"chn":"7", "dev":"PORT56"} + ] + } + }, + "CPLD1": + { + "dev_info": {"device_type": "CPLD", "device_name": "CPLD1", "device_parent": "MUX1"}, + "i2c": + { + "topo_info": {"parent_bus": "0x2", "dev_addr": "0x32", "dev_type": "i2c_cpld"}, + "dev_attr": {} + } + }, + "PSU1": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU 1", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + { "itf":"pmbus", "dev":"PSU1-PMBUS" } + ] + } + }, + "PSU1-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU1-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU1"}, + "i2c": + { + "topo_info":{ "parent_bus":"0x4", "dev_addr":"0x58", "dev_type":"psu_pmbus"}, + "attr_list": + [ + { "attr_name":"psu_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x10", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"psu_power_good", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"psu_model_name", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13" }, + { "attr_name":"psu_mfr_id", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"11" }, + { "attr_name":"psu_serial_num", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"14" }, + { "attr_name":"psu_v_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_i_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_fan_dir", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x80", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"1"}, + { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + "PSU2": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU 2", "device_parent":"MUX1" }, + "dev_attr": { "dev_idx":"2", "num_psu_fans":"1"}, + "i2c": + { + "interface": + [ + { "itf":"pmbus", "dev":"PSU2-PMBUS"} + ] + } + }, + "PSU2-PMBUS": + { + "dev_info": {"device_type":"PSU-PMBUS", "device_name":"PSU2-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x59", "dev_type":"psu_pmbus"}, + "attr_list": + [ + { "attr_name":"psu_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x20", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"psu_power_good", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x41", "attr_mask":"0x8", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"psu_model_name", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13" }, + { "attr_name":"psu_mfr_id", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"11" }, + { "attr_name":"psu_serial_num", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"14" }, + { "attr_name":"psu_v_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_i_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_fan_dir", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x80", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"1"}, + { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + "TEMP1": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"MUX1"}, + "dev_attr": { "display_name":"Front Left Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x48", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP2": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"MUX1"}, + "dev_attr": { "display_name":"Front Right Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x49", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP3": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"MUX1"}, + "dev_attr": { "display_name":"Rear Right Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x4a", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP4": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"MUX1"}, + "dev_attr": { "display_name":"ASIC External Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x49", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "PORT49": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT49", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"49"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT49-EEPROM" }, + { "itf":"control", "dev":"PORT49-CTRL" } + ] + } + }, + "PORT49-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT49-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT49"}, + "i2c": + { + "topo_info": { "parent_bus":"0xA", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT49-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT49-CTRL", "device_parent":"MUX2", "virt_parent":"PORT49"}, + "i2c": + { + "topo_info": { "parent_bus":"0xA", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"} + ] + } + }, + "PORT50": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT50", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"50"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT50-EEPROM" }, + { "itf":"control", "dev":"PORT50-CTRL" } + ] + } + }, + "PORT50-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT50-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT50"}, + "i2c": + { + "topo_info": { "parent_bus":"0xB", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT50-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT50-CTRL", "device_parent":"MUX2", "virt_parent":"PORT50"}, + "i2c": + { + "topo_info": { "parent_bus":"0xB", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"} + ] + } + }, + "PORT51": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT51", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"51"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT51-EEPROM" }, + { "itf":"control", "dev":"PORT51-CTRL" } + ] + } + }, + "PORT51-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT51-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT51"}, + "i2c": + { + "topo_info": { "parent_bus":"0xC", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT51-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT51-CTRL", "device_parent":"MUX2", "virt_parent":"PORT51"}, + "i2c": + { + "topo_info": { "parent_bus":"0xC", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"} + ] + } + }, + "PORT52": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT52", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"52"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT52-EEPROM" }, + { "itf":"control", "dev":"PORT52-CTRL" } + ] + } + }, + "PORT52-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT52-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT52"}, + "i2c": + { + "topo_info": { "parent_bus":"0xD", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT52-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT52-CTRL", "device_parent":"MUX2", "virt_parent":"PORT52"}, + "i2c": + { + "topo_info": { "parent_bus":"0xD", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x3", "attr_cmpval":"0x8", "attr_len":"1"} + ] + } + }, + "PORT53": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT53", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"53"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT53-EEPROM" }, + { "itf":"control", "dev":"PORT53-CTRL" } + ] + } + }, + "PORT53-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT53-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT53"}, + "i2c": + { + "topo_info": { "parent_bus":"0xE", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT53-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT53-CTRL", "device_parent":"MUX2", "virt_parent":"PORT53"}, + "i2c": + { + "topo_info": { "parent_bus":"0xE", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + "PORT54": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT54", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"54"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT54-EEPROM" }, + { "itf":"control", "dev":"PORT54-CTRL" } + ] + } + }, + "PORT54-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT54-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT54"}, + "i2c": + { + "topo_info": { "parent_bus":"0xF", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT54-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT54-CTRL", "device_parent":"MUX2", "virt_parent":"PORT54"}, + "i2c": + { + "topo_info": { "parent_bus":"0xF", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x5", "attr_cmpval":"0x20", "attr_len":"1"} + ] + } + }, + "PORT55": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT55", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"55"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT55-EEPROM" }, + { "itf":"control", "dev":"PORT55-CTRL" } + ] + } + }, + "PORT55-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT55-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT55"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT55-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT55-CTRL", "device_parent":"MUX2", "virt_parent":"PORT55"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + "PORT56": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT56", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"56"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT56-EEPROM" }, + { "itf":"control", "dev":"PORT56-CTRL" } + ] + } + }, + "PORT56-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT56-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT56-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT56-CTRL", "device_parent":"MUX2", "virt_parent":"PORT56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x47", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x4a", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, + { "attr_name":"xcvr_present", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x49", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x48", "attr_mask":"0x7", "attr_cmpval":"0x80", "attr_len":"1"} + ] + } + }, + "FAN-CTRL": + { + "dev_info": { "device_type":"FAN", "device_name":"FAN-CTRL", "device_parent":"MUX1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x66", "dev_type":"fan_cpld"}, + "dev_attr": { "num_fantrays":"3"}, + "attr_list": + [ + { "attr_name":"fan1_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x32", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan2_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x36", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan3_pwm", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x3a", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan1_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan2_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan3_direction", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x88", "attr_mask":"0x1", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan1_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x31", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + { "attr_name":"fan2_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x35", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150" , "attr_is_divisor":0}, + { "attr_name":"fan3_input", "attr_devaddr":"0x32", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x39", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0} + ] + } + }, + "SYS_LED": + { + "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, + "dev_attr": { "index":"0"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"amber","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x1","swpld_addr_offset":"0x43"}, + {"attr_name":"green","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x2","swpld_addr_offset":"0x43"}, + {"attr_name":"off","swpld_addr":"0x32","attr_devtype":"cpld","attr_devname":"CPLD1", "bits":"5:4","descr":"","value":"0x3","swpld_addr_offset":"0x43"} + ] + } + }, + "FANTRAY1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"0"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x33"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x33"} + ] + } + }, + "FANTRAY2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"1"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x37"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x37"} + ] + } + }, + "FANTRAY3_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"2"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x1","swpld_addr":"0x32","swpld_addr_offset":"0x3b"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD1","bits":"1:0","descr":"","value":"0x2","swpld_addr":"0x32","swpld_addr_offset":"0x3b"} + ] + } + } +} diff --git a/device/celestica/x86_64-cel_belgite-r0/pddf_support b/device/celestica/x86_64-cel_ds1000-r0/pddf_support similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/pddf_support rename to device/celestica/x86_64-cel_ds1000-r0/pddf_support diff --git a/device/celestica/x86_64-cel_belgite-r0/platform.json b/device/celestica/x86_64-cel_ds1000-r0/platform.json similarity index 62% rename from device/celestica/x86_64-cel_belgite-r0/platform.json rename to device/celestica/x86_64-cel_ds1000-r0/platform.json index 0e40fe8a88fa..79ae7f0bad87 100644 --- a/device/celestica/x86_64-cel_belgite-r0/platform.json +++ b/device/celestica/x86_64-cel_ds1000-r0/platform.json @@ -1,94 +1,70 @@ { "chassis": { - "name": "E1070", + "name": "DS1000", "status_led": { "controllable": true, "colors": ["green", "amber", "off"] }, - "thermal_manager": false, + "thermal_manager": false, "components": [ - { - "name": "SWCPLD" - }, - { - "name": "BIOS" - } - ], - "fans": [ { - "name": "Fantray1_1", - "speed": { - "controllable": true - }, - "status_led": { - "controllable": true, - "colors": ["green", "amber","off"] - } + "name": "CPLD SW" }, { - "name": "Fantray2_1", - "speed": { - "controllable": true - }, - "status_led": { - "controllable": true, - "colors": ["green", "amber","off"] - } + "name": "BIOS" }, { - "name": "Fantray3_1", - "speed": { - "controllable": true - }, - "status_led": { - "controllable": true, - "colors": ["green", "amber","off"] - } + "name": "ONIE" }, { - "name": "Fantray1_1", + "name": "SSD" + } + ], + "fans": [ + { + "name": "Fan 1", "speed": { "controllable": true }, "status_led": { "controllable": true, - "colors": ["green", "amber","off"] + "colors": ["green", "amber", "off"] } }, { - "name": "Fantray2_1", + "name": "Fan 2", "speed": { "controllable": true }, "status_led": { "controllable": true, - "colors": ["green", "amber","off"] + "colors": ["green", "amber", "off"] } }, { - "name": "Fantray3_1", + "name": "Fan 3", "speed": { "controllable": true }, "status_led": { "controllable": true, - "colors": ["green", "amber","off"] + "colors": ["green", "amber", "off"] } } ], "fan_drawers": [ { - "name": "Fantray1", + "name": "Drawer 1", "speed": { "controllable": false }, "status_led": { "controllable": false }, - "max_consumed_power": false, + "max_consumed_power": false, "fans": [ { - "name": "Fantray1_1", + "name": "Fan 1", "speed": { "controllable": false }, @@ -99,17 +75,17 @@ ] }, { - "name": "Fantray2", + "name": "Drawer 2", "speed": { "controllable": false }, "status_led": { "controllable": false }, - "max_consumed_power": false, + "max_consumed_power": false, "fans": [ { - "name": "Fantray2_1", + "name": "Fan 2", "speed": { "controllable": false }, @@ -120,17 +96,17 @@ ] }, { - "name": "Fantray3", + "name": "Drawer 3", "speed": { "controllable": false }, "status_led": { "controllable": false }, - "max_consumed_power": false, + "max_consumed_power": false, "fans": [ { - "name": "Fantray3_1", + "name": "Fan 3", "speed": { "controllable": false }, @@ -143,10 +119,10 @@ ], "psus": [ { - "name": "PSU1", + "name": "PSU 1", "fans": [ { - "name": "PSU1_FAN1", + "name": "PSU 1 Fan 1", "speed": { "controllable": false }, @@ -155,7 +131,7 @@ } } ], - "current": true, + "current": true, "power": true, "max_power": false, "voltage_high_threshold": false, @@ -167,10 +143,10 @@ } }, { - "name": "PSU2", + "name": "PSU 2", "fans": [ { - "name": "PSU2_FAN1", + "name": "PSU 2 Fan 1", "speed": { "controllable": false }, @@ -179,7 +155,7 @@ } } ], - "current": true, + "current": true, "power": true, "max_power": false, "voltage_high_threshold": false, @@ -193,175 +169,31 @@ ], "thermals": [ { - "name": "LM75_U10", + "name": "Front Left Temp", "controllable": false, "low-threshold": false, "low-crit-threshold": true }, { - "name": "LM75_U4", + "name": "Front Right Temp", "controllable": false, "low-threshold": false, "low-crit-threshold": true }, { - "name": "LM75_U7", + "name": "Rear Right Temp", "controllable": false, "low-threshold": false, "low-crit-threshold": true }, { - "name": "LM75_U60", + "name": "ASIC External Temp", "controllable": false, "low-threshold": false, "low-crit-threshold": true } ], "sfps": [ - { - "name": "PORT0" - }, - { - "name": "PORT1" - }, - { - "name": "PORT2" - }, - { - "name": "PORT3" - }, - { - "name": "PORT4" - }, - { - "name": "PORT5" - }, - { - "name": "PORT6" - }, - { - "name": "PORT7" - }, - { - "name": "PORT8" - }, - { - "name": "PORT9" - }, - { - "name": "PORT10" - }, - { - "name": "PORT11" - }, - { - "name": "PORT12" - }, - { - "name": "PORT13" - }, - { - "name": "PORT14" - }, - { - "name": "PORT15" - }, - { - "name": "PORT16" - }, - { - "name": "PORT17" - }, - { - "name": "PORT18" - }, - { - "name": "PORT19" - }, - { - "name": "PORT20" - }, - { - "name": "PORT21" - }, - { - "name": "PORT22" - }, - { - "name": "PORT23" - }, - { - "name": "PORT24" - }, - { - "name": "PORT25" - }, - { - "name": "PORT26" - }, - { - "name": "PORT27" - }, - { - "name": "PORT28" - }, - { - "name": "PORT29" - }, - { - "name": "PORT30" - }, - { - "name": "PORT31" - }, - { - "name": "PORT32" - }, - { - "name": "PORT33" - }, - { - "name": "PORT34" - }, - { - "name": "PORT35" - }, - { - "name": "PORT36" - }, - { - "name": "PORT37" - }, - { - "name": "PORT38" - }, - { - "name": "PORT39" - }, - { - "name": "PORT40" - }, - { - "name": "PORT41" - }, - { - "name": "PORT42" - }, - { - "name": "PORT43" - }, - { - "name": "PORT44" - }, - { - "name": "PORT45" - }, - { - "name": "PORT46" - }, - { - "name": "PORT47" - }, { "name": "PORT48" }, @@ -393,392 +225,392 @@ "index": "1", "lanes": "26", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/1"] + "1x1000[100,10]": ["Eth1/1"] } }, "Ethernet1": { "index": "2", "lanes": "25", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/2"] + "1x1000[100,10]": ["Eth2/1"] } }, "Ethernet2": { "index": "3", "lanes": "28", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/3"] + "1x1000[100,10]": ["Eth3/1"] } }, "Ethernet3": { "index": "4", "lanes": "27", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/4"] + "1x1000[100,10]": ["Eth4/1"] } }, "Ethernet4": { "index": "5", "lanes": "30", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/5"] + "1x1000[100,10]": ["Eth5/1"] } }, "Ethernet5": { "index": "6", "lanes": "29", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/6"] + "1x1000[100,10]": ["Eth6/1"] } }, "Ethernet6": { "index": "7", "lanes": "32", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/7"] + "1x1000[100,10]": ["Eth7/1"] } }, "Ethernet7": { "index": "8", "lanes": "31", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/8"] + "1x1000[100,10]": ["Eth8/1"] } }, "Ethernet8": { "index": "9", "lanes": "34", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/9"] + "1x1000[100,10]": ["Eth9/1"] } }, "Ethernet9": { "index": "10", "lanes": "33", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/10"] + "1x1000[100,10]": ["Eth10/1"] } }, "Ethernet10": { "index": "11", "lanes": "36", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/11"] + "1x1000[100,10]": ["Eth11/1"] } }, "Ethernet11": { "index": "12", "lanes": "35", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/12"] + "1x1000[100,10]": ["Eth12/1"] } }, "Ethernet12": { "index": "13", "lanes": "38", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/13"] + "1x1000[100,10]": ["Eth13/1"] } }, "Ethernet13": { "index": "14", "lanes": "37", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/14"] + "1x1000[100,10]": ["Eth14/1"] } }, "Ethernet14": { "index": "15", "lanes": "40", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/15"] + "1x1000[100,10]": ["Eth15/1"] } }, "Ethernet15": { "index": "16", "lanes": "39", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/16"] + "1x1000[100,10]": ["Eth16/1"] } }, "Ethernet16": { "index": "17", "lanes": "42", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/17"] + "1x1000[100,10]": ["Eth17/1"] } }, "Ethernet17": { "index": "18", "lanes": "41", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/18"] + "1x1000[100,10]": ["Eth18/1"] } }, "Ethernet18": { "index": "19", "lanes": "44", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/19"] + "1x1000[100,10]": ["Eth19/1"] } }, "Ethernet19": { "index": "20", "lanes": "43", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/20"] + "1x1000[100,10]": ["Eth20/1"] } }, "Ethernet20": { "index": "21", "lanes": "50", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/21"] + "1x1000[100,10]": ["Eth21/1"] } }, "Ethernet21": { "index": "22", "lanes": "49", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/22"] + "1x1000[100,10]": ["Eth22/1"] } }, "Ethernet22": { "index": "23", "lanes": "52", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/23"] + "1x1000[100,10]": ["Eth23/1"] } }, "Ethernet23": { "index": "24", "lanes": "51", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/24"] + "1x1000[100,10]": ["Eth24/1"] } }, "Ethernet24": { "index": "25", "lanes": "2", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/25"] + "1x1000[100,10]": ["Eth25/1"] } }, "Ethernet25": { "index": "26", "lanes": "1", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/26"] + "1x1000[100,10]": ["Eth26/1"] } }, "Ethernet26": { "index": "27", "lanes": "4", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/27"] + "1x1000[100,10]": ["Eth27/1"] } }, "Ethernet27": { "index": "28", "lanes": "3", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/28"] + "1x1000[100,10]": ["Eth28/1"] } }, "Ethernet28": { "index": "29", "lanes": "6", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/29"] + "1x1000[100,10]": ["Eth29/1"] } }, "Ethernet29": { "index": "30", "lanes": "5", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/30"] + "1x1000[100,10]": ["Eth30/1"] } }, "Ethernet30": { "index": "31", "lanes": "8", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/31"] + "1x1000[100,10]": ["Eth31/1"] } }, "Ethernet31": { "index": "32", "lanes": "7", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/32"] + "1x1000[100,10]": ["Eth32/1"] } }, "Ethernet32": { "index": "33", "lanes": "10", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/33"] + "1x1000[100,10]": ["Eth33/1"] } }, "Ethernet33": { "index": "34", "lanes": "9", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/34"] + "1x1000[100,10]": ["Eth34/1"] } }, "Ethernet34": { "index": "35", "lanes": "12", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/35"] + "1x1000[100,10]": ["Eth35/1"] } }, "Ethernet35": { "index": "36", "lanes": "11", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/36"] + "1x1000[100,10]": ["Eth36/1"] } }, "Ethernet36": { "index": "37", "lanes": "14", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/37"] + "1x1000[100,10]": ["Eth37/1"] } }, "Ethernet37": { "index": "38", "lanes": "13", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/38"] + "1x1000[100,10]": ["Eth38/1"] } }, "Ethernet38": { "index": "39", "lanes": "16", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/39"] + "1x1000[100,10]": ["Eth39/1"] } }, "Ethernet39": { "index": "40", "lanes": "15", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/40"] + "1x1000[100,10]": ["Eth40/1"] } }, "Ethernet40": { "index": "41", "lanes": "18", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/41"] + "1x1000[100,10]": ["Eth41/1"] } }, "Ethernet41": { "index": "42", "lanes": "17", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/42"] + "1x1000[100,10]": ["Eth42/1"] } }, "Ethernet42": { "index": "43", "lanes": "20", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/43"] + "1x1000[100,10]": ["Eth43/1"] } }, "Ethernet43": { "index": "44", "lanes": "19", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/44"] + "1x1000[100,10]": ["Eth44/1"] } }, "Ethernet44": { "index": "45", "lanes": "22", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/45"] + "1x1000[100,10]": ["Eth45/1"] } }, "Ethernet45": { "index": "46", "lanes": "21", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/46"] + "1x1000[100,10]": ["Eth46/1"] } }, "Ethernet46": { "index": "47", "lanes": "24", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/47"] + "1x1000[100,10]": ["Eth47/1"] } }, "Ethernet47": { "index": "48", "lanes": "23", "breakout_modes": { - "1x1000[100,10]": ["Ethernet1/0/48"] + "1x1000[100,10]": ["Eth48/1"] } }, "Ethernet48": { "index": "49", "lanes": "60", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/49"] + "1x10G[1G]": ["Eth49/1"] } }, "Ethernet49": { "index": "50", "lanes": "58", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/50"] + "1x10G[1G]": ["Eth50/1"] } }, "Ethernet50": { "index": "51", "lanes": "59", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/51"] + "1x10G[1G]": ["Eth51/1"] } }, "Ethernet51": { "index": "52", "lanes": "57", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/52"] + "1x10G[1G]": ["Eth52/1"] } }, "Ethernet52": { "index": "53", "lanes": "62", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/53"] + "1x10G[1G]": ["Eth53/1"] } }, "Ethernet53": { "index": "54", "lanes": "64", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/54"] + "1x10G[1G]": ["Eth54/1"] } }, "Ethernet54": { "index": "55", "lanes": "61", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/55"] + "1x10G[1G]": ["Eth55/1"] } }, "Ethernet55": { "index": "56", "lanes": "63", "breakout_modes": { - "1x10G[1G]": ["Ethernet1/0/56"] + "1x10G[1G]": ["Eth56/1"] } } } diff --git a/device/celestica/x86_64-cel_belgite-r0/platform_asic b/device/celestica/x86_64-cel_ds1000-r0/platform_asic similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/platform_asic rename to device/celestica/x86_64-cel_ds1000-r0/platform_asic diff --git a/device/celestica/x86_64-cel_ds1000-r0/platform_components.json b/device/celestica/x86_64-cel_ds1000-r0/platform_components.json new file mode 100644 index 000000000000..deeabc3dee41 --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/platform_components.json @@ -0,0 +1,12 @@ +{ + "chassis": { + "DS1000": { + "component": { + "BIOS": {}, + "ONIE": {}, + "CPLD SW": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds1000-r0/platform_reboot b/device/celestica/x86_64-cel_ds1000-r0/platform_reboot new file mode 100755 index 000000000000..233af9d08514 --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/platform_reboot @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/local/bin/ds1000_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_belgite-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_ds1000-r0/plugins/eeprom.py similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/plugins/eeprom.py rename to device/celestica/x86_64-cel_ds1000-r0/plugins/eeprom.py diff --git a/device/celestica/x86_64-cel_belgite-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_ds1000-r0/plugins/psuutil.py similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/plugins/psuutil.py rename to device/celestica/x86_64-cel_ds1000-r0/plugins/psuutil.py diff --git a/device/celestica/x86_64-cel_belgite-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_ds1000-r0/plugins/sfputil.py similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/plugins/sfputil.py rename to device/celestica/x86_64-cel_ds1000-r0/plugins/sfputil.py diff --git a/device/celestica/x86_64-cel_belgite-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_ds1000-r0/pmon_daemon_control.json similarity index 100% rename from device/celestica/x86_64-cel_belgite-r0/pmon_daemon_control.json rename to device/celestica/x86_64-cel_ds1000-r0/pmon_daemon_control.json diff --git a/device/celestica/x86_64-cel_ds1000-r0/sensors.conf b/device/celestica/x86_64-cel_ds1000-r0/sensors.conf new file mode 100644 index 000000000000..aeb82af7eaf5 --- /dev/null +++ b/device/celestica/x86_64-cel_ds1000-r0/sensors.conf @@ -0,0 +1,45 @@ +# libsensors configuration file for Celestica DS1000 + +bus "i2c-6" "i2c-0-mux (chan_id 4)" +bus "i2c-4" "i2c-0-mux (chan_id 2)" +bus "i2c-2" "i2c-0-mux (chan_id 0)" +bus "i2c-5" "i2c-0-mux (chan_id 3)" + +chip "fan_cpld-i2c-2-66" + label fan1 "Fantray1_1 speed" + label fan2 "Fantray2_1 speed" + label fan3 "Fantray3_1 speed" + +chip "psu_pmbus-i2c-4-58" + label fan1 "PSU1 fan speed" + label in3 "PSU1 output voltage" + label temp1 "PSU1 temperature" + label power2 "PSU1 output power" + label curr2 "PSU1 output current" + +chip "psu_pmbus-i2c-4-59" + label fan1 "PSU2 fan speed" + label in3 "PSU2 output voltage" + label temp1 "PSU2 temperature" + label power2 "PSU2 output power" + label curr2 "PSU2 output current" + +chip "lm75-i2c-5-48" + label temp1 "Front Left Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "lm75-i2c-5-49" + label temp1 "Front Right Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "lm75-i2c-6-4a" + label temp1 "Rear Right Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "lm75-i2c-6-49" + set temp1_max 110 + set temp1_max_hyst 105 + label temp1 "ASIC External Temp" diff --git a/device/celestica/x86_64-cel_belgite-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_ds1000-r0/system_health_monitoring_config.json similarity index 86% rename from device/celestica/x86_64-cel_belgite-r0/system_health_monitoring_config.json rename to device/celestica/x86_64-cel_ds1000-r0/system_health_monitoring_config.json index 28b3e30a6699..6f7d70895afd 100644 --- a/device/celestica/x86_64-cel_belgite-r0/system_health_monitoring_config.json +++ b/device/celestica/x86_64-cel_ds1000-r0/system_health_monitoring_config.json @@ -3,8 +3,8 @@ "devices_to_ignore": [ "asic", "psu.temperature", - "PSU1_FAN1", - "PSU2_FAN1" + "PSU 1 Fan 1", + "PSU 2 Fan 1" ], "user_defined_checkers": [], "polling_interval": 60, diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers.json.j2 b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_def.j2 b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_def.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_def.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..44fcf21887a6 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t0.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t1.j2 b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..5fe9cabcfd34 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "196608", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "33004032", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "12766208", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"33004032" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/hwsku.json b/device/celestica/x86_64-cel_ds2000-r0/DS2000/hwsku.json new file mode 100644 index 000000000000..059666102d99 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/hwsku.json @@ -0,0 +1,284 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet1": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet2": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet3": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet5": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet6": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet7": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet9": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet10": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet11": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet13": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet14": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet15": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet17": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet18": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet19": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet21": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet22": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet23": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet25": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet26": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet27": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet29": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet30": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet31": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet33": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet34": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet35": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet37": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet38": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet39": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet41": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet42": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet43": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet45": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet46": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet47": { + "default_brkout_mode": "1x25G[10G]", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/l2/config b/device/celestica/x86_64-cel_ds2000-r0/DS2000/l2/config new file mode 100644 index 000000000000..1cc35f24ade0 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/l2/config @@ -0,0 +1,7 @@ +l2_mem_entries=229376 +l3_mem_entries=16384 +l3_alpm_enable=0 +fpem_mem_entries=32768 +sai_tunnel_support=1 +use_all_splithorizon_groups=1 +flow_init_mode=1 diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/l3/config b/device/celestica/x86_64-cel_ds2000-r0/DS2000/l3/config new file mode 100644 index 000000000000..fff0cf54b08a --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/l3/config @@ -0,0 +1,5 @@ +l2_mem_entries=40960 +l3_mem_entries=40960 +l3_alpm_enable=2 +use_all_splithorizon_groups=1 +sai_tunnel_support=1 diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/port_config.ini b/device/celestica/x86_64-cel_ds2000-r0/DS2000/port_config.ini new file mode 100644 index 000000000000..9b9c028ebaac --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed mtu admin_status fec +Ethernet0 29 Eth1/1 1 25000 9216 up rs +Ethernet1 30 Eth2/1 2 25000 9216 up rs +Ethernet2 31 Eth3/1 3 25000 9216 up rs +Ethernet3 32 Eth4/1 4 25000 9216 up rs +Ethernet4 33 Eth5/1 5 25000 9216 up rs +Ethernet5 34 Eth6/1 6 25000 9216 up rs +Ethernet6 35 Eth7/1 7 25000 9216 up rs +Ethernet7 36 Eth8/1 8 25000 9216 up rs +Ethernet8 37 Eth9/1 9 25000 9216 up rs +Ethernet9 38 Eth10/1 10 25000 9216 up rs +Ethernet10 39 Eth11/1 11 25000 9216 up rs +Ethernet11 40 Eth12/1 12 25000 9216 up rs +Ethernet12 49 Eth13/1 13 25000 9216 up rs +Ethernet13 50 Eth14/1 14 25000 9216 up rs +Ethernet14 51 Eth15/1 15 25000 9216 up rs +Ethernet15 52 Eth16/1 16 25000 9216 up rs +Ethernet16 53 Eth17/1 17 25000 9216 up rs +Ethernet17 54 Eth18/1 18 25000 9216 up rs +Ethernet18 55 Eth19/1 19 25000 9216 up rs +Ethernet19 56 Eth20/1 20 25000 9216 up rs +Ethernet20 57 Eth21/1 21 25000 9216 up rs +Ethernet21 58 Eth22/1 22 25000 9216 up rs +Ethernet22 59 Eth23/1 23 25000 9216 up rs +Ethernet23 60 Eth24/1 24 25000 9216 up rs +Ethernet24 9 Eth25/1 25 25000 9216 up rs +Ethernet25 10 Eth26/1 26 25000 9216 up rs +Ethernet26 11 Eth27/1 27 25000 9216 up rs +Ethernet27 12 Eth28/1 28 25000 9216 up rs +Ethernet28 13 Eth29/1 29 25000 9216 up rs +Ethernet29 14 Eth30/1 30 25000 9216 up rs +Ethernet30 15 Eth31/1 31 25000 9216 up rs +Ethernet31 16 Eth32/1 32 25000 9216 up rs +Ethernet32 17 Eth33/1 33 25000 9216 up rs +Ethernet33 18 Eth34/1 34 25000 9216 up rs +Ethernet34 19 Eth35/1 35 25000 9216 up rs +Ethernet35 20 Eth36/1 36 25000 9216 up rs +Ethernet36 61 Eth37/1 37 25000 9216 up rs +Ethernet37 62 Eth38/1 38 25000 9216 up rs +Ethernet38 63 Eth39/1 39 25000 9216 up rs +Ethernet39 64 Eth40/1 40 25000 9216 up rs +Ethernet40 65 Eth41/1 41 25000 9216 up rs +Ethernet41 66 Eth42/1 42 25000 9216 up rs +Ethernet42 67 Eth43/1 43 25000 9216 up rs +Ethernet43 68 Eth44/1 44 25000 9216 up rs +Ethernet44 69 Eth45/1 45 25000 9216 up rs +Ethernet45 70 Eth46/1 46 25000 9216 up rs +Ethernet46 71 Eth47/1 47 25000 9216 up rs +Ethernet47 72 Eth48/1 48 25000 9216 up rs +Ethernet48 41,42,43,44 Eth49/1 49 100000 9216 up rs +Ethernet52 45,46,47,48 Eth50/1 50 100000 9216 up rs +Ethernet56 73,74,75,76 Eth51/1 51 100000 9216 up rs +Ethernet60 77,78,79,80 Eth52/1 52 100000 9216 up rs +Ethernet64 1,2,3,4 Eth53/1 53 100000 9216 up rs +Ethernet68 21,22,23,24 Eth54/1 54 100000 9216 up rs +Ethernet72 5,6,7,8 Eth55/1 55 100000 9216 up rs +Ethernet76 25,26,27,28 Eth56/1 56 100000 9216 up rs diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/qos.json.j2 b/device/celestica/x86_64-cel_ds2000-r0/DS2000/qos.json.j2 new file mode 100644 index 000000000000..ee67c6e26221 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config_t1.j2' %} diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/qos_config_t1.j2 b/device/celestica/x86_64-cel_ds2000-r0/DS2000/qos_config_t1.j2 new file mode 100644 index 000000000000..5fe5324a85c1 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/qos_config_t1.j2 @@ -0,0 +1,175 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, +{% if asic_type in pfc_to_pg_map_supported_asics %} + "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{% endif %} + "PORT_QOS_MAP": { +{% for port in PORT_ACTIVE %} + "{{ port }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", +{% if asic_type in pfc_to_pg_map_supported_asics %} + "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP|AZURE]", +{% endif %} + "pfc_enable" : "3,4" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/sai.profile b/device/celestica/x86_64-cel_ds2000-r0/DS2000/sai.profile new file mode 100644 index 000000000000..6ca4984b91d3 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as13-48f8h-2a.config.bcm +SAI_LED_PORT_LOCATOR_FW_FILE=/usr/share/sonic/platform/port_locator.bin diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/sai_postinit_cmd.soc b/device/celestica/x86_64-cel_ds2000-r0/DS2000/sai_postinit_cmd.soc new file mode 100644 index 000000000000..731625308a5e --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/sai_postinit_cmd.soc @@ -0,0 +1,2 @@ +modreg ING_MISC_CONFIG INPUT_PRI_TAGGED=1 +modreg ING_MISC_CONFIG INPUT_PRI_UNTAGGED=1 diff --git a/device/celestica/x86_64-cel_ds2000-r0/DS2000/td3-as13-48f8h-2a.config.bcm b/device/celestica/x86_64-cel_ds2000-r0/DS2000/td3-as13-48f8h-2a.config.bcm new file mode 100644 index 000000000000..5abc527f9419 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/DS2000/td3-as13-48f8h-2a.config.bcm @@ -0,0 +1,461 @@ +#polarity/lanemap is using TH2 style. +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 + + +oversubscribe_mode=1 + +pbmp_xport_xe=0x1FFFFFFFFFFFFFFFE + +parity_enable=0 +mem_cache_enable=0 + +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +# Tunnel +sai_tunnel_support=1 +bcm_tunnel_term_compatible_mode=1 +use_all_splithorizon_groups=1 + +# RIOT Enable +riot_enable=1 +riot_overlay_l3_intf_mem_size=8192 +riot_overlay_l3_egress_mem_size=32768 +l3_ecmp_levels=2 +riot_overlay_ecmp_resilient_hash_size=16384 +flow_init_mode=1 + +# Platform specfic +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +help_cli_enable=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_alpm_enable=2 +l3_max_ecmp_mode=1 +max_vp_lags=0 +memlist_enable=1 +reglist_enable=1 +miim_intr_enable=0 +module_64ports=1 +port_flex_enable=1 +schan_intr_enable=0 +stable_size=0x5500000 ;Specify the stable cache size in bytes used for Warm boot operations +tdma_timeout_usec=3000000 +skip_L2_USER_ENTRY=0 +l3_alpm_ipv6_128b_bkt_rsvd=1 + + + +#FC0 +portmap_1=1:100 + +#FC1 +portmap_2=5:100 + +#FC2 +portmap_3=9:25 +portmap_4=10:25 +portmap_5=11:25 +portmap_6=12:25 + +#FC3 +portmap_7=13:25 +portmap_8=14:25 +portmap_9=15:25 +portmap_10=16:25 + +#FC4 +portmap_11=17:25 +portmap_12=18:25 +portmap_13=19:25 +portmap_14=20:25 + +#FC5 +portmap_15=21:100 + +#FC6 +portmap_16=25:100 + +#FC7 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_20=32:25 + +#FC8 +portmap_21=33:25 +portmap_22=34:25 +portmap_23=35:25 +portmap_24=36:25 + +#FC9 +portmap_25=37:25 +portmap_26=38:25 +portmap_27=39:25 +portmap_28=40:25 + +#FC10 +portmap_33=41:100 + +#FC11 +portmap_61=45:100 + +#FC12 +portmap_62=49:25 +portmap_63=50:25 +portmap_37=51:25 +portmap_38=52:25 + +#FC13 +portmap_39=53:25 +portmap_40=54:25 +portmap_41=55:25 +portmap_42=56:25 + +#FC14 +portmap_43=57:25 +portmap_44=58:25 +portmap_45=59:25 +portmap_46=60:25 + +#FC15 +portmap_47=61:25 +portmap_48=62:25 +portmap_49=63:25 +portmap_50=64:25 + +#FC16 +portmap_51=65:25 +portmap_52=66:25 +portmap_53=67:25 +portmap_54=68:25 + +#FC17 +portmap_55=69:25 +portmap_56=70:25 +portmap_57=71:25 +portmap_58=72:25 + +#FC18 +portmap_59=73:100 + +#FC19 +portmap_60=77:100 + + +#portmap_64=81:10 + +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{5.0}=0x1032 +phy_chain_rx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{9.0}=0x1032 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x1302 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{25.0}=0x3120 +phy_chain_rx_lane_map_physical{25.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x1302 +phy_chain_rx_lane_map_physical{41.0}=0x1023 +phy_chain_tx_lane_map_physical{45.0}=0x1032 +phy_chain_rx_lane_map_physical{45.0}=0x0213 +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{49.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{53.0}=0x2301 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x2301 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0132 +phy_chain_rx_lane_map_physical{77.0}=0x3012 +phy_chain_tx_lane_map_physical{81.0}=0x3210 +phy_chain_rx_lane_map_physical{81.0}=0x3201 + +#FC0 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +#FC1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +#FC2 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +#FC3 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 + +#FC4 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +#FC5 +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}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +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 + +#FC6 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 + +#FC7 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 + +#FC8 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +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}=0x1 + +#FC9 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 + +#FC10 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +#FC11 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 + +#FC12 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +#FC13 +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 + +#FC14 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +#FC15 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +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}=0x0 + +#FC16 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 + +#FC17 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +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}=0x1 + +#FC18 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 + +#FC19 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 + + +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x1 + +dport_map_port_29=1 +dport_map_port_30=2 +dport_map_port_31=3 +dport_map_port_20=4 +dport_map_port_21=5 +dport_map_port_22=6 +dport_map_port_23=7 +dport_map_port_24=8 +dport_map_port_25=9 +dport_map_port_26=10 +dport_map_port_27=11 +dport_map_port_28=12 +dport_map_port_62=13 +dport_map_port_63=14 +dport_map_port_37=15 +dport_map_port_38=16 +dport_map_port_39=17 +dport_map_port_40=18 +dport_map_port_41=19 +dport_map_port_42=20 +dport_map_port_43=21 +dport_map_port_44=22 +dport_map_port_45=23 +dport_map_port_46=24 +dport_map_port_3=25 +dport_map_port_4=26 +dport_map_port_5=27 +dport_map_port_6=28 +dport_map_port_7=29 +dport_map_port_8=30 +dport_map_port_9=31 +dport_map_port_10=32 +dport_map_port_11=33 +dport_map_port_12=34 +dport_map_port_13=35 +dport_map_port_14=36 +dport_map_port_47=37 +dport_map_port_48=38 +dport_map_port_49=39 +dport_map_port_50=40 +dport_map_port_51=41 +dport_map_port_52=42 +dport_map_port_53=43 +dport_map_port_54=44 +dport_map_port_55=45 +dport_map_port_56=46 +dport_map_port_57=47 +dport_map_port_58=48 +dport_map_port_33=49 +dport_map_port_61=50 +dport_map_port_59=51 +dport_map_port_60=52 +dport_map_port_1=53 +dport_map_port_15=54 +dport_map_port_2=55 +dport_map_port_16=56 + +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc + diff --git a/device/celestica/x86_64-cel_ds2000-r0/custom_led.bin b/device/celestica/x86_64-cel_ds2000-r0/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..7e6b6f96c1d420e32a26357685b97149cd1eabbb GIT binary patch literal 264 zcmV+j0r&p!wcbWoMovaWM&Pw6OavkWC4eKCMt(aBK%7RRCUyV{;6X+UKv_arK>{&D zXqi$3G66KQLJrVFXq{3ccmX?`vYP+_Xj@txLh8^d0B1%3FYD3e=KvxBAw(mYMgk-_ zJD5g*L;xe4Mj11jMnf~3Mg`!(U;$xEMnhqQVF5DJvH&ag&;ctA&=mnjMrTHMQ2{gC zvIHyf+3>u(MzTh!MxaLUy}@BqMgwA7MnhtRV&vzzH~;`09v>hfA|oUvCMPH{GBY$a zHa9pqIy*cG3JVMk4i69!5)%|XK0iP~LPJDFMn^~i0s{mU78e)=1_uZk8XFubDl054 OE-x@iN=r;lPESzT@lU@1 literal 0 HcmV?d00001 diff --git a/device/celestica/x86_64-cel_ds2000-r0/default_sku b/device/celestica/x86_64-cel_ds2000-r0/default_sku new file mode 100644 index 000000000000..ae9d33331e85 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/default_sku @@ -0,0 +1 @@ +DS2000 t1 diff --git a/device/celestica/x86_64-cel_ds2000-r0/installer.conf b/device/celestica/x86_64-cel_ds2000-r0/installer.conf new file mode 100644 index 000000000000..bb956b2aefb1 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_DEV=0 +CONSOLE_PORT=0xe060 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="processor.max_cstate=1 intel_idle.max_cstate=0 intel_iommu=off noirqdebug acpi_no_watchdog" diff --git a/device/celestica/x86_64-cel_ds2000-r0/led_proc_init.soc b/device/celestica/x86_64-cel_ds2000-r0/led_proc_init.soc new file mode 100644 index 000000000000..6f242fa07d89 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/led_proc_init.soc @@ -0,0 +1,8 @@ +#Enable all ports +#port all en=1 +#sleep 6 +#linkscan 250000; port xe,ce linkscan=on + +#Load LED +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on; led start diff --git a/device/celestica/x86_64-cel_ds2000-r0/media_settings.json b/device/celestica/x86_64-cel_ds2000-r0/media_settings.json new file mode 100644 index 000000000000..299dfd211ecf --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/media_settings.json @@ -0,0 +1,834 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-48": { + "25000-copper-1.0M": { + "preemphasis": { + "lane0": "0x1a400a" + } + }, + "25000-copper-3.0M": { + "preemphasis": { + "lane0": "0x1a400a" + } + }, + "25000-copper-5.0M": { + "preemphasis": { + "lane0": "0x1a400a" + } + }, + "10000-copper-1.0M": { + "preemphasis": { + "lane0": "0x19410a" + } + }, + "10000-copper-3.0M": { + "preemphasis": { + "lane0": "0x19410a" + } + }, + "10000-copper-5.0M": { + "preemphasis": { + "lane0": "0x19410a" + } + }, + "10000-copper-7.0M": { + "preemphasis": { + "lane0": "0x19410a" + } + }, + "Default": { + "preemphasis": { + "lane0": "0x14410a" + } + } + }, + "49-60": { + "25000-copper-1.0M": { + "preemphasis": { + "lane0": "0x1a400a", + "lane1": "0x1a400a", + "lane2": "0x1a400a", + "lane3": "0x1a400a" + } + }, + "25000-copper-3.0M": { + "preemphasis": { + "lane0": "0x1a400a", + "lane1": "0x1a400a", + "lane2": "0x1a400a", + "lane3": "0x1a400a" + } + }, + "25000-copper-5.0M": { + "preemphasis": { + "lane0": "0x1a400a", + "lane1": "0x1a400a", + "lane2": "0x1a400a", + "lane3": "0x1a400a" + } + }, + "10000-copper-1.0M": { + "preemphasis": { + "lane0": "0x19410a", + "lane1": "0x19410a", + "lane2": "0x19410a", + "lane3": "0x19410a" + } + }, + "10000-copper-3.0M": { + "preemphasis": { + "lane0": "0x19410a", + "lane1": "0x19410a", + "lane2": "0x19410a", + "lane3": "0x19410a" + } + }, + "10000-copper-5.0M": { + "preemphasis": { + "lane0": "0x19410a", + "lane1": "0x19410a", + "lane2": "0x19410a", + "lane3": "0x19410a" + } + }, + "10000-copper-7.0M": { + "preemphasis": { + "lane0": "0x19410a", + "lane1": "0x19410a", + "lane2": "0x19410a", + "lane3": "0x19410a" + } + }, + "Default": { + "preemphasis": { + "lane0": "0x14410a", + "lane1": "0x14410a", + "lane2": "0x14410a", + "lane3": "0x14410a" + } + } + } + }, + "PORT_MEDIA_SETTINGS": { + "1": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x053602" + } + } + }, + "2": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x053602" + } + } + }, + "3": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x053602" + } + } + }, + "4": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094a04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x083902" + } + } + }, + "5": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b06" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073802" + } + } + }, + "6": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073802" + } + } + }, + "7": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073702" + } + } + }, + "8": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073702" + } + } + }, + "9": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073702" + } + } + }, + "10": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073702" + } + } + }, + "11": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x053602" + } + } + }, + "12": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x053602" + } + } + }, + "13": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x093a02" + } + } + }, + "14": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0a3b02" + } + } + }, + "15": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0d4002" + } + } + }, + "16": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0d4002" + } + } + }, + "17": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0d4002" + } + } + }, + "18": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0d4002" + } + } + }, + "19": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02" + } + } + }, + "20": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02" + } + } + }, + "21": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3d02" + } + } + }, + "22": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02" + } + } + }, + "23": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3d02" + } + } + }, + "24": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02" + } + } + }, + "25": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x124702" + } + } + }, + "26": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x114602" + } + } + }, + "27": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0f4402" + } + } + }, + "28": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0f4402" + } + } + }, + "29": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0e4202" + } + } + }, + "30": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0e4202" + } + } + }, + "31": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0d4002" + } + } + }, + "32": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124305" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0d4002" + } + } + }, + "33": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124b07" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02" + } + } + }, + "34": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124b07" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3d02" + } + } + }, + "35": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124b07" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0b3c02" + } + } + }, + "36": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124b07" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0b3c02" + } + } + }, + "37": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3d02" + } + } + }, + "38": { + "25000-optical": { + "preemphasis": { + "lane0": "0x104c05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3d02" + } + } + }, + "39": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073702" + } + } + }, + "40": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073802" + } + } + }, + "41": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073802" + } + } + }, + "42": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073802" + } + } + }, + "43": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x073802" + } + } + }, + "44": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094c04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x083902" + } + } + }, + "45": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x083902" + } + } + }, + "46": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x093a02" + } + } + }, + "47": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b05" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x093a02" + } + } + }, + "48": { + "25000-optical": { + "preemphasis": { + "lane0": "0x094b04" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x093a02" + } + } + }, + "49": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0e4202", + "lane1": "0x0e4202", + "lane2": "0x0e4202", + "lane3": "0x0e4202" + } + } + }, + "50": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124a08", + "lane1": "0x124a08", + "lane2": "0x124a08", + "lane3": "0x124a08" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x124702", + "lane1": "0x124702", + "lane2": "0x124702", + "lane3": "0x124702" + } + } + }, + "51": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0f4402", + "lane1": "0x0f4402", + "lane2": "0x0f4402", + "lane3": "0x0f4402" + } + } + }, + "52": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0f4402", + "lane1": "0x0f4402", + "lane2": "0x0f4402", + "lane3": "0x0f4402" + } + } + }, + "53": { + "25000-optical": { + "preemphasis": { + "lane0": "0x154708", + "lane1": "0x154708", + "lane2": "0x154708", + "lane3": "0x154708" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0a3b02", + "lane1": "0x0a3b02", + "lane2": "0x0a3b02", + "lane3": "0x0a3b02" + } + } + }, + "54": { + "25000-optical": { + "preemphasis": { + "lane0": "0x154609", + "lane1": "0x154609", + "lane2": "0x154609", + "lane3": "0x154609" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02", + "lane1": "0x0c3f02", + "lane2": "0x0c3f02", + "lane3": "0x0c3f02" + } + } + }, + "55": { + "25000-optical": { + "preemphasis": { + "lane0": "0x164509", + "lane1": "0x164509", + "lane2": "0x164509", + "lane3": "0x164509" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0a3b02", + "lane1": "0x0a3b02", + "lane2": "0x0a3b02", + "lane3": "0x0a3b02" + } + } + }, + "56": { + "25000-optical": { + "preemphasis": { + "lane0": "0x154708", + "lane1": "0x154708", + "lane2": "0x154708", + "lane3": "0x154708" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0x0c3f02", + "lane1": "0x0c3f02", + "lane2": "0x0c3f02", + "lane3": "0x0c3f02" + } + } + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_ds2000-r0/pddf/pd-plugin.json b/device/celestica/x86_64-cel_ds2000-r0/pddf/pd-plugin.json new file mode 100644 index 000000000000..839c9b5dfccd --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/pddf/pd-plugin.json @@ -0,0 +1,145 @@ +{ + "PSU": + { + "name": + { + "1": "PSU 1", + "2": "PSU 2" + }, + "fan_name": + { + "1": + { + "1": "PSU 1 Fan 1" + }, + "2": + { + "1": "PSU 2 Fan 1" + } + }, + "thermal_name": + { + "1": "PSU 1 Temp1", + "2": "PSU 2 Temp1" + }, + "psu_present": + { + "bmc": + { + "valmap": { "0": true, "4":false, "8":false } + }, + "i2c": + { + "valmap": {"1":true, "0": false} + } + }, + + "psu_power_good": + { + "bmc": + { + "valmap": { "1": true, "2": true, "0":false } + }, + "i2c": + { + "valmap": {"1":true, "0": false} + } + + }, + + "psu_fan_dir": + { + "bmc": + { + "valmap": { "B2F":"INTAKE", "F2B":"EXHAUST" } + }, + "i2c": + { + "valmap": { "FSP550-29FM":"INTAKE", "FSP550-20FM":"EXHAUST"} + } + + }, + + "psu_led_color": + { + "colmap": {"green":"green", "red":"amber"} + }, + + "PSU_FAN_MAX_SPEED":"18000" + }, + + "FAN": + { + "direction": + { + "bmc": + { + "valmap": { "1":"INTAKE", "0":"EXHAUST" } + }, + "i2c": + { + "valmap": { "1":"INTAKE", "0":"EXHAUST" } + } + }, + "drawer_name": + { + "1": "Fantray 1", + "2": "Fantray 2", + "3": "Fantray 3", + "4": "Fantray 4" + }, + "name": + { + "1": + { + "1": "Fan 1 Front", + "2": "Fan 1 Rear" + }, + "2": + { + "1": "Fan 2 Front", + "2": "Fan 2 Rear" + }, + "3": + { + "1": "Fan 3 Front", + "2": "Fan 3 Rear" + }, + "4": + { + "1": "Fan 4 Front", + "2": "Fan 4 Rear" + } + }, + "present": + { + "bmc": + { + "valmap": {"0":true, "1":false} + }, + "bmc": + { + "valmap": {"0":true, "1":false} + }, + "i2c": + { + "valmap": {"1":true, "0":false} + } + }, + + "fan_master_led_color": + { + "colmap": {"green":"green", "red":"amber"} + }, + + "duty_cycle_to_pwm": "lambda dc: ((dc*255.0)/100)", + + "pwm_to_duty_cycle": "lambda pwm: ((pwm*100.0)/256)", + + "FAN_MAX_RPM_SPEED": + { + "Front": "23300", + "Rear": "20300" + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-bmc.json b/device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-bmc.json new file mode 100644 index 000000000000..5f4ef1700b91 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-bmc.json @@ -0,0 +1,2891 @@ +{ +"PLATFORM": +{ + "num_psus":2, + "num_fantrays":4, + "num_fans_pertray":2, + "num_ports":56, + "num_temps":9, + "bmc_present": "True", + "pddf_dev_types": + { + "description":" - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld" + ], + "PSU": + [ + "psu_eeprom", + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ], + "FPGAPCIE": + [ + "fpgapci" + ] + + }, + "std_perm_kos": + [ + "i2c_ismt", + "i2c-i801" + ], + + "std_kos": + [ + "lpc_ich", + "i2c_dev", + "ipmi_devintf", + "ipmi_si", + "i2c_mux_pca954x", + "optoe", + "mc24lc64t" + ], + + "pddf_kos": + [ + "pddf_client_module", + "pddf_cpld_module", + "pddf_cpld_driver", + "pddf_mux_module", + "pddf_led_module", + "pddf_fpgai2c_module", + "pddf_fpgai2c_driver", + "pddf_xcvr_module", + "pddf_xcvr_driver_module", + "pddf_fpgapci_driver", + "pddf_fpgapci_module" + ], + + "custom_kos": + [ + "pddf_custom_fpga_algo" + ] + }, + + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + { "dev_name":"i2c-0", "dev":"SMBUS0" }, + { "dev_name":"pcie-0", "dev":"PCIE0" } + ] + } + }, + + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"} + ] + } + }, + + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x56", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + + "PCIE0": + { + "dev_info": {"device_type": "PCIE", "device_name": "PCIE0", "device_parent": "SYSTEM"}, + "i2c": + { + "DEVICES": + [ + {"dev": "FPGAPCIE0"} + ] + } + }, + + "FPGAPCIE0": + { + "dev_info": {"device_type": "FPGAPCIE", "device_name": "FPGAPCIE0", "device_parent": "PCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x0"}, + "dev_attr": { "vendor_id":"0x10EE", "device_id": "0x7021", "virt_bus": "0x64", "data_base_offset":"0x0", "data_size":"0x25000", "i2c_ch_base_offset":"0x00010000", "i2c_ch_size":"0x1000", "virt_i2c_ch":"0xd"}, + "channel": + [ + { "chn":"1", "dev":"MUX1" }, + { "chn":"1", "dev":"MUX2" }, + { "chn":"1", "dev":"MUX3" }, + { "chn":"1", "dev":"MUX4" }, + { "chn":"1", "dev":"MUX5" }, + { "chn":"1", "dev":"MUX6" }, + { "chn":"2", "dev":"MUX7" }, + { "chn":"3", "dev":"CPLD1" }, + { "chn":"3", "dev":"CPLD2" }, + { "chn":"4", "dev":"CPLD_B" } + ] + } + }, + + "MUX1": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT1" }, + { "chn":"1", "dev":"PORT2" }, + { "chn":"2", "dev":"PORT3" }, + { "chn":"3", "dev":"PORT4" }, + { "chn":"4", "dev":"PORT5" }, + { "chn":"5", "dev":"PORT6" }, + { "chn":"6", "dev":"PORT7" }, + { "chn":"7", "dev":"PORT8" } + ] + } + }, + + "MUX2": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x73", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0xa", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT9" }, + { "chn":"1", "dev":"PORT10" }, + { "chn":"2", "dev":"PORT11" }, + { "chn":"3", "dev":"PORT12" }, + { "chn":"4", "dev":"PORT13" }, + { "chn":"5", "dev":"PORT14" }, + { "chn":"6", "dev":"PORT15" }, + { "chn":"7", "dev":"PORT16" } + ] + } + }, + + + "MUX3": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX3", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x74", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x12", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT17" }, + { "chn":"1", "dev":"PORT18" }, + { "chn":"2", "dev":"PORT19" }, + { "chn":"3", "dev":"PORT20" }, + { "chn":"4", "dev":"PORT21" }, + { "chn":"5", "dev":"PORT22" }, + { "chn":"6", "dev":"PORT23" }, + { "chn":"7", "dev":"PORT24" } + ] + } + }, + + "MUX4": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX4", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x75", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x1a", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT25" }, + { "chn":"1", "dev":"PORT26" }, + { "chn":"2", "dev":"PORT27" }, + { "chn":"3", "dev":"PORT28" }, + { "chn":"4", "dev":"PORT29" }, + { "chn":"5", "dev":"PORT30" }, + { "chn":"6", "dev":"PORT31" }, + { "chn":"7", "dev":"PORT32" } + ] + } + }, + + "MUX5": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX5", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x76", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x22", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT33" }, + { "chn":"1", "dev":"PORT34" }, + { "chn":"2", "dev":"PORT35" }, + { "chn":"3", "dev":"PORT36" }, + { "chn":"4", "dev":"PORT37" }, + { "chn":"5", "dev":"PORT38" }, + { "chn":"6", "dev":"PORT39" }, + { "chn":"7", "dev":"PORT40" } + ] + } + }, + + "MUX6": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX6", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x77", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2a", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT41" }, + { "chn":"1", "dev":"PORT42" }, + { "chn":"2", "dev":"PORT43" }, + { "chn":"3", "dev":"PORT44" }, + { "chn":"4", "dev":"PORT45" }, + { "chn":"5", "dev":"PORT46" }, + { "chn":"6", "dev":"PORT47" }, + { "chn":"7", "dev":"PORT48" } + ] + } + }, + "MUX7": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX7", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x74", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x32", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT53" }, + { "chn":"1", "dev":"PORT54" }, + { "chn":"2", "dev":"PORT55" }, + { "chn":"3", "dev":"PORT56" }, + { "chn":"4", "dev":"PORT49" }, + { "chn":"5", "dev":"PORT50" }, + { "chn":"6", "dev":"PORT51" }, + { "chn":"7", "dev":"PORT52" } + ] + } + }, + + "CPLD1": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x30", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD2": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x31", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_B": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD_B", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x67", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "PORT1": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT1", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"1"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT1-EEPROM" }, + { "itf":"control", "dev":"PORT1-CTRL" } + + ] + } + }, + "PORT1-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT1-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT1-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT1-CTRL", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT2": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT2", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"2"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT2-EEPROM" }, + { "itf":"control", "dev":"PORT2-CTRL" } + ] + } + }, + + "PORT2-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT2-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT2-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT2-CTRL", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT3": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT3", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"3"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT3-EEPROM" }, + { "itf":"control", "dev":"PORT3-CTRL" } + ] + } + }, + "PORT3-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT3-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT3-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT3-CTRL", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT4": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT4", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"4"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT4-EEPROM" }, + { "itf":"control", "dev":"PORT4-CTRL" } + ] + } + }, + "PORT4-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT4-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT4-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT4-CTRL", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT5": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT5", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"5"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT5-EEPROM" }, + { "itf":"control", "dev":"PORT5-CTRL" } + ] + } + }, + + "PORT5-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT5-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT5-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT5-CTRL", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT6": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT6", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"6"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT6-EEPROM" }, + { "itf":"control", "dev":"PORT6-CTRL" } + ] + } + }, + "PORT6-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT6-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT6-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT6-CTRL", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT7": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT7", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"7"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT7-EEPROM" }, + { "itf":"control", "dev":"PORT7-CTRL" } + ] + } + }, + "PORT7-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT7-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT7-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT7-CTRL", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT8": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT8", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"8"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT8-EEPROM" }, + { "itf":"control", "dev":"PORT8-CTRL" } + ] + } + }, + "PORT8-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT8-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT8-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT8-CTRL", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT9": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT9", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"9"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT9-EEPROM" }, + { "itf":"control", "dev":"PORT9-CTRL" } + ] + } + }, + "PORT9-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT9-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT9-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT9-CTRL", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT10": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT10", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"10"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT10-EEPROM" }, + { "itf":"control", "dev":"PORT10-CTRL" } + ] + } + }, + "PORT10-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT10-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT10-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT10-CTRL", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT11": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT11", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"11"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT11-EEPROM" }, + { "itf":"control", "dev":"PORT11-CTRL" } + ] + } + }, + "PORT11-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT11-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT11-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT11-CTRL", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT12": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT12", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"12"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT12-EEPROM" }, + { "itf":"control", "dev":"PORT12-CTRL" } + ] + } + }, + "PORT12-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT12-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT12-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT12-CTRL", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT13": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT13", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"13"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT13-EEPROM" }, + { "itf":"control", "dev":"PORT13-CTRL" } + ] + } + }, + "PORT13-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT13-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT13-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT13-CTRL", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT14": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT14", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"14"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT14-EEPROM" }, + { "itf":"control", "dev":"PORT14-CTRL" } + ] + } + }, + "PORT14-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT14-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xF", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT14-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT14-CTRL", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xf", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT15": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT15", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"15"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT15-EEPROM" }, + { "itf":"control", "dev":"PORT15-CTRL" } + ] + } + }, + "PORT15-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT15-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT15-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT15-CTRL", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT16": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT16", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"16"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT16-EEPROM" }, + { "itf":"control", "dev":"PORT16-CTRL" } + ] + } + }, + "PORT16-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT16-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT16-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT16-CTRL", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT17": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT17", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"17"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT17-EEPROM" }, + { "itf":"control", "dev":"PORT17-CTRL" } + ] + } + }, + "PORT17-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT17-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT17-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT17-CTRL", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT18": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT18", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"18"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT18-EEPROM" }, + { "itf":"control", "dev":"PORT18-CTRL" } + ] + } + }, + "PORT18-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT18-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT18-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT18-CTRL", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT19": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT19", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"19"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT19-EEPROM" }, + { "itf":"control", "dev":"PORT19-CTRL" } + ] + } + }, + "PORT19-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT19-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT19-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT19-CTRL", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT20": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT20", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"20"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT20-EEPROM" }, + { "itf":"control", "dev":"PORT20-CTRL" } + ] + } + }, + "PORT20-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT20-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT20-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT20-CTRL", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT21": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT21", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"21"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT21-EEPROM" }, + { "itf":"control", "dev":"PORT21-CTRL" } + ] + } + }, + "PORT21-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT21-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT21-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT21-CTRL", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT22": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT22", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"22"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT22-EEPROM" }, + { "itf":"control", "dev":"PORT22-CTRL" } + ] + } + }, + "PORT22-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT22-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT22-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT22-CTRL", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT23": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT23", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"23"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT23-EEPROM" }, + { "itf":"control", "dev":"PORT23-CTRL" } + ] + } + }, + "PORT23-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT23-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT23-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT23-CTRL", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT24": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT24", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"24"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT24-EEPROM" }, + { "itf":"control", "dev":"PORT24-CTRL" } + ] + } + }, + "PORT24-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT24-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT24-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT24-CTRL", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT25": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT25", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"25"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT25-EEPROM" }, + { "itf":"control", "dev":"PORT25-CTRL" } + ] + } + }, + "PORT25-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT25-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT25-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT25-CTRL", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT26": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT26", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"26"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT26-EEPROM" }, + { "itf":"control", "dev":"PORT26-CTRL" } + ] + } + }, + "PORT26-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT26-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT26-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT26-CTRL", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT27": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT27", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"27"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT27-EEPROM" }, + { "itf":"control", "dev":"PORT27-CTRL" } + ] + } + }, + "PORT27-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT27-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT27-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT27-CTRL", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT28": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT28", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"28"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT28-EEPROM" }, + { "itf":"control", "dev":"PORT28-CTRL" } + ] + } + }, + "PORT28-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT28-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT28-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT28-CTRL", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT29": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT29", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"29"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT29-EEPROM" }, + { "itf":"control", "dev":"PORT29-CTRL" } + ] + } + }, + "PORT29-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT29-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT29-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT29-CTRL", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT30": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT30", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"30"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT30-EEPROM" }, + { "itf":"control", "dev":"PORT30-CTRL" } + ] + } + }, + "PORT30-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT30-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT30-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT30-CTRL", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT31": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT31", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"31"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT31-EEPROM" }, + { "itf":"control", "dev":"PORT31-CTRL" } + ] + } + }, + "PORT31-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT31-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT31-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT31-CTRL", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT32": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT32", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"32"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT32-EEPROM" }, + { "itf":"control", "dev":"PORT32-CTRL" } + ] + } + }, + "PORT32-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT32-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT32-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT32-CTRL", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT33": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT33", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"33"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT33-EEPROM" }, + { "itf":"control", "dev":"PORT33-CTRL" } + ] + } + }, + "PORT33-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT33-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT33-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT33-CTRL", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x210", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT34": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT34", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"34"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT34-EEPROM" }, + { "itf":"control", "dev":"PORT34-CTRL" } + ] + } + }, + "PORT34-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT34-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": { "parent_bus":"0x23", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT34-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT34-CTRL", "device_parent":"MUX5", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": { "parent_bus":"0x23", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x220", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT35": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT35", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"35"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT35-EEPROM" }, + { "itf":"control", "dev":"PORT35-CTRL" } + ] + } + }, + "PORT35-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT35-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT35"}, + "i2c": + { + "topo_info": { "parent_bus":"0x24", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT35-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT35-CTRL", "device_parent":"MUX5", "virt_parent":"PORT35"}, + "i2c": + { + "topo_info": { "parent_bus":"0x24", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x230", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT36": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT36", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"36"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT36-EEPROM" }, + { "itf":"control", "dev":"PORT36-CTRL" } + ] + } + }, + "PORT36-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT36-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT36"}, + "i2c": + { + "topo_info": { "parent_bus":"0x25", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT36-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT36-CTRL", "device_parent":"MUX5", "virt_parent":"PORT36"}, + "i2c": + { + "topo_info": { "parent_bus":"0x25", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x240", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT37": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT37", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"37"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT37-EEPROM" }, + { "itf":"control", "dev":"PORT37-CTRL" } + ] + } + }, + "PORT37-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT37-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT37"}, + "i2c": + { + "topo_info": { "parent_bus":"0x26", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT37-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT37-CTRL", "device_parent":"MUX5", "virt_parent":"PORT37"}, + "i2c": + { + "topo_info": { "parent_bus":"0x26", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x250", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT38": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT38", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"38"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT38-EEPROM" }, + { "itf":"control", "dev":"PORT38-CTRL" } + ] + } + }, + "PORT38-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT38-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT38"}, + "i2c": + { + "topo_info": { "parent_bus":"0x27", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT38-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT38-CTRL", "device_parent":"MUX5", "virt_parent":"PORT38"}, + "i2c": + { + "topo_info": { "parent_bus":"0x27", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x260", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT39": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT39", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"39"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT39-EEPROM" }, + { "itf":"control", "dev":"PORT39-CTRL" } + ] + } + }, + "PORT39-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT39-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT39"}, + "i2c": + { + "topo_info": { "parent_bus":"0x28", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT39-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT39-CTRL", "device_parent":"MUX5", "virt_parent":"PORT39"}, + "i2c": + { + "topo_info": { "parent_bus":"0x28", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x270", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT40": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT40", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"40"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT40-EEPROM" }, + { "itf":"control", "dev":"PORT40-CTRL" } + ] + } + }, + "PORT40-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT40-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT40"}, + "i2c": + { + "topo_info": { "parent_bus":"0x29", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT40-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT40-CTRL", "device_parent":"MUX5", "virt_parent":"PORT40"}, + "i2c": + { + "topo_info": { "parent_bus":"0x29", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x280", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT41": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT41", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"41"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT41-EEPROM" }, + { "itf":"control", "dev":"PORT41-CTRL" } + ] + } + }, + "PORT41-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT41-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT41"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2a", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT41-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT41-CTRL", "device_parent":"MUX6", "virt_parent":"PORT41"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2a", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x290", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT42": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT42", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"42"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT42-EEPROM" }, + { "itf":"control", "dev":"PORT42-CTRL" } + ] + } + }, + "PORT42-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT42-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT42"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2b", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT42-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT42-CTRL", "device_parent":"MUX6", "virt_parent":"PORT42"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2b", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2a0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT43": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT43", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"43"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT43-EEPROM" }, + { "itf":"control", "dev":"PORT43-CTRL" } + ] + } + }, + "PORT43-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT43-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT43"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2c", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT43-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT43-CTRL", "device_parent":"MUX6", "virt_parent":"PORT43"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2c", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2b0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT44": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT44", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"44"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT44-EEPROM" }, + { "itf":"control", "dev":"PORT44-CTRL" } + ] + } + }, + "PORT44-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT44-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT44"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2d", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT44-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT44-CTRL", "device_parent":"MUX6", "virt_parent":"PORT44"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2d", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2c0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT45": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT45", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"45"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT45-EEPROM" }, + { "itf":"control", "dev":"PORT45-CTRL" } + ] + } + }, + "PORT45-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT45-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT45"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2e", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT45-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT45-CTRL", "device_parent":"MUX6", "virt_parent":"PORT45"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2e", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2d0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT46": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT46", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"46"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT46-EEPROM" }, + { "itf":"control", "dev":"PORT46-CTRL" } + ] + } + }, + "PORT46-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT46-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT46"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2f", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT46-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT46-CTRL", "device_parent":"MUX6", "virt_parent":"PORT46"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2f", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2e0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT47": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT47", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"47"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT47-EEPROM" }, + { "itf":"control", "dev":"PORT47-CTRL" } + ] + } + }, + "PORT47-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT47-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT47"}, + "i2c": + { + "topo_info": { "parent_bus":"0x30", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT47-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT47-CTRL", "device_parent":"MUX6", "virt_parent":"PORT47"}, + "i2c": + { + "topo_info": { "parent_bus":"0x30", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2f0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT48": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT48", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"48"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT48-EEPROM" }, + { "itf":"control", "dev":"PORT48-CTRL" } + ] + } + }, + "PORT48-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT48-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT48"}, + "i2c": + { + "topo_info": { "parent_bus":"0x31", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT48-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT48-CTRL", "device_parent":"MUX6", "virt_parent":"PORT48"}, + "i2c": + { + "topo_info": { "parent_bus":"0x31", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x300", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT49": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT49", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"49"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT49-EEPROM" }, + { "itf":"control", "dev":"PORT49-CTRL" } + ] + } + }, + "PORT49-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT49-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT49"}, + "i2c": + { + "topo_info": { "parent_bus":"0x36", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT49-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT49-CTRL", "device_parent":"MUX7", "virt_parent":"PORT49"}, + "i2c": + { + "topo_info": { "parent_bus":"0x36", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x310", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x310", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x310", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + + ] + } + }, + + "PORT50": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT50", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"50"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT50-EEPROM" }, + { "itf":"control", "dev":"PORT50-CTRL" } + ] + } + }, + "PORT50-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT50-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT50"}, + "i2c": + { + "topo_info": { "parent_bus":"0x37", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT50-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT50-CTRL", "device_parent":"MUX7", "virt_parent":"PORT50"}, + "i2c": + { + "topo_info": { "parent_bus":"0x37", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x320", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x320", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x320", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT51": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT51", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"51"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT51-EEPROM" }, + { "itf":"control", "dev":"PORT51-CTRL" } + ] + } + }, + "PORT51-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT51-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT51"}, + "i2c": + { + "topo_info": { "parent_bus":"0x38", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT51-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT51-CTRL", "device_parent":"MUX7", "virt_parent":"PORT51"}, + "i2c": + { + "topo_info": { "parent_bus":"0x38", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x330", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x330", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x330", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT52": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT52", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"52"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT52-EEPROM" }, + { "itf":"control", "dev":"PORT52-CTRL" } + ] + } + }, + "PORT52-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT52-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT52"}, + "i2c": + { + "topo_info": { "parent_bus":"0x39", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT52-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT52-CTRL", "device_parent":"MUX7", "virt_parent":"PORT52"}, + "i2c": + { + "topo_info": { "parent_bus":"0x39", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x340", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x340", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x340", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT53": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT53", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"53"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT53-EEPROM" }, + { "itf":"control", "dev":"PORT53-CTRL" } + ] + } + }, + "PORT53-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT53-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT53"}, + "i2c": + { + "topo_info": { "parent_bus":"0x32", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT53-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT53-CTRL", "device_parent":"MUX7", "virt_parent":"PORT53"}, + "i2c": + { + "topo_info": { "parent_bus":"0x32", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x350", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x350", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x350", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT54": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT54", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"54"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT54-EEPROM" }, + { "itf":"control", "dev":"PORT54-CTRL" } + ] + } + }, + "PORT54-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT54-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT54"}, + "i2c": + { + "topo_info": { "parent_bus":"0x33", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT54-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT54-CTRL", "device_parent":"MUX7", "virt_parent":"PORT54"}, + "i2c": + { + "topo_info": { "parent_bus":"0x33", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x360", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x360", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x360", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT55": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT55", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"55"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT55-EEPROM" }, + { "itf":"control", "dev":"PORT55-CTRL" } + ] + } + }, + "PORT55-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT55-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT55"}, + "i2c": + { + "topo_info": { "parent_bus":"0x34", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT55-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT55-CTRL", "device_parent":"MUX7", "virt_parent":"PORT55"}, + "i2c": + { + "topo_info": { "parent_bus":"0x34", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x370", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x370", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x370", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT56": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT56", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"56"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT56-EEPROM" }, + { "itf":"control", "dev":"PORT56-CTRL" } + ] + } + }, + "PORT56-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT56-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x35", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT56-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT56-CTRL", "device_parent":"MUX7", "virt_parent":"PORT56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x35", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x380", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x380", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x380", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PSU1": + { + "dev_info": { "device_type":"PSU"}, + "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"psu_power_good", "bmc_cmd":"ipmitool raw 0x3A 0x64 0x0 0x1 0x60", "raw": "1", "type":"mask", "mask":"0x2"}, + { "attr_name":"psu_present", "bmc_cmd":"ipmitool raw 0x3A 0x64 0x0 0x1 0x60", "raw": "1", "type":"mask", "mask":"0x8"}, + { "attr_name":"psu_model_name", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Name", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_serial_num", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Serial", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_mfr_id", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Manufacturer", "separator":":", "field_pos":"2"}, + { "attr_name":"psu_fan_dir", "bmc_cmd":"ipmitool fru print 0 | grep -e B2F -e F2B", "raw": "0", "field_name":"Product Extra", "separator":":", "field_pos":"2"}, + { "attr_name":"psu_p_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x21", "type": "raw", "raw": "1", "offset": "0", "multiplier": "6000000"}, + { "attr_name":"psu_v_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1F", "type": "raw", "raw": "1", "offset" : "0", "multiplier": "100"}, + { "attr_name":"psu_i_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x20", "type": "raw", "raw": "1", "offset" : "0", "multiplier": "500"}, + { "attr_name":"psu_p_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1B", "type": "raw", "raw": "1", "offset": "0", "multiplier": "6000000"}, + { "attr_name":"psu_v_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x19", "type": "raw", "raw": "1", "offset": "0", "multiplier": "100"}, + { "attr_name":"psu_i_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1A", "type": "raw", "raw": "1", "offset": "0", "multiplier": "500"}, + { "attr_name":"psu_fan1_speed_rpm", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1C", "type": "raw", "raw": "1", "offset": "0", "multiplier": "200"}, + { "attr_name":"psu_temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1D", "type": "raw", "raw":"1", "offset": "0", "multiplier": "1000"}, + { "attr_name":"psu_temp2_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1E", "type": "raw", "raw":"1", "offset": "0", "multiplier": "1000"} + ] + } + } + }, + + "PSU2": + { + "dev_info": { "device_type":"PSU"}, + "dev_attr": { "dev_idx":"2", "num_psu_fans": "1"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"psu_power_good", "bmc_cmd":"ipmitool raw 0x3A 0x64 0x0 0x1 0x60", "raw": "1", "type":"mask", "mask":"0x1"}, + { "attr_name":"psu_present", "bmc_cmd":"ipmitool raw 0x3A 0x64 0x0 0x1 0x60", "raw": "1", "type":"mask", "mask":"0x4"}, + { "attr_name":"psu_model_name", "bmc_cmd":"ipmitool fru print 4", "raw": "0", "field_name":"Product Name", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_serial_num", "bmc_cmd":"ipmitool fru print 4", "raw": "0", "field_name":"Product Serial", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_mfr_id", "bmc_cmd":"ipmitool fru print 4", "raw": "0", "field_name":"Product Manufacturer", "separator":":", "field_pos":"2"}, + { "attr_name":"psu_fan_dir", "bmc_cmd":"ipmitool fru print 0 | grep -e B2F -e F2B", "raw": "0", "field_name":"Product Extra", "separator":":", "field_pos":"2"}, + { "attr_name":"psu_p_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2A", "type": "raw", "raw": "1", "offset": "0", "multiplier": "6000000"}, + { "attr_name":"psu_v_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x28", "type": "raw", "raw": "1", "offset" : "0", "multiplier": "100"}, + { "attr_name":"psu_i_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x29", "type": "raw", "raw": "1", "offset" : "0", "multiplier": "500"}, + { "attr_name":"psu_p_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x24", "type": "raw", "raw": "1", "offset": "0", "multiplier": "6000000"}, + { "attr_name":"psu_v_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x22", "type": "raw", "raw": "1", "offset": "0", "multiplier": "100"}, + { "attr_name":"psu_i_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x23", "type": "raw", "raw": "1", "offset": "0", "multiplier": "500"}, + { "attr_name":"psu_fan1_speed_rpm", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x25", "type": "raw", "raw": "1", "offset": "0", "multiplier": "200"}, + { "attr_name":"psu_temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x26", "type": "raw", "raw":"1", "offset": "0", "multiplier": "1000"}, + { "attr_name":"psu_temp2_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x27", "type": "raw", "raw":"1", "offset": "0", "multiplier": "1000"} + ] + } + } + }, + + "FAN-CTRL": + { + "dev_info": { "device_type":"FAN"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"fan1_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x00", "type": "raw", "raw": "1"}, + { "attr_name":"fan2_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x00", "type": "raw", "raw": "1"}, + { "attr_name":"fan3_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x01", "type": "raw", "raw": "1"}, + { "attr_name":"fan4_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x01", "type": "raw", "raw": "1"}, + { "attr_name":"fan5_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x02", "type": "raw", "raw": "1"}, + { "attr_name":"fan6_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x02", "type": "raw", "raw": "1"}, + { "attr_name":"fan7_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x03", "type": "raw", "raw": "1"}, + { "attr_name":"fan8_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x03", "type": "raw", "raw": "1"}, + { "attr_name":"fan1_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x00", "type": "raw", "raw": "1"}, + { "attr_name":"fan2_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x00", "type": "raw", "raw": "1"}, + { "attr_name":"fan3_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x01", "type": "raw", "raw": "1"}, + { "attr_name":"fan4_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x01", "type": "raw", "raw": "1"}, + { "attr_name":"fan5_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x02", "type": "raw", "raw": "1"}, + { "attr_name":"fan6_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x02", "type": "raw", "raw": "1"}, + { "attr_name":"fan7_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x03", "type": "raw", "raw": "1"}, + { "attr_name":"fan8_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x03", "type": "raw", "raw": "1"}, + { "attr_name":"fan1_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x00", "raw": "1", "type": "raw", "offset": "0", "multiplier": "120"}, + { "attr_name":"fan2_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x00", "raw": "1", "type": "raw", "offset": "1", "multiplier": "120"}, + { "attr_name":"fan3_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x01", "raw": "1", "type": "raw", "offset": "0", "multiplier": "120"}, + { "attr_name":"fan4_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x01", "raw": "1", "type": "raw", "offset": "1", "multiplier": "120"}, + { "attr_name":"fan5_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x02", "raw": "1", "type": "raw", "offset": "0", "multiplier": "120"}, + { "attr_name":"fan6_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x02", "raw": "1", "type": "raw", "offset": "1", "multiplier": "120"}, + { "attr_name":"fan7_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x03", "raw": "1", "type": "raw", "offset": "0", "multiplier": "120"}, + { "attr_name":"fan8_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 0x03", "raw": "1", "type": "raw", "offset": "1", "multiplier": "120"}, + { "attr_name":"fan1_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x00", "type": "raw", "raw": "1"}, + { "attr_name":"fan2_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x00", "type": "raw", "raw": "1"}, + { "attr_name":"fan3_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x01", "type": "raw", "raw": "1"}, + { "attr_name":"fan4_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x01", "type": "raw", "raw": "1"}, + { "attr_name":"fan5_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x02", "type": "raw", "raw": "1"}, + { "attr_name":"fan6_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x02", "type": "raw", "raw": "1"}, + { "attr_name":"fan7_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x03", "type": "raw", "raw": "1"}, + { "attr_name":"fan8_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x16 0x03", "type": "raw", "raw": "1"} + ] + } + } + }, + + "TEMP1": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"CPU Internal Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x7", "type": "raw", "raw":"1", "offset": "5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x7", "type": "raw", "raw": "1", "offset": "0"} + + ] + } + } + }, + + "TEMP2": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Baseboard Left Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x01", "type": "raw", "raw": "1", "offset":"0"} + + ] + } + } + }, + + "TEMP3": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Baseboard Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x02", "type": "raw", "raw": "1", "offset": "0"} + + ] + } + } + }, + + + "TEMP4": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"ASIC External Front Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x03", "type": "raw", "raw": "1", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x03", "type": "raw", "raw": "1", "offset" : "0"} + + ] + } + } + }, + + "TEMP5": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"ASIC External Rear Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x04", "type": "raw", "raw": "1", "offset" : "0"} + + ] + } + } + }, + + "TEMP6": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Switchboard Left Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x06", "type": "raw", "raw": "1", "offset":"5", "decrementor": "5"}, + { "attr_name":"temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x06", "type": "raw", "raw": "1", "offset":"4", "decrementor": "5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x06", "type": "raw", "raw": "1", "offset" : "0"} + + ] + } + } + }, + + + "TEMP7": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Switchboard Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x05", "type": "raw", "raw": "1", "offset":"5", "decrementor": "5"}, + { "attr_name":"temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x05", "type": "raw", "raw": "1", "offset":"4", "decrementor": "5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x05", "type": "raw", "raw": "1", "offset" : "0"} + + ] + } + } + }, + + "TEMP8": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"VDD CORE Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x49", "type": "raw", "raw": "1", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x49", "type": "raw", "raw": "1", "offset" : "0"} + + ] + } + } + }, + + "TEMP9": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"VDD ANLG Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x50", "type": "raw", "raw": "1", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x50", "type": "raw", "raw": "1", "offset" : "0"} + + ] + } + } + }, + "SYS_LED": + { + "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, + "dev_attr": { "index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"amber_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"}, + { "attr_name":"amber_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x04"}, + { "attr_name":"green_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x05"}, + { "attr_name":"green_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x06"}, + { "attr_name":"both_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x07"}, + { "attr_name":"both_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x0", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x08"} + ] + } + } + }, + "ALARM_LED": + { + "dev_info": { "device_type":"LED", "device_name":"ALARM_LED"}, + "dev_attr": { "index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"amber_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"}, + { "attr_name":"amber_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x04"}, + { "attr_name":"green_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x05"}, + { "attr_name":"green_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x06"}, + { "attr_name":"both_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x07"}, + { "attr_name":"both_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x1", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x08"} + ] + } + } + }, + "FANTRAY1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY1_LED"}, + "dev_attr": { "index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x4", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x4", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x4", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"} + ] + } + } + }, + "FANTRAY2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY2_LED"}, + "dev_attr": { "index":"1", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x5", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x5", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x5", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"} + ] + } + } + }, + "FANTRAY3_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY3_LED"}, + "dev_attr": { "index":"2", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x6", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x6", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x6", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"} + ] + } + } + }, + "FANTRAY4_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY4_LED"}, + "dev_attr": { "index":"3", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x7", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x7", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x1 0x7", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"} + ] + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-nonbmc.json b/device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-nonbmc.json new file mode 100644 index 000000000000..0335e9cf8c03 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/pddf/pddf-device-nonbmc.json @@ -0,0 +1,2889 @@ +{ +"PLATFORM": +{ + "num_psus":2, + "num_fantrays":4, + "num_fans_pertray":2, + "num_ports":56, + "num_temps":8, + "bmc_present": "False", + "pddf_dev_types": + { + "description":" - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld" + ], + "PSU": + [ + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl", + "fan_cpld" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ], + "FPGAPCIE": + [ + "fpgapci" + ] + + }, + "std_perm_kos": + [ + "i2c_ismt", + "i2c-i801" + ], + + "std_kos": + [ + "lpc_ich", + "i2c_dev", + "i2c_mux_pca954x", + "optoe", + "mc24lc64t" + ], + + "pddf_kos": + [ + "pddf_client_module", + "pddf_psu_module", + "pddf_fan_module", + "pddf_cpld_module", + "pddf_cpld_driver", + "pddf_mux_module", + "pddf_led_module", + "pddf_fpgai2c_module", + "pddf_fpgai2c_driver", + "pddf_xcvr_module", + "pddf_xcvr_driver_module", + "pddf_fpgapci_driver", + "pddf_fpgapci_module" + ], + + "custom_kos": + [ + "pddf_custom_fpga_algo", + "pddf_custom_psu_driver_module" + ] + }, + + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + { "dev_name":"i2c-0", "dev":"SMBUS0" }, + { "dev_name":"pcie-0", "dev":"PCIE0" } + ] + } + }, + + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"} + ] + } + }, + + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x56", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + + "PCIE0": + { + "dev_info": {"device_type": "PCIE", "device_name": "PCIE0", "device_parent": "SYSTEM"}, + "i2c": + { + "DEVICES": + [ + {"dev": "FPGAPCIE0"} + ] + } + }, + + "FPGAPCIE0": + { + "dev_info": {"device_type": "FPGAPCIE", "device_name": "FPGAPCIE0", "device_parent": "PCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x0"}, + "dev_attr": { "vendor_id":"0x10EE", "device_id": "0x7021", "virt_bus": "0x64", "data_base_offset":"0x0", "data_size":"0x25000", "i2c_ch_base_offset":"0x00010000", "i2c_ch_size":"0x1000", "virt_i2c_ch":"0xd"}, + "channel": + [ + { "chn":"1", "dev":"MUX1" }, + { "chn":"1", "dev":"MUX2" }, + { "chn":"1", "dev":"MUX3" }, + { "chn":"1", "dev":"MUX4" }, + { "chn":"1", "dev":"MUX5" }, + { "chn":"1", "dev":"MUX6" }, + { "chn":"2", "dev":"MUX7" }, + { "chn":"3", "dev":"CPLD1" }, + { "chn":"3", "dev":"CPLD2" }, + { "chn":"6", "dev":"CPLD_B" }, + { "chn":"6", "dev":"FAN-CTRL" }, + { "chn":"7", "dev":"MUX8" }, + { "chn":"9", "dev":"TEMP7" }, + { "chn":"9", "dev":"TEMP8" }, + { "chn":"10", "dev":"TEMP1" }, + { "chn":"10", "dev":"TEMP2" }, + { "chn":"10", "dev":"TEMP3" }, + { "chn":"10", "dev":"TEMP4" }, + { "chn":"10", "dev":"TEMP5" }, + { "chn":"10", "dev":"TEMP6" } + ] + } + }, + + "MUX1": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT1" }, + { "chn":"1", "dev":"PORT2" }, + { "chn":"2", "dev":"PORT3" }, + { "chn":"3", "dev":"PORT4" }, + { "chn":"4", "dev":"PORT5" }, + { "chn":"5", "dev":"PORT6" }, + { "chn":"6", "dev":"PORT7" }, + { "chn":"7", "dev":"PORT8" } + ] + } + }, + + "MUX2": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x73", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0xa", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT9" }, + { "chn":"1", "dev":"PORT10" }, + { "chn":"2", "dev":"PORT11" }, + { "chn":"3", "dev":"PORT12" }, + { "chn":"4", "dev":"PORT13" }, + { "chn":"5", "dev":"PORT14" }, + { "chn":"6", "dev":"PORT15" }, + { "chn":"7", "dev":"PORT16" } + ] + } + }, + + + "MUX3": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX3", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x74", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x12", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT17" }, + { "chn":"1", "dev":"PORT18" }, + { "chn":"2", "dev":"PORT19" }, + { "chn":"3", "dev":"PORT20" }, + { "chn":"4", "dev":"PORT21" }, + { "chn":"5", "dev":"PORT22" }, + { "chn":"6", "dev":"PORT23" }, + { "chn":"7", "dev":"PORT24" } + ] + } + }, + + "MUX4": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX4", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x75", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x1a", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT25" }, + { "chn":"1", "dev":"PORT26" }, + { "chn":"2", "dev":"PORT27" }, + { "chn":"3", "dev":"PORT28" }, + { "chn":"4", "dev":"PORT29" }, + { "chn":"5", "dev":"PORT30" }, + { "chn":"6", "dev":"PORT31" }, + { "chn":"7", "dev":"PORT32" } + ] + } + }, + + "MUX5": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX5", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x76", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x22", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT33" }, + { "chn":"1", "dev":"PORT34" }, + { "chn":"2", "dev":"PORT35" }, + { "chn":"3", "dev":"PORT36" }, + { "chn":"4", "dev":"PORT37" }, + { "chn":"5", "dev":"PORT38" }, + { "chn":"6", "dev":"PORT39" }, + { "chn":"7", "dev":"PORT40" } + ] + } + }, + + "MUX6": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX6", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x77", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2a", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT41" }, + { "chn":"1", "dev":"PORT42" }, + { "chn":"2", "dev":"PORT43" }, + { "chn":"3", "dev":"PORT44" }, + { "chn":"4", "dev":"PORT45" }, + { "chn":"5", "dev":"PORT46" }, + { "chn":"6", "dev":"PORT47" }, + { "chn":"7", "dev":"PORT48" } + ] + } + }, + "MUX7": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX7", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x74", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x32", "idle_state":"-2"}, + "channel": + [ + { "chn":"0", "dev":"PORT53" }, + { "chn":"1", "dev":"PORT54" }, + { "chn":"2", "dev":"PORT55" }, + { "chn":"3", "dev":"PORT56" }, + { "chn":"4", "dev":"PORT49" }, + { "chn":"5", "dev":"PORT50" }, + { "chn":"6", "dev":"PORT51" }, + { "chn":"7", "dev":"PORT52" } + ] + } + }, + + "CPLD1": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x30", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD2": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x31", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_B": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD_B", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x69", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "MUX8": + { + "dev_info": {"device_type":"MUX", "device_name":"MUX8", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6a", "dev_addr":"0x70", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x3a", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PSU1"}, + {"chn":"1", "dev":"PSU2"} + ] + } + }, + + "PORT1": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT1", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"1"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT1-EEPROM" }, + { "itf":"control", "dev":"PORT1-CTRL" } + + ] + } + }, + "PORT1-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT1-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT1-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT1-CTRL", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT2": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT2", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"2"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT2-EEPROM" }, + { "itf":"control", "dev":"PORT2-CTRL" } + ] + } + }, + + "PORT2-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT2-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT2-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT2-CTRL", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT3": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT3", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"3"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT3-EEPROM" }, + { "itf":"control", "dev":"PORT3-CTRL" } + ] + } + }, + "PORT3-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT3-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT3-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT3-CTRL", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT4": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT4", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"4"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT4-EEPROM" }, + { "itf":"control", "dev":"PORT4-CTRL" } + ] + } + }, + "PORT4-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT4-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT4-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT4-CTRL", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT5": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT5", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"5"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT5-EEPROM" }, + { "itf":"control", "dev":"PORT5-CTRL" } + ] + } + }, + + "PORT5-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT5-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT5-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT5-CTRL", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT6": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT6", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"6"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT6-EEPROM" }, + { "itf":"control", "dev":"PORT6-CTRL" } + ] + } + }, + "PORT6-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT6-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT6-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT6-CTRL", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT7": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT7", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"7"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT7-EEPROM" }, + { "itf":"control", "dev":"PORT7-CTRL" } + ] + } + }, + "PORT7-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT7-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT7-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT7-CTRL", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT8": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT8", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"8"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT8-EEPROM" }, + { "itf":"control", "dev":"PORT8-CTRL" } + ] + } + }, + "PORT8-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT8-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT8-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT8-CTRL", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT9": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT9", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"9"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT9-EEPROM" }, + { "itf":"control", "dev":"PORT9-CTRL" } + ] + } + }, + "PORT9-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT9-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT9-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT9-CTRL", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT10": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT10", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"10"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT10-EEPROM" }, + { "itf":"control", "dev":"PORT10-CTRL" } + ] + } + }, + "PORT10-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT10-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT10-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT10-CTRL", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT11": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT11", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"11"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT11-EEPROM" }, + { "itf":"control", "dev":"PORT11-CTRL" } + ] + } + }, + "PORT11-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT11-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT11-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT11-CTRL", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT12": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT12", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"12"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT12-EEPROM" }, + { "itf":"control", "dev":"PORT12-CTRL" } + ] + } + }, + "PORT12-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT12-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT12-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT12-CTRL", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT13": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT13", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"13"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT13-EEPROM" }, + { "itf":"control", "dev":"PORT13-CTRL" } + ] + } + }, + "PORT13-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT13-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT13-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT13-CTRL", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT14": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT14", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"14"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT14-EEPROM" }, + { "itf":"control", "dev":"PORT14-CTRL" } + ] + } + }, + "PORT14-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT14-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xF", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT14-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT14-CTRL", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xf", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT15": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT15", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"15"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT15-EEPROM" }, + { "itf":"control", "dev":"PORT15-CTRL" } + ] + } + }, + "PORT15-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT15-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT15-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT15-CTRL", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT16": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT16", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"16"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT16-EEPROM" }, + { "itf":"control", "dev":"PORT16-CTRL" } + ] + } + }, + "PORT16-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT16-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT16-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT16-CTRL", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT17": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT17", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"17"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT17-EEPROM" }, + { "itf":"control", "dev":"PORT17-CTRL" } + ] + } + }, + "PORT17-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT17-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT17-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT17-CTRL", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT18": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT18", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"18"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT18-EEPROM" }, + { "itf":"control", "dev":"PORT18-CTRL" } + ] + } + }, + "PORT18-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT18-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT18-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT18-CTRL", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT19": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT19", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"19"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT19-EEPROM" }, + { "itf":"control", "dev":"PORT19-CTRL" } + ] + } + }, + "PORT19-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT19-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT19-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT19-CTRL", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT20": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT20", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"20"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT20-EEPROM" }, + { "itf":"control", "dev":"PORT20-CTRL" } + ] + } + }, + "PORT20-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT20-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT20-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT20-CTRL", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT21": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT21", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"21"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT21-EEPROM" }, + { "itf":"control", "dev":"PORT21-CTRL" } + ] + } + }, + "PORT21-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT21-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT21-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT21-CTRL", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT22": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT22", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"22"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT22-EEPROM" }, + { "itf":"control", "dev":"PORT22-CTRL" } + ] + } + }, + "PORT22-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT22-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT22-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT22-CTRL", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT23": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT23", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"23"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT23-EEPROM" }, + { "itf":"control", "dev":"PORT23-CTRL" } + ] + } + }, + "PORT23-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT23-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT23-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT23-CTRL", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT24": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT24", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"24"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT24-EEPROM" }, + { "itf":"control", "dev":"PORT24-CTRL" } + ] + } + }, + "PORT24-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT24-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT24-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT24-CTRL", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT25": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT25", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"25"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT25-EEPROM" }, + { "itf":"control", "dev":"PORT25-CTRL" } + ] + } + }, + "PORT25-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT25-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT25-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT25-CTRL", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT26": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT26", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"26"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT26-EEPROM" }, + { "itf":"control", "dev":"PORT26-CTRL" } + ] + } + }, + "PORT26-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT26-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT26-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT26-CTRL", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT27": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT27", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"27"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT27-EEPROM" }, + { "itf":"control", "dev":"PORT27-CTRL" } + ] + } + }, + "PORT27-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT27-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT27-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT27-CTRL", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT28": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT28", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"28"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT28-EEPROM" }, + { "itf":"control", "dev":"PORT28-CTRL" } + ] + } + }, + "PORT28-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT28-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT28-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT28-CTRL", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT29": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT29", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"29"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT29-EEPROM" }, + { "itf":"control", "dev":"PORT29-CTRL" } + ] + } + }, + "PORT29-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT29-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT29-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT29-CTRL", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT30": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT30", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"30"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT30-EEPROM" }, + { "itf":"control", "dev":"PORT30-CTRL" } + ] + } + }, + "PORT30-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT30-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT30-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT30-CTRL", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT31": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT31", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"31"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT31-EEPROM" }, + { "itf":"control", "dev":"PORT31-CTRL" } + ] + } + }, + "PORT31-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT31-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT31-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT31-CTRL", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + + "PORT32": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT32", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"32"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT32-EEPROM" }, + { "itf":"control", "dev":"PORT32-CTRL" } + ] + } + }, + "PORT32-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT32-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT32-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT32-CTRL", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT33": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT33", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"33"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT33-EEPROM" }, + { "itf":"control", "dev":"PORT33-CTRL" } + ] + } + }, + "PORT33-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT33-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT33-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT33-CTRL", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x210", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT34": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT34", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"34"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT34-EEPROM" }, + { "itf":"control", "dev":"PORT34-CTRL" } + ] + } + }, + "PORT34-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT34-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": { "parent_bus":"0x23", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT34-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT34-CTRL", "device_parent":"MUX5", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": { "parent_bus":"0x23", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x220", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT35": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT35", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"35"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT35-EEPROM" }, + { "itf":"control", "dev":"PORT35-CTRL" } + ] + } + }, + "PORT35-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT35-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT35"}, + "i2c": + { + "topo_info": { "parent_bus":"0x24", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT35-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT35-CTRL", "device_parent":"MUX5", "virt_parent":"PORT35"}, + "i2c": + { + "topo_info": { "parent_bus":"0x24", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x230", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT36": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT36", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"36"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT36-EEPROM" }, + { "itf":"control", "dev":"PORT36-CTRL" } + ] + } + }, + "PORT36-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT36-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT36"}, + "i2c": + { + "topo_info": { "parent_bus":"0x25", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT36-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT36-CTRL", "device_parent":"MUX5", "virt_parent":"PORT36"}, + "i2c": + { + "topo_info": { "parent_bus":"0x25", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x240", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT37": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT37", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"37"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT37-EEPROM" }, + { "itf":"control", "dev":"PORT37-CTRL" } + ] + } + }, + "PORT37-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT37-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT37"}, + "i2c": + { + "topo_info": { "parent_bus":"0x26", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT37-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT37-CTRL", "device_parent":"MUX5", "virt_parent":"PORT37"}, + "i2c": + { + "topo_info": { "parent_bus":"0x26", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x250", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT38": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT38", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"38"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT38-EEPROM" }, + { "itf":"control", "dev":"PORT38-CTRL" } + ] + } + }, + "PORT38-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT38-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT38"}, + "i2c": + { + "topo_info": { "parent_bus":"0x27", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT38-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT38-CTRL", "device_parent":"MUX5", "virt_parent":"PORT38"}, + "i2c": + { + "topo_info": { "parent_bus":"0x27", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x260", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT39": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT39", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"39"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT39-EEPROM" }, + { "itf":"control", "dev":"PORT39-CTRL" } + ] + } + }, + "PORT39-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT39-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT39"}, + "i2c": + { + "topo_info": { "parent_bus":"0x28", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT39-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT39-CTRL", "device_parent":"MUX5", "virt_parent":"PORT39"}, + "i2c": + { + "topo_info": { "parent_bus":"0x28", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x270", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT40": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT40", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"40"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT40-EEPROM" }, + { "itf":"control", "dev":"PORT40-CTRL" } + ] + } + }, + "PORT40-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT40-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT40"}, + "i2c": + { + "topo_info": { "parent_bus":"0x29", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT40-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT40-CTRL", "device_parent":"MUX5", "virt_parent":"PORT40"}, + "i2c": + { + "topo_info": { "parent_bus":"0x29", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x280", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT41": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT41", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"41"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT41-EEPROM" }, + { "itf":"control", "dev":"PORT41-CTRL" } + ] + } + }, + "PORT41-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT41-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT41"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2a", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT41-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT41-CTRL", "device_parent":"MUX6", "virt_parent":"PORT41"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2a", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x290", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT42": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT42", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"42"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT42-EEPROM" }, + { "itf":"control", "dev":"PORT42-CTRL" } + ] + } + }, + "PORT42-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT42-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT42"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2b", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT42-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT42-CTRL", "device_parent":"MUX6", "virt_parent":"PORT42"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2b", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2a0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT43": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT43", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"43"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT43-EEPROM" }, + { "itf":"control", "dev":"PORT43-CTRL" } + ] + } + }, + "PORT43-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT43-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT43"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2c", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT43-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT43-CTRL", "device_parent":"MUX6", "virt_parent":"PORT43"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2c", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2b0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT44": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT44", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"44"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT44-EEPROM" }, + { "itf":"control", "dev":"PORT44-CTRL" } + ] + } + }, + "PORT44-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT44-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT44"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2d", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT44-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT44-CTRL", "device_parent":"MUX6", "virt_parent":"PORT44"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2d", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2c0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT45": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT45", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"45"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT45-EEPROM" }, + { "itf":"control", "dev":"PORT45-CTRL" } + ] + } + }, + "PORT45-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT45-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT45"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2e", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT45-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT45-CTRL", "device_parent":"MUX6", "virt_parent":"PORT45"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2e", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2d0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT46": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT46", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"46"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT46-EEPROM" }, + { "itf":"control", "dev":"PORT46-CTRL" } + ] + } + }, + "PORT46-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT46-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT46"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2f", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT46-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT46-CTRL", "device_parent":"MUX6", "virt_parent":"PORT46"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2f", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2e0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT47": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT47", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"47"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT47-EEPROM" }, + { "itf":"control", "dev":"PORT47-CTRL" } + ] + } + }, + "PORT47-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT47-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT47"}, + "i2c": + { + "topo_info": { "parent_bus":"0x30", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT47-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT47-CTRL", "device_parent":"MUX6", "virt_parent":"PORT47"}, + "i2c": + { + "topo_info": { "parent_bus":"0x30", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x2f0", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT48": + { + "dev_info": { "device_type":"SFP28", "device_name":"PORT48", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"48"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT48-EEPROM" }, + { "itf":"control", "dev":"PORT48-CTRL" } + ] + } + }, + "PORT48-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT48-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT48"}, + "i2c": + { + "topo_info": { "parent_bus":"0x31", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT48-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT48-CTRL", "device_parent":"MUX6", "virt_parent":"PORT48"}, + "i2c": + { + "topo_info": { "parent_bus":"0x31", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x300", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "PORT49": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT49", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"49"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT49-EEPROM" }, + { "itf":"control", "dev":"PORT49-CTRL" } + ] + } + }, + "PORT49-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT49-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT49"}, + "i2c": + { + "topo_info": { "parent_bus":"0x36", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT49-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT49-CTRL", "device_parent":"MUX7", "virt_parent":"PORT49"}, + "i2c": + { + "topo_info": { "parent_bus":"0x36", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x310", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x310", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x310", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + + ] + } + }, + + "PORT50": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT50", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"50"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT50-EEPROM" }, + { "itf":"control", "dev":"PORT50-CTRL" } + ] + } + }, + "PORT50-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT50-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT50"}, + "i2c": + { + "topo_info": { "parent_bus":"0x37", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT50-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT50-CTRL", "device_parent":"MUX7", "virt_parent":"PORT50"}, + "i2c": + { + "topo_info": { "parent_bus":"0x37", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x320", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x320", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x320", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT51": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT51", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"51"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT51-EEPROM" }, + { "itf":"control", "dev":"PORT51-CTRL" } + ] + } + }, + "PORT51-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT51-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT51"}, + "i2c": + { + "topo_info": { "parent_bus":"0x38", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT51-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT51-CTRL", "device_parent":"MUX7", "virt_parent":"PORT51"}, + "i2c": + { + "topo_info": { "parent_bus":"0x38", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x330", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x330", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x330", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT52": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT52", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"52"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT52-EEPROM" }, + { "itf":"control", "dev":"PORT52-CTRL" } + ] + } + }, + "PORT52-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT52-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT52"}, + "i2c": + { + "topo_info": { "parent_bus":"0x39", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT52-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT52-CTRL", "device_parent":"MUX7", "virt_parent":"PORT52"}, + "i2c": + { + "topo_info": { "parent_bus":"0x39", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x340", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x340", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x340", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT53": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT53", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"53"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT53-EEPROM" }, + { "itf":"control", "dev":"PORT53-CTRL" } + ] + } + }, + "PORT53-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT53-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT53"}, + "i2c": + { + "topo_info": { "parent_bus":"0x32", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT53-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT53-CTRL", "device_parent":"MUX7", "virt_parent":"PORT53"}, + "i2c": + { + "topo_info": { "parent_bus":"0x32", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x350", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x350", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x350", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT54": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT54", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"54"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT54-EEPROM" }, + { "itf":"control", "dev":"PORT54-CTRL" } + ] + } + }, + "PORT54-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT54-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT54"}, + "i2c": + { + "topo_info": { "parent_bus":"0x33", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT54-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT54-CTRL", "device_parent":"MUX7", "virt_parent":"PORT54"}, + "i2c": + { + "topo_info": { "parent_bus":"0x33", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x360", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x360", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x360", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT55": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT55", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"55"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT55-EEPROM" }, + { "itf":"control", "dev":"PORT55-CTRL" } + ] + } + }, + "PORT55-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT55-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT55"}, + "i2c": + { + "topo_info": { "parent_bus":"0x34", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT55-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT55-CTRL", "device_parent":"MUX7", "virt_parent":"PORT55"}, + "i2c": + { + "topo_info": { "parent_bus":"0x34", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x370", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x370", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x370", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PORT56": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT56", "device_parent":"MUX7"}, + "dev_attr": { "dev_idx":"56"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT56-EEPROM" }, + { "itf":"control", "dev":"PORT56-CTRL" } + ] + } + }, + "PORT56-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT56-EEPROM", "device_parent":"MUX7", "virt_parent":"PORT56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x35", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT56-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT56-CTRL", "device_parent":"MUX7", "virt_parent":"PORT56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x35", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1004", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x380", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x380", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x380", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"} + ] + } + }, + + "PSU1": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU1", "device_parent":"MUX8"}, + "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + {"itf":"pmbus", "dev":"PSU1-PMBUS"} + + ] + } + }, + + "PSU1-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU1-PMBUS", "device_parent":"MUX8", "virt_parent":"PSU1"}, + "i2c": + { + "topo_info":{ "parent_bus":"0x3a", "dev_addr":"0x5a", "dev_type":"psu_pmbus"}, + "attr_list": + [ + {"attr_name":"psu_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x08", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_power_good", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x02", "attr_cmpval":"0x02", "attr_len":"1"}, + {"attr_name":"psu_model_name", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_serial_num", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"14"}, + {"attr_name":"psu_mfr_id", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"7"}, + {"attr_name":"psu_fan_dir", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_p_out", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_out", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_in", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x97", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_in", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_in", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_input", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x8e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_max", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_min", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_out_max", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + + "PSU2": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU2", "device_parent":"MUX8"}, + "dev_attr": { "dev_idx":"2", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + {"itf":"pmbus", "dev":"PSU2-PMBUS"} + + ] + } + }, + + "PSU2-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU2-PMBUS", "device_parent":"MUX8", "virt_parent":"PSU2"}, + "i2c": + { + "topo_info":{ "parent_bus":"0x3b", "dev_addr":"0x5b", "dev_type":"psu_pmbus"}, + "attr_list": + [ + {"attr_name":"psu_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x04", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_power_good", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x01", "attr_cmpval":"0x01", "attr_len":"1"}, + {"attr_name":"psu_model_name", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_serial_num", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"14"}, + {"attr_name":"psu_mfr_id", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"7"}, + {"attr_name":"psu_fan_dir", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_p_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_in", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x97", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_in", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_in", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_input", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_max", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_min", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_out_max", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + + "FAN-CTRL": + { + "dev_info": { "device_type":"FAN", "device_name":"FAN-CTRL", "device_parent":"FPGAPCIE0"}, + "i2c": { + "topo_info": { "parent_bus":"0x69", "dev_addr":"0x16", "dev_type":"fan_cpld"}, + "dev_attr": { "num_fantrays":"4"}, + "attr_list": + [ + { "attr_name":"fan1_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb4", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan2_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb4", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan3_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xba", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan4_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xba", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan5_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc6", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan6_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc6", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan7_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xcc", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan8_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xcc", "attr_mask":"0x01", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan1_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb4", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan2_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb4", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan3_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xba", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan4_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xba", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan5_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc6", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan6_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc6", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan7_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xcc", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan8_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xcc", "attr_mask":"0x02", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"fan1_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb0", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan2_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb1", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan3_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb6", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan4_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb7", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan5_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc2", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan6_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc3", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan7_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc8", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan8_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc9", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + { "attr_name":"fan1_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb2", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan2_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb2", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan3_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb8", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan4_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xb8", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan5_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc4", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan6_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xc4", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan7_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xca", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"fan8_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0xca", "attr_mask":"0xff", "attr_cmpval":"0x0", "attr_len":"1"} + ] + } + }, + + "TEMP1": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP1", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"Base_Temp_U5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4d", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP2": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP2", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"Base_Temp_U56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4e", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP3": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP3", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"Switch_Temp_U31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4c", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP4": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP4", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"Switch_Temp_U30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x49", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP5": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP5", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"Switch_Temp_U28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4b", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP6": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP6", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"Switch_Temp_U29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4a", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP7": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP7", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"VDD_CORE_Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6c", "dev_addr":"0x7a", "dev_type":"mp2975"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP8": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP8", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"VDD_ANLG_Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6c", "dev_addr":"0x70", "dev_type":"mp2975"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "SYS_LED": + { + "dev_info": {"device_type":"LED", "device_name":"SYS_LED"}, + "dev_attr": {"index":"0"}, + "i2c": { + "attr_list": + [ + {"attr_name":"green", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"green", "value":"0x10", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"}, + {"attr_name":"amber", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"amber", "value":"0x20", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"}, + {"attr_name":"green_blink", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"green_blink", "value":"0x02", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"}, + {"attr_name":"off", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"off", "value":"0x33", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"} + ] + } + }, + "FANTRAY1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"0"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xb3"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xb3"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xb3"} + ] + } + }, + "FANTRAY2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"1"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xb9"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xb9"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xb9"} + ] + } + }, + "FANTRAY3_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"2"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xc5"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xc5"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xc5"} + ] + } + }, + "FANTRAY4_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"3"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xcb"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xcb"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_B","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xcb"} + ] + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/pddf_support b/device/celestica/x86_64-cel_ds2000-r0/pddf_support new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_ds2000-r0/platform.json b/device/celestica/x86_64-cel_ds2000-r0/platform.json new file mode 100644 index 000000000000..876067eaaba3 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/platform.json @@ -0,0 +1,404 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "29", + "breakout_modes": { + "1x25G[10G]": ["Eth1/1"] + } + }, + "Ethernet1": { + "index": "2", + "lanes": "30", + "breakout_modes": { + "1x25G[10G]": ["Eth2/1"] + } + }, + "Ethernet2": { + "index": "3", + "lanes": "31", + "breakout_modes": { + "1x25G[10G]": ["Eth3/1"] + } + }, + "Ethernet3": { + "index": "4", + "lanes": "32", + "breakout_modes": { + "1x25G[10G]": ["Eth4/1"] + } + }, + "Ethernet4": { + "index": "5", + "lanes": "33", + "breakout_modes": { + "1x25G[10G]": ["Eth5/1"] + } + }, + "Ethernet5": { + "index": "6", + "lanes": "34", + "breakout_modes": { + "1x25G[10G]": ["Eth6/1"] + } + }, + "Ethernet6": { + "index": "7", + "lanes": "35", + "breakout_modes": { + "1x25G[10G]": ["Eth7/1"] + } + }, + "Ethernet7": { + "index": "8", + "lanes": "36", + "breakout_modes": { + "1x25G[10G]": ["Eth8/1"] + } + }, + "Ethernet8": { + "index": "9", + "lanes": "37", + "breakout_modes": { + "1x25G[10G]": ["Eth9/1"] + } + }, + "Ethernet9": { + "index": "10", + "lanes": "38", + "breakout_modes": { + "1x25G[10G]": ["Eth10/1"] + } + }, + "Ethernet10": { + "index": "11", + "lanes": "39", + "breakout_modes": { + "1x25G[10G]": ["Eth11/1"] + } + }, + "Ethernet11": { + "index": "12", + "lanes": "40", + "breakout_modes": { + "1x25G[10G]": ["Eth12/1"] + } + }, + "Ethernet12": { + "index": "13", + "lanes": "49", + "breakout_modes": { + "1x25G[10G]": ["Eth13/1"] + } + }, + "Ethernet13": { + "index": "14", + "lanes": "50", + "breakout_modes": { + "1x25G[10G]": ["Eth14/1"] + } + }, + "Ethernet14": { + "index": "15", + "lanes": "51", + "breakout_modes": { + "1x25G[10G]": ["Eth15/1"] + } + }, + "Ethernet15": { + "index": "16", + "lanes": "52", + "breakout_modes": { + "1x25G[10G]": ["Eth16/1"] + } + }, + "Ethernet16": { + "index": "17", + "lanes": "53", + "breakout_modes": { + "1x25G[10G]": ["Eth17/1"] + } + }, + "Ethernet17": { + "index": "18", + "lanes": "54", + "breakout_modes": { + "1x25G[10G]": ["Eth18/1"] + } + }, + "Ethernet18": { + "index": "19", + "lanes": "55", + "breakout_modes": { + "1x25G[10G]": ["Eth19/1"] + } + }, + "Ethernet19": { + "index": "20", + "lanes": "56", + "breakout_modes": { + "1x25G[10G]": ["Eth20/1"] + } + }, + "Ethernet20": { + "index": "21", + "lanes": "57", + "breakout_modes": { + "1x25G[10G]": ["Eth21/1"] + } + }, + "Ethernet21": { + "index": "22", + "lanes": "58", + "breakout_modes": { + "1x25G[10G]": ["Eth22/1"] + } + }, + "Ethernet22": { + "index": "23", + "lanes": "59", + "breakout_modes": { + "1x25G[10G]": ["Eth23/1"] + } + }, + "Ethernet23": { + "index": "24", + "lanes": "60", + "breakout_modes": { + "1x25G[10G]": ["Eth24/1"] + } + }, + "Ethernet24": { + "index": "25", + "lanes": "9", + "breakout_modes": { + "1x25G[10G]": ["Eth25/1"] + } + }, + "Ethernet25": { + "index": "26", + "lanes": "10", + "breakout_modes": { + "1x25G[10G]": ["Eth26/1"] + } + }, + "Ethernet26": { + "index": "27", + "lanes": "11", + "breakout_modes": { + "1x25G[10G]": ["Eth27/1"] + } + }, + "Ethernet27": { + "index": "28", + "lanes": "12", + "breakout_modes": { + "1x25G[10G]": ["Eth28/1"] + } + }, + "Ethernet28": { + "index": "29", + "lanes": "13", + "breakout_modes": { + "1x25G[10G]": ["Eth29/1"] + } + }, + "Ethernet29": { + "index": "30", + "lanes": "14", + "breakout_modes": { + "1x25G[10G]": ["Eth30/1"] + } + }, + "Ethernet30": { + "index": "31", + "lanes": "15", + "breakout_modes": { + "1x25G[10G]": ["Eth31/1"] + } + }, + "Ethernet31": { + "index": "32", + "lanes": "16", + "breakout_modes": { + "1x25G[10G]": ["Eth32/1"] + } + }, + "Ethernet32": { + "index": "33", + "lanes": "17", + "breakout_modes": { + "1x25G[10G]": ["Eth33/1"] + } + }, + "Ethernet33": { + "index": "34", + "lanes": "18", + "breakout_modes": { + "1x25G[10G]": ["Eth34/1"] + } + }, + "Ethernet34": { + "index": "35", + "lanes": "19", + "breakout_modes": { + "1x25G[10G]": ["Eth35/1"] + } + }, + "Ethernet35": { + "index": "36", + "lanes": "20", + "breakout_modes": { + "1x25G[10G]": ["Eth36/1"] + } + }, + "Ethernet36": { + "index": "37", + "lanes": "61", + "breakout_modes": { + "1x25G[10G]": ["Eth37/1"] + } + }, + "Ethernet37": { + "index": "38", + "lanes": "62", + "breakout_modes": { + "1x25G[10G]": ["Eth38/1"] + } + }, + "Ethernet38": { + "index": "39", + "lanes": "63", + "breakout_modes": { + "1x25G[10G]": ["Eth39/1"] + } + }, + "Ethernet39": { + "index": "40", + "lanes": "64", + "breakout_modes": { + "1x25G[10G]": ["Eth40/1"] + } + }, + "Ethernet40": { + "index": "41", + "lanes": "65", + "breakout_modes": { + "1x25G[10G]": ["Eth41/1"] + } + }, + "Ethernet41": { + "index": "42", + "lanes": "66", + "breakout_modes": { + "1x25G[10G]": ["Eth42/1"] + } + }, + "Ethernet42": { + "index": "43", + "lanes": "67", + "breakout_modes": { + "1x25G[10G]": ["Eth43/1"] + } + }, + "Ethernet43": { + "index": "44", + "lanes": "68", + "breakout_modes": { + "1x25G[10G]": ["Eth44/1"] + } + }, + "Ethernet44": { + "index": "45", + "lanes": "69", + "breakout_modes": { + "1x25G[10G]": ["Eth45/1"] + } + }, + "Ethernet45": { + "index": "46", + "lanes": "70", + "breakout_modes": { + "1x25G[10G]": ["Eth46/1"] + } + }, + "Ethernet46": { + "index": "47", + "lanes": "71", + "breakout_modes": { + "1x25G[10G]": ["Eth47/1"] + } + }, + "Ethernet47": { + "index": "48", + "lanes": "72", + "breakout_modes": { + "1x25G[10G]": ["Eth48/1"] + } + }, + "Ethernet48": { + "index": "49,49,49,49", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G" : ["Eth49/1"], + "1x40G": ["Eth49/1"] + } + }, + "Ethernet52": { + "index": "50,50,50,50", + "lanes": "45,46,47,48", + "breakout_modes": { + "1x100G" : ["Eth50/1"], + "1x40G": ["Eth50/1"] + } + }, + "Ethernet56": { + "index": "51,51,51,51", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G" : ["Eth51/1"], + "1x40G": ["Eth51/1"] + } + }, + "Ethernet60": { + "index": "52,52,52,52", + "lanes": "77,78,79,80", + "breakout_modes": { + "1x100G" : ["Eth52/1"], + "1x40G": ["Eth52/1"] + } + }, + "Ethernet64": { + "index": "53,53,53,53", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G" : ["Eth53/1"], + "1x40G": ["Eth53/1"] + } + }, + "Ethernet68": { + "index": "54,54,54,54", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x100G" : ["Eth54/1"], + "1x40G": ["Eth54/1"] + } + }, + "Ethernet72": { + "index": "55,55,55,55", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G" : ["Eth55/1"], + "1x40G": ["Eth55/1"] + } + }, + "Ethernet76": { + "index": "56,56,56,56", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x100G" : ["Eth56/1"], + "1x40G": ["Eth56/1"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/platform_asic b/device/celestica/x86_64-cel_ds2000-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/celestica/x86_64-cel_ds2000-r0/platform_components-bmc.json b/device/celestica/x86_64-cel_ds2000-r0/platform_components-bmc.json new file mode 100644 index 000000000000..f2afe7f6b7d5 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/platform_components-bmc.json @@ -0,0 +1,18 @@ +{ + "chassis": { + "DS2000": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "ASIC PCIe": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/platform_components-nonbmc.json b/device/celestica/x86_64-cel_ds2000-r0/platform_components-nonbmc.json new file mode 100644 index 000000000000..6acc9a21ba5c --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/platform_components-nonbmc.json @@ -0,0 +1,15 @@ +{ + "chassis": { + "Questone2a_v2": { + "component": { + "ONIE": {}, + "ASIC_PCIe": {}, + "SSD": {}, + "BIOS": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/platform_reboot b/device/celestica/x86_64-cel_ds2000-r0/platform_reboot new file mode 100644 index 000000000000..d3d10c5b4324 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/platform_reboot @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/local/bin/ds2000_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_ds2000-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_ds2000-r0/plugins/eeprom.py new file mode 100644 index 000000000000..22895539823f --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica DX010 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError 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/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + diff --git a/device/celestica/x86_64-cel_ds2000-r0/plugins/pcie.yaml b/device/celestica/x86_64-cel_ds2000-r0/plugins/pcie.yaml new file mode 100644 index 000000000000..2074bf094d56 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/plugins/pcie.yaml @@ -0,0 +1,22 @@ +- bus: '00' + dev: '14' + fn: '0' + id: 19c2 + name: 'SATA controller: Intel Corporation DNV SATA Controller 1 (rev 11)' +- bus: '02' + dev: '00' + fn: '0' + id: b870 + name: 'Ethernet controller: Broadcom Limited Device b870 (rev 01)' +- bus: '03' + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: '04' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' + diff --git a/device/celestica/x86_64-cel_ds2000-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_ds2000-r0/plugins/sfputil.py new file mode 100755 index 000000000000..03882c65ac00 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/plugins/sfputil.py @@ -0,0 +1,312 @@ +#!/usr/bin/env python +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + import struct +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 + QSFP_PORT_START = 48 + QSFP_PORT_END = 55 + __xcvr_presence = {} + + EEPROM_OFFSET = 9 + PORT_INFO_PATH = '/sys/class/questone2_fpga' + + _port_name = "" + _port_to_eeprom_mapping = {} + _port_to_i2cbus_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def port_to_i2cbus_mapping(self): + return self._port_to_i2cbus_mapping + + def get_port_name(self, port_num): + if port_num in self.qsfp_ports: + self._port_name = "QSFP" + str(port_num - self.QSFP_PORT_START + 1) + else: + self._port_name = "SFP" + str(port_num + 1) + return self._port_name + + 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.DOM_EEPROM_ADDR, 256) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + + for x in range(self.PORT_START, self.PORT_END+1): + # port_index = 0 , it's path = /sys/bus/i2c/devices/i2c-10/10-0050/eeprom + # port_index = 55, it's path = /sys/bus/i2c/devices/i2c-65/65-0050/eeprom + # so the real offset is 10 + self.port_to_i2cbus_mapping[x] = (x + 1 + self.EEPROM_OFFSET) + self.port_to_eeprom_mapping[x] = eeprom_path.format( + x + 1 + self.EEPROM_OFFSET) + SfpUtilBase.__init__(self) + for x in range(self.PORT_START, self.PORT_END+1): + self.__xcvr_presence[x] = self.get_presence(x) + + def _do_write_file(self, file_handle, offset, value): + file_handle.seek(offset) + file_handle.write(hex(value)) + file_handle.close() + + def get_presence(self, port_num): + + # Check for invalid port_num + if port_num not in range(self.port_start, self.port_end + 1): + return False + + # Get path for access port presence status + port_name = self.get_port_name(port_num) + sysfs_filename = "qsfp_modprs" if port_num in self.qsfp_ports else "sfp_modabs" + reg_path = "/".join([self.PORT_INFO_PATH, port_name, sysfs_filename]) + + # Read status + try: + reg_file = open(reg_path) + content = reg_file.readline().rstrip() + reg_value = int(content) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # Module present is active low + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + if not self.get_presence(port_num): + return None + + eeprom_raw = [] + eeprom_raw.append("0x00") + + lpmode = False + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'.format(port_num + 1 + self.EEPROM_OFFSET) + if port_num >= 49: + try: + with open(eeprom_path, mode="rb", buffering=0) as eeprom: + eeprom.seek(93) + raw = eeprom.read(1) + eeprom.close() + except Exception as err: + return None + + if len(raw) == 0: + return None + eeprom_raw[0] = hex(ord(raw[0]))[2:].zfill(2) + + power_data = int(eeprom_raw[0], 16) + # if lpmod, power-override bit and power-set bit are both setted + # bit0 bit1 + lpmode = power_data & 0x03 != 0 + else: + return None + + return lpmode + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + if not self.get_presence(port_num): + return False + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'.format(port_num + 1 + self.EEPROM_OFFSET) + try: + reg_file = open(eeprom_path, mode="wb+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_file.seek(93) + power_raw = reg_file.read(1) + if power_raw is None: + return False + power_data = int(hex(ord(power_raw))[2:].zfill(2), 16) + + if lpmode: + power_data |= 0x03 + else: + power_data &= ~(0x03) + + reg_file.seek(93) + reg_file.write(struct.pack('B', int(power_data))) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + try: + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(0)) + reg_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + # Flip the bit back high and write back to the register to take port out of reset + try: + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_file.seek(0) + reg_file.write(hex(1)) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + """ + To detect if any transceiver change event happens. + """ + start_ms = time.time() * 1000 + xcvr_change_event_dict = {} + event = False + + while True: + time.sleep(0.5) + for port in range(self.port_start, self.port_end+1): + curr_presence = self.get_presence(port) + if curr_presence != self.__xcvr_presence[port]: + if curr_presence is True: + xcvr_change_event_dict[str(port)] = '1' + self.__xcvr_presence[port] = True + elif curr_presence is False: + xcvr_change_event_dict[str(port)] = '0' + self.__xcvr_presence[port] = False + event = True + + if event is True: + return True, xcvr_change_event_dict + + if timeout: + now_ms = time.time() * 1000 + if (now_ms - start_ms >= timeout): + return True, xcvr_change_event_dict + + def tx_disable(self, port_num, disable): + """ + @param port_num index of physical port + @param disable, True -- disable port tx signal + False -- enable port tx signal + @return True when operation success, False on failure. + """ + TX_DISABLE_BYTE_OFFSET = 86 + if port_num not in range(self.port_start, self.port_end + 1) or type(disable) != bool: + return False + + # QSFP, set eeprom to disable tx + if port_num in self.qsfp_ports: + presence = self.get_presence(port_num) + if not presence: + return True + + disable = b'\x0f' if disable else b'\x00' + # open eeprom + try: + with open(self.port_to_eeprom_mapping[port_num], mode="wb", buffering=0) as sysfsfile: + sysfsfile.seek(TX_DISABLE_BYTE_OFFSET) + sysfsfile.write(bytearray(disable)) + except IOError: + return False + + # SFP, set tx_disable pin + else: + try: + disable = hex(1) if disable else hex(0) + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "sfp_txdisable"]), "w") + reg_file.write(disable) + reg_file.close() + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + return True + + def reset_all(self): + result = True + port_sysfs_path = [] + for port in range(self.port_start, self.port_end+1): + if port not in self.qsfp_ports: + continue + + presence = self.get_presence(port) + if not presence: + continue + + try: + port_name = self.get_port_name(port) + sysfs_path = "/".join([self.PORT_INFO_PATH, + port_name, "qsfp_reset"]) + reg_file = open(sysfs_path, "w") + port_sysfs_path.append(sysfs_path) + except IOError as e: + result = False + continue + + self._do_write_file(reg_file, 0, 0) + + time.sleep(1) + + for sysfs_path in port_sysfs_path: + try: + reg_file = open(sysfs_path, "w") + except IOError as e: + result = False + continue + + self._do_write_file(reg_file, 0, 1) + + return result diff --git a/device/celestica/x86_64-cel_ds2000-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_ds2000-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/celestica/x86_64-cel_ds2000-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_ds2000-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..5661a0d21396 --- /dev/null +++ b/device/celestica/x86_64-cel_ds2000-r0/system_health_monitoring_config.json @@ -0,0 +1,16 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature", + "PSU 1 Fan 1", + "PSU 2 Fan 1" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "alternate_blink_4hz" + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers.json.j2 b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_def.j2 b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_def.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_def.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..44fcf21887a6 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t0.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t1.j2 b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/hwsku.json b/device/celestica/x86_64-cel_ds3000-r0/DS3000/hwsku.json new file mode 100644 index 000000000000..28e50b8c0385 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/hwsku.json @@ -0,0 +1,169 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet128": { + "default_brkout_mode": "1x10G", + "autoneg": "off", + "fec": "none" + } + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/l2/config b/device/celestica/x86_64-cel_ds3000-r0/DS3000/l2/config new file mode 100644 index 000000000000..45a7b84d5032 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/l2/config @@ -0,0 +1,3 @@ +l2_mem_entries=139264 +l3_mem_entries=8192 +l3_alpm_enable=0 diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/l3/config b/device/celestica/x86_64-cel_ds3000-r0/DS3000/l3/config new file mode 100644 index 000000000000..3467c1b39716 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/l3/config @@ -0,0 +1,3 @@ +l2_mem_entries=40000 +l3_mem_entries=40000 +l3_alpm_enable=2 diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/pg_profile_lookup.ini b/device/celestica/x86_64-cel_ds3000-r0/DS3000/pg_profile_lookup.ini new file mode 100644 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 56368 18432 55120 -3 2496 + 25000 5m 56368 18432 55120 -3 2496 + 40000 5m 56368 18432 55120 -3 2496 + 50000 5m 56368 18432 55120 -3 2496 + 100000 5m 56368 18432 55120 -3 2496 + 10000 40m 56368 18432 55120 -3 2496 + 25000 40m 56368 18432 55120 -3 2496 + 40000 40m 56368 18432 55120 -3 2496 + 50000 40m 56368 18432 55120 -3 2496 + 100000 40m 56368 18432 55120 -3 2496 + 10000 300m 56368 18432 55120 -3 2496 + 25000 300m 56368 18432 55120 -3 2496 + 40000 300m 56368 18432 55120 -3 2496 + 50000 300m 56368 18432 55120 -3 2496 + 100000 300m 56368 18432 55120 -3 2496 diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/port_config.ini b/device/celestica/x86_64-cel_ds3000-r0/DS3000/port_config.ini new file mode 100644 index 000000000000..8cd1c833a929 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/port_config.ini @@ -0,0 +1,34 @@ +# name lanes alias index speed valid_speeds +Ethernet0 1,2,3,4 Eth1/1 1 100000 100000,40000 +Ethernet4 5,6,7,8 Eth2/1 2 100000 100000,40000 +Ethernet8 9,10,11,12 Eth3/1 3 100000 100000,40000 +Ethernet12 13,14,15,16 Eth4/1 4 100000 100000,40000 +Ethernet16 17,18,19,20 Eth5/1 5 100000 100000,40000 +Ethernet20 21,22,23,24 Eth6/1 6 100000 100000,40000 +Ethernet24 25,26,27,28 Eth7/1 7 100000 100000,40000 +Ethernet28 29,30,31,32 Eth8/1 8 100000 100000,40000 +Ethernet32 33,34,35,36 Eth9/1 9 100000 100000,40000 +Ethernet36 37,38,39,40 Eth10/1 10 100000 100000,40000 +Ethernet40 41,42,43,44 Eth11/1 11 100000 100000,40000 +Ethernet44 45,46,47,48 Eth12/1 12 100000 100000,40000 +Ethernet48 49,50,51,52 Eth13/1 13 100000 100000,40000 +Ethernet52 53,54,55,56 Eth14/1 14 100000 100000,40000 +Ethernet56 57,58,59,60 Eth15/1 15 100000 100000,40000 +Ethernet60 61,62,63,64 Eth16/1 16 100000 100000,40000 +Ethernet64 65,66,67,68 Eth17/1 17 100000 100000,40000 +Ethernet68 69,70,71,72 Eth18/1 18 100000 100000,40000 +Ethernet72 73,74,75,76 Eth19/1 19 100000 100000,40000 +Ethernet76 77,78,79,80 Eth20/1 20 100000 100000,40000 +Ethernet80 81,82,83,84 Eth21/1 21 100000 100000,40000 +Ethernet84 85,86,87,88 Eth22/1 22 100000 100000,40000 +Ethernet88 89,90,91,92 Eth23/1 23 100000 100000,40000 +Ethernet92 93,94,95,96 Eth24/1 24 100000 100000,40000 +Ethernet96 97,98,99,100 Eth25/1 25 100000 100000,40000 +Ethernet100 101,102,103,104 Eth26/1 26 100000 100000,40000 +Ethernet104 105,106,107,108 Eth27/1 27 100000 100000,40000 +Ethernet108 109,110,111,112 Eth28/1 28 100000 100000,40000 +Ethernet112 113,114,115,116 Eth29/1 29 100000 100000,40000 +Ethernet116 117,118,119,120 Eth30/1 30 100000 100000,40000 +Ethernet120 121,122,123,124 Eth31/1 31 100000 100000,40000 +Ethernet124 125,126,127,128 Eth32/1 32 100000 100000,40000 +Ethernet128 129 Eth33/1 33 10000 10000,1000 diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/qos.json.j2 b/device/celestica/x86_64-cel_ds3000-r0/DS3000/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/sai.profile b/device/celestica/x86_64-cel_ds3000-r0/DS3000/sai.profile new file mode 100644 index 000000000000..992e6ba1f49a --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-ds3000-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_ds3000-r0/DS3000/td3-ds3000-32x100G.config.bcm b/device/celestica/x86_64-cel_ds3000-r0/DS3000/td3-ds3000-32x100G.config.bcm new file mode 100644 index 000000000000..8987f360b2b0 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/DS3000/td3-ds3000-32x100G.config.bcm @@ -0,0 +1,545 @@ +help_cli_enable=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l2_mem_entries=32768 +l2xmsg_mode=1 +l3_max_ecmp_mode=1 +l3_mem_entries=32768 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l3_alpm_enable=2 +#lpm_scaling_enable=1 +max_vp_lags=0 +#mem_cache_enable=0 +memlist_enable=1 +reglist_enable=1 +#scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 +parity_enable=0 +serdes_lane_config_dfe=on +#serdes_fec_enable=1 +serdes_if_type_ce=14 +pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 +pbmp_xport_xe=0x3ffffffffffffffffffffffffffffffffe +port_flex_enable=1 +fpem_mem_entries=32768 + +#Tunnels +bcm_tunnel_term_compatible_mode=1 +sai_tunnel_support=1 +use_all_splithorizon_groups=1 + +#RIOT Enable +riot_enable=1 +riot_overlay_l3_intf_mem_size=8192 +riot_overlay_l3_egress_mem_size=32768 +l3_ecmp_levels=2 +riot_overlay_ecmp_resilient_hash_size=16384 +flow_init_mode=1 + +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +phy_an_c73=1 + +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_21=21:100 +portmap_25=25:100 +portmap_29=29:100 +portmap_33=33:100 +portmap_37=37:100 +portmap_41=41:100 +portmap_45=45:100 +portmap_49=49:100 +portmap_53=53:100 +portmap_57=57:100 +portmap_61=61:100 +portmap_67=65:100 +portmap_71=69:100 +portmap_75=73:100 +portmap_79=77:100 +portmap_83=81:100 +portmap_87=85:100 +portmap_91=89:100 +portmap_95=93:100 +portmap_99=97:100 +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 +portmap_66=129:10:m +#portmap_130=128:10:m + +#wc0 lane swap +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 + +#wc1 lane swap +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 + +#wc2 lane swap +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 + +#wc3 lane swap +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 + +#wc4 lane swap +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 + +#wc5 lane swap +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 + +#wc6 lane swap +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 + +#wc7 lane swap +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 + +#wc8 lane swap +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 + +#wc9 lane swap +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 + +#wc10 lane swap +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 + +#wc11 lane swap +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 + +#wc12 lane swap +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 + +#wc13 lane swap +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 + +#wc14 lane swap +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 + +#wc15 lane swap +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +#wc16 lane swap +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 + +#wc17 lane swap +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 + +#wc18 lane swap +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 + +#wc19 lane swap +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 + +#wc20 lane swap +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 + +#wc21 lane swap +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 + +#wc22 lane swap +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 + +#wc23 lane swap +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 + +#wc24 lane swap +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 + +#wc25 lane swap +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 + +#wc26 lane swap +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 + +#wc27 lane swap +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 + +#wc28 lane swap +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 + +#wc29 lane swap +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 + +#wc30 lane swap +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 + +#wc31 lane swap +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 + +#MC lane swap +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x3210 + + +#wc0 P/N flip +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +#wc1 P/N flip +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +#wc2 P/N flip +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 + +#wc3 P/N flip +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}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 + +#wc4 P/N flip +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 + +#wc5 P/N flip +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 + +#wc6 P/N flip +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 + +#wc7 P/N flip +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 + +#wc8 P/N flip +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 + +#wc9 P/N flip +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +#wc10 P/N flip +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 + +#wc11 P/N flip +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 + +#wc12 P/N flip +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 + +#wc13 P/N flip +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +#wc14 P/N flip +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 + +#wc15 P/N flip +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}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +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}=0x0 + +#wc16 P/N flip +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +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}=0x0 + +#wc17 P/N flip +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +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}=0x1 +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 + +#wc18 P/N flip +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 + +#wc19 P/N flip +phy_chain_tx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +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 + +#wc20 P/N flip +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_tx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_tx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_tx_polarity_flip_physical{84.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 + +#wc21 P/N flip +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}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 + +#wc22 P/N flip +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 + +#wc23 P/N flip +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}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 + +#wc24 P/N flip +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 + +#wc25 P/N flip +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_tx_polarity_flip_physical{103.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 + +#wc26 P/N flip +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +#wc27 P/N flip +phy_chain_tx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 + +#wc28 P/N flip +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}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x0 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +#wc29 P/N flip +phy_chain_tx_polarity_flip_physical{117.0}=0x1 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_rx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_rx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 + +#wc30 P/N flip +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +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 + +#wc31 P/N flip +phy_chain_tx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +#MC P/N flip +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 diff --git a/device/celestica/x86_64-cel_ds3000-r0/custom_led.bin b/device/celestica/x86_64-cel_ds3000-r0/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..3fb048fce6b5e36050a06ecf8b7198dce531197d GIT binary patch literal 130 zcmeycl~I{djaijhg-MCaVTv330|(>To8sm6GdN~c1u;U|O&OOY7_EdVj2u=;P1?km zaWb06iTOgJ8-pgp1to?CZI&Aj+K+BJSkK<{@VR5gsbG-47VU>O85IvEFeo!8Ix9IP dI$AX)9!#`1WK424bWCbWI-GPk`EbgIy#OM^FH8Uc literal 0 HcmV?d00001 diff --git a/device/celestica/x86_64-cel_ds3000-r0/default_sku b/device/celestica/x86_64-cel_ds3000-r0/default_sku new file mode 100644 index 000000000000..dbfb3ae8e6b9 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/default_sku @@ -0,0 +1 @@ +DS3000 t1 diff --git a/device/celestica/x86_64-cel_ds3000-r0/installer.conf b/device/celestica/x86_64-cel_ds3000-r0/installer.conf new file mode 100644 index 000000000000..6e8098123edb --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_DEV=0 +CONSOLE_PORT=0xe060 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off noirqdebug earlycon=uart8250,mmio,0xdf37b000" diff --git a/device/celestica/x86_64-cel_belgite-r0/led_proc_init.soc b/device/celestica/x86_64-cel_ds3000-r0/led_proc_init.soc similarity index 71% rename from device/celestica/x86_64-cel_belgite-r0/led_proc_init.soc rename to device/celestica/x86_64-cel_ds3000-r0/led_proc_init.soc index 57ee7fedaf2b..90aa9ba607ac 100644 --- a/device/celestica/x86_64-cel_belgite-r0/led_proc_init.soc +++ b/device/celestica/x86_64-cel_ds3000-r0/led_proc_init.soc @@ -1,3 +1,2 @@ m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin -led auto on -led start +led auto on; led start diff --git a/device/celestica/x86_64-cel_ds3000-r0/media_settings.json b/device/celestica/x86_64-cel_ds3000-r0/media_settings.json new file mode 100644 index 000000000000..ded54074ab7e --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/media_settings.json @@ -0,0 +1,408 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-32": { + "25000-copper-1.0M": { + "preemphasis": { + "lane0": "0x16440a", + "lane1": "0x16440a", + "lane2": "0x16440a", + "lane3": "0x16440a" + } + }, + "25000-copper-2.0M": { + "preemphasis": { + "lane0": "0x18420a", + "lane1": "0x18420a", + "lane2": "0x18420a", + "lane3": "0x18420a" + } + }, + "25000-copper-3.0M": { + "preemphasis": { + "lane0": "0x1a400a", + "lane1": "0x1a400a", + "lane2": "0x1a400a", + "lane3": "0x1a400a" + } + }, + "25000-copper-5.0M": { + "preemphasis": { + "lane0": "0x1a400a", + "lane1": "0x1a400a", + "lane2": "0x1a400a", + "lane3": "0x1a400a" + } + }, + "10000-copper-1.0M": { + "preemphasis": { + "lane0": "0xc2808", + "lane1": "0xc2808", + "lane2": "0xc2808", + "lane3": "0xc2808" + } + }, + "10000-copper-3.0M": { + "preemphasis": { + "lane0": "0xc2808", + "lane1": "0xc2808", + "lane2": "0xc2808", + "lane3": "0xc2808" + } + }, + "10000-copper-5.0M": { + "preemphasis": { + "lane0": "0xc2808", + "lane1": "0xc2808", + "lane2": "0xc2808", + "lane3": "0xc2808" + } + }, + "10000-copper-7.0M": { + "preemphasis": { + "lane0": "0xd2708", + "lane1": "0xd2708", + "lane2": "0xd2708", + "lane3": "0xd2708" + } + }, + "10000-optical": { + "preemphasis": { + "lane0": "0xa4200", + "lane1": "0xa4200", + "lane2": "0xa4200", + "lane3": "0xa4200" + } + }, + "Default": { + "preemphasis": { + "lane0": "0x14410a", + "lane1": "0x14410a", + "lane2": "0x14410a", + "lane3": "0x14410a" + } + } + } + }, + "PORT_MEDIA_SETTINGS": { + "1": { + "25000-optical": { + "preemphasis": { + "lane0": "0x164608", + "lane1": "0x164608", + "lane2": "0x164608", + "lane3": "0x164608" + } + } + }, + "2": { + "25000-optical": { + "preemphasis": { + "lane0": "0x164608", + "lane1": "0x164608", + "lane2": "0x164608", + "lane3": "0x164608" + } + } + }, + "3": { + "25000-optical": { + "preemphasis": { + "lane0": "0x164608", + "lane1": "0x164608", + "lane2": "0x164608", + "lane3": "0x164608" + } + } + }, + "4": { + "25000-optical": { + "preemphasis": { + "lane0": "0x134908", + "lane1": "0x134908", + "lane2": "0x134908", + "lane3": "0x134908" + } + } + }, + "5": { + "25000-optical": { + "preemphasis": { + "lane0": "0x134908", + "lane1": "0x134908", + "lane2": "0x134908", + "lane3": "0x134908" + } + } + }, + "6": { + "25000-optical": { + "preemphasis": { + "lane0": "0x134908", + "lane1": "0x134908", + "lane2": "0x134908", + "lane3": "0x134908" + } + } + }, + "7": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124a08", + "lane1": "0x124a08", + "lane2": "0x124a08", + "lane3": "0x124a08" + } + } + }, + "8": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124a08", + "lane1": "0x124a08", + "lane2": "0x124a08", + "lane3": "0x124a08" + } + } + }, + "9": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + } + }, + "10": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + } + }, + "11": { + "25000-optical": { + "preemphasis": { + "lane0": "0xf4d08", + "lane1": "0xf4d08", + "lane2": "0xf4d08", + "lane3": "0xf4d08" + } + } + }, + "12": { + "25000-optical": { + "preemphasis": { + "lane0": "0xf4d08", + "lane1": "0xf4d08", + "lane2": "0xf4d08", + "lane3": "0xf4d08" + } + } + }, + "13": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "14": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "15": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "16": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "17": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "18": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "19": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "20": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "21": { + "25000-optical": { + "preemphasis": { + "lane0": "0xd4f08", + "lane1": "0xd4f08", + "lane2": "0xd4f08", + "lane3": "0xd4f08" + } + } + }, + "22": { + "25000-optical": { + "preemphasis": { + "lane0": "0xf4d08", + "lane1": "0xf4d08", + "lane2": "0xf4d08", + "lane3": "0xf4d08" + } + } + }, + "23": { + "25000-optical": { + "preemphasis": { + "lane0": "0xf4d08", + "lane1": "0xf4d08", + "lane2": "0xf4d08", + "lane3": "0xf4d08" + } + } + }, + "24": { + "25000-optical": { + "preemphasis": { + "lane0": "0xf4d08", + "lane1": "0xf4d08", + "lane2": "0xf4d08", + "lane3": "0xf4d08" + } + } + }, + "25": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + } + }, + "26": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + } + }, + "27": { + "25000-optical": { + "preemphasis": { + "lane0": "0x114b08", + "lane1": "0x114b08", + "lane2": "0x114b08", + "lane3": "0x114b08" + } + } + }, + "28": { + "25000-optical": { + "preemphasis": { + "lane0": "0x124a08", + "lane1": "0x124a08", + "lane2": "0x124a08", + "lane3": "0x124a08" + } + } + }, + "29": { + "25000-optical": { + "preemphasis": { + "lane0": "0x134908", + "lane1": "0x134908", + "lane2": "0x134908", + "lane3": "0x134908" + } + } + }, + "30": { + "25000-optical": { + "preemphasis": { + "lane0": "0x134908", + "lane1": "0x134908", + "lane2": "0x134908", + "lane3": "0x134908" + } + } + }, + "31": { + "25000-optical": { + "preemphasis": { + "lane0": "0x134908", + "lane1": "0x134908", + "lane2": "0x134908", + "lane3": "0x134908" + } + } + }, + "32": { + "25000-optical": { + "preemphasis": { + "lane0": "0x164608", + "lane1": "0x164608", + "lane2": "0x164608", + "lane3": "0x164608" + } + } + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_ds3000-r0/pcie.yaml b/device/celestica/x86_64-cel_ds3000-r0/pcie.yaml new file mode 100644 index 000000000000..2b9612671602 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/pcie.yaml @@ -0,0 +1,165 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1980' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev + 11)' +- bus: '00' + dev: '04' + fn: '0' + id: 19a1 + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers + (rev 11)' +- bus: '00' + dev: '05' + fn: '0' + id: 19a2 + name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 + Series Root Complex Event Collector (rev 11)' +- bus: '00' + dev: '06' + fn: '0' + id: 19a3 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT + Root Port (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 19a4 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #0 (rev 11)' +- bus: '00' + dev: 0b + fn: '0' + id: 19a6 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #2 (rev 11)' +- bus: '00' + dev: 0c + fn: '0' + id: 19a7 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #3 (rev 11)' +- bus: '00' + dev: 0e + fn: '0' + id: 19a8 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #4 (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 19aa + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #6 (rev 11)' +- bus: '00' + dev: '12' + fn: '0' + id: 19ac + name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller + - Host (rev 11)' +- bus: '00' + dev: '14' + fn: '0' + id: 19c2 + name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller + 1 (rev 11)' +- bus: '00' + dev: '15' + fn: '0' + id: 19d0 + name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI + Controller (rev 11)' +- bus: '00' + dev: '16' + fn: '0' + id: 19d1 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #0 (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 19d3 + name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME + HECI 1 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1c + fn: '0' + id: 19db + name: 'SD Host controller: Intel Corporation Device 19db (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 19dc + name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev + 11)' +- bus: '00' + dev: 1f + fn: '2' + id: 19de + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management + Controller (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 19df + name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev + 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 19e0 + name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series + SPI Controller (rev 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 19e2 + name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology + (rev 11)' +- bus: '02' + dev: '00' + fn: '0' + id: b870 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b870 (rev 01)' +- bus: '03' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '06' + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: '07' + dev: '00' + fn: '0' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: '07' + dev: '00' + fn: '1' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' diff --git a/device/celestica/x86_64-cel_ds3000-r0/pddf/pd-plugin.json b/device/celestica/x86_64-cel_ds3000-r0/pddf/pd-plugin.json new file mode 100644 index 000000000000..a3660c24c82e --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/pddf/pd-plugin.json @@ -0,0 +1,138 @@ +{ + "PSU": + { + "name": + { + "1": "PSU 1", + "2": "PSU 2" + }, + "fan_name": + { + "1": + { + "1": "PSU 1 Fan 1" + }, + "2": + { + "1": "PSU 2 Fan 1" + } + }, + "thermal_name": + { + "1": "PSU 1 Temp1", + "2": "PSU 2 Temp1" + }, + "psu_present": + { + "bmc": + { + "valmap": { "1":true, "0":false } + }, + "i2c": + { + "valmap": { "1":true, "0":false } + } + }, + + "psu_power_good": + { + "bmc": + { + "valmap": { "0": true, "8":false } + }, + "i2c": + { + "valmap": { "1": true, "0": false } + } + }, + + "psu_fan_dir": + { + "bmc": + { + "valmap": { "1":"INTAKE", "0":"EXHAUST" } + }, + "i2c": + { + "valmap": { "0": "INTAKE", "1":"EXHAUST" } + } + }, + + "psu_led_color": + { + "colmap": {"green":"green", "red":"amber"} + }, + + "PSU_FAN_MAX_SPEED":"18000" + }, + + "FAN": + { + "drawer_name": + { + "1": "Fantray 1", + "2": "Fantray 2", + "3": "Fantray 3", + "4": "Fantray 4" + }, + "name": + { + "1": + { + "1": "Fan 1 Front", + "2": "Fan 1 Rear" + }, + "2": + { + "1": "Fan 2 Front", + "2": "Fan 2 Rear" + }, + "3": + { + "1": "Fan 3 Front", + "2": "Fan 3 Rear" + }, + "4": + { + "1": "Fan 4 Front", + "2": "Fan 4 Rear" + } + }, + "direction": + { + "bmc": + { + "valmap": { "1":"INTAKE", "0":"EXHAUST" } + }, + "i2c": + { + "valmap": { "1":"INTAKE", "0":"EXHAUST" } + } + }, + + "present": + { + "bmc": + { + "valmap": {"0":true, "1":false} + }, + "i2c": + { + "valmap": {"0":true, "1":false} + } + }, + + "fan_master_led_color": + { + "colmap": {"green":"green", "red":"amber"} + }, + + "duty_cycle_to_pwm": "lambda dc: ((dc*255.0)/100)", + + "pwm_to_duty_cycle": "lambda pwm: ((pwm*100.0)/256)", + + "FRONT_FAN_MAX_RPM_SPEED":"24000", + "REAR_FAN_MAX_RPM_SPEED":"21000" + } + +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-bmc.json b/device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-bmc.json new file mode 100644 index 000000000000..961169bde17a --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-bmc.json @@ -0,0 +1,2123 @@ +{ +"PLATFORM": +{ + "num_psus":2, + "num_fantrays":4, + "num_fans_pertray":2, + "num_ports":33, + "num_temps":11, + "num_components":10, + "pddf_dev_types": + { + "description":" - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld" + ], + "PSU": + [ + "psu_eeprom", + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ], + "FPGAPCIE": + [ + "fpgapci" + ] + + }, + "std_perm_kos": + [ + "i2c_ismt", + "i2c-i801" + ], + + "std_kos": + [ + "lpc_ich", + "i2c_dev", + "ipmi_devintf", + "ipmi_si", + "i2c_mux_pca954x", + "optoe", + "mc24lc64t", + "baseboard_cpld" + ], + + "pddf_kos": + [ + "pddf_client_module", + "pddf_cpld_module", + "pddf_cpld_driver", + "pddf_mux_module", + "pddf_led_module", + "pddf_fpgai2c_module", + "pddf_fpgai2c_driver", + "pddf_xcvr_module", + "pddf_xcvr_driver_module", + "pddf_fpgapci_driver", + "pddf_fpgapci_module" + ], + + "custom_kos": + [ + "pddf_custom_fpga_algo" + ] + }, + + "COMPONENT1": + { + "comp_attr":{ "name": "BIOS", "type": "bios", "description": "Basic Input/Output System"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "echo `dmidecode -s bios-version`-`dmidecode -s bios-release-date`" }, + { "attr_name":"update", "cmd": "afulnx_64 {} /p /b /n /me /x /k" } + ] + }, + "COMPONENT2": + { + "comp_attr":{ "name": "BMC", "type": "bmc", "description":"Baseboard Management Controller "}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=(`ipmitool raw 0x6 0x1 | cut -d ' ' -f 4,5,16,15,14`) && echo ${r[0]}.${r[1]}.${r[4]}.${r[3]}${r[2]}" } + ] + }, + "COMPONENT3": + { + "comp_attr":{ "name": "CPLD BASE", "type": "cpld", "description": "Base Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(cat /sys/devices/platform/baseboard/version) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" }, + { "attr_name":"update", "cmd": "ispvm {}" } + ] + }, + "COMPONENT4": + { + "comp_attr":{ "name": "CPLD SW1", "type": "cpld", "description":"Switch Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(i2cget -y -f 102 0x30 0) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" } + ] + }, + "COMPONENT5": + { + "comp_attr":{ "name": "CPLD SW2", "type": "cpld", "description":"Switch Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(i2cget -y -f 102 0x31 0) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" } + ] + }, + "COMPONENT6": + { + "comp_attr":{ "name": "CPLD COMe", "type": "cpld", "description": "COMe Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(cat /sys/devices/platform/baseboard/come_cpld_version) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" } + ] + }, + "COMPONENT7": + { + "comp_attr":{ "name": "FPGA", "type": "fpga", "description": "Baseboard FPGA"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(cat /sys/devices/platform/fpga_sysfs/version) && printf '%d.%d' $(($r>>16)) $(($r&0xffff))" }, + { "attr_name":"update", "cmd": "fpga_prog /sys/bus/pci/devices/0000:06:00.0/resource0 {}" } + ] + }, + "COMPONENT8": + { + "comp_attr":{ "name": "PCIe", "type": "pcie", "description":"ASIC PCIe Firmware"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "bcmcmd 'pciephy fw version' | grep 'PCIe FW version' | cut -d ' ' -f 4" } + ] + }, + "COMPONENT9": + { + "comp_attr":{ "name": "SSD", "type": "ssd", "description":"SSD firmware version"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "ssdutil -v | grep 'Firmware' | awk '{ print $3 }'" } + ] + }, + + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + { "dev_name":"i2c-0", "dev":"SMBUS0" }, + { "dev_name":"i2c-1", "dev":"SMBUS1" }, + { "dev_name":"pcie-0", "dev":"PCIE0" } + ] + } + }, + + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"} + ] + } + }, + + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x56", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "SMBUS1": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS1", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x1"}, + "DEVICES": + [ + {"dev": "COME_CPLD"} + ] + } + }, + + "COME_CPLD": + { + "dev_info": {"device_type": "CPLD", "device_name": "CPLD COMe", "device_parent": "SMBUS1"}, + "i2c": + { + "topo_info": {"parent_bus": "0x1", "dev_addr": "0x0d", "dev_type": "i2c_cpld"}, + "dev_attr": {} + } + }, + + "PCIE0": + { + "dev_info": {"device_type": "PCIE", "device_name": "PCIE0", "device_parent": "SYSTEM"}, + "i2c": + { + "DEVICES": + [ + {"dev": "FPGAPCIE0"} + ] + } + }, + + "FPGAPCIE0": + { + "dev_info": {"device_type": "FPGAPCIE", "device_name": "FPGAPCIE0", "device_parent": "PCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x0"}, + "dev_attr": { "vendor_id":"0x10EE", "device_id": "0x7021", "virt_bus": "0x64", "data_base_offset":"0x0", "data_size":"0x25000", "i2c_ch_base_offset":"0x10000", "i2c_ch_size":"0x1000", "virt_i2c_ch":"0xc"}, + "channel": + [ + { "chn":"3", "dev":"CPLD_S1" }, + { "chn":"3", "dev":"CPLD_S2" }, + { "chn":"2", "dev":"MUX1" }, + { "chn":"2", "dev":"MUX2" }, + { "chn":"2", "dev":"MUX3" }, + { "chn":"2", "dev":"MUX4" }, + { "chn":"1", "dev":"MUX5" } + ] + } + }, + + "CPLD_S1": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD SW1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x30", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_S2": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD SW2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x31", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "MUX1": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT1" }, + { "chn":"1", "dev":"PORT2" }, + { "chn":"2", "dev":"PORT3" }, + { "chn":"3", "dev":"PORT4" }, + { "chn":"4", "dev":"PORT5" }, + { "chn":"5", "dev":"PORT6" }, + { "chn":"6", "dev":"PORT7" }, + { "chn":"7", "dev":"PORT8" } + ] + } + }, + + "MUX2": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x73", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0xa", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT9" }, + { "chn":"1", "dev":"PORT10" }, + { "chn":"2", "dev":"PORT11" }, + { "chn":"3", "dev":"PORT12" }, + { "chn":"4", "dev":"PORT13" }, + { "chn":"5", "dev":"PORT14" }, + { "chn":"6", "dev":"PORT15" }, + { "chn":"7", "dev":"PORT16" } + ] + } + }, + + "MUX3": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX3", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x74", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x12", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT17" }, + { "chn":"1", "dev":"PORT18" }, + { "chn":"2", "dev":"PORT19" }, + { "chn":"3", "dev":"PORT20" }, + { "chn":"4", "dev":"PORT21" }, + { "chn":"5", "dev":"PORT22" }, + { "chn":"6", "dev":"PORT23" }, + { "chn":"7", "dev":"PORT24" } + ] + } + }, + + "MUX4": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX4", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x75", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x1a", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT25" }, + { "chn":"1", "dev":"PORT26" }, + { "chn":"2", "dev":"PORT27" }, + { "chn":"3", "dev":"PORT28" }, + { "chn":"4", "dev":"PORT29" }, + { "chn":"5", "dev":"PORT30" }, + { "chn":"6", "dev":"PORT31" }, + { "chn":"7", "dev":"PORT32" } + ] + } + }, + "MUX5": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX5", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x22"}, + "channel": + [ + { "chn":"0", "dev":"PORT33" } + ] + } + }, + + "PORT1": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT1", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"1"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT1-EEPROM" }, + { "itf":"control", "dev":"PORT1-CTRL" } + + ] + } + }, + "PORT1-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT1-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT1-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT1-CTRL", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + "PORT2": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT2", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"2"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT2-EEPROM" }, + { "itf":"control", "dev":"PORT2-CTRL" } + ] + } + }, + + "PORT2-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT2-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT2-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT2-CTRL", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT3": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT3", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"3"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT3-EEPROM" }, + { "itf":"control", "dev":"PORT3-CTRL" } + ] + } + }, + "PORT3-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT3-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT3-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT3-CTRL", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT4": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT4", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"4"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT4-EEPROM" }, + { "itf":"control", "dev":"PORT4-CTRL" } + ] + } + }, + "PORT4-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT4-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT4-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT4-CTRL", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT5": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT5", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"5"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT5-EEPROM" }, + { "itf":"control", "dev":"PORT5-CTRL" } + ] + } + }, + + "PORT5-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT5-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT5-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT5-CTRL", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT6": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT6", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"6"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT6-EEPROM" }, + { "itf":"control", "dev":"PORT6-CTRL" } + ] + } + }, + "PORT6-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT6-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT6-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT6-CTRL", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT7": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT7", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"7"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT7-EEPROM" }, + { "itf":"control", "dev":"PORT7-CTRL" } + ] + } + }, + "PORT7-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT7-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT7-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT7-CTRL", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT8": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT8", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"8"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT8-EEPROM" }, + { "itf":"control", "dev":"PORT8-CTRL" } + ] + } + }, + "PORT8-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT8-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT8-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT8-CTRL", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT9": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT9", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"9"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT9-EEPROM" }, + { "itf":"control", "dev":"PORT9-CTRL" } + ] + } + }, + "PORT9-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT9-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT9-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT9-CTRL", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT10": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT10", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"10"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT10-EEPROM" }, + { "itf":"control", "dev":"PORT10-CTRL" } + ] + } + }, + "PORT10-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT10-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT10-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT10-CTRL", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT11": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT11", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"11"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT11-EEPROM" }, + { "itf":"control", "dev":"PORT11-CTRL" } + ] + } + }, + "PORT11-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT11-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT11-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT11-CTRL", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT12": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT12", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"12"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT12-EEPROM" }, + { "itf":"control", "dev":"PORT12-CTRL" } + ] + } + }, + "PORT12-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT12-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT12-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT12-CTRL", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT13": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT13", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"13"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT13-EEPROM" }, + { "itf":"control", "dev":"PORT13-CTRL" } + ] + } + }, + "PORT13-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT13-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT13-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT13-CTRL", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT14": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT14", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"14"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT14-EEPROM" }, + { "itf":"control", "dev":"PORT14-CTRL" } + ] + } + }, + "PORT14-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT14-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xF", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT14-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT14-CTRL", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xf", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT15": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT15", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"15"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT15-EEPROM" }, + { "itf":"control", "dev":"PORT15-CTRL" } + ] + } + }, + "PORT15-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT15-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT15-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT15-CTRL", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT16": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT16", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"16"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT16-EEPROM" }, + { "itf":"control", "dev":"PORT16-CTRL" } + ] + } + }, + "PORT16-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT16-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT16-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT16-CTRL", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT17": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT17", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"17"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT17-EEPROM" }, + { "itf":"control", "dev":"PORT17-CTRL" } + ] + } + }, + "PORT17-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT17-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT17-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT17-CTRL", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT18": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT18", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"18"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT18-EEPROM" }, + { "itf":"control", "dev":"PORT18-CTRL" } + ] + } + }, + "PORT18-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT18-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT18-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT18-CTRL", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT19": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT19", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"19"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT19-EEPROM" }, + { "itf":"control", "dev":"PORT19-CTRL" } + ] + } + }, + "PORT19-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT19-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT19-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT19-CTRL", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT20": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT20", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"20"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT20-EEPROM" }, + { "itf":"control", "dev":"PORT20-CTRL" } + ] + } + }, + "PORT20-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT20-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT20-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT20-CTRL", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT21": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT21", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"21"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT21-EEPROM" }, + { "itf":"control", "dev":"PORT21-CTRL" } + ] + } + }, + "PORT21-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT21-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT21-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT21-CTRL", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT22": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT22", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"22"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT22-EEPROM" }, + { "itf":"control", "dev":"PORT22-CTRL" } + ] + } + }, + "PORT22-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT22-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT22-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT22-CTRL", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT23": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT23", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"23"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT23-EEPROM" }, + { "itf":"control", "dev":"PORT23-CTRL" } + ] + } + }, + "PORT23-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT23-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT23-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT23-CTRL", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT24": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT24", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"24"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT24-EEPROM" }, + { "itf":"control", "dev":"PORT24-CTRL" } + ] + } + }, + "PORT24-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT24-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT24-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT24-CTRL", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT25": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT25", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"25"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT25-EEPROM" }, + { "itf":"control", "dev":"PORT25-CTRL" } + ] + } + }, + "PORT25-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT25-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT25-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT25-CTRL", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT26": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT26", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"26"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT26-EEPROM" }, + { "itf":"control", "dev":"PORT26-CTRL" } + ] + } + }, + "PORT26-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT26-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT26-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT26-CTRL", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT27": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT27", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"27"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT27-EEPROM" }, + { "itf":"control", "dev":"PORT27-CTRL" } + ] + } + }, + "PORT27-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT27-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT27-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT27-CTRL", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT28": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT28", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"28"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT28-EEPROM" }, + { "itf":"control", "dev":"PORT28-CTRL" } + ] + } + }, + "PORT28-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT28-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT28-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT28-CTRL", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT29": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT29", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"29"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT29-EEPROM" }, + { "itf":"control", "dev":"PORT29-CTRL" } + ] + } + }, + "PORT29-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT29-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT29-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT29-CTRL", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT30": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT30", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"30"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT30-EEPROM" }, + { "itf":"control", "dev":"PORT30-CTRL" } + ] + } + }, + "PORT30-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT30-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT30-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT30-CTRL", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT31": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT31", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"31"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT31-EEPROM" }, + { "itf":"control", "dev":"PORT31-CTRL" } + ] + } + }, + "PORT31-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT31-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT31-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT31-CTRL", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT32": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT32", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"32"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT32-EEPROM" }, + { "itf":"control", "dev":"PORT32-CTRL" } + ] + } + }, + "PORT32-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT32-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT32-CTRL": + { + "dev_info": { "device_type":"pci", "device_name":"PORT32-CTRL", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT33": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT33", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"33"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT33-EEPROM" }, + { "itf":"control", "dev":"PORT33-CTRL" } + ] + } + }, + "PORT33-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT33-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT33-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT33-CTRL", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"} + ] + } + }, + + "PSU1": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU 1"}, + "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"psu_power_good", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x0f", "raw": "1", "type":"raw", "offset":"2", "mask":"0x8"}, + { "attr_name":"psu_present", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x0f", "raw": "1", "type":"raw", "offset":"2", "mask":"0x1"}, + { "attr_name":"psu_model_name", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Name", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_serial_num", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Serial", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_mfr_id", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Manufacturer", "separator":":", "field_pos":"2"}, + { "attr_name":"psu_p_out", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x21", "raw": "1", "type":"raw", "offset":"0", "multiplier":"6000000"}, + { "attr_name":"psu_v_out", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x1f", "raw":"1", "type":"raw", "offset":"0", "multiplier":"100"}, + { "attr_name":"psu_i_out", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x20", "raw":"1", "type":"raw", "offset":"0", "multiplier":"500"}, + { "attr_name":"psu_p_in", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x1b", "raw": "1", "type":"raw", "offset":"0", "multiplier":"6000000"}, + { "attr_name":"psu_v_in", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x19", "raw":"1", "type":"raw", "offset":"0", "multiplier":"100"}, + { "attr_name":"psu_i_in", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x1a", "raw":"1", "type":"raw", "offset":"0", "multiplier":"500"}, + { "attr_name":"psu_fan1_speed_rpm", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x1c", "raw":"1", "type":"raw", "offset":"0", "multiplier":"200"}, + { "attr_name":"psu_temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x1d", "raw":"1", "type":"raw", "offset":"0", "multiplier":"1000"}, + { "attr_name":"psu_temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x1d", "raw":"1", "type":"raw", "offset":"5", "multiplier":"1000"} + ] + } + } + }, + + "PSU2": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU 2"}, + "dev_attr": { "dev_idx":"2", "num_psu_fans": "1"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"psu_power_good", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x10", "raw": "1", "type":"raw", "offset":"2", "mask":"0x8"}, + { "attr_name":"psu_present", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x10", "raw": "1", "type":"raw", "offset":"2", "mask":"0x1"}, + { "attr_name":"psu_model_name", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Name", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_serial_num", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Serial", "separator":": ","field_pos":"2"}, + { "attr_name":"psu_mfr_id", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Product Manufacturer", "separator":":", "field_pos":"2"}, + { "attr_name":"psu_p_out", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x2a", "raw": "1", "type":"raw", "offset":"0", "multiplier":"6000000"}, + { "attr_name":"psu_v_out", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x28", "raw":"1", "type":"raw", "offset":"0", "multiplier":"100"}, + { "attr_name":"psu_i_out", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x29", "raw":"1", "type":"raw", "offset":"0", "multiplier":"500"}, + { "attr_name":"psu_p_in", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x24", "raw": "1", "type":"raw", "offset":"0", "multiplier":"6000000"}, + { "attr_name":"psu_v_in", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x22", "raw":"1", "type":"raw", "offset":"0", "multiplier":"100"}, + { "attr_name":"psu_i_in", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x23", "raw":"1", "type":"raw", "offset":"0", "multiplier":"500"}, + { "attr_name":"psu_fan1_speed_rpm", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x25", "raw":"1", "type":"raw", "offset":"0", "multiplier":"200"}, + { "attr_name":"psu_temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2d 0x26", "raw":"1", "type":"raw", "offset":"0", "multiplier":"1000"}, + { "attr_name":"psu_temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x26", "raw":"1", "type":"raw", "offset":"5", "multiplier":"1000"} + ] + } + } + }, + + "FAN-CTRL": + { + "dev_info": { "device_type":"FAN"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"fan1_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x00", "type":"raw", "raw":"1"}, + {"attr_name":"fan2_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x00", "type":"raw", "raw":"1"}, + {"attr_name":"fan3_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x01", "type":"raw", "raw":"1"}, + {"attr_name":"fan4_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x01", "type":"raw", "raw":"1"}, + {"attr_name":"fan5_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x02", "type":"raw", "raw":"1"}, + {"attr_name":"fan6_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x02", "type":"raw", "raw":"1"}, + {"attr_name":"fan7_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x03", "type":"raw", "raw":"1"}, + {"attr_name":"fan8_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x03", "type":"raw", "raw":"1"}, + {"attr_name":"fan1_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x00", "type":"raw", "raw": "1"}, + {"attr_name":"fan2_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x00", "type":"raw", "raw": "1"}, + {"attr_name":"fan3_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x01", "type":"raw", "raw": "1"}, + {"attr_name":"fan4_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x01", "type":"raw", "raw": "1"}, + {"attr_name":"fan5_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x02", "type":"raw", "raw": "1"}, + {"attr_name":"fan6_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x02", "type":"raw", "raw": "1"}, + {"attr_name":"fan7_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x03", "type":"raw", "raw": "1"}, + {"attr_name":"fan8_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x03", "type":"raw", "raw": "1"}, + {"attr_name":"fan1_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 00", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan2_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 00", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan3_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 01", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan4_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 01", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan5_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 02", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan6_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 02", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan7_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 03", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan8_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 03", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + { "attr_name":"fan1_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan1_Front", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan2_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan1_Rear", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan3_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan2_Front", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan4_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan2_Rear", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan5_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan3_Front", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan6_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan3_Rear", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan7_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan4_Front", "field_pos":"3", "multiplier":"1"}, + { "attr_name":"fan8_pwm", "bmc_cmd":"ipmitool sensor", "raw":"0", "field_name" : "Fan4_Rear", "field_pos":"3", "multiplier":"1"} + ] + } + } + }, + + "TEMP1": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"CPU Internal Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x7", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x7", "raw":"1", "type": "raw", "offset":"6"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x7", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP2": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Baseboard Left Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x1", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1", "raw":"1", "type": "raw", "offset":"0"} + + ] + } + } + }, + "TEMP3": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Baseboard Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x1", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP4": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"ASIC External Front Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x3", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP5": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"ASIC External Rear Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x4", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP6": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Switchboard Left Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x6", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP7": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"Switchboard Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x5", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP8": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"MP2975 VDD CORE Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x49", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x49", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP9": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"MP2975 VDD ANLG Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x50", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x50", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP10": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"PSU 1 Temp2"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x1E", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x1E", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "TEMP11": + { + "dev_info": { "device_type":"TEMP_SENSOR"}, + "dev_attr": { "display_name":"PSU 2 Temp2"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x27", "raw":"1", "type": "raw", "offset":"5"}, + { "attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x27", "raw":"1", "type": "raw", "offset":"0"} + ] + } + } + }, + "SYS_LED": + { + "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, + "dev_attr": { "index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"amber_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"}, + { "attr_name":"amber_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x04"}, + { "attr_name":"green_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x05"}, + { "attr_name":"green_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x06"}, + { "attr_name":"both_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x07"}, + { "attr_name":"both_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x08"}, + { "attr_name":"unknown", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x09"} + ] + } + } + }, + "ALARM_LED": + { + "dev_info": { "device_type":"LED", "device_name":"ALARM_LED"}, + "dev_attr": { "index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"amber_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"}, + { "attr_name":"amber_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x04"}, + { "attr_name":"green_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x05"}, + { "attr_name":"green_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x06"}, + { "attr_name":"unknown", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x09"} + ] + } + } + }, + "FANTRAY1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY1_LED"}, + "dev_attr": { "index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x04", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x04", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x04", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"unknown", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x04", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"} + ] + } + } + }, + "FANTRAY2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY2_LED"}, + "dev_attr": { "index":"1", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x05", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x05", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x05", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"unknown", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x05", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"} + ] + } + } + }, + "FANTRAY3_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY3_LED"}, + "dev_attr": { "index":"2", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x06", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x06", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x06", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"unknown", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x06", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"} + ] + } + } + }, + "FANTRAY4_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY4_LED"}, + "dev_attr": { "index":"3", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + { "attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x07", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x00"}, + { "attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x07", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x01"}, + { "attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x07", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x02"}, + { "attr_name":"unknown", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x07", "raw": "1", "type":"mask", "mask" : "0xff", "descr" :"OFF", "value" : "0x03"} + ] + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-nonbmc.json b/device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-nonbmc.json new file mode 100644 index 000000000000..f50535020007 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/pddf/pddf-device-nonbmc.json @@ -0,0 +1,2216 @@ +{ +"PLATFORM": +{ + "num_psus":2, + "num_fantrays":4, + "num_fans_pertray":2, + "num_ports":33, + "num_temps":6, + "num_components":8, + "pddf_dev_types": + { + "description":" - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld" + ], + "PSU": + [ + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl", + "fan_eeprom", + "fan_cpld" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ], + "FPGAPCIE": + [ + "fpgapci" + ] + + }, + "std_perm_kos": + [ + "i2c_ismt", + "i2c-i801" + ], + + "std_kos": + [ + "lpc_ich", + "i2c_dev", + "i2c_mux_pca954x", + "optoe", + "mc24lc64t", + "ucd9000", + "mp2975", + "lm75", + "at24" + ], + + "pddf_kos": + [ + "pddf_client_module", + "pddf_cpld_module", + "pddf_cpld_driver", + "pddf_mux_module", + "pddf_fan_module", + "pddf_psu_module", + "pddf_led_module", + "pddf_fpgai2c_module", + "pddf_fpgai2c_driver", + "pddf_xcvr_module", + "pddf_xcvr_driver_module", + "pddf_fpgapci_driver", + "pddf_fpgapci_module" + ], + + "custom_kos": + [ + "pddf_custom_psu_driver_module", + "pddf_custom_fpga_algo" + ] + }, + + "COMPONENT1": + { + "comp_attr":{ "name": "BIOS", "type": "bios", "description": "Basic Input/Output System"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "echo `dmidecode -s bios-version`-`dmidecode -s bios-release-date`" }, + { "attr_name":"update", "cmd": "afulnx_64 {} /p /b /n /me /x /k" } + ] + }, + "COMPONENT2": + { + "comp_attr":{ "name": "CPLD BASE", "type": "cpld", "description": "Base Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(cat /sys/devices/platform/baseboard/version) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" }, + { "attr_name":"update", "cmd": "ispvm {}" } + ] + }, + "COMPONENT3": + { + "comp_attr":{ "name": "CPLD SW1", "type": "cpld", "description":"Switch Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(i2cget -y -f 102 0x30 0) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" } + ] + }, + "COMPONENT4": + { + "comp_attr":{ "name": "CPLD SW2", "type": "cpld", "description":"Switch Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(i2cget -y -f 102 0x31 0) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" } + ] + }, + "COMPONENT5": + { + "comp_attr":{ "name": "CPLD COMe", "type": "cpld", "description": "COMe Board CPLD"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(cat /sys/devices/platform/baseboard/come_cpld_version) && printf '%d.%d' $(($r>>4)) $(($r&0xf))" } + ] + }, + "COMPONENT6": + { + "comp_attr":{ "name": "FPGA", "type": "fpga", "description": "Baseboard FPGA"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "r=$(cat /sys/devices/platform/fpga_sysfs/version) && printf '%d.%d' $(($r>>16)) $(($r&0xffff))" }, + { "attr_name":"update", "cmd": "fpga_prog /sys/bus/pci/devices/0000:06:00.0/resource0 {}" } + ] + }, + "COMPONENT7": + { + "comp_attr":{ "name": "PCIe", "type": "pcie", "description":"ASIC PCIe Firmware"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "bcmcmd 'pciephy fw version' | grep 'PCIe FW version' | cut -d ' ' -f 4" } + ] + }, + "COMPONENT8": + { + "comp_attr":{ "name": "SSD", "type": "ssd", "description":"SSD firmware version"}, + "attr_list": + [ + { "attr_name":"version", "get_cmd": "ssdutil -v | grep 'Firmware' | awk '{ print $3 }'" } + ] + }, + + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + { "dev_name":"i2c-0", "dev":"SMBUS0" }, + { "dev_name":"i2c-1", "dev":"SMBUS1" }, + { "dev_name":"pcie-0", "dev":"PCIE0" } + ] + } + }, + + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"} + ] + } + }, + + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x56", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "SMBUS1": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS1", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x1"}, + "DEVICES": + [ + {"dev": "COME_CPLD"} + ] + } + }, + + "COME_CPLD": + { + "dev_info": {"device_type": "CPLD", "device_name": "CPLD COMe", "device_parent": "SMBUS1"}, + "i2c": + { + "topo_info": {"parent_bus": "0x1", "dev_addr": "0x0d", "dev_type": "i2c_cpld"}, + "dev_attr": {} + } + }, + + "PCIE0": + { + "dev_info": {"device_type": "PCIE", "device_name": "PCIE0", "device_parent": "SYSTEM"}, + "i2c": + { + "DEVICES": + [ + {"dev": "FPGAPCIE0"} + ] + } + }, + + "FPGAPCIE0": + { + "dev_info": {"device_type": "FPGAPCIE", "device_name": "FPGAPCIE0", "device_parent": "PCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x0"}, + "dev_attr": { "vendor_id":"0x10EE", "device_id": "0x7021", "virt_bus": "0x64", "data_base_offset":"0x0", "data_size":"0x25000", "i2c_ch_base_offset":"0x10000", "i2c_ch_size":"0x1000", "virt_i2c_ch":"0xc"}, + "channel": + [ + { "chn":"2", "dev":"MUX1" }, + { "chn":"2", "dev":"MUX2" }, + { "chn":"2", "dev":"MUX3" }, + { "chn":"2", "dev":"MUX4" }, + { "chn":"1", "dev":"MUX5" }, + { "chn":"3", "dev":"CPLD_S1" }, + { "chn":"3", "dev":"CPLD_S2" }, + { "chn":"4", "dev":"EEPROM_COME" }, + { "chn":"4", "dev":"CPLD_COME" }, + { "chn":"5", "dev":"EEPROM_BASEBOARD" }, + { "chn":"6", "dev":"FAN-CTRL" }, + { "chn":"6", "dev":"CPLD_BASEBOARD" }, + { "chn":"7", "dev":"MUX6" }, + { "chn":"10", "dev":"TEMP1" }, + { "chn":"10", "dev":"TEMP2" }, + { "chn":"10", "dev":"TEMP3" }, + { "chn":"10", "dev":"TEMP4" }, + { "chn":"10", "dev":"TEMP5" }, + { "chn":"10", "dev":"TEMP6" }, + { "chn":"11", "dev":"MUX7" } + ] + } + }, + + "TEMP1": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP1", "device_parent":"FPGAPCIE0"}, + "dev_attr": { "display_name":"Base_Temp_U5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4d", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP2": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP2", "device_parent":"FPGAPCIE0"}, + "dev_attr": { "display_name":"Base_Temp_U56"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4e", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP3": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP3", "device_parent":"FPGAPCIE0"}, + "dev_attr": { "display_name":"Switch_Temp_U17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4c", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP4": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4", "device_parent":"FPGAPCIE0"}, + "dev_attr": { "display_name":"Switch_Temp_U18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x49", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP5": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP5", "device_parent":"FPGAPCIE0"}, + "dev_attr": { "display_name":"Switch_Temp_U28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4a", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP6": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP6", "device_parent":"FPGAPCIE0"}, + "dev_attr": { "display_name":"Switch_Temp_U29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6d", "dev_addr":"0x4b", "dev_type":"lm75"}, + "attr_list": + [ + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_max_hyst"}, + { "attr_name": "temp1_input"} + ] + } + }, + + "CPLD_BASEBOARD": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD BASE", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x69", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "EEPROM_BASEBOARD": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM_BASEBOARD", "device_parent": "FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x68", "dev_addr": "0x57", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "EEPROM_COME": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM_COME", "device_parent": "FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x67", "dev_addr": "0x50", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "CPLD_COME": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD_COME", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x67", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_S1": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD SW1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x30", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_S2": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD SW2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x31", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "MUX1": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT1" }, + { "chn":"1", "dev":"PORT2" }, + { "chn":"2", "dev":"PORT3" }, + { "chn":"3", "dev":"PORT4" }, + { "chn":"4", "dev":"PORT5" }, + { "chn":"5", "dev":"PORT6" }, + { "chn":"6", "dev":"PORT7" }, + { "chn":"7", "dev":"PORT8" } + ] + } + }, + + "MUX2": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x73", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0xa", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT9" }, + { "chn":"1", "dev":"PORT10" }, + { "chn":"2", "dev":"PORT11" }, + { "chn":"3", "dev":"PORT12" }, + { "chn":"4", "dev":"PORT13" }, + { "chn":"5", "dev":"PORT14" }, + { "chn":"6", "dev":"PORT15" }, + { "chn":"7", "dev":"PORT16" } + ] + } + }, + + "MUX3": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX3", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x74", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x12", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT17" }, + { "chn":"1", "dev":"PORT18" }, + { "chn":"2", "dev":"PORT19" }, + { "chn":"3", "dev":"PORT20" }, + { "chn":"4", "dev":"PORT21" }, + { "chn":"5", "dev":"PORT22" }, + { "chn":"6", "dev":"PORT23" }, + { "chn":"7", "dev":"PORT24" } + ] + } + }, + + "MUX4": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX4", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x65", "dev_addr":"0x75", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x1a", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PORT25" }, + { "chn":"1", "dev":"PORT26" }, + { "chn":"2", "dev":"PORT27" }, + { "chn":"3", "dev":"PORT28" }, + { "chn":"4", "dev":"PORT29" }, + { "chn":"5", "dev":"PORT30" }, + { "chn":"6", "dev":"PORT31" }, + { "chn":"7", "dev":"PORT32" } + ] + } + }, + "MUX5": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX5", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x22"}, + "channel": + [ + { "chn":"0", "dev":"PORT33" } + ] + } + }, + + "MUX6": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX6", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6a", "dev_addr":"0x70", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x2a", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"PSU1" }, + { "chn":"0", "dev":"PSU1-EEPROM" }, + { "chn":"1", "dev":"PSU2" }, + { "chn":"1", "dev":"PSU2-EEPROM" } + ] + } + }, + + "MUX7": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX7", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6e", "dev_addr":"0x77", "dev_type":"pca9548"}, + "dev_attr": { "virt_bus":"0x32", "idle_state":"-2" }, + "channel": + [ + { "chn":"0", "dev":"FANTRAY1_EEPROM" }, + { "chn":"1", "dev":"FANTRAY2_EEPROM" }, + { "chn":"3", "dev":"FANTRAY3_EEPROM" }, + { "chn":"4", "dev":"FANTRAY4_EEPROM" } + ] + } + }, + + "PORT1": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT1", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"1"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT1-EEPROM" }, + { "itf":"control", "dev":"PORT1-CTRL" } + + ] + } + }, + "PORT1-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT1-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + "PORT1-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT1-CTRL", "device_parent":"MUX1", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": { "parent_bus":"0x2", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + "PORT2": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT2", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"2"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT2-EEPROM" }, + { "itf":"control", "dev":"PORT2-CTRL" } + ] + } + }, + + "PORT2-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT2-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT2-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT2-CTRL", "device_parent":"MUX1", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": { "parent_bus":"0x3", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x10", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT3": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT3", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"3"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT3-EEPROM" }, + { "itf":"control", "dev":"PORT3-CTRL" } + ] + } + }, + "PORT3-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT3-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT3-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT3-CTRL", "device_parent":"MUX1", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": { "parent_bus":"0x4", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x20", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT4": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT4", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"4"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT4-EEPROM" }, + { "itf":"control", "dev":"PORT4-CTRL" } + ] + } + }, + "PORT4-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT4-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT4-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT4-CTRL", "device_parent":"MUX1", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": { "parent_bus":"0x5", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x30", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT5": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT5", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"5"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT5-EEPROM" }, + { "itf":"control", "dev":"PORT5-CTRL" } + ] + } + }, + + "PORT5-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT5-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT5-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT5-CTRL", "device_parent":"MUX1", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x40", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT6": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT6", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"6"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT6-EEPROM" }, + { "itf":"control", "dev":"PORT6-CTRL" } + ] + } + }, + "PORT6-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT6-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT6-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT6-CTRL", "device_parent":"MUX1", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": { "parent_bus":"0x7", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x50", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT7": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT7", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"7"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT7-EEPROM" }, + { "itf":"control", "dev":"PORT7-CTRL" } + ] + } + }, + "PORT7-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT7-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT7-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT7-CTRL", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": { "parent_bus":"0x8", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x60", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT8": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT8", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"8"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT8-EEPROM" }, + { "itf":"control", "dev":"PORT8-CTRL" } + ] + } + }, + "PORT8-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT8-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT8-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT8-CTRL", "device_parent":"MUX1", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": { "parent_bus":"0x9", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x70", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT9": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT9", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"9"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT9-EEPROM" }, + { "itf":"control", "dev":"PORT9-CTRL" } + ] + } + }, + "PORT9-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT9-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT9-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT9-CTRL", "device_parent":"MUX2", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": { "parent_bus":"0xa", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x80", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT10": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT10", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"10"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT10-EEPROM" }, + { "itf":"control", "dev":"PORT10-CTRL" } + ] + } + }, + "PORT10-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT10-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT10-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT10-CTRL", "device_parent":"MUX2", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": { "parent_bus":"0xb", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x90", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT11": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT11", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"11"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT11-EEPROM" }, + { "itf":"control", "dev":"PORT11-CTRL" } + ] + } + }, + "PORT11-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT11-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT11-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT11-CTRL", "device_parent":"MUX2", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": { "parent_bus":"0xc", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xa0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT12": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT12", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"12"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT12-EEPROM" }, + { "itf":"control", "dev":"PORT12-CTRL" } + ] + } + }, + "PORT12-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT12-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT12-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT12-CTRL", "device_parent":"MUX2", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": { "parent_bus":"0xd", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xb0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT13": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT13", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"13"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT13-EEPROM" }, + { "itf":"control", "dev":"PORT13-CTRL" } + ] + } + }, + "PORT13-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT13-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT13-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT13-CTRL", "device_parent":"MUX2", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": { "parent_bus":"0xe", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xc0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT14": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT14", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"14"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT14-EEPROM" }, + { "itf":"control", "dev":"PORT14-CTRL" } + ] + } + }, + "PORT14-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT14-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xF", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT14-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT14-CTRL", "device_parent":"MUX2", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": { "parent_bus":"0xf", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xd0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT15": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT15", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"15"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT15-EEPROM" }, + { "itf":"control", "dev":"PORT15-CTRL" } + ] + } + }, + "PORT15-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT15-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT15-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT15-CTRL", "device_parent":"MUX2", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xe0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT16": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT16", "device_parent":"MUX2"}, + "dev_attr": { "dev_idx":"16"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT16-EEPROM" }, + { "itf":"control", "dev":"PORT16-CTRL" } + ] + } + }, + "PORT16-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT16-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT16-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT16-CTRL", "device_parent":"MUX2", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x11", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0xf0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT17": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT17", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"17"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT17-EEPROM" }, + { "itf":"control", "dev":"PORT17-CTRL" } + ] + } + }, + "PORT17-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT17-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT17-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT17-CTRL", "device_parent":"MUX3", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x12", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x100", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT18": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT18", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"18"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT18-EEPROM" }, + { "itf":"control", "dev":"PORT18-CTRL" } + ] + } + }, + "PORT18-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT18-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT18-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT18-CTRL", "device_parent":"MUX3", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": { "parent_bus":"0x13", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x110", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT19": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT19", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"19"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT19-EEPROM" }, + { "itf":"control", "dev":"PORT19-CTRL" } + ] + } + }, + "PORT19-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT19-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT19-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT19-CTRL", "device_parent":"MUX3", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": { "parent_bus":"0x14", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x120", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT20": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT20", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"20"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT20-EEPROM" }, + { "itf":"control", "dev":"PORT20-CTRL" } + ] + } + }, + "PORT20-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT20-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT20-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT20-CTRL", "device_parent":"MUX3", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": { "parent_bus":"0x15", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x130", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT21": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT21", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"21"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT21-EEPROM" }, + { "itf":"control", "dev":"PORT21-CTRL" } + ] + } + }, + "PORT21-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT21-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT21-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT21-CTRL", "device_parent":"MUX3", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x140", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT22": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT22", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"22"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT22-EEPROM" }, + { "itf":"control", "dev":"PORT22-CTRL" } + ] + } + }, + "PORT22-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT22-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT22-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT22-CTRL", "device_parent":"MUX3", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x150", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT23": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT23", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"23"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT23-EEPROM" }, + { "itf":"control", "dev":"PORT23-CTRL" } + ] + } + }, + "PORT23-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT23-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT23-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT23-CTRL", "device_parent":"MUX3", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": { "parent_bus":"0x18", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x160", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT24": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT24", "device_parent":"MUX3"}, + "dev_attr": { "dev_idx":"24"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT24-EEPROM" }, + { "itf":"control", "dev":"PORT24-CTRL" } + ] + } + }, + "PORT24-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT24-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT24-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT24-CTRL", "device_parent":"MUX3", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": { "parent_bus":"0x19", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x170", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT25": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT25", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"25"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT25-EEPROM" }, + { "itf":"control", "dev":"PORT25-CTRL" } + ] + } + }, + "PORT25-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT25-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT25-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT25-CTRL", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1a", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x180", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT26": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT26", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"26"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT26-EEPROM" }, + { "itf":"control", "dev":"PORT26-CTRL" } + ] + } + }, + "PORT26-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT26-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + + "PORT26-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT26-CTRL", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1b", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x190", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT27": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT27", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"27"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT27-EEPROM" }, + { "itf":"control", "dev":"PORT27-CTRL" } + ] + } + }, + "PORT27-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT27-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT27-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT27-CTRL", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1c", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1a0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT28": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT28", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"28"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT28-EEPROM" }, + { "itf":"control", "dev":"PORT28-CTRL" } + ] + } + }, + "PORT28-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT28-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT28-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT28-CTRL", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1d", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1b0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT29": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT29", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"29"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT29-EEPROM" }, + { "itf":"control", "dev":"PORT29-CTRL" } + ] + } + }, + "PORT29-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT29-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT29-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT29-CTRL", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1e", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1c0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT30": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT30", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"30"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT30-EEPROM" }, + { "itf":"control", "dev":"PORT30-CTRL" } + ] + } + }, + "PORT30-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT30-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT30-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT30-CTRL", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": { "parent_bus":"0x1f", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1d0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT31": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT31", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"31"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT31-EEPROM" }, + { "itf":"control", "dev":"PORT31-CTRL" } + ] + } + }, + "PORT31-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT31-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT31-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT31-CTRL", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": { "parent_bus":"0x20", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1e0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + + "PORT32": + { + "dev_info": { "device_type":"QSFP28", "device_name":"PORT32", "device_parent":"MUX4"}, + "dev_attr": { "dev_idx":"32"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT32-EEPROM" }, + { "itf":"control", "dev":"PORT32-CTRL" } + ] + } + }, + "PORT32-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT32-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT32-CTRL": + { + "dev_info": { "device_type":"pci", "device_name":"PORT32-CTRL", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": { "parent_bus":"0x21", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_lpmode", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x6", "attr_cmpval":"0x40", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x1f0", "attr_mask":"0x4", "attr_cmpval":"0x10", "attr_len":"1"} + ] + } + }, + + "PORT33": + { + "dev_info": { "device_type":"SFP+", "device_name":"PORT33", "device_parent":"MUX5"}, + "dev_attr": { "dev_idx":"33"}, + "i2c": + { + "interface": + [ + { "itf":"eeprom", "dev":"PORT33-EEPROM" }, + { "itf":"control", "dev":"PORT33-CTRL" } + ] + } + }, + "PORT33-EEPROM": + { + "dev_info": { "device_type":"", "device_name":"PORT33-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + { "attr_name":"eeprom"} + ] + } + }, + + "PORT33-CTRL": + { + "dev_info": { "device_type":"", "device_name":"PORT33-CTRL", "device_parent":"MUX5", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": { "parent_bus":"0x22", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x2", "attr_cmpval":"0x4", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x1010", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x1014", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x1", "attr_cmpval":"0x2", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x1018", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x200", "attr_mask":"0x0", "attr_cmpval":"0x1", "attr_len":"1"} + ] + } + }, + + "PSU1": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU 1", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + { "itf":"pmbus", "dev":"PSU1-PMBUS" } + ] + } + }, + "PSU1-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU1-PMBUS", "device_parent":"MUX6", "virt_parent":"PSU1" }, + "i2c": + { + "topo_info":{ "parent_bus":"0x2a", "dev_addr":"0x5a", "dev_type":"psu_pmbus"}, + "attr_list": + [ + {"attr_name":"psu_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0x60", "attr_mask":"0x08", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_power_good", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0x60", "attr_mask":"0x02", "attr_cmpval":"0x02", "attr_len":"1"}, + {"attr_name":"psu_model_name", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_serial_num", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"13"}, + {"attr_name":"psu_mfr_id", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"7"}, + {"attr_name":"psu_fan_dir", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_p_out", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_out", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_in", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x97", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_in", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_in", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_input", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0x8e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_max", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_min", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_out_max", "attr_devaddr":"0x5a", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + "PSU1-EEPROM": + { + "dev_info": {"device_type": "EEPROM", "device_name": "PSU1-EEPROM", "device_parent": "MUX6"}, + "i2c": + { + "topo_info": {"parent_bus": "0x2a", "dev_addr": "0x52", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "PSU2": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU 2", "device_parent":"MUX6"}, + "dev_attr": { "dev_idx":"2", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + { "itf":"pmbus", "dev":"PSU2-PMBUS" } + ] + } + }, + "PSU2-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU2-PMBUS", "device_parent":"MUX6", "virt_parent":"PSU2" }, + "i2c": + { + "topo_info":{ "parent_bus":"0x2b", "dev_addr":"0x5b", "dev_type":"psu_pmbus"}, + "attr_list": + [ + {"attr_name":"psu_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0x60", "attr_mask":"0x04", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_power_good", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0x60", "attr_mask":"0x01", "attr_cmpval":"0x01", "attr_len":"1"}, + {"attr_name":"psu_model_name", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_serial_num", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13"}, + {"attr_name":"psu_mfr_id", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"7"}, + {"attr_name":"psu_fan_dir", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_p_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_in", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x97", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_in", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_in", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_input", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_max", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_min", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_out_max", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + "PSU2-EEPROM": + { + "dev_info": {"device_type": "EEPROM", "device_name": "PSU2-EEPROM", "device_parent": "MUX6"}, + "i2c": + { + "topo_info": {"parent_bus": "0x2b", "dev_addr": "0x53", "dev_type": "24lc64t"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "FANTRAY1_EEPROM": + { + "dev_info": {"device_type": "EEPROM", "device_name": "FANTRAY1_EEPROM", "device_parent": "MUX7"}, + "i2c": + { + "topo_info": {"parent_bus": "0x32", "dev_addr": "0x50", "dev_type": "24c64"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + "FANTRAY2_EEPROM": + { + "dev_info": {"device_type": "EEPROM", "device_name": "FANTRAY2_EEPROM", "device_parent": "MUX7"}, + "i2c": + { + "topo_info": {"parent_bus": "0x33", "dev_addr": "0x50", "dev_type": "24c64"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + "FANTRAY3_EEPROM": + { + "dev_info": {"device_type": "EEPROM", "device_name": "FANTRAY3_EEPROM", "device_parent": "MUX7"}, + "i2c": + { + "topo_info": {"parent_bus": "0x35", "dev_addr": "0x50", "dev_type": "24c64"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + "FANTRAY4_EEPROM": + { + "dev_info": {"device_type": "EEPROM", "device_name": "FANTRAY4_EEPROM", "device_parent": "MUX7"}, + "i2c": + { + "topo_info": {"parent_bus": "0x36", "dev_addr": "0x50", "dev_type": "24c64"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "FAN-CTRL": + { + "dev_info": { "device_type":"FAN", "device_name":"FAN-CTRL", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x69", "dev_addr":"0x16", "dev_type":"fan_cpld"}, + "dev_attr": { "num_fantrays":"4"}, + "attr_list": + [ + {"attr_name":"fan1_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb4", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan2_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb4", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan3_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xba", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan4_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xba", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan5_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc6", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan6_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc6", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan7_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xcc", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan8_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xcc", "attr_mask":"0x01", "attr_cmpval": "0x1", "attr_len":"1"}, + {"attr_name":"fan1_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb4", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan2_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb4", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan3_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xba", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan4_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xba", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan5_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc6", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan6_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc6", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan7_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xcc", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan8_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xcc", "attr_mask":"0x02", "attr_cmpval": "0x2", "attr_len":"1"}, + {"attr_name":"fan1_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb0", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan2_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb1", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan3_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb6", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan4_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb7", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan5_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc2", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan6_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc3", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan7_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc8", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan8_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc9", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"120", "attr_is_divisor":0}, + {"attr_name":"fan1_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb2", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan2_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb2", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan3_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb8", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan4_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xb8", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan5_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc4", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan6_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xc4", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan7_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xca", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"}, + {"attr_name":"fan8_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "attr_offset":"0xca", "attr_mask":"0xff", "attr_cmpval": "0x0","attr_len":"1"} + ] + } + }, + + "FANTRAY1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"0"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xb3"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xb3"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xb3"} + ] + } + }, + "FANTRAY2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"1"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xb9"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xb9"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xb9"} + ] + } + }, + "FANTRAY3_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"2"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xbf"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xbf"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xbf"} + ] + } + }, + "FANTRAY4_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"3"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"off","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Off","value":"0x03","swpld_addr":"0x0d","swpld_addr_offset":"0xc5"}, + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Green","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0xc5"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"CPLD_BASEBOARD","bits":"1:0","descr":"Amber","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0xc5"} + ] + } + }, + + "PSU_LED": + { + "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, + "dev_attr": { "index":"0", "flag": "rw"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green", "descr": "Green", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "bits" : "7:6", "value" : "0x1", "swpld_addr" : "0x0d", "swpld_addr_offset" : "0x61"}, + {"attr_name":"amber", "descr": "Amber", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "bits" : "7:6", "value" : "0x2", "swpld_addr" : "0x0d", "swpld_addr_offset" : "0x61"}, + {"attr_name":"off", "descr": "Off", "attr_devtype":"cpld", "attr_devname":"CPLD_BASEBOARD", "bits" : "7:6", "value" : "0x3", "swpld_addr" : "0x0d", "swpld_addr_offset" : "0x61"} + ] + } + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/pddf_support b/device/celestica/x86_64-cel_ds3000-r0/pddf_support new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_ds3000-r0/platform.json b/device/celestica/x86_64-cel_ds3000-r0/platform.json new file mode 100644 index 000000000000..c180d6d186d5 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/platform.json @@ -0,0 +1,267 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G":["Eth1/1"], + "1x40G": ["Eth1/1"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G": ["Eth2/1"], + "1x40G": ["Eth2/1"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "9,10,11,12", + "breakout_modes": { + "1x100G": ["Eth3/1"], + "1x40G": ["Eth3/1"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "13,14,15,16", + "breakout_modes": { + "1x100G": ["Eth4/1"], + "1x40G": ["Eth4/1"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "17,18,19,20", + "breakout_modes": { + "1x100G": ["Eth5/1"], + "1x40G": ["Eth5/1"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x100G": ["Eth6/1"], + "1x40G": ["Eth6/1"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x100G": ["Eth7/1"], + "1x40G": ["Eth7/1"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "29,30,31,32", + "breakout_modes": { + "1x100G": ["Eth8/1"], + "1x40G": ["Eth8/1"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "33,34,35,36", + "breakout_modes": { + "1x100G": ["Eth9/1"], + "1x40G": ["Eth9/1"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "37,38,39,40", + "breakout_modes": { + "1x100G": ["Eth10/1"], + "1x40G": ["Eth10/1"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G": ["Eth11/1"], + "1x40G": ["Eth11/1"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "45,46,47,48", + "breakout_modes": { + "1x100G": ["Eth12/1"], + "1x40G": ["Eth12/1"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "49,50,51,52", + "breakout_modes": { + "1x100G": ["Eth13/1"], + "1x40G": ["Eth13/1"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "53,54,55,56", + "breakout_modes": { + "1x100G": ["Eth14/1"], + "1x40G": ["Eth14/1"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "57,58,59,60", + "breakout_modes": { + "1x100G": ["Eth15/1"], + "1x40G": ["Eth15/1"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "61,62,63,64", + "breakout_modes": { + "1x100G": ["Eth16/1"], + "1x40G": ["Eth16/1"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "65,66,67,68", + "breakout_modes": { + "1x100G": ["Eth17/1"], + "1x40G": ["Eth17/1"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G": ["Eth18/1"], + "1x40G": ["Eth18/1"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G": ["Eth19/1"], + "1x40G": ["Eth19/1"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "77,78,79,80", + "breakout_modes": { + "1x100G": ["Eth20/1"], + "1x40G": ["Eth20/1"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "81,82,83,84", + "breakout_modes": { + "1x100G": ["Eth21/1"], + "1x40G": ["Eth21/1"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "85,86,87,88", + "breakout_modes": { + "1x100G": ["Eth22/1"], + "1x40G": ["Eth22/1"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "89,90,91,92", + "breakout_modes": { + "1x100G": ["Eth23/1"], + "1x40G": ["Eth23/1"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "93,94,95,96", + "breakout_modes": { + "1x100G": ["Eth24/1"], + "1x40G": ["Eth24/1"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "97,98,99,100", + "breakout_modes": { + "1x100G": ["Eth25/1"], + "1x40G": ["Eth25/1"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "101,102,103,104", + "breakout_modes": { + "1x100G": ["Eth26/1"], + "1x40G": ["Eth26/1"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "105,106,107,108", + "breakout_modes": { + "1x100G": ["Eth27/1"], + "1x40G": ["Eth27/1"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "109,110,111,112", + "breakout_modes": { + "1x100G": ["Eth28/1"], + "1x40G": ["Eth28/1"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "113,114,115,116", + "breakout_modes": { + "1x100G": ["Eth29/1"], + "1x40G": ["Eth29/1"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "117,118,119,120", + "breakout_modes": { + "1x100G": ["Eth30/1"], + "1x40G": ["Eth30/1"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "121,122,123,124", + "breakout_modes": { + "1x100G": ["Eth31/1"], + "1x40G": ["Eth31/1"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "125,126,127,128", + "breakout_modes": { + "1x100G": ["Eth32/1"], + "1x40G": ["Eth32/1"] + } + }, + "Ethernet128": { + "index": "33", + "lanes": "129", + "breakout_modes": { + "1x10G": ["Eth33/1"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/platform_asic b/device/celestica/x86_64-cel_ds3000-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/celestica/x86_64-cel_ds3000-r0/platform_components.json b/device/celestica/x86_64-cel_ds3000-r0/platform_components.json new file mode 100644 index 000000000000..fa985b8f01e9 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/platform_components.json @@ -0,0 +1,18 @@ +{ + "chassis": { + "DS3000": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "ASIC PCIe": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/platform_reboot b/device/celestica/x86_64-cel_ds3000-r0/platform_reboot new file mode 100755 index 000000000000..b5212804e636 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/platform_reboot @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/local/bin/ds3000_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_ds3000-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_ds3000-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..5e59513ef696 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false, + "skip_syseepromd": false, + "skip_fancontrol": true +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_ds3000-r0/sensors.conf b/device/celestica/x86_64-cel_ds3000-r0/sensors.conf new file mode 100644 index 000000000000..8d441077a677 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/sensors.conf @@ -0,0 +1,87 @@ +# LM75B temperature sensors +bus "i2c-109" "i2c-pci-9" + chip "lm75-i2c-109-4a" + label temp1 "Switchboard U28 Sensor Temp" + set temp1_max 60 + set temp1_max_hyst 57 + chip "lm75-i2c-109-4b" + label temp1 "Switchboard U29 Sensor Temp" + set temp1_max 60 + set temp1_max_hyst 57 + chip "lm75-i2c-109-4c" + label temp1 "Switchboard U17 Sensor Temp" + chip "lm75-i2c-109-49" + label temp1 "Switchboard U18 Sensor Temp" + chip "lm75-i2c-109-4d" + label temp1 "Baseboard U5 Sensor Temp" + set temp1_max 55 + set temp1_max_hyst 52 + chip "lm75-i2c-109-4e" + label temp1 "Baseboard U56 Sensor Temp" + set temp1_max 55 + set temp1_max_hyst 52 + +# PSU +bus "i2c-43" "i2c-106-mux (chan_id 1)" + chip "psu_pmbus-i2c-43-5b" + label in3 "PSU2 input voltage" + label fan1 "PSU2 FAN speed" + label temp1 "PSU2 temperature" + label power2 "PSU2 AC Power Voltage" + label curr2 "PSU2 AC current" + +bus "i2c-42" "i2c-106-mux (chan_id 0)" + chip "psu_pmbus-i2c-42-5a" + label in3 "PSU1 input voltage" + label fan1 "PSU1 FAN speed" + label temp1 "PSU1 temperature" + label power2 "PSU1 AC Power Voltage" + label curr2 "PSU1 AC current" + +# MP2975 power chip +bus "i2c-108" "i2c-pci-8" + chip "mp2975-i2c-108-70" + label in1 "VDD ANLG input voltage" + label in2 "VDD ANLG output voltage" + label in3 "VDD ANLG output voltage" + label temp1 "VDD ANLG temperature" + label power1 "VDD ANLG input power" + label power2 "VDD ANLG output power" + label power3 "VDD ANLG output power" + label curr1 "VDD ANLG input current" + label curr2 "VDD ANLG output current" + label curr3 "VDD ANLG output current" + label curr4 "VDD ANLG output current" + label curr5 "VDD ANLG output current" + +bus "i2c-108" "i2c-pci-8" + chip "mp2975-i2c-108-7a" + label in1 "VDD CORE input voltage" + label in2 "VDD CORE output voltage" + label in3 "VDD CORE output voltage" + label temp1 "VDD CORE temperature" + label power1 "VDD CORE input power" + label power2 "VDD CORE output power" + label power3 "VDD CORE output power" + label curr1 "VDD CORE input current" + label curr2 "VDD CORE output current" + label curr3 "VDD CORE output current" + label curr4 "VDD CORE output current" + label curr5 "VDD CORE output current" + label curr6 "VDD CORE output current" + label curr7 "VDD CORE output current" + label curr8 "VDD CORE output current" + label curr9 "VDD CORE output current" + label curr10 "VDD CORE output current" + +# CPLD FAN +bus "i2c-105" "i2c-pci-5" + chip "fan_cpld-i2c-105-16" + label fan1 "FAN1 Front Fan" + label fan2 "FAN1 Rear Fan" + label fan3 "FAN2 Front Fan" + label fan4 "FAN2 Rear Fan" + label fan5 "FAN3 Front Fan" + label fan6 "FAN3 Rear Fan" + label fan7 "FAN4 Front Fan" + label fan8 "FAN4 Rear Fan" diff --git a/device/celestica/x86_64-cel_ds3000-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_ds3000-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..5661a0d21396 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/system_health_monitoring_config.json @@ -0,0 +1,16 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature", + "PSU 1 Fan 1", + "PSU 2 Fan 1" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "alternate_blink_4hz" + } +} diff --git a/device/celestica/x86_64-cel_ds3000-r0/thermal_policy.json b/device/celestica/x86_64-cel_ds3000-r0/thermal_policy.json new file mode 100644 index 000000000000..515348ec6ab0 --- /dev/null +++ b/device/celestica/x86_64-cel_ds3000-r0/thermal_policy.json @@ -0,0 +1,136 @@ +{ + "interval": 4, + "thermal_control_algorithm": { + "run_at_boot_up": "True", + "fan_speed_when_suspend": "50" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "thermal_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "temp over high critical threshold", + "conditions": [ + { + "type": "thermal.over.high_critical_threshold" + } + ], + "actions": [ + { + "type": "switch.shutdown" + } + ] + }, + { + "name": "any fantray absence", + "conditions": [ + { + "type": "fantray.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "more than one fan rotor failed", + "conditions": [ + { + "type": "fan.rotor.more_than_one.failed" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any thermal over high threshold", + "conditions": [ + { + "type": "thermal.any.over.high_threshold" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any thermal below high threshold", + "conditions": [ + { + "type": "thermal.any.below.low_threshold" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "10" + } + ] + }, + { + "name": "thermal control algorithm", + "conditions": [ + { + "type": "fantray.all.presence" + }, + { + "type": "fan.rotor.less_than_two.failed" + }, + { + "type": "psu.all.presence" + }, + { + "type": "thermal.all.below.high_threshold" + }, + { + "type": "thermal.all.over.low_threshold" + } + ], + "actions": [ + { + "thermal_log_level": 5, + "type": "thermal.temp_check_and_fsc_algo_control", + "cpu_pid_params": [78, 3, 0.5, 0.2], + "bcm_pid_params": [88, 4, 0.3, 0.4], + "f2b_linear_params": [34, 54, 3, 35, 100], + "b2f_linear_params": [27, 48, 3, 35, 100] + } + ] + } + ] +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/custom_led.bin b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..b2ed8cb8d09014028181c580ddaaafa943990585 GIT binary patch literal 248 zcmeycHQp`E&DYJv?ZXx>232oK1`ESZHwKjk#SS-SH6_n3Hzq|vhaNZiiYmED46GTU z(MAl8ZkkR47n(9INitdqRj^uJ+{B{EdZUXW(5)+Cx*L-c(*q+0h6jvFdQQw265SXy z87>$xxMpYtGa9p)c)Q-b$f$TQfkBx$QCi69)viwcCfi2i(?JFfcp;VnZWi6J9=k0Z}n=30XOL1w|!g6-_N|9Y!W*7FITP mj?l31h}gLJgv6xel+3K`9825E!dgdP*C?RgARq?OFg5^j6GYhn literal 0 HcmV?d00001 diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/hwsku.json b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/hwsku.json new file mode 100644 index 000000000000..a559890f3a18 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/hwsku.json @@ -0,0 +1,284 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet1": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet2": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet3": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet5": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet6": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet7": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet9": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet10": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet11": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet13": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet14": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet15": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet17": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet18": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet19": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet21": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet22": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet23": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet25": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet26": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet27": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet29": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet30": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet31": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet33": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet34": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet35": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet37": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet38": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet39": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet41": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet42": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet43": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet45": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet46": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet47": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform.json b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform.json new file mode 100644 index 000000000000..0805efbc7ba4 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform.json @@ -0,0 +1,396 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "49", + "breakout_modes": { + "1x25G": ["Eth1/1"] + } + }, + "Ethernet1": { + "index": "2", + "lanes": "50", + "breakout_modes": { + "1x25G": ["Eth2/1"] + } + }, + "Ethernet2": { + "index": "3", + "lanes": "51", + "breakout_modes": { + "1x25G": ["Eth3/1"] + } + }, + "Ethernet3": { + "index": "4", + "lanes": "52", + "breakout_modes": { + "1x25G": ["Eth4/1"] + } + }, + "Ethernet4": { + "index": "5", + "lanes": "57", + "breakout_modes": { + "1x25G": ["Eth5/1"] + } + }, + "Ethernet5": { + "index": "6", + "lanes": "58", + "breakout_modes": { + "1x25G": ["Eth6/1"] + } + }, + "Ethernet6": { + "index": "7", + "lanes": "59", + "breakout_modes": { + "1x25G": ["Eth7/1"] + } + }, + "Ethernet7": { + "index": "8", + "lanes": "60", + "breakout_modes": { + "1x25G": ["Eth8/1"] + } + }, + "Ethernet8": { + "index": "9", + "lanes": "61", + "breakout_modes": { + "1x25G": ["Eth9/1"] + } + }, + "Ethernet9": { + "index": "10", + "lanes": "62", + "breakout_modes": { + "1x25G": ["Eth10/1"] + } + }, + "Ethernet10": { + "index": "11", + "lanes": "63", + "breakout_modes": { + "1x25G": ["Eth11/1"] + } + }, + "Ethernet11": { + "index": "12", + "lanes": "64", + "breakout_modes": { + "1x25G": ["Eth12/1"] + } + }, + "Ethernet12": { + "index": "13", + "lanes": "77", + "breakout_modes": { + "1x25G": ["Eth13/1"] + } + }, + "Ethernet13": { + "index": "14", + "lanes": "78", + "breakout_modes": { + "1x25G": ["Eth14/1"] + } + }, + "Ethernet14": { + "index": "15", + "lanes": "79", + "breakout_modes": { + "1x25G": ["Eth15/1"] + } + }, + "Ethernet15": { + "index": "16", + "lanes": "80", + "breakout_modes": { + "1x25G": ["Eth16/1"] + } + }, + "Ethernet16": { + "index": "17", + "lanes": "85", + "breakout_modes": { + "1x25G": ["Eth17/1"] + } + }, + "Ethernet17": { + "index": "18", + "lanes": "86", + "breakout_modes": { + "1x25G": ["Eth18/1"] + } + }, + "Ethernet18": { + "index": "19", + "lanes": "87", + "breakout_modes": { + "1x25G": ["Eth19/1"] + } + }, + "Ethernet19": { + "index": "20", + "lanes": "88", + "breakout_modes": { + "1x25G": ["Eth20/1"] + } + }, + "Ethernet20": { + "index": "21", + "lanes": "93", + "breakout_modes": { + "1x25G": ["Eth21/1"] + } + }, + "Ethernet21": { + "index": "22", + "lanes": "94", + "breakout_modes": { + "1x25G": ["Eth22/1"] + } + }, + "Ethernet22": { + "index": "23", + "lanes": "95", + "breakout_modes": { + "1x25G": ["Eth23/1"] + } + }, + "Ethernet23": { + "index": "24", + "lanes": "96", + "breakout_modes": { + "1x25G": ["Eth24/1"] + } + }, + "Ethernet24": { + "index": "25", + "lanes": "13", + "breakout_modes": { + "1x25G": ["Eth25/1"] + } + }, + "Ethernet25": { + "index": "26", + "lanes": "14", + "breakout_modes": { + "1x25G": ["Eth26/1"] + } + }, + "Ethernet26": { + "index": "27", + "lanes": "15", + "breakout_modes": { + "1x25G": ["Eth27/1"] + } + }, + "Ethernet27": { + "index": "28", + "lanes": "16", + "breakout_modes": { + "1x25G": ["Eth28/1"] + } + }, + "Ethernet28": { + "index": "29", + "lanes": "21", + "breakout_modes": { + "1x25G": ["Eth29/1"] + } + }, + "Ethernet29": { + "index": "30", + "lanes": "22", + "breakout_modes": { + "1x25G": ["Eth30/1"] + } + }, + "Ethernet30": { + "index": "31", + "lanes": "23", + "breakout_modes": { + "1x25G": ["Eth31/1"] + } + }, + "Ethernet31": { + "index": "32", + "lanes": "24", + "breakout_modes": { + "1x25G": ["Eth32/1"] + } + }, + "Ethernet32": { + "index": "33", + "lanes": "29", + "breakout_modes": { + "1x25G": ["Eth33/1"] + } + }, + "Ethernet33": { + "index": "34", + "lanes": "30", + "breakout_modes": { + "1x25G": ["Eth34/1"] + } + }, + "Ethernet34": { + "index": "35", + "lanes": "31", + "breakout_modes": { + "1x25G": ["Eth35/1"] + } + }, + "Ethernet35": { + "index": "36", + "lanes": "32", + "breakout_modes": { + "1x25G": ["Eth36/1"] + } + }, + "Ethernet36": { + "index": "37", + "lanes": "97", + "breakout_modes": { + "1x25G": ["Eth37/1"] + } + }, + "Ethernet37": { + "index": "38", + "lanes": "98", + "breakout_modes": { + "1x25G": ["Eth38/1"] + } + }, + "Ethernet38": { + "index": "39", + "lanes": "99", + "breakout_modes": { + "1x25G": ["Eth39/1"] + } + }, + "Ethernet39": { + "index": "40", + "lanes": "100", + "breakout_modes": { + "1x25G": ["Eth40/1"] + } + }, + "Ethernet40": { + "index": "41", + "lanes": "105", + "breakout_modes": { + "1x25G": ["Eth41/1"] + } + }, + "Ethernet41": { + "index": "42", + "lanes": "106", + "breakout_modes": { + "1x25G": ["Eth42/1"] + } + }, + "Ethernet42": { + "index": "43", + "lanes": "107", + "breakout_modes": { + "1x25G": ["Eth43/1"] + } + }, + "Ethernet43": { + "index": "44", + "lanes": "108", + "breakout_modes": { + "1x25G": ["Eth44/1"] + } + }, + "Ethernet44": { + "index": "45", + "lanes": "113", + "breakout_modes": { + "1x25G": ["Eth45/1"] + } + }, + "Ethernet45": { + "index": "46", + "lanes": "114", + "breakout_modes": { + "1x25G": ["Eth46/1"] + } + }, + "Ethernet46": { + "index": "47", + "lanes": "115", + "breakout_modes": { + "1x25G": ["Eth47/1"] + } + }, + "Ethernet47": { + "index": "48", + "lanes": "116", + "breakout_modes": { + "1x25G": ["Eth48/1"] + } + }, + "Ethernet48": { + "index": "49,49,49,49", + "lanes": "65,66,67,68", + "breakout_modes": { + "1x100G": ["Eth49/1"] + } + }, + "Ethernet52": { + "index": "50,50,50,50", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G": ["Eth50/1"] + } + }, + "Ethernet56": { + "index": "51,51,51,51", + "lanes": "121,122,123,124", + "breakout_modes": { + "1x100G": ["Eth51/1"] + } + }, + "Ethernet60": { + "index": "52,52,52,52", + "lanes": "125,126,127,128", + "breakout_modes": { + "1x100G": ["Eth52/1"] + } + }, + "Ethernet64": { + "index": "53,53,53,53", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G": ["Eth53/1"] + } + }, + "Ethernet68": { + "index": "54,54,54,54", + "lanes": "33,34,35,36", + "breakout_modes": { + "1x100G": ["Eth54/1"] + } + }, + "Ethernet72": { + "index": "55,55,55,55", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G": ["Eth55/1"] + } + }, + "Ethernet76": { + "index": "56,56,56,56", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G": ["Eth56/1"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform_components.json b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform_components.json new file mode 100644 index 000000000000..b86899e311ab --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/platform_components.json @@ -0,0 +1,17 @@ +{ + "chassis": { + "Questone_2": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/port_config.ini b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/port_config.ini new file mode 100644 index 000000000000..37c4f0cfd042 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed mtu admin_status fec +Ethernet0 49 Eth1/1 1 25000 9216 up rs +Ethernet1 50 Eth2/1 2 25000 9216 up rs +Ethernet2 51 Eth3/1 3 25000 9216 up rs +Ethernet3 52 Eth4/1 4 25000 9216 up rs +Ethernet4 57 Eth5/1 5 25000 9216 up rs +Ethernet5 58 Eth6/1 6 25000 9216 up rs +Ethernet6 59 Eth7/1 7 25000 9216 up rs +Ethernet7 60 Eth8/1 8 25000 9216 up rs +Ethernet8 61 Eth9/1 9 25000 9216 up rs +Ethernet9 62 Eth10/1 10 25000 9216 up rs +Ethernet10 63 Eth11/1 11 25000 9216 up rs +Ethernet11 64 Eth12/1 12 25000 9216 up rs +Ethernet12 77 Eth13/1 13 25000 9216 up rs +Ethernet13 78 Eth14/1 14 25000 9216 up rs +Ethernet14 79 Eth15/1 15 25000 9216 up rs +Ethernet15 80 Eth16/1 16 25000 9216 up rs +Ethernet16 85 Eth17/1 17 25000 9216 up rs +Ethernet17 86 Eth18/1 18 25000 9216 up rs +Ethernet18 87 Eth19/1 19 25000 9216 up rs +Ethernet19 88 Eth20/1 20 25000 9216 up rs +Ethernet20 93 Eth21/1 21 25000 9216 up rs +Ethernet21 94 Eth22/1 22 25000 9216 up rs +Ethernet22 95 Eth23/1 23 25000 9216 up rs +Ethernet23 96 Eth24/1 24 25000 9216 up rs +Ethernet24 13 Eth25/1 25 25000 9216 up rs +Ethernet25 14 Eth26/1 26 25000 9216 up rs +Ethernet26 15 Eth27/1 27 25000 9216 up rs +Ethernet27 16 Eth28/1 28 25000 9216 up rs +Ethernet28 21 Eth29/1 29 25000 9216 up rs +Ethernet29 22 Eth30/1 30 25000 9216 up rs +Ethernet30 23 Eth31/1 31 25000 9216 up rs +Ethernet31 24 Eth32/1 32 25000 9216 up rs +Ethernet32 29 Eth33/1 33 25000 9216 up rs +Ethernet33 30 Eth34/1 34 25000 9216 up rs +Ethernet34 31 Eth35/1 35 25000 9216 up rs +Ethernet35 32 Eth36/1 36 25000 9216 up rs +Ethernet36 97 Eth37/1 37 25000 9216 up rs +Ethernet37 98 Eth38/1 38 25000 9216 up rs +Ethernet38 99 Eth39/1 39 25000 9216 up rs +Ethernet39 100 Eth40/1 40 25000 9216 up rs +Ethernet40 105 Eth41/1 41 25000 9216 up rs +Ethernet41 106 Eth42/1 42 25000 9216 up rs +Ethernet42 107 Eth43/1 43 25000 9216 up rs +Ethernet43 108 Eth44/1 44 25000 9216 up rs +Ethernet44 113 Eth45/1 45 25000 9216 up rs +Ethernet45 114 Eth46/1 46 25000 9216 up rs +Ethernet46 115 Eth47/1 47 25000 9216 up rs +Ethernet47 116 Eth48/1 48 25000 9216 up rs +Ethernet48 65,66,67,68 Eth49/1 49 100000 9216 up rs +Ethernet52 69,70,71,72 Eth50/1 50 100000 9216 up rs +Ethernet56 121,122,123,124 Eth51/1 51 100000 9216 up rs +Ethernet60 125,126,127,128 Eth52/1 52 100000 9216 up rs +Ethernet64 1,2,3,4 Eth53/1 53 100000 9216 up rs +Ethernet68 33,34,35,36 Eth54/1 54 100000 9216 up rs +Ethernet72 5,6,7,8 Eth55/1 55 100000 9216 up rs +Ethernet76 41,42,43,44 Eth56/1 56 100000 9216 up rs diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai.profile b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai.profile new file mode 100644 index 000000000000..636d9d72fc17 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as13-48f8h.config.bcm diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai_postinit_cmd.soc b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai_postinit_cmd.soc new file mode 100644 index 000000000000..731625308a5e --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/sai_postinit_cmd.soc @@ -0,0 +1,2 @@ +modreg ING_MISC_CONFIG INPUT_PRI_TAGGED=1 +modreg ING_MISC_CONFIG INPUT_PRI_UNTAGGED=1 diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2/td3-as13-48f8h.config.bcm b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/td3-as13-48f8h.config.bcm new file mode 100644 index 000000000000..f9f3308d30cb --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2/td3-as13-48f8h.config.bcm @@ -0,0 +1,359 @@ +help_cli_enable=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l2_mem_entries=32768 +l2xmsg_mode=1 +l3_max_ecmp_mode=1 +l3_mem_entries=49152 +l3_alpm_enable=2 +bcm_stat_interval=1000000 +host_as_route_disable=1 +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 +serdes_lane_config_dfe=on +#serdes_fec_enable=1 +serdes_if_type_xe=13 +serdes_if_type_ce=14 +pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 +#pbmp_xport_xe=0x48878787f8787808dfe1e0203e1e1e022 +pbmp_xport_xe=0x8808787f87808088221e1e1fe1e1e1fe + + +portmap_1.0=1:100 +portmap_5.0=5:100 +portmap_13.0=13:25 +portmap_14.0=14:25 +portmap_15.0=15:25 +portmap_16.0=16:25 +portmap_21.0=21:25 +portmap_22.0=22:25 +portmap_23.0=23:25 +portmap_24.0=24:25 +portmap_29.0=29:25 +portmap_30.0=30:25 +portmap_31.0=31:25 +portmap_32.0=32:25 +portmap_33.0=33:100 +portmap_41.0=41:100 +portmap_49.0=49:25 +portmap_50.0=50:25 +portmap_51.0=51:25 +portmap_52.0=52:25 +portmap_57.0=57:25 +portmap_58.0=58:25 +portmap_59.0=59:25 +portmap_60.0=60:25 +portmap_61.0=61:25 +portmap_62.0=62:25 +portmap_63.0=63:25 +portmap_64.0=64:25 +portmap_67.0=65:100 +portmap_71.0=69:100 +portmap_79.0=77:25 +portmap_80.0=78:25 +portmap_81.0=79:25 +portmap_82.0=80:25 +portmap_87.0=85:25 +portmap_88.0=86:25 +portmap_89.0=87:25 +portmap_90.0=88:25 +portmap_95.0=93:25 +portmap_96.0=94:25 +portmap_97.0=95:25 +portmap_98.0=96:25 +portmap_99.0=97:25 +portmap_100.0=98:25 +portmap_101.0=99:25 +portmap_102.0=100:25 +portmap_107.0=105:25 +portmap_108.0=106:25 +portmap_109.0=107:25 +portmap_110.0=108:25 +portmap_115.0=113:25 +portmap_116.0=114:25 +portmap_117.0=115:25 +portmap_118.0=116:25 +portmap_123.0=121:100 +portmap_127.0=125:100 + +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{5.0}=0x1032 +phy_chain_rx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x3120 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x0123 +phy_chain_rx_lane_map_physical{49.0}=0x1032 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x1032 +phy_chain_tx_lane_map_physical{61.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x1302 +phy_chain_rx_lane_map_physical{65.0}=0x1023 +phy_chain_tx_lane_map_physical{69.0}=0x1032 +phy_chain_rx_lane_map_physical{69.0}=0x0213 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x2301 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x2301 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x2301 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x2301 +phy_chain_tx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x2031 +phy_chain_tx_lane_map_physical{125.0}=0x0132 +phy_chain_rx_lane_map_physical{125.0}=0x3012 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +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}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +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}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +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}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{77.0}=0x0 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x1 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 +phy_chain_tx_polarity_flip_physical{125.0}=0x1 +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 + +#MC P/N flip +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 + +dport_map_port_49=1 +dport_map_port_50=2 +dport_map_port_51=3 +dport_map_port_52=4 +dport_map_port_57=5 +dport_map_port_58=6 +dport_map_port_59=7 +dport_map_port_60=8 +dport_map_port_61=9 +dport_map_port_62=10 +dport_map_port_63=11 +dport_map_port_64=12 +dport_map_port_79=13 +dport_map_port_80=14 +dport_map_port_81=15 +dport_map_port_82=16 +dport_map_port_87=17 +dport_map_port_88=18 +dport_map_port_89=19 +dport_map_port_90=20 +dport_map_port_95=21 +dport_map_port_96=22 +dport_map_port_97=23 +dport_map_port_98=24 +dport_map_port_13=25 +dport_map_port_14=26 +dport_map_port_15=27 +dport_map_port_16=28 +dport_map_port_21=29 +dport_map_port_22=30 +dport_map_port_23=31 +dport_map_port_24=32 +dport_map_port_29=33 +dport_map_port_30=34 +dport_map_port_31=35 +dport_map_port_32=36 +dport_map_port_99=37 +dport_map_port_100=38 +dport_map_port_101=39 +dport_map_port_102=40 +dport_map_port_107=41 +dport_map_port_108=42 +dport_map_port_109=43 +dport_map_port_110=44 +dport_map_port_115=45 +dport_map_port_116=46 +dport_map_port_117=47 +dport_map_port_118=48 +dport_map_port_67=49 +dport_map_port_71=50 +dport_map_port_123=51 +dport_map_port_127=52 +dport_map_port_1=53 +dport_map_port_33=54 +dport_map_port_5=55 +dport_map_port_41=56 + +reglist_enable=1 +scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 + +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/custom_led.bin b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/custom_led.bin new file mode 100755 index 0000000000000000000000000000000000000000..fb33257fbbe9d075892a096e3c581c6710df296c GIT binary patch literal 308 zcmV-40n7gIwO>Y7MomUUM)0%^95hS>BLgB2A&5o-Cb32VC%Q&494SDIMnz~^Qzdu- zJ*~2?00(IHTZd?WUAsmyLIcnh9AQQPDHYKb9DpY`LJ`nKMp;G;Kn5)b&;r;6Ee6pC z;0G-Q&D&pBZypTqjMxsWmM)1AlH~;`09v>hfA|oUvCMPH{GBY$aHa9pqIy*cG z3JVMk4i69!5)%|XK0iP~LPJDFMn^~i0s{mU78e)=1_uZk8XFubDl054E-x@iN=r;l GPESx?i&_={ literal 0 HcmV?d00001 diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/hwsku.json b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/hwsku.json new file mode 100644 index 000000000000..a559890f3a18 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/hwsku.json @@ -0,0 +1,284 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet1": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet2": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet3": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet5": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet6": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet7": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet9": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet10": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet11": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet13": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet14": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet15": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet17": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet18": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet19": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet21": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet22": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet23": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet25": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet26": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet27": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet29": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet30": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet31": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet33": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet34": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet35": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet37": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet38": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet39": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet41": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet42": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet43": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet45": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet46": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet47": { + "default_brkout_mode": "1x25G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform.json b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform.json new file mode 100644 index 000000000000..b303755d5910 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform.json @@ -0,0 +1,396 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "29", + "breakout_modes": { + "1x25G": ["Eth1/1"] + } + }, + "Ethernet1": { + "index": "2", + "lanes": "30", + "breakout_modes": { + "1x25G": ["Eth2/1"] + } + }, + "Ethernet2": { + "index": "3", + "lanes": "31", + "breakout_modes": { + "1x25G": ["Eth3/1"] + } + }, + "Ethernet3": { + "index": "4", + "lanes": "32", + "breakout_modes": { + "1x25G": ["Eth4/1"] + } + }, + "Ethernet4": { + "index": "5", + "lanes": "33", + "breakout_modes": { + "1x25G": ["Eth5/1"] + } + }, + "Ethernet5": { + "index": "6", + "lanes": "34", + "breakout_modes": { + "1x25G": ["Eth6/1"] + } + }, + "Ethernet6": { + "index": "7", + "lanes": "35", + "breakout_modes": { + "1x25G": ["Eth7/1"] + } + }, + "Ethernet7": { + "index": "8", + "lanes": "36", + "breakout_modes": { + "1x25G": ["Eth8/1"] + } + }, + "Ethernet8": { + "index": "9", + "lanes": "37", + "breakout_modes": { + "1x25G": ["Eth9/1"] + } + }, + "Ethernet9": { + "index": "10", + "lanes": "38", + "breakout_modes": { + "1x25G": ["Eth10/1"] + } + }, + "Ethernet10": { + "index": "11", + "lanes": "39", + "breakout_modes": { + "1x25G": ["Eth11/1"] + } + }, + "Ethernet11": { + "index": "12", + "lanes": "40", + "breakout_modes": { + "1x25G": ["Eth12/1"] + } + }, + "Ethernet12": { + "index": "13", + "lanes": "49", + "breakout_modes": { + "1x25G": ["Eth13/1"] + } + }, + "Ethernet13": { + "index": "14", + "lanes": "50", + "breakout_modes": { + "1x25G": ["Eth14/1"] + } + }, + "Ethernet14": { + "index": "15", + "lanes": "51", + "breakout_modes": { + "1x25G": ["Eth15/1"] + } + }, + "Ethernet15": { + "index": "16", + "lanes": "52", + "breakout_modes": { + "1x25G": ["Eth16/1"] + } + }, + "Ethernet16": { + "index": "17", + "lanes": "53", + "breakout_modes": { + "1x25G": ["Eth17/1"] + } + }, + "Ethernet17": { + "index": "18", + "lanes": "54", + "breakout_modes": { + "1x25G": ["Eth18/1"] + } + }, + "Ethernet18": { + "index": "19", + "lanes": "55", + "breakout_modes": { + "1x25G": ["Eth19/1"] + } + }, + "Ethernet19": { + "index": "20", + "lanes": "56", + "breakout_modes": { + "1x25G": ["Eth20/1"] + } + }, + "Ethernet20": { + "index": "21", + "lanes": "57", + "breakout_modes": { + "1x25G": ["Eth21/1"] + } + }, + "Ethernet21": { + "index": "22", + "lanes": "58", + "breakout_modes": { + "1x25G": ["Eth22/1"] + } + }, + "Ethernet22": { + "index": "23", + "lanes": "59", + "breakout_modes": { + "1x25G": ["Eth23/1"] + } + }, + "Ethernet23": { + "index": "24", + "lanes": "60", + "breakout_modes": { + "1x25G": ["Eth24/1"] + } + }, + "Ethernet24": { + "index": "25", + "lanes": "9", + "breakout_modes": { + "1x25G": ["Eth25/1"] + } + }, + "Ethernet25": { + "index": "26", + "lanes": "10", + "breakout_modes": { + "1x25G": ["Eth26/1"] + } + }, + "Ethernet26": { + "index": "27", + "lanes": "11", + "breakout_modes": { + "1x25G": ["Eth27/1"] + } + }, + "Ethernet27": { + "index": "28", + "lanes": "12", + "breakout_modes": { + "1x25G": ["Eth28/1"] + } + }, + "Ethernet28": { + "index": "29", + "lanes": "13", + "breakout_modes": { + "1x25G": ["Eth29/1"] + } + }, + "Ethernet29": { + "index": "30", + "lanes": "14", + "breakout_modes": { + "1x25G": ["Eth30/1"] + } + }, + "Ethernet30": { + "index": "31", + "lanes": "15", + "breakout_modes": { + "1x25G": ["Eth31/1"] + } + }, + "Ethernet31": { + "index": "32", + "lanes": "16", + "breakout_modes": { + "1x25G": ["Eth32/1"] + } + }, + "Ethernet32": { + "index": "33", + "lanes": "17", + "breakout_modes": { + "1x25G": ["Eth33/1"] + } + }, + "Ethernet33": { + "index": "34", + "lanes": "18", + "breakout_modes": { + "1x25G": ["Eth34/1"] + } + }, + "Ethernet34": { + "index": "35", + "lanes": "19", + "breakout_modes": { + "1x25G": ["Eth35/1"] + } + }, + "Ethernet35": { + "index": "36", + "lanes": "20", + "breakout_modes": { + "1x25G": ["Eth36/1"] + } + }, + "Ethernet36": { + "index": "37", + "lanes": "61", + "breakout_modes": { + "1x25G": ["Eth37/1"] + } + }, + "Ethernet37": { + "index": "38", + "lanes": "62", + "breakout_modes": { + "1x25G": ["Eth38/1"] + } + }, + "Ethernet38": { + "index": "39", + "lanes": "63", + "breakout_modes": { + "1x25G": ["Eth39/1"] + } + }, + "Ethernet39": { + "index": "40", + "lanes": "64", + "breakout_modes": { + "1x25G": ["Eth40/1"] + } + }, + "Ethernet40": { + "index": "41", + "lanes": "65", + "breakout_modes": { + "1x25G": ["Eth41/1"] + } + }, + "Ethernet41": { + "index": "42", + "lanes": "66", + "breakout_modes": { + "1x25G": ["Eth42/1"] + } + }, + "Ethernet42": { + "index": "43", + "lanes": "67", + "breakout_modes": { + "1x25G": ["Eth43/1"] + } + }, + "Ethernet43": { + "index": "44", + "lanes": "68", + "breakout_modes": { + "1x25G": ["Eth44/1"] + } + }, + "Ethernet44": { + "index": "45", + "lanes": "69", + "breakout_modes": { + "1x25G": ["Eth45/1"] + } + }, + "Ethernet45": { + "index": "46", + "lanes": "70", + "breakout_modes": { + "1x25G": ["Eth46/1"] + } + }, + "Ethernet46": { + "index": "47", + "lanes": "71", + "breakout_modes": { + "1x25G": ["Eth47/1"] + } + }, + "Ethernet47": { + "index": "48", + "lanes": "72", + "breakout_modes": { + "1x25G": ["Eth48/1"] + } + }, + "Ethernet48": { + "index": "49,49,49,49", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G": ["Eth49/1"] + } + }, + "Ethernet52": { + "index": "50,50,50,50", + "lanes": "45,46,47,48", + "breakout_modes": { + "1x100G": ["Eth50/1"] + } + }, + "Ethernet56": { + "index": "51,51,51,51", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G": ["Eth51/1"] + } + }, + "Ethernet60": { + "index": "52,52,52,52", + "lanes": "77,78,79,80", + "breakout_modes": { + "1x100G": ["Eth52/1"] + } + }, + "Ethernet64": { + "index": "53,53,53,53", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G": ["Eth53/1"] + } + }, + "Ethernet68": { + "index": "54,54,54,54", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x100G": ["Eth54/1"] + } + }, + "Ethernet72": { + "index": "55,55,55,55", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G": ["Eth55/1"] + } + }, + "Ethernet76": { + "index": "56,56,56,56", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x100G": ["Eth56/1"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform_components.json b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform_components.json new file mode 100644 index 000000000000..165eacad2dd3 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/platform_components.json @@ -0,0 +1,17 @@ +{ + "chassis": { + "Questone_2A": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/port_config.ini b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/port_config.ini new file mode 100644 index 000000000000..37d2d92652ed --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed mtu admin_status fec +Ethernet0 29 Eth1/1 1 25000 9216 up rs +Ethernet1 30 Eth2/1 2 25000 9216 up rs +Ethernet2 31 Eth3/1 3 25000 9216 up rs +Ethernet3 32 Eth4/1 4 25000 9216 up rs +Ethernet4 33 Eth5/1 5 25000 9216 up rs +Ethernet5 34 Eth6/1 6 25000 9216 up rs +Ethernet6 35 Eth7/1 7 25000 9216 up rs +Ethernet7 36 Eth8/1 8 25000 9216 up rs +Ethernet8 37 Eth9/1 9 25000 9216 up rs +Ethernet9 38 Eth10/1 10 25000 9216 up rs +Ethernet10 39 Eth11/1 11 25000 9216 up rs +Ethernet11 40 Eth12/1 12 25000 9216 up rs +Ethernet12 49 Eth13/1 13 25000 9216 up rs +Ethernet13 50 Eth14/1 14 25000 9216 up rs +Ethernet14 51 Eth15/1 15 25000 9216 up rs +Ethernet15 52 Eth16/1 16 25000 9216 up rs +Ethernet16 53 Eth17/1 17 25000 9216 up rs +Ethernet17 54 Eth18/1 18 25000 9216 up rs +Ethernet18 55 Eth19/1 19 25000 9216 up rs +Ethernet19 56 Eth20/1 20 25000 9216 up rs +Ethernet20 57 Eth21/1 21 25000 9216 up rs +Ethernet21 58 Eth22/1 22 25000 9216 up rs +Ethernet22 59 Eth23/1 23 25000 9216 up rs +Ethernet23 60 Eth24/1 24 25000 9216 up rs +Ethernet24 9 Eth25/1 25 25000 9216 up rs +Ethernet25 10 Eth26/1 26 25000 9216 up rs +Ethernet26 11 Eth27/1 27 25000 9216 up rs +Ethernet27 12 Eth28/1 28 25000 9216 up rs +Ethernet28 13 Eth29/1 29 25000 9216 up rs +Ethernet29 14 Eth30/1 30 25000 9216 up rs +Ethernet30 15 Eth31/1 31 25000 9216 up rs +Ethernet31 16 Eth32/1 32 25000 9216 up rs +Ethernet32 17 Eth33/1 33 25000 9216 up rs +Ethernet33 18 Eth34/1 34 25000 9216 up rs +Ethernet34 19 Eth35/1 35 25000 9216 up rs +Ethernet35 20 Eth36/1 36 25000 9216 up rs +Ethernet36 61 Eth37/1 37 25000 9216 up rs +Ethernet37 62 Eth38/1 38 25000 9216 up rs +Ethernet38 63 Eth39/1 39 25000 9216 up rs +Ethernet39 64 Eth40/1 40 25000 9216 up rs +Ethernet40 65 Eth41/1 41 25000 9216 up rs +Ethernet41 66 Eth42/1 42 25000 9216 up rs +Ethernet42 67 Eth43/1 43 25000 9216 up rs +Ethernet43 68 Eth44/1 44 25000 9216 up rs +Ethernet44 69 Eth45/1 45 25000 9216 up rs +Ethernet45 70 Eth46/1 46 25000 9216 up rs +Ethernet46 71 Eth47/1 47 25000 9216 up rs +Ethernet47 72 Eth48/1 48 25000 9216 up rs +Ethernet48 41,42,43,44 Eth49/1 49 100000 9216 up rs +Ethernet52 45,46,47,48 Eth50/1 50 100000 9216 up rs +Ethernet56 73,74,75,76 Eth51/1 51 100000 9216 up rs +Ethernet60 77,78,79,80 Eth52/1 52 100000 9216 up rs +Ethernet64 1,2,3,4 Eth53/1 53 100000 9216 up rs +Ethernet68 21,22,23,24 Eth54/1 54 100000 9216 up rs +Ethernet72 5,6,7,8 Eth55/1 55 100000 9216 up rs +Ethernet76 25,26,27,28 Eth56/1 56 100000 9216 up rs diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai.profile.j2 b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai.profile.j2 new file mode 100644 index 000000000000..62a1db9e0960 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai.profile.j2 @@ -0,0 +1,16 @@ +{# Get sai.profile based on vxlan_profile. Vxlan's config.bcm file is the default one #} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as13-48f8h-vxlan.config.bcm' -%} +{%- if DEVICE_METADATA is defined and DEVICE_METADATA['localhost'] is defined -%} +{%- if DEVICE_METADATA['localhost']['vxlan_profile'] is defined -%} +{%- set vxlan_profile = DEVICE_METADATA['localhost']['vxlan_profile'] -%} +{%- if 'enable' in vxlan_profile.lower() %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as13-48f8h-vxlan.config.bcm' -%} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as13-48f8h.config.bcm' -%} +{%- endif %} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as13-48f8h-vxlan.config.bcm' -%} +{%- endif %} +{%- endif %} +{# Write the contents of sai_profile_filename to sai.profile file #} +{{ sai_profile_contents }} diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai_postinit_cmd.soc b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai_postinit_cmd.soc new file mode 100644 index 000000000000..731625308a5e --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/sai_postinit_cmd.soc @@ -0,0 +1,2 @@ +modreg ING_MISC_CONFIG INPUT_PRI_TAGGED=1 +modreg ING_MISC_CONFIG INPUT_PRI_UNTAGGED=1 diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h-vxlan.config.bcm b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h-vxlan.config.bcm new file mode 100755 index 000000000000..7d444dfb53f6 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h-vxlan.config.bcm @@ -0,0 +1,423 @@ +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +oversubscribe_mode=1 +pbmp_xport_xe=0x11ffffffe1ffffffe +stable_size=0x5500000 +ifp_inports_support_enable=1 + +#FC0 +portmap_1.0=1:100 + +#FC1 +portmap_2.0=5:100 + +#FC2 +portmap_3.0=9:25 +portmap_4.0=10:25 +portmap_5.0=11:25 +portmap_6.0=12:25 + +#FC3 +portmap_7.0=13:25 +portmap_8.0=14:25 +portmap_9.0=15:25 +portmap_10.0=16:25 + +#FC4 +portmap_11.0=17:25 +portmap_12.0=18:25 +portmap_13.0=19:25 +portmap_14.0=20:25 + +#FC5 +portmap_15.0=21:100 + +#FC6 +portmap_16.0=25:100 + +#FC7 +portmap_17.0=29:25 +portmap_18.0=30:25 +portmap_19.0=31:25 +portmap_20.0=32:25 + +#FC8 +portmap_21.0=33:25 +portmap_22.0=34:25 +portmap_23.0=35:25 +portmap_24.0=36:25 + +#FC9 +portmap_25.0=37:25 +portmap_26.0=38:25 +portmap_27.0=39:25 +portmap_28.0=40:25 + +#FC10 +portmap_33.0=41:100 + +#FC11 +portmap_34.0=45:100 + +#FC12 +portmap_35.0=49:25 +portmap_36.0=50:25 +portmap_37.0=51:25 +portmap_38.0=52:25 + +#FC13 +portmap_39.0=53:25 +portmap_40.0=54:25 +portmap_41.0=55:25 +portmap_42.0=56:25 + +#FC14 +portmap_43.0=57:25 +portmap_44.0=58:25 +portmap_45.0=59:25 +portmap_46.0=60:25 + +#FC15 +portmap_47.0=61:25 +portmap_48.0=62:25 +portmap_49.0=63:25 +portmap_50.0=64:25 + +#FC16 +portmap_51.0=65:25 +portmap_52.0=66:25 +portmap_53.0=67:25 +portmap_54.0=68:25 + +#FC17 +portmap_55.0=69:25 +portmap_56.0=70:25 +portmap_57.0=71:25 +portmap_58.0=72:25 + +#FC18 +portmap_59.0=73:100 + +#FC19 +portmap_60.0=77:100 + + +#portmap_64.0=81:10 + +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{5.0}=0x1032 +phy_chain_rx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{9.0}=0x1032 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x1302 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{25.0}=0x3120 +phy_chain_rx_lane_map_physical{25.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x1302 +phy_chain_rx_lane_map_physical{41.0}=0x1023 +phy_chain_tx_lane_map_physical{45.0}=0x1032 +phy_chain_rx_lane_map_physical{45.0}=0x0213 +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{49.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{53.0}=0x2301 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x2301 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0132 +phy_chain_rx_lane_map_physical{77.0}=0x3012 +phy_chain_tx_lane_map_physical{81.0}=0x3210 +phy_chain_rx_lane_map_physical{81.0}=0x3201 + +#FC0 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +#FC1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +#FC2 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +#FC3 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 + +#FC4 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +#FC5 +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}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +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 + +#FC6 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 + +#FC7 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 + +#FC8 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +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}=0x1 + +#FC9 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 + +#FC10 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +#FC11 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 + +#FC12 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +#FC13 +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 + +#FC14 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +#FC15 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +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}=0x0 + +#FC16 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 + +#FC17 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +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}=0x1 + +#FC18 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 + +#FC19 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 + + +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x1 + + +dport_map_port_17=1 +dport_map_port_18=2 +dport_map_port_19=3 +dport_map_port_20=4 +dport_map_port_21=5 +dport_map_port_22=6 +dport_map_port_23=7 +dport_map_port_24=8 +dport_map_port_25=9 +dport_map_port_26=10 +dport_map_port_27=11 +dport_map_port_28=12 +dport_map_port_35=13 +dport_map_port_36=14 +dport_map_port_37=15 +dport_map_port_38=16 +dport_map_port_39=17 +dport_map_port_40=18 +dport_map_port_41=19 +dport_map_port_42=20 +dport_map_port_43=21 +dport_map_port_44=22 +dport_map_port_45=23 +dport_map_port_46=24 +dport_map_port_3=25 +dport_map_port_4=26 +dport_map_port_5=27 +dport_map_port_6=28 +dport_map_port_7=29 +dport_map_port_8=30 +dport_map_port_9=31 +dport_map_port_10=32 +dport_map_port_11=33 +dport_map_port_12=34 +dport_map_port_13=35 +dport_map_port_14=36 +dport_map_port_47=37 +dport_map_port_48=38 +dport_map_port_49=39 +dport_map_port_50=40 +dport_map_port_51=41 +dport_map_port_52=42 +dport_map_port_53=43 +dport_map_port_54=44 +dport_map_port_55=45 +dport_map_port_56=46 +dport_map_port_57=47 +dport_map_port_58=48 +dport_map_port_33=49 +dport_map_port_34=50 +dport_map_port_59=51 +dport_map_port_60=52 +dport_map_port_1=53 +dport_map_port_15=54 +dport_map_port_2=55 +dport_map_port_16=56 +#dport_map_port_64=57 + +#VxLAN +sai_tunnel_support=1 +use_all_splithorizon_groups=1 +bcm_tunnel_term_compatible_mode=1 +flow_init_mode=1 +l3_ecmp_levels=2 +riot_enable=1 +riot_overlay_l3_intf_mem_size=8192 +riot_overlay_l3_egress_mem_size=32768 +riot_overlay_ecmp_resilient_hash_size=16384 diff --git a/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h.config.bcm b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h.config.bcm new file mode 100755 index 000000000000..e76aa8eb34e9 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/Questone_2A/td3-as13-48f8h.config.bcm @@ -0,0 +1,414 @@ +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +oversubscribe_mode=1 +pbmp_xport_xe=0x11ffffffe1ffffffe +stable_size=0x5500000 +ifp_inports_support_enable=1 + +#FC0 +portmap_1.0=1:100 + +#FC1 +portmap_2.0=5:100 + +#FC2 +portmap_3.0=9:25 +portmap_4.0=10:25 +portmap_5.0=11:25 +portmap_6.0=12:25 + +#FC3 +portmap_7.0=13:25 +portmap_8.0=14:25 +portmap_9.0=15:25 +portmap_10.0=16:25 + +#FC4 +portmap_11.0=17:25 +portmap_12.0=18:25 +portmap_13.0=19:25 +portmap_14.0=20:25 + +#FC5 +portmap_15.0=21:100 + +#FC6 +portmap_16.0=25:100 + +#FC7 +portmap_17.0=29:25 +portmap_18.0=30:25 +portmap_19.0=31:25 +portmap_20.0=32:25 + +#FC8 +portmap_21.0=33:25 +portmap_22.0=34:25 +portmap_23.0=35:25 +portmap_24.0=36:25 + +#FC9 +portmap_25.0=37:25 +portmap_26.0=38:25 +portmap_27.0=39:25 +portmap_28.0=40:25 + +#FC10 +portmap_33.0=41:100 + +#FC11 +portmap_34.0=45:100 + +#FC12 +portmap_35.0=49:25 +portmap_36.0=50:25 +portmap_37.0=51:25 +portmap_38.0=52:25 + +#FC13 +portmap_39.0=53:25 +portmap_40.0=54:25 +portmap_41.0=55:25 +portmap_42.0=56:25 + +#FC14 +portmap_43.0=57:25 +portmap_44.0=58:25 +portmap_45.0=59:25 +portmap_46.0=60:25 + +#FC15 +portmap_47.0=61:25 +portmap_48.0=62:25 +portmap_49.0=63:25 +portmap_50.0=64:25 + +#FC16 +portmap_51.0=65:25 +portmap_52.0=66:25 +portmap_53.0=67:25 +portmap_54.0=68:25 + +#FC17 +portmap_55.0=69:25 +portmap_56.0=70:25 +portmap_57.0=71:25 +portmap_58.0=72:25 + +#FC18 +portmap_59.0=73:100 + +#FC19 +portmap_60.0=77:100 + + +#portmap_64.0=81:10 + +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{5.0}=0x1032 +phy_chain_rx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{9.0}=0x1032 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x1302 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{25.0}=0x3120 +phy_chain_rx_lane_map_physical{25.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x1302 +phy_chain_rx_lane_map_physical{41.0}=0x1023 +phy_chain_tx_lane_map_physical{45.0}=0x1032 +phy_chain_rx_lane_map_physical{45.0}=0x0213 +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{49.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{53.0}=0x2301 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x2301 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0132 +phy_chain_rx_lane_map_physical{77.0}=0x3012 +phy_chain_tx_lane_map_physical{81.0}=0x3210 +phy_chain_rx_lane_map_physical{81.0}=0x3201 + +#FC0 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +#FC1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +#FC2 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +#FC3 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 + +#FC4 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +#FC5 +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}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +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 + +#FC6 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 + +#FC7 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 + +#FC8 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +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}=0x1 + +#FC9 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 + +#FC10 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +#FC11 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 + +#FC12 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +#FC13 +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 + +#FC14 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +#FC15 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +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}=0x0 + +#FC16 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 + +#FC17 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +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}=0x1 + +#FC18 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 + +#FC19 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 + + +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x1 + + +dport_map_port_17=1 +dport_map_port_18=2 +dport_map_port_19=3 +dport_map_port_20=4 +dport_map_port_21=5 +dport_map_port_22=6 +dport_map_port_23=7 +dport_map_port_24=8 +dport_map_port_25=9 +dport_map_port_26=10 +dport_map_port_27=11 +dport_map_port_28=12 +dport_map_port_35=13 +dport_map_port_36=14 +dport_map_port_37=15 +dport_map_port_38=16 +dport_map_port_39=17 +dport_map_port_40=18 +dport_map_port_41=19 +dport_map_port_42=20 +dport_map_port_43=21 +dport_map_port_44=22 +dport_map_port_45=23 +dport_map_port_46=24 +dport_map_port_3=25 +dport_map_port_4=26 +dport_map_port_5=27 +dport_map_port_6=28 +dport_map_port_7=29 +dport_map_port_8=30 +dport_map_port_9=31 +dport_map_port_10=32 +dport_map_port_11=33 +dport_map_port_12=34 +dport_map_port_13=35 +dport_map_port_14=36 +dport_map_port_47=37 +dport_map_port_48=38 +dport_map_port_49=39 +dport_map_port_50=40 +dport_map_port_51=41 +dport_map_port_52=42 +dport_map_port_53=43 +dport_map_port_54=44 +dport_map_port_55=45 +dport_map_port_56=46 +dport_map_port_57=47 +dport_map_port_58=48 +dport_map_port_33=49 +dport_map_port_34=50 +dport_map_port_59=51 +dport_map_port_60=52 +dport_map_port_1=53 +dport_map_port_15=54 +dport_map_port_2=55 +dport_map_port_16=56 +#dport_map_port_64=57 + +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc diff --git a/device/celestica/x86_64-cel_questone_2-r0/installer.conf b/device/celestica/x86_64-cel_questone_2-r0/installer.conf new file mode 100644 index 000000000000..48126f43549a --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0xe060 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="processor.max_cstate=1 intel_idle.max_cstate=0 intel_iommu=off thermal.off=1 noirqdebug" diff --git a/device/celestica/x86_64-cel_questone_2-r0/led_proc_init.soc b/device/celestica/x86_64-cel_questone_2-r0/led_proc_init.soc new file mode 100644 index 000000000000..6f242fa07d89 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/led_proc_init.soc @@ -0,0 +1,8 @@ +#Enable all ports +#port all en=1 +#sleep 6 +#linkscan 250000; port xe,ce linkscan=on + +#Load LED +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on; led start diff --git a/device/celestica/x86_64-cel_questone_2-r0/opennsl-postinit.cfg b/device/celestica/x86_64-cel_questone_2-r0/opennsl-postinit.cfg new file mode 100644 index 000000000000..7008c14c0ffc --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/opennsl-postinit.cfg @@ -0,0 +1,3 @@ +linkscan 250000; port xe,ce linkscan=on +sleep 1 +led auto on; led start diff --git a/device/celestica/x86_64-cel_questone_2-r0/pcie.yaml b/device/celestica/x86_64-cel_questone_2-r0/pcie.yaml new file mode 100644 index 000000000000..bafe4a0d6d2a --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/pcie.yaml @@ -0,0 +1,153 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1980' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev + 11)' +- bus: '00' + dev: '04' + fn: '0' + id: 19a1 + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers + (rev 11)' +- bus: '00' + dev: '05' + fn: '0' + id: 19a2 + name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 + Series Root Complex Event Collector (rev 11)' +- bus: '00' + dev: '06' + fn: '0' + id: 19a3 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT + Root Port (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 19a4 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #0 (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 19aa + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #6 (rev 11)' +- bus: '00' + dev: '11' + fn: '0' + id: 19ab + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #7 (rev 11)' +- bus: '00' + dev: '12' + fn: '0' + id: 19ac + name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller + - Host (rev 11)' +- bus: '00' + dev: '14' + fn: '0' + id: 19c2 + name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller + 1 (rev 11)' +- bus: '00' + dev: '15' + fn: '0' + id: 19d0 + name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI + Controller (rev 11)' +- bus: '00' + dev: '16' + fn: '0' + id: 19d1 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #0 (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 19d3 + name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME + HECI 1 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1c + fn: '0' + id: 19db + name: 'SD Host controller: Intel Corporation Device 19db (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 19dc + name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev + 11)' +- bus: '00' + dev: 1f + fn: '2' + id: 19de + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management + Controller (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 19df + name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev + 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 19e0 + name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series + SPI Controller (rev 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 19e2 + name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology + (rev 11)' +- bus: '02' + dev: '00' + fn: '0' + id: b770 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b770 (rev 01)' +- bus: '03' + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: '04' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '05' + dev: '00' + fn: '0' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: '05' + dev: '00' + fn: '1' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' diff --git a/device/celestica/x86_64-cel_questone_2-r0/platform_asic b/device/celestica/x86_64-cel_questone_2-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/celestica/x86_64-cel_questone_2-r0/platform_reboot b/device/celestica/x86_64-cel_questone_2-r0/platform_reboot new file mode 100755 index 000000000000..12a18efe1d0b --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/platform_reboot @@ -0,0 +1,6 @@ +#!/bin/bash + +# Set all LEDs to BMC's control +ipmitool raw 0x3a 0x0f 0x02 0x01 &> /dev/null + +/usr/local/bin/questone2_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_questone_2-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_questone_2-r0/plugins/eeprom.py new file mode 100644 index 000000000000..22895539823f --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica DX010 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError 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/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + diff --git a/device/celestica/x86_64-cel_questone_2-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_questone_2-r0/plugins/sfputil.py new file mode 100755 index 000000000000..03882c65ac00 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/plugins/sfputil.py @@ -0,0 +1,312 @@ +#!/usr/bin/env python +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + import struct +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 + QSFP_PORT_START = 48 + QSFP_PORT_END = 55 + __xcvr_presence = {} + + EEPROM_OFFSET = 9 + PORT_INFO_PATH = '/sys/class/questone2_fpga' + + _port_name = "" + _port_to_eeprom_mapping = {} + _port_to_i2cbus_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def port_to_i2cbus_mapping(self): + return self._port_to_i2cbus_mapping + + def get_port_name(self, port_num): + if port_num in self.qsfp_ports: + self._port_name = "QSFP" + str(port_num - self.QSFP_PORT_START + 1) + else: + self._port_name = "SFP" + str(port_num + 1) + return self._port_name + + 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.DOM_EEPROM_ADDR, 256) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + + for x in range(self.PORT_START, self.PORT_END+1): + # port_index = 0 , it's path = /sys/bus/i2c/devices/i2c-10/10-0050/eeprom + # port_index = 55, it's path = /sys/bus/i2c/devices/i2c-65/65-0050/eeprom + # so the real offset is 10 + self.port_to_i2cbus_mapping[x] = (x + 1 + self.EEPROM_OFFSET) + self.port_to_eeprom_mapping[x] = eeprom_path.format( + x + 1 + self.EEPROM_OFFSET) + SfpUtilBase.__init__(self) + for x in range(self.PORT_START, self.PORT_END+1): + self.__xcvr_presence[x] = self.get_presence(x) + + def _do_write_file(self, file_handle, offset, value): + file_handle.seek(offset) + file_handle.write(hex(value)) + file_handle.close() + + def get_presence(self, port_num): + + # Check for invalid port_num + if port_num not in range(self.port_start, self.port_end + 1): + return False + + # Get path for access port presence status + port_name = self.get_port_name(port_num) + sysfs_filename = "qsfp_modprs" if port_num in self.qsfp_ports else "sfp_modabs" + reg_path = "/".join([self.PORT_INFO_PATH, port_name, sysfs_filename]) + + # Read status + try: + reg_file = open(reg_path) + content = reg_file.readline().rstrip() + reg_value = int(content) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # Module present is active low + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + if not self.get_presence(port_num): + return None + + eeprom_raw = [] + eeprom_raw.append("0x00") + + lpmode = False + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'.format(port_num + 1 + self.EEPROM_OFFSET) + if port_num >= 49: + try: + with open(eeprom_path, mode="rb", buffering=0) as eeprom: + eeprom.seek(93) + raw = eeprom.read(1) + eeprom.close() + except Exception as err: + return None + + if len(raw) == 0: + return None + eeprom_raw[0] = hex(ord(raw[0]))[2:].zfill(2) + + power_data = int(eeprom_raw[0], 16) + # if lpmod, power-override bit and power-set bit are both setted + # bit0 bit1 + lpmode = power_data & 0x03 != 0 + else: + return None + + return lpmode + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + if not self.get_presence(port_num): + return False + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'.format(port_num + 1 + self.EEPROM_OFFSET) + try: + reg_file = open(eeprom_path, mode="wb+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_file.seek(93) + power_raw = reg_file.read(1) + if power_raw is None: + return False + power_data = int(hex(ord(power_raw))[2:].zfill(2), 16) + + if lpmode: + power_data |= 0x03 + else: + power_data &= ~(0x03) + + reg_file.seek(93) + reg_file.write(struct.pack('B', int(power_data))) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + try: + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(0)) + reg_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + # Flip the bit back high and write back to the register to take port out of reset + try: + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_file.seek(0) + reg_file.write(hex(1)) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + """ + To detect if any transceiver change event happens. + """ + start_ms = time.time() * 1000 + xcvr_change_event_dict = {} + event = False + + while True: + time.sleep(0.5) + for port in range(self.port_start, self.port_end+1): + curr_presence = self.get_presence(port) + if curr_presence != self.__xcvr_presence[port]: + if curr_presence is True: + xcvr_change_event_dict[str(port)] = '1' + self.__xcvr_presence[port] = True + elif curr_presence is False: + xcvr_change_event_dict[str(port)] = '0' + self.__xcvr_presence[port] = False + event = True + + if event is True: + return True, xcvr_change_event_dict + + if timeout: + now_ms = time.time() * 1000 + if (now_ms - start_ms >= timeout): + return True, xcvr_change_event_dict + + def tx_disable(self, port_num, disable): + """ + @param port_num index of physical port + @param disable, True -- disable port tx signal + False -- enable port tx signal + @return True when operation success, False on failure. + """ + TX_DISABLE_BYTE_OFFSET = 86 + if port_num not in range(self.port_start, self.port_end + 1) or type(disable) != bool: + return False + + # QSFP, set eeprom to disable tx + if port_num in self.qsfp_ports: + presence = self.get_presence(port_num) + if not presence: + return True + + disable = b'\x0f' if disable else b'\x00' + # open eeprom + try: + with open(self.port_to_eeprom_mapping[port_num], mode="wb", buffering=0) as sysfsfile: + sysfsfile.seek(TX_DISABLE_BYTE_OFFSET) + sysfsfile.write(bytearray(disable)) + except IOError: + return False + + # SFP, set tx_disable pin + else: + try: + disable = hex(1) if disable else hex(0) + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "sfp_txdisable"]), "w") + reg_file.write(disable) + reg_file.close() + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + return True + + def reset_all(self): + result = True + port_sysfs_path = [] + for port in range(self.port_start, self.port_end+1): + if port not in self.qsfp_ports: + continue + + presence = self.get_presence(port) + if not presence: + continue + + try: + port_name = self.get_port_name(port) + sysfs_path = "/".join([self.PORT_INFO_PATH, + port_name, "qsfp_reset"]) + reg_file = open(sysfs_path, "w") + port_sysfs_path.append(sysfs_path) + except IOError as e: + result = False + continue + + self._do_write_file(reg_file, 0, 0) + + time.sleep(1) + + for sysfs_path in port_sysfs_path: + try: + reg_file = open(sysfs_path, "w") + except IOError as e: + result = False + continue + + self._do_write_file(reg_file, 0, 1) + + return result diff --git a/device/celestica/x86_64-cel_questone_2-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_questone_2-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..f5b2736b13e0 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_fancontrol": true, + "skip_xcvrd_cmis_mgr": true +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_questone_2-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..56fda7de4f5d --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/system_health_monitoring_config.json @@ -0,0 +1,13 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "psu.temperature" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "green_blink_1hz" + } +} diff --git a/device/celestica/x86_64-cel_questone_2-r0/warm-reboot_plugin b/device/celestica/x86_64-cel_questone_2-r0/warm-reboot_plugin new file mode 100755 index 000000000000..d0fb8b29e191 --- /dev/null +++ b/device/celestica/x86_64-cel_questone_2-r0/warm-reboot_plugin @@ -0,0 +1,4 @@ +#!/bin/bash + +# Set all LEDs to BMC's control +ipmitool raw 0x3a 0x0f 0x02 0x01 &> /dev/null diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers.json.j2 b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_def.j2 b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_def.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_def.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..44fcf21887a6 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t0.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t1.j2 b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/hwsku.json b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/hwsku.json new file mode 100644 index 000000000000..28e50b8c0385 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/hwsku.json @@ -0,0 +1,169 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet128": { + "default_brkout_mode": "1x10G", + "autoneg": "off", + "fec": "none" + } + } +} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l2/config b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l2/config new file mode 100644 index 000000000000..45a7b84d5032 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l2/config @@ -0,0 +1,3 @@ +l2_mem_entries=139264 +l3_mem_entries=8192 +l3_alpm_enable=0 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l3/config b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l3/config new file mode 100644 index 000000000000..3467c1b39716 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/l3/config @@ -0,0 +1,3 @@ +l2_mem_entries=40000 +l3_mem_entries=40000 +l3_alpm_enable=2 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/pg_profile_lookup.ini b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/pg_profile_lookup.ini new file mode 100644 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 56368 18432 55120 -3 2496 + 25000 5m 56368 18432 55120 -3 2496 + 40000 5m 56368 18432 55120 -3 2496 + 50000 5m 56368 18432 55120 -3 2496 + 100000 5m 56368 18432 55120 -3 2496 + 10000 40m 56368 18432 55120 -3 2496 + 25000 40m 56368 18432 55120 -3 2496 + 40000 40m 56368 18432 55120 -3 2496 + 50000 40m 56368 18432 55120 -3 2496 + 100000 40m 56368 18432 55120 -3 2496 + 10000 300m 56368 18432 55120 -3 2496 + 25000 300m 56368 18432 55120 -3 2496 + 40000 300m 56368 18432 55120 -3 2496 + 50000 300m 56368 18432 55120 -3 2496 + 100000 300m 56368 18432 55120 -3 2496 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini index 1596faa8af96..8cd1c833a929 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini @@ -1,34 +1,34 @@ -# name lanes alias fec index speed -Ethernet0 1,2,3,4 QSFP1 rs 1 100000 -Ethernet4 5,6,7,8 QSFP2 rs 2 100000 -Ethernet8 9,10,11,12 QSFP3 rs 3 100000 -Ethernet12 13,14,15,16 QSFP4 rs 4 100000 -Ethernet16 17,18,19,20 QSFP5 rs 5 100000 -Ethernet20 21,22,23,24 QSFP6 rs 6 100000 -Ethernet24 25,26,27,28 QSFP7 rs 7 100000 -Ethernet28 29,30,31,32 QSFP8 rs 8 100000 -Ethernet32 33,34,35,36 QSFP9 rs 9 100000 -Ethernet36 37,38,39,40 QSFP10 rs 10 100000 -Ethernet40 41,42,43,44 QSFP11 rs 11 100000 -Ethernet44 45,46,47,48 QSFP12 rs 12 100000 -Ethernet48 49,50,51,52 QSFP13 rs 13 100000 -Ethernet52 53,54,55,56 QSFP14 rs 14 100000 -Ethernet56 57,58,59,60 QSFP15 rs 15 100000 -Ethernet60 61,62,63,64 QSFP16 rs 16 100000 -Ethernet64 65,66,67,68 QSFP17 rs 17 100000 -Ethernet68 69,70,71,72 QSFP18 rs 18 100000 -Ethernet72 73,74,75,76 QSFP19 rs 19 100000 -Ethernet76 77,78,79,80 QSFP20 rs 20 100000 -Ethernet80 81,82,83,84 QSFP21 rs 21 100000 -Ethernet84 85,86,87,88 QSFP22 rs 22 100000 -Ethernet88 89,90,91,92 QSFP23 rs 23 100000 -Ethernet92 93,94,95,96 QSFP24 rs 24 100000 -Ethernet96 97,98,99,100 QSFP25 rs 25 100000 -Ethernet100 101,102,103,104 QSFP26 rs 26 100000 -Ethernet104 105,106,107,108 QSFP27 rs 27 100000 -Ethernet108 109,110,111,112 QSFP28 rs 28 100000 -Ethernet112 113,114,115,116 QSFP29 rs 29 100000 -Ethernet116 117,118,119,120 QSFP30 rs 30 100000 -Ethernet120 121,122,123,124 QSFP31 rs 31 100000 -Ethernet124 125,126,127,128 QSFP32 rs 32 100000 -Ethernet128 129 SFP1 none 33 10000 +# name lanes alias index speed valid_speeds +Ethernet0 1,2,3,4 Eth1/1 1 100000 100000,40000 +Ethernet4 5,6,7,8 Eth2/1 2 100000 100000,40000 +Ethernet8 9,10,11,12 Eth3/1 3 100000 100000,40000 +Ethernet12 13,14,15,16 Eth4/1 4 100000 100000,40000 +Ethernet16 17,18,19,20 Eth5/1 5 100000 100000,40000 +Ethernet20 21,22,23,24 Eth6/1 6 100000 100000,40000 +Ethernet24 25,26,27,28 Eth7/1 7 100000 100000,40000 +Ethernet28 29,30,31,32 Eth8/1 8 100000 100000,40000 +Ethernet32 33,34,35,36 Eth9/1 9 100000 100000,40000 +Ethernet36 37,38,39,40 Eth10/1 10 100000 100000,40000 +Ethernet40 41,42,43,44 Eth11/1 11 100000 100000,40000 +Ethernet44 45,46,47,48 Eth12/1 12 100000 100000,40000 +Ethernet48 49,50,51,52 Eth13/1 13 100000 100000,40000 +Ethernet52 53,54,55,56 Eth14/1 14 100000 100000,40000 +Ethernet56 57,58,59,60 Eth15/1 15 100000 100000,40000 +Ethernet60 61,62,63,64 Eth16/1 16 100000 100000,40000 +Ethernet64 65,66,67,68 Eth17/1 17 100000 100000,40000 +Ethernet68 69,70,71,72 Eth18/1 18 100000 100000,40000 +Ethernet72 73,74,75,76 Eth19/1 19 100000 100000,40000 +Ethernet76 77,78,79,80 Eth20/1 20 100000 100000,40000 +Ethernet80 81,82,83,84 Eth21/1 21 100000 100000,40000 +Ethernet84 85,86,87,88 Eth22/1 22 100000 100000,40000 +Ethernet88 89,90,91,92 Eth23/1 23 100000 100000,40000 +Ethernet92 93,94,95,96 Eth24/1 24 100000 100000,40000 +Ethernet96 97,98,99,100 Eth25/1 25 100000 100000,40000 +Ethernet100 101,102,103,104 Eth26/1 26 100000 100000,40000 +Ethernet104 105,106,107,108 Eth27/1 27 100000 100000,40000 +Ethernet108 109,110,111,112 Eth28/1 28 100000 100000,40000 +Ethernet112 113,114,115,116 Eth29/1 29 100000 100000,40000 +Ethernet116 117,118,119,120 Eth30/1 30 100000 100000,40000 +Ethernet120 121,122,123,124 Eth31/1 31 100000 100000,40000 +Ethernet124 125,126,127,128 Eth32/1 32 100000 100000,40000 +Ethernet128 129 Eth33/1 33 10000 10000,1000 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/qos.json.j2 b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile deleted file mode 100644 index b57101d114f0..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile +++ /dev/null @@ -1,2 +0,0 @@ -SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-seastone_2-32x100G.config.bcm -SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile.j2 b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile.j2 new file mode 100644 index 000000000000..0c9245de7cd2 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile.j2 @@ -0,0 +1,17 @@ +{# Get sai.profile based on vxlan_profile. Vxlan's config.bcm file is the default one #} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-seastone_2-32x100G-vxlan.config.bcm' -%} +{%- if DEVICE_METADATA is defined and DEVICE_METADATA['localhost'] is defined -%} +{%- if DEVICE_METADATA['localhost']['vxlan_profile'] is defined -%} +{%- set vxlan_profile = DEVICE_METADATA['localhost']['vxlan_profile'] -%} +{%- if 'enable' in vxlan_profile.lower() %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-seastone_2-32x100G-vxlan.config.bcm' -%} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-seastone_2-32x100G.config.bcm' -%} +{%- endif %} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-seastone_2-32x100G-vxlan.config.bcm' -%} +{%- endif %} +{%- endif %} +{# Write the contents of sai_profile_filename to sai.profile file #} +{{ sai_profile_contents }} +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G-vxlan.config.bcm b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G-vxlan.config.bcm new file mode 100644 index 000000000000..83c535a24b35 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G-vxlan.config.bcm @@ -0,0 +1,576 @@ +help_cli_enable=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l2_mem_entries=32768 +l2xmsg_mode=1 +l3_max_ecmp_mode=1 +l3_mem_entries=16384 +lpm_scaling_enable=1 +max_vp_lags=0 +#mem_cache_enable=0 +memlist_enable=1 +reglist_enable=1 +#scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 +parity_enable=0 +serdes_lane_config_dfe=on +#serdes_fec_enable=1 +serdes_if_type_ce=14 +pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 +pbmp_xport_xe=0x3ffffffffffffffffffffffffffffffffe +port_flex_enable=1 + +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +bcm_tunnel_term_compatible_mode=1 +phy_an_c73=1 + +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_21=21:100 +portmap_25=25:100 +portmap_29=29:100 +portmap_33=33:100 +portmap_37=37:100 +portmap_41=41:100 +portmap_45=45:100 +portmap_49=49:100 +portmap_53=53:100 +portmap_57=57:100 +portmap_61=61:100 +portmap_67=65:100 +portmap_71=69:100 +portmap_75=73:100 +portmap_79=77:100 +portmap_83=81:100 +portmap_87=85:100 +portmap_91=89:100 +portmap_95=93:100 +portmap_99=97:100 +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 +portmap_66=129:10:m +#portmap_130=128:10:m + +#wc0 lane swap +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 + +#wc1 lane swap +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 + +#wc2 lane swap +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 + +#wc3 lane swap +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 + +#wc4 lane swap +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 + +#wc5 lane swap +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 + +#wc6 lane swap +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 + +#wc7 lane swap +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 + +#wc8 lane swap +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 + +#wc9 lane swap +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 + +#wc10 lane swap +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 + +#wc11 lane swap +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 + +#wc12 lane swap +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 + +#wc13 lane swap +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 + +#wc14 lane swap +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 + +#wc15 lane swap +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +#wc16 lane swap +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 + +#wc17 lane swap +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 + +#wc18 lane swap +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 + +#wc19 lane swap +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 + +#wc20 lane swap +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 + +#wc21 lane swap +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 + +#wc22 lane swap +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 + +#wc23 lane swap +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 + +#wc24 lane swap +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 + +#wc25 lane swap +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 + +#wc26 lane swap +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 + +#wc27 lane swap +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 + +#wc28 lane swap +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 + +#wc29 lane swap +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 + +#wc30 lane swap +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 + +#wc31 lane swap +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 + +#MC lane swap +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x0231 + + +#wc0 P/N flip +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +#wc1 P/N flip +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +#wc2 P/N flip +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 + +#wc3 P/N flip +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}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 + +#wc4 P/N flip +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 + +#wc5 P/N flip +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 + +#wc6 P/N flip +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 + +#wc7 P/N flip +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 + +#wc8 P/N flip +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 + +#wc9 P/N flip +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +#wc10 P/N flip +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 + +#wc11 P/N flip +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 + +#wc12 P/N flip +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 + +#wc13 P/N flip +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +#wc14 P/N flip +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 + +#wc15 P/N flip +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}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +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}=0x0 + +#wc16 P/N flip +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +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}=0x0 + +#wc17 P/N flip +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +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}=0x1 +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 + +#wc18 P/N flip +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 + +#wc19 P/N flip +phy_chain_tx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +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 + +#wc20 P/N flip +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_tx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_tx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_tx_polarity_flip_physical{84.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 + +#wc21 P/N flip +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}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 + +#wc22 P/N flip +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 + +#wc23 P/N flip +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}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 + +#wc24 P/N flip +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 + +#wc25 P/N flip +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_tx_polarity_flip_physical{103.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 + +#wc26 P/N flip +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +#wc27 P/N flip +phy_chain_tx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 + +#wc28 P/N flip +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}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x0 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +#wc29 P/N flip +phy_chain_tx_polarity_flip_physical{117.0}=0x1 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_rx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_rx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 + +#wc30 P/N flip +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +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 + +#wc31 P/N flip +phy_chain_tx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +#MC P/N flip +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 + + +# configuration for 100G optical module +serdes_preemphasis_1=0x164608 +serdes_preemphasis_5=0x164608 +serdes_preemphasis_9=0x164608 +serdes_preemphasis_13=0x134908 +serdes_preemphasis_17=0x134908 +serdes_preemphasis_21=0x134908 +serdes_preemphasis_25=0x124a08 +serdes_preemphasis_29=0x124a08 +serdes_preemphasis_33=0x114b08 +serdes_preemphasis_37=0x114b08 +serdes_preemphasis_41=0x0f4d08 +serdes_preemphasis_45=0x0f4d08 +serdes_preemphasis_49=0x0d4f08 +serdes_preemphasis_53=0x0d4f08 +serdes_preemphasis_57=0x0d4f08 +serdes_preemphasis_61=0x0d4f08 +serdes_preemphasis_67=0x0d4f08 +serdes_preemphasis_71=0x0d4f08 +serdes_preemphasis_75=0x0d4f08 +serdes_preemphasis_79=0x0d4f08 +serdes_preemphasis_83=0x0d4f08 +serdes_preemphasis_87=0x0f4d08 +serdes_preemphasis_91=0x0f4d08 +serdes_preemphasis_95=0x0f4d08 +serdes_preemphasis_99=0x114b08 +serdes_preemphasis_103=0x114b08 +serdes_preemphasis_107=0x114b08 +serdes_preemphasis_111=0x124a08 +serdes_preemphasis_115=0x134908 +serdes_preemphasis_119=0x134908 +serdes_preemphasis_123=0x134908 +serdes_preemphasis_127=0x164608 + +#VxLAN +sai_tunnel_support=1 +use_all_splithorizon_groups=1 +bcm_tunnel_term_compatible_mode=1 +flow_init_mode=1 +l3_ecmp_levels=2 +riot_enable=1 +riot_overlay_l3_intf_mem_size=8192 +riot_overlay_l3_egress_mem_size=32768 +riot_overlay_ecmp_resilient_hash_size=16384 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm index d9d2f47750d9..7803fa422f1a 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm @@ -1,4 +1,3 @@ -sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_premium_issu/b870.6.4.1/ help_cli_enable=1 ifp_inports_support_enable=1 ipv6_lpm_128b_enable=0x1 @@ -8,8 +7,13 @@ l3_max_ecmp_mode=1 l3_mem_entries=16384 lpm_scaling_enable=1 max_vp_lags=0 -mem_cache_enable=0 +#mem_cache_enable=0 memlist_enable=1 +reglist_enable=1 +#scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 miim_intr_enable=0 module_64ports=1 oversubscribe_mode=1 @@ -18,47 +22,49 @@ serdes_lane_config_dfe=on #serdes_fec_enable=1 serdes_if_type_ce=14 pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 -pbmp_xport_xe=0x888888888888888c2222222222222222 +pbmp_xport_xe=0x3ffffffffffffffffffffffffffffffffe +port_flex_enable=1 ptp_ts_pll_fref=50000000 ptp_bs_fref_0=50000000 ptp_bs_fref_1=50000000 - -portmap_1.0=1:100 -portmap_5.0=5:100 -portmap_9.0=9:100 -portmap_13.0=13:100 -portmap_17.0=17:100 -portmap_21.0=21:100 -portmap_25.0=25:100 -portmap_29.0=29:100 -portmap_33.0=33:100 -portmap_37.0=37:100 -portmap_41.0=41:100 -portmap_45.0=45:100 -portmap_49.0=49:100 -portmap_53.0=53:100 -portmap_57.0=57:100 -portmap_61.0=61:100 - -portmap_67.0=65:100 -portmap_71.0=69:100 -portmap_75.0=73:100 -portmap_79.0=77:100 -portmap_83.0=81:100 -portmap_87.0=85:100 -portmap_91.0=89:100 -portmap_95.0=93:100 -portmap_99.0=97:100 -portmap_103.0=101:100 -portmap_107.0=105:100 -portmap_111.0=109:100 -portmap_115.0=113:100 -portmap_119.0=117:100 -portmap_123.0=121:100 -portmap_127.0=125:100 -portmap_66.0=129:10:m -#portmap_130.0=128:10:m +bcm_tunnel_term_compatible_mode=1 +phy_an_c73=1 + +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_21=21:100 +portmap_25=25:100 +portmap_29=29:100 +portmap_33=33:100 +portmap_37=37:100 +portmap_41=41:100 +portmap_45=45:100 +portmap_49=49:100 +portmap_53=53:100 +portmap_57=57:100 +portmap_61=61:100 +portmap_67=65:100 +portmap_71=69:100 +portmap_75=73:100 +portmap_79=77:100 +portmap_83=81:100 +portmap_87=85:100 +portmap_91=89:100 +portmap_95=93:100 +portmap_99=97:100 +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 +portmap_66=129:10:m +#portmap_130=128:10:m #wc0 lane swap phy_chain_tx_lane_map_physical{1.0}=0x0132 @@ -518,45 +524,11 @@ phy_chain_tx_polarity_flip_physical{129.0}=0x1 phy_chain_rx_polarity_flip_physical{129.0}=0x0 phy_chain_tx_polarity_flip_physical{130.0}=0x0 phy_chain_rx_polarity_flip_physical{130.0}=0x0 -phy_chain_tx_polarity_flip_physical{131.0}=0x0 -phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 phy_chain_tx_polarity_flip_physical{132.0}=0x0 -phy_chain_rx_polarity_flip_physical{132.0}=0x0 - -dport_map_port_1=1 -dport_map_port_5=2 -dport_map_port_9=3 -dport_map_port_13=4 -dport_map_port_17=5 -dport_map_port_21=6 -dport_map_port_25=7 -dport_map_port_29=8 -dport_map_port_33=9 -dport_map_port_37=10 -dport_map_port_41=11 -dport_map_port_45=12 -dport_map_port_49=13 -dport_map_port_53=14 -dport_map_port_57=15 -dport_map_port_61=16 -dport_map_port_67=17 -dport_map_port_71=18 -dport_map_port_75=19 -dport_map_port_79=20 -dport_map_port_83=21 -dport_map_port_87=22 -dport_map_port_91=23 -dport_map_port_95=24 -dport_map_port_99=25 -dport_map_port_103=26 -dport_map_port_107=27 -dport_map_port_111=28 -dport_map_port_115=29 -dport_map_port_119=30 -dport_map_port_123=31 -dport_map_port_127=32 -dport_map_port_66=33 -#dport_map_port_130=34 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 + # configuration for 100G optical module serdes_preemphasis_1=0x164608 @@ -592,8 +564,3 @@ serdes_preemphasis_119=0x134908 serdes_preemphasis_123=0x134908 serdes_preemphasis_127=0x164608 -reglist_enable=1 -scache_filename=/tmp/scache -schan_intr_enable=0 -stable_size=0x5500000 -tdma_timeout_usec=3000000 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/custom.bin b/device/celestica/x86_64-cel_seastone_2-r0/custom_led.bin similarity index 100% rename from device/celestica/x86_64-cel_seastone_2-r0/custom.bin rename to device/celestica/x86_64-cel_seastone_2-r0/custom_led.bin diff --git a/device/celestica/x86_64-cel_seastone_2-r0/installer.conf b/device/celestica/x86_64-cel_seastone_2-r0/installer.conf index 3222a45fe1d4..1d21376ff555 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/installer.conf +++ b/device/celestica/x86_64-cel_seastone_2-r0/installer.conf @@ -1,3 +1,4 @@ +CONSOLE_PORT=0xe060 CONSOLE_DEV=0 CONSOLE_SPEED=115200 -ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="earlycon=uart8250,mmio,0xdf37b000" \ No newline at end of file +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off thermal.off=1 noirqdebug acpi_no_watchdog earlycon=uart8250,mmio,0xdf37b000" diff --git a/device/celestica/x86_64-cel_seastone_2-r0/led_proc_init.soc b/device/celestica/x86_64-cel_seastone_2-r0/led_proc_init.soc index b6b474bd53d6..90aa9ba607ac 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/led_proc_init.soc +++ b/device/celestica/x86_64-cel_seastone_2-r0/led_proc_init.soc @@ -1,5 +1,2 @@ -linkscan off -m0 load 0 0x3800 /usr/share/sonic/platform/custom.bin -sleep 10 +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin led auto on; led start -linkscan on diff --git a/device/celestica/x86_64-cel_seastone_2-r0/pcie.yaml b/device/celestica/x86_64-cel_seastone_2-r0/pcie.yaml new file mode 100644 index 000000000000..95e9b6954714 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/pcie.yaml @@ -0,0 +1,153 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1980' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev + 11)' +- bus: '00' + dev: '04' + fn: '0' + id: 19a1 + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers + (rev 11)' +- bus: '00' + dev: '05' + fn: '0' + id: 19a2 + name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 + Series Root Complex Event Collector (rev 11)' +- bus: '00' + dev: '06' + fn: '0' + id: 19a3 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT + Root Port (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 19a4 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #0 (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 19aa + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #6 (rev 11)' +- bus: '00' + dev: '11' + fn: '0' + id: 19ab + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #7 (rev 11)' +- bus: '00' + dev: '12' + fn: '0' + id: 19ac + name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller + - Host (rev 11)' +- bus: '00' + dev: '14' + fn: '0' + id: 19c2 + name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller + 1 (rev 11)' +- bus: '00' + dev: '15' + fn: '0' + id: 19d0 + name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI + Controller (rev 11)' +- bus: '00' + dev: '16' + fn: '0' + id: 19d1 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #0 (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 19d3 + name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME + HECI 1 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1c + fn: '0' + id: 19db + name: 'SD Host controller: Intel Corporation Device 19db (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 19dc + name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev + 11)' +- bus: '00' + dev: 1f + fn: '2' + id: 19de + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management + Controller (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 19df + name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev + 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 19e0 + name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series + SPI Controller (rev 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 19e2 + name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology + (rev 11)' +- bus: '02' + dev: '00' + fn: '0' + id: b870 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b870 (rev 01)' +- bus: '03' + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: '04' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '05' + dev: '00' + fn: '0' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: '05' + dev: '00' + fn: '1' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' diff --git a/device/celestica/x86_64-cel_seastone_2-r0/platform.json b/device/celestica/x86_64-cel_seastone_2-r0/platform.json new file mode 100644 index 000000000000..9d2b5841f179 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/platform.json @@ -0,0 +1,235 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G": ["Eth1/1"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G": ["Eth2/1"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "9,10,11,12", + "breakout_modes": { + "1x100G": ["Eth3/1"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "13,14,15,16", + "breakout_modes": { + "1x100G": ["Eth4/1"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "17,18,19,20", + "breakout_modes": { + "1x100G": ["Eth5/1"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x100G": ["Eth6/1"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x100G": ["Eth7/1"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "29,30,31,32", + "breakout_modes": { + "1x100G": ["Eth8/1"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "33,34,35,36", + "breakout_modes": { + "1x100G": ["Eth9/1"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "37,38,39,40", + "breakout_modes": { + "1x100G": ["Eth10/1"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G": ["Eth11/1"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "45,46,47,48", + "breakout_modes": { + "1x100G": ["Eth12/1"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "49,50,51,52", + "breakout_modes": { + "1x100G": ["Eth13/1"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "53,54,55,56", + "breakout_modes": { + "1x100G": ["Eth14/1"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "57,58,59,60", + "breakout_modes": { + "1x100G": ["Eth15/1"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "61,62,63,64", + "breakout_modes": { + "1x100G": ["Eth16/1"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "65,66,67,68", + "breakout_modes": { + "1x100G": ["Eth17/1"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G": ["Eth18/1"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G": ["Eth19/1"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "77,78,79,80", + "breakout_modes": { + "1x100G": ["Eth20/1"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "81,82,83,84", + "breakout_modes": { + "1x100G": ["Eth21/1"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "85,86,87,88", + "breakout_modes": { + "1x100G": ["Eth22/1"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "89,90,91,92", + "breakout_modes": { + "1x100G": ["Eth23/1"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "93,94,95,96", + "breakout_modes": { + "1x100G": ["Eth24/1"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "97,98,99,100", + "breakout_modes": { + "1x100G": ["Eth25/1"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "101,102,103,104", + "breakout_modes": { + "1x100G": ["Eth26/1"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "105,106,107,108", + "breakout_modes": { + "1x100G": ["Eth27/1"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "109,110,111,112", + "breakout_modes": { + "1x100G": ["Eth28/1"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "113,114,115,116", + "breakout_modes": { + "1x100G": ["Eth29/1"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "117,118,119,120", + "breakout_modes": { + "1x100G": ["Eth30/1"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "121,122,123,124", + "breakout_modes": { + "1x100G": ["Eth31/1"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "125,126,127,128", + "breakout_modes": { + "1x100G": ["Eth32/1"] + } + }, + "Ethernet128": { + "index": "33", + "lanes": "129", + "breakout_modes": { + "1x10G": ["Eth33/1"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/platform_components.json b/device/celestica/x86_64-cel_seastone_2-r0/platform_components.json new file mode 100644 index 000000000000..7daf37202c76 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/platform_components.json @@ -0,0 +1,17 @@ +{ + "chassis": { + "Seastone_2": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/platform_reboot b/device/celestica/x86_64-cel_seastone_2-r0/platform_reboot new file mode 100755 index 000000000000..be80ddbdd1a2 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/platform_reboot @@ -0,0 +1,6 @@ +#!/bin/bash + +# Set all LEDs to BMC's control +ipmitool raw 0x3a 0x0f 0x02 0x01 &> /dev/null + +/usr/local/bin/seastone2_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json index 5e59513ef696..f5b2736b13e0 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json +++ b/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json @@ -1,7 +1,5 @@ { "skip_ledd": true, - "skip_xcvrd": false, - "skip_psud": false, - "skip_syseepromd": false, - "skip_fancontrol": true -} \ No newline at end of file + "skip_fancontrol": true, + "skip_xcvrd_cmis_mgr": true +} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json deleted file mode 100644 index dfa1a1bddff8..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "eeprom": "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom", - "get_reboot_cause": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x0c 0x0 0x2 0x06", - "output_translator": { - "00": "Hardware - Other", - "11": "Hardware - Other", - "22": "Non-Hardware", - "33": "Hardware - Other", - "44": "Non-Hardware", - "55": "Non-Hardware", - "77": "Watchdog", - "88": "Thermal Overload: CPU", - "99": "Thermal Overload: ASIC" - } - }, - "get_reboot_description": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x0c 0x0 0x2 0x06", - "output_translator": { - "00": "The last reset is power cycle reset (set register 0xA164)", - "11": "The last reset is Power on reset", - "22": "The last reset is soft-set CPU warm reset", - "33": "The last reset is soft-set CPU cold reset", - "44": "The last reset is CPU warm reset", - "55": "The last reset is CPU cold reset", - "77": "The last reset is watchdog reset", - "88": "The last reset is CPU thermal overload", - "99": "The last reset is ASIC thermal overload" - } - }, - "get_watchdog": { - "output_source": "class", - "host_path": "/usr/share/sonic/device/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py", - "pmon_path": "/usr/share/sonic/platform/sonic_platform_config/watchdog.py", - "class": "Watchdog" - }, - "get_change_event": { - "output_source": "class", - "host_path": "/usr/share/sonic/device/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py", - "pmon_path": "/usr/share/sonic/platform/sonic_platform_config/event.py", - "class": "SfpEvent" - } -} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json deleted file mode 100644 index 96f646206f97..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "component_num": 5, - "get_name": { - "output_source": "value_list", - "value_list": [ - "BIOS", - "CPLD_BASEBOARD", - "CPLD_SWITCHBOARD", - "FPGA", - "BMC" - ] - }, - "get_description": { - "output_source": "value_list", - "value_list": [ - "Used to perform hardware initialization during the booting process", - "Used to control the system power & reset, Control FAN, UART Mux etc", - "Used for managing QSFP ports", - "Used for managing I2C, SPI, PCIe etc", - "Used for monitoring and managing whole system" - ] - }, - "get_firmware_version": { - "output_source": "function", - "function": [ - "_get_bios_ver", - "_get_base_cpld_ver", - "_get_sw_cpld_ver", - "_get_fpga_ver", - "_get_bmc_ver" - ] - }, - "_get_bmc_ver": { - "output_source": "ipmitool", - "command": "ipmitool mc info | grep 'Firmware Revision'", - "output_translator": "'{}'.split(':')[-1].strip()" - }, - "_get_bios_ver": { - "output_source": "txt_file", - "path": "/sys/class/dmi/id/bios_version" - }, - "_get_base_cpld_ver": { - "output_source": "hex_version_file", - "num_of_points": 1, - "num_of_bits": 8, - "path": "/sys/devices/platform/baseboard/version" - }, - "_get_sw_cpld_ver": { - "output_source": "hex_version_getreg", - "num_of_points": 1, - "num_of_bits": 8, - "reg_addr": "0x00", - "path": "/sys/devices/platform/switchboard/CPLD1/getreg" - }, - "_get_fpga_ver": { - "output_source": "hex_version_getreg", - "num_of_points": 1, - "num_of_bits": 32, - "reg_addr": "0x00", - "path": "/sys/devices/platform/switchboard/FPGA/getreg" - } -} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py deleted file mode 100644 index 32073479a1e6..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py +++ /dev/null @@ -1,117 +0,0 @@ -############################################################################# -# Celestica Seastone2 -# -# SfpEvent contains an implementation of SONiC Platform Base API -# -############################################################################# -try: - import time - import os - from sonic_platform.common import Common -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - - -PLATFORM_PATH = "/sys/devices/platform/" -SWITCH_BRD_PLATFORM = "switchboard" -POLL_INTERVAL = 1 - - -class SfpEvent: - ''' Listen to insert/remove sfp events ''' - - PORT_INFO_DIR = 'SFF' - PATH_INT_SYSFS = "{0}/{port_name}/{type_prefix}_isr_flags" - PATH_INTMASK_SYSFS = "{0}/{port_name}/{type_prefix}_isr_mask" - PATH_PRS_SYSFS = "{0}/{port_name}/{prs_file_name}" - PRESENT_EN = 0x01 - - def __init__(self, sfp_list): - self.num_sfp = len(sfp_list) - self._api_common = Common() - self._initialize_interrupts() - - def _initialize_interrupts(self): - sfp_info_obj = {} - port_info_path = os.path.join( - PLATFORM_PATH, SWITCH_BRD_PLATFORM, self.PORT_INFO_DIR) - - for index in range(self.num_sfp): - port_num = index + 1 - if port_num <= 32: - port_name = "QSFP{}".format(port_num) - port_type = "qsfp" - sysfs_prs_file = "{}_modprs".format(port_type) - else: - port_name = "SFP{}".format(port_num - 32) - port_type = "sfp" - sysfs_prs_file = "{}_modabs".format(port_type) - - sfp_info_obj[index] = {} - sfp_info_obj[index]['intmask_sysfs'] = self.PATH_INTMASK_SYSFS.format( - port_info_path, - port_name=port_name, - type_prefix=port_type) - - sfp_info_obj[index]['int_sysfs'] = self.PATH_INT_SYSFS.format( - port_info_path, - port_name=port_name, - type_prefix=port_type) - - sfp_info_obj[index]['prs_sysfs'] = self.PATH_PRS_SYSFS.format( - port_info_path, - port_name=port_name, - prs_file_name=sysfs_prs_file) - - self._api_common.write_txt_file( - sfp_info_obj[index]["intmask_sysfs"], hex(self.PRESENT_EN)) - - self.sfp_info_obj = sfp_info_obj - - def _is_port_device_present(self, port_idx): - prs_path = self.sfp_info_obj[port_idx]["prs_sysfs"] - is_present = 1 - int(self._api_common.read_txt_file(prs_path)) - return is_present - - def _update_port_event_object(self, interrup_devices, port_dict): - for port_idx in interrup_devices: - device_id = str(port_idx + 1) - port_dict[device_id] = str(self._is_port_device_present(port_idx)) - return port_dict - - def _clear_event_flag(self, path): - self._api_common.write_txt_file(path, hex(0xff)) - time.sleep(0.1) - self._api_common.write_txt_file(path, hex(0x0)) - - def _check_all_port_interrupt_event(self): - interrupt_devices = {} - for i in range(self.num_sfp): - int_sysfs = self.sfp_info_obj[i]["int_sysfs"] - interrupt_flags = self._api_common.read_txt_file(int_sysfs) - if interrupt_flags != '0x00': - interrupt_devices[i] = 1 - self._clear_event_flag(int_sysfs) - return interrupt_devices - - def get_event(self, timeout): - sleep_time = min( - timeout, POLL_INTERVAL) if timeout != 0 else POLL_INTERVAL - start_milli_time = int(round(time.time() * 1000)) - int_sfp = {} - - while True: - chk_sfp = self._check_all_port_interrupt_event() - int_sfp = self._update_port_event_object( - chk_sfp, int_sfp) if chk_sfp else int_sfp - current_milli_time = int(round(time.time() * 1000)) - if (int_sfp) or \ - (timeout != 0 and current_milli_time - start_milli_time > timeout): - break - - time.sleep(sleep_time) - - change_dict = dict() - change_dict['sfp'] = int_sfp - - return True, change_dict diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json deleted file mode 100644 index 724f6edf53c1..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "fan_num_per_drawer": 2, - "drawer_num": 4, - "get_name": { - "output_source": "value_list", - "value_list": [ - "Fan1-F", - "Fan1-R", - "Fan2-F", - "Fan2-R", - "Fan3-F", - "Fan3-R", - "Fan4-F", - "Fan4-R" - ] - }, - "get_presence": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x03 0x03 {}", - "argument": [ - "0x00", - "0x00", - "0x01", - "0x01", - "0x02", - "0x02", - "0x03", - "0x03" - ], - "output_translator": "True if '00' in '{}' else False" - }, - "get_model": { - "output_source": "ipmitool", - "command": "ipmitool fru list {} | grep 'Board Part Number'", - "argument": [ - "5", - "5", - "6", - "6", - "7", - "7", - "8", - "8" - ], - "output_translator": "'{}'.split()[-1]" - }, - "get_serial": { - "output_source": "ipmitool", - "command": "ipmitool fru list {} | grep 'Board Serial'", - "argument": [ - "5", - "5", - "6", - "6", - "7", - "7", - "8", - "8" - ], - "output_translator": "'{}'.split()[-1]" - }, - "get_direction": { - "output_source": "ipmitool", - "command": "ipmitool fru list {} | grep 'F2B\\|B2F'", - "argument": [ - "5", - "5", - "6", - "6", - "7", - "7", - "8", - "8" - ], - "output_translator": "'intake' if 'B2F' in '{}' else 'exhaust'" - }, - "get_speed": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x04 0x2d {}", - "argument": [ - "0x81", - "0x80", - "0x83", - "0x82", - "0x85", - "0x84", - "0x87", - "0x86" - ], - "output_translator": "int('{}'.split()[0],16)*150", - "max_front": 23000, - "max_rear": 20500 - }, - "get_target_speed": { - "output_source": "value", - "value": "N/A" - }, - "get_speed_tolerance": { - "output_source": "value", - "value": 10 - }, - "set_speed": { - "set_method": "ipmitool", - "input_translator": "hex(int({} * 255 / 100.0))", - "command": "ipmitool raw 0x3a 0x0c 0x00 0x03 {}", - "argument": [ - "0x40 {}", - "0x40 {}", - "0x44 {}", - "0x44 {}", - "0x4c {}", - "0x4c {}", - "0x50 {}", - "0x50 {}" - ] - }, - "set_status_led": { - "set_method": "ipmitool", - "avaliable_input": [ - "off", - "amber", - "green" - ], - "input_translator": { - "off": "0x0", - "amber": "0x1", - "green": "0x2" - }, - "command": "ipmitool raw 0x3a 0x0a {}", - "argument": [ - "0x4 {}", - "0x4 {}", - "0x5 {}", - "0x5 {}", - "0x6 {}", - "0x6 {}", - "0x7 {}", - "0x7 {}" - ] - }, - "get_status_led": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x0b {}", - "argument": [ - "0x4", - "0x4", - "0x5", - "0x5", - "0x6", - "0x6", - "0x7", - "0x7" - ], - "output_translator": { - "00": "off", - "01": "amber", - "02": "green" - } - }, - "psu_fan": [ - { - "num_of_fan": 1, - "get_name": { - "output_source": "value_list", - "value_list": [ - "PSU-R-Fan" - ] - }, - "get_speed": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x04 0x2d {}", - "argument": [ - "0x8b" - ], - "output_translator": "int('{}'.split()[0],16)*100", - "max_front": 22600, - "max_rear": 22600 - } - }, - { - "num_of_fan": 1, - "get_name": { - "output_source": "value_list", - "value_list": [ - "PSU-L-Fan" - ] - }, - "get_speed": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x04 0x2d {}", - "argument": [ - "0x8a" - ], - "output_translator": "int('{}'.split()[0],16)*100", - "max_front": 22600, - "max_rear": 22600 - } - } - ] -} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json deleted file mode 100644 index c3e953c082a7..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "psu_num": 2, - "fan_per_psu_num": 1, - "get_name": { - "output_source": "value_list", - "value_list": [ - "PSU-R", - "PSU-L" - ] - }, - "get_power": { - "output_source": "ipmitool", - "command": "ipmitool sdr | grep {}", - "argument": [ - "PSUR_POut", - "PSUL_POut" - ], - "output_translator": "float('{}'.split()[2])" - }, - "get_current": { - "output_source": "ipmitool", - "command": "ipmitool sdr | grep {}", - "argument": [ - "PSUR_COut", - "PSUL_COut" - ], - "output_translator": "float('{}'.split()[2])" - }, - "get_voltage": { - "output_source": "ipmitool", - "command": "ipmitool sdr | grep {}", - "argument": [ - "PSUR_VOut", - "PSUL_VOut" - ], - "output_translator": "float('{}'.split()[2])" - }, - "get_voltage_high_threshold": { - "output_source": "ipmitool", - "command": "ipmitool sensor list | grep {}", - "argument": [ - "PSUR_Temp2", - "PSUL_Temp2" - ], - "output_translator": "float(0 if '{0}'.split()[-3]=='na' else '{0}'.split()[-3])" - }, - "get_voltage_low_threshold": { - "output_source": "ipmitool", - "command": "ipmitool sensor list | grep {}", - "argument": [ - "PSUR_Temp2", - "PSUL_Temp2" - ], - "output_translator": "float(0 if '{0}'.split()[-9]=='na' else '{0}'.split()[-9])" - }, - "get_presence": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x0c 0x00 0x2 0x60", - "output_translator": [ - "True if (int('{}', 16) >> 4 & 1) == 0 else False", - "True if (int('{}', 16) >> 5 & 1) == 0 else False" - ] - }, - "get_model": { - "output_source": "ipmitool", - "command": "ipmitool fru list {} | grep 'Product Part Number'", - "argument": [ - "4", - "3" - ], - "output_translator": "'{}'.split()[-1]" - }, - "get_serial": { - "output_source": "ipmitool", - "command": "ipmitool fru list {} | grep 'Product Serial'", - "argument": [ - "4", - "3" - ], - "output_translator": "'{}'.split()[-1]" - }, - "get_powergood_status": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x0c 0x0 0x2 0x60", - "output_translator": [ - "True if (int('{}', 16) >> 2 & 1) == 1 else False", - "True if (int('{}', 16) >> 3 & 1) == 1 else False" - ] - }, - "set_status_led": { - "set_method": "ipmitool", - "avaliable_input": [ - "amber" - ], - "input_translator": { - "amber": "0x1" - }, - "command": "ipmitool raw 0x3a 0x0a {}", - "argument": [ - "0x3 {}", - "0x2 {}" - ] - }, - "get_status_led": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x3a 0x0b {}", - "argument": [ - "0x3", - "0x2" - ], - "output_translator": { - "00": "green", - "01": "amber" - }, - "default_output": "off" - }, - "get_temperature": { - "output_source": "ipmitool", - "command": "ipmitool sdr | grep {}", - "argument": [ - "PSUR_Temp2", - "PSUL_Temp2" - ], - "output_translator": "float('{}'.split()[2])" - }, - "get_temperature_high_threshold": { - "output_source": "ipmitool", - "command": "ipmitool sensor list | grep {}", - "argument": [ - "PSUR_Temp2", - "PSUL_Temp2" - ], - "output_translator": "float(0 if '{0}'.split()[-3]=='na' else '{0}'.split()[-3])" - } -} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json deleted file mode 100644 index d12f0c3ffc1b..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "port_num": 33, - "eeprom_path": "/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom", - "port_i2c_mapping": [ - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34 - ], - "get_presence": { - "output_source": "sysfs_value", - "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}", - "argument": "$ref:_presence_file", - "output_translator": "False if '{}' == '1' else True" - }, - "get_lpmode": { - "output_source": "sysfs_value", - "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_lpmode", - "argument": "$ref:_port_name", - "output_translator": "True if '{}' == '1' else False" - }, - "get_reset_status": { - "output_source": "sysfs_value", - "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_reset", - "argument": "$ref:_port_name", - "output_translator": "False if '{}' == '1' else True" - }, - "reset": { - "set_method": "sysfs_value", - "write_offset": 0, - "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_reset", - "argument": "$ref:_port_name" - }, - "set_lpmode": { - "set_method": "sysfs_value", - "input_translator": { - "True": "0x1", - "False": "0x0" - }, - "write_offset": 0, - "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_lpmode", - "argument": "$ref:_port_name" - }, - "_port_name": [ - "QSFP1", - "QSFP2", - "QSFP3", - "QSFP4", - "QSFP5", - "QSFP6", - "QSFP7", - "QSFP8", - "QSFP9", - "QSFP10", - "QSFP11", - "QSFP12", - "QSFP13", - "QSFP14", - "QSFP15", - "QSFP16", - "QSFP17", - "QSFP18", - "QSFP19", - "QSFP20", - "QSFP21", - "QSFP22", - "QSFP23", - "QSFP24", - "QSFP25", - "QSFP26", - "QSFP27", - "QSFP28", - "QSFP29", - "QSFP30", - "QSFP31", - "QSFP32", - "SFP1" - ], - "_presence_file": [ - "QSFP1/qsfp_modprs", - "QSFP2/qsfp_modprs", - "QSFP3/qsfp_modprs", - "QSFP4/qsfp_modprs", - "QSFP5/qsfp_modprs", - "QSFP6/qsfp_modprs", - "QSFP7/qsfp_modprs", - "QSFP8/qsfp_modprs", - "QSFP9/qsfp_modprs", - "QSFP10/qsfp_modprs", - "QSFP11/qsfp_modprs", - "QSFP12/qsfp_modprs", - "QSFP13/qsfp_modprs", - "QSFP14/qsfp_modprs", - "QSFP15/qsfp_modprs", - "QSFP16/qsfp_modprs", - "QSFP17/qsfp_modprs", - "QSFP18/qsfp_modprs", - "QSFP19/qsfp_modprs", - "QSFP20/qsfp_modprs", - "QSFP21/qsfp_modprs", - "QSFP22/qsfp_modprs", - "QSFP23/qsfp_modprs", - "QSFP24/qsfp_modprs", - "QSFP25/qsfp_modprs", - "QSFP26/qsfp_modprs", - "QSFP27/qsfp_modprs", - "QSFP28/qsfp_modprs", - "QSFP29/qsfp_modprs", - "QSFP30/qsfp_modprs", - "QSFP31/qsfp_modprs", - "QSFP32/qsfp_modprs", - "SFP1/sfp_modabs" - ] -} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json deleted file mode 100644 index e3dcb7fb9271..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "thermal_num": 9, - "get_name": { - "output_source": "value_list", - "value_list": [ - "Base_Temp_U5", - "Base_Temp_U7", - "CPU_Temp", - "Switch_Temp_U1", - "Switch_Temp_U18", - "Switch_Temp_U28", - "Switch_Temp_U29", - "Switch_U21_Temp", - "Switch_U33_Temp" - ] - }, - "get_temperature": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x04 0x2D {}", - "argument": [ - "0x1", - "0x2", - "0x7", - "0x3", - "0x4", - "0x5", - "0x6", - "0x56", - "0x4C" - ], - "output_translator": "int('{}'.split()[0],16)" - }, - "get_high_threshold": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x04 0x27 {}", - "argument": [ - "0x1", - "0x2", - "0x7", - "0x3", - "0x4", - "0x5", - "0x6", - "0x56", - "0x4c" - ], - "output_translator": "int('{}'.split()[4], 16)" - }, - "get_low_threshold": { - "output_source": "value", - "value": "N/A" - }, - "set_high_threshold": { - "set_method": "ipmitool", - "command": "ipmitool sensor thresh {}", - "input_translator": "{}", - "argument": [ - "Base_Temp_U5 unc {}", - "Base_Temp_U7 unc {}", - "CPU_Temp unc {}", - "Switch_Temp_U1 unc {}", - "Switch_Temp_U18 unc {}", - "Switch_Temp_U28 unc {}", - "Switch_Temp_U29 unc {}", - "Switch_U21_Temp unc {}", - "Switch_U33_Temp unc {}" - ] - }, - "set_low_threshold": { - "output_source": "ipmitool", - "command": "ipmitool sensor thresh {}", - "input_translator": "{}", - "argument": [ - "Base_Temp_U5 lnc {}", - "Base_Temp_U7 lnc {}", - "CPU_Temp lnc {}", - "Switch_Temp_U1 lnc {}", - "Switch_Temp_U18 lnc {}", - "Switch_Temp_U28 lnc {}", - "Switch_Temp_U29 lnc {}", - "Switch_U21_Temp lnc {}", - "Switch_U33_Temp lnc {}" - ] - }, - "get_high_critical_threshold": { - "output_source": "ipmitool", - "command": "ipmitool raw 0x04 0x27 {}", - "argument": [ - "0x1", - "0x2", - "0x7", - "0x3", - "0x4", - "0x5", - "0x6", - "0x56", - "0x4c" - ], - "output_translator": "int('{}'.split()[5], 16)" - }, - "get_low_critical_threshold": { - "output_source": "value", - "value": "N/A" - } -} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py deleted file mode 100644 index fac5c40e134f..000000000000 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py +++ /dev/null @@ -1,191 +0,0 @@ -############################################################################# -# Celestica Seastone2 -# -# Watchdog contains an implementation of SONiC Platform Base API -# -############################################################################# -import os -import time - -try: - from sonic_platform_base.watchdog_base import WatchdogBase - from sonic_platform.common import Common -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -PLATFORM_CPLD_PATH = '/sys/devices/platform/baseboard/' -GETREG_FILE = 'getreg' -SETREG_FILE = 'setreg' -WDT_ENABLE_REG = '0xA181' -WDT_TIMER_L_BIT_REG = '0xA182' -WDT_TIMER_M_BIT_REG = '0xA183' -WDT_TIMER_H_BIT_REG = '0xA184' -WDT_KEEP_ALVIVE_REG = '0xA185' -ENABLE_CMD = '0x1' -DISABLE_CMD = '0x0' -WDT_COMMON_ERROR = -1 - - -class Watchdog(WatchdogBase): - - def __init__(self): - WatchdogBase.__init__(self) - - self._api_common = Common() - - # Init cpld reg path - self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE) - self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE) - - # Set default value - self._disable() - self.armed = False - self.timeout = self._gettimeout() - - def _enable(self): - """ - Turn on the watchdog timer - """ - # echo 0xA181 0x1 > /sys/devices/platform/baseboard/setreg - enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD) - return self._api_common.write_txt_file(self.setreg_path, enable_val) - - def _disable(self): - """ - Turn off the watchdog timer - """ - # echo 0xA181 0x0 > /sys/devices/platform/baseboard/setreg - disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD) - return self._api_common.write_txt_file(self.setreg_path, disable_val) - - def _keepalive(self): - """ - Keep alive watchdog timer - """ - # echo 0xA185 0x1 > /sys/devices/platform/baseboard/setreg - enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD) - return self._api_common.write_txt_file(self.setreg_path, enable_val) - - def _get_level_hex(self, sub_hex): - sub_hex_str = sub_hex.replace("x", "0") - return hex(int(sub_hex_str, 16)) - - def _seconds_to_lmh_hex(self, seconds): - ms = seconds*1000 # calculate timeout in ms format - hex_str = hex(ms) - l = self._get_level_hex(hex_str[-2:]) - m = self._get_level_hex(hex_str[-4:-2]) - h = self._get_level_hex(hex_str[-6:-4]) - return (l, m, h) - - def _settimeout(self, seconds): - """ - Set watchdog timer timeout - @param seconds - timeout in seconds - @return is the actual set timeout - """ - # max = 0xffffff = 16777.215 seconds - - (l, m, h) = self._seconds_to_lmh_hex(seconds) - set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h) - set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m) - set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l) - - self._api_common.write_txt_file( - self.setreg_path, set_h_val) # set high bit - self._api_common.write_txt_file( - self.setreg_path, set_m_val) # set med bit - self._api_common.write_txt_file( - self.setreg_path, set_l_val) # set low bit - - return seconds - - def _gettimeout(self): - """ - Get watchdog timeout - @return watchdog timeout - """ - - h_bit = self._api_common.get_reg( - self.getreg_path, WDT_TIMER_H_BIT_REG) - m_bit = self._api_common.get_reg( - self.getreg_path, WDT_TIMER_M_BIT_REG) - l_bit = self._api_common.get_reg( - self.getreg_path, WDT_TIMER_L_BIT_REG) - - hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:]) - ms = int(hex_time, 16) - return int(float(ms)/1000) - - ################################################################# - - 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. - """ - - ret = WDT_COMMON_ERROR - if seconds < 0: - return ret - - try: - if self.timeout != seconds: - self.timeout = self._settimeout(seconds) - - if self.armed: - self._keepalive() - else: - self._enable() - self.armed = True - - ret = self.timeout - self.arm_timestamp = time.time() - except IOError as e: - pass - - return ret - - def disarm(self): - """ - Disarm the hardware watchdog - Returns: - A boolean, True if watchdog is disarmed successfully, False if not - """ - disarmed = False - if self.is_armed(): - try: - self._disable() - self.armed = False - disarmed = True - except IOError: - pass - - return disarmed - - def is_armed(self): - """ - Retrieves the armed state of the hardware watchdog. - Returns: - A boolean, True if watchdog is armed, False if not - """ - - return self.armed - - 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. - """ - - return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR diff --git a/device/celestica/x86_64-cel_seastone_2-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_seastone_2-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..56fda7de4f5d --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/system_health_monitoring_config.json @@ -0,0 +1,13 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "psu.temperature" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "green_blink_1hz" + } +} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/warm-reboot_plugin b/device/celestica/x86_64-cel_seastone_2-r0/warm-reboot_plugin new file mode 100755 index 000000000000..d0fb8b29e191 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/warm-reboot_plugin @@ -0,0 +1,4 @@ +#!/bin/bash + +# Set all LEDs to BMC's control +ipmitool raw 0x3a 0x0f 0x02 0x01 &> /dev/null diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm index 447de2e85b5a..baddedd9c61b 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm @@ -9,8 +9,6 @@ phy_enable=0 phy_null=1 pll_bypass=1 -init_all_modules=0 - sai_tunnel_global_sip_mask_enable=1 portmap_20=33:100:2 diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/hwsku.json b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/hwsku.json new file mode 100644 index 000000000000..b97d516509ec --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/hwsku.json @@ -0,0 +1,164 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet128": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet136": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet144": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet152": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet160": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet168": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet176": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet184": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet192": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet200": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet208": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet216": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet224": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet232": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet240": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet248": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini index 9cd85ee34798..1d2b56d9fed9 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini @@ -1,33 +1,33 @@ # name lanes alias index speed -Ethernet0 33,34,35,36,37,38,39,40 QSFPDD1 1 400000 -Ethernet4 41,42,43,44,45,46,47,48 QSFPDD2 2 400000 -Ethernet8 49,50,51,52,53,54,55,56 QSFPDD3 3 400000 -Ethernet12 57,58,59,60,61,62,63,64 QSFPDD4 4 400000 -Ethernet16 65,66,67,68,69,70,71,72 QSFPDD5 5 400000 -Ethernet20 73,74,75,76,77,78,79,80 QSFPDD6 6 400000 -Ethernet24 81,82,83,84,85,86,87,88 QSFPDD7 7 400000 -Ethernet28 89,90,91,92,93,94,95,96 QSFPDD8 8 400000 -Ethernet32 1,2,3,4,5,6,7,8 QSFPDD9 9 400000 -Ethernet36 9,10,11,12,13,14,15,16 QSFPDD10 10 400000 -Ethernet40 17,18,19,20,21,22,23,24 QSFPDD11 11 400000 -Ethernet44 25,26,27,28,29,30,31,32 QSFPDD12 12 400000 -Ethernet48 97,98,99,100,101,102,103,104 QSFPDD13 13 400000 -Ethernet52 105,106,107,108,109,110,111,112 QSFPDD14 14 400000 -Ethernet56 113,114,115,116,117,118,119,120 QSFPDD15 15 400000 -Ethernet60 121,122,123,124,125,126,127,128 QSFPDD16 16 400000 -Ethernet64 129,130,131,132,133,134,135,136 QSFPDD17 17 400000 -Ethernet68 137,138,139,140,141,142,143,144 QSFPDD18 18 400000 -Ethernet72 145,146,147,148,149,150,151,152 QSFPDD19 19 400000 -Ethernet76 153,154,155,156,157,158,159,160 QSFPDD20 20 400000 -Ethernet80 225,226,227,228,229,230,231,232 QSFPDD21 21 400000 -Ethernet84 233,234,235,236,237,238,239,240 QSFPDD22 22 400000 -Ethernet88 241,242,243,244,245,246,247,248 QSFPDD23 23 400000 -Ethernet92 249,250,251,252,253,254,255,256 QSFPDD24 24 400000 -Ethernet96 161,162,163,164,165,166,167,168 QSFPDD25 25 400000 -Ethernet100 169,170,171,172,173,174,175,176 QSFPDD26 26 400000 -Ethernet104 177,178,179,180,181,182,183,184 QSFPDD27 27 400000 -Ethernet108 185,186,187,188,189,190,191,192 QSFPDD28 28 400000 -Ethernet112 193,194,195,196,197,198,199,200 QSFPDD29 29 400000 -Ethernet116 201,202,203,204,205,206,207,208 QSFPDD30 30 400000 -Ethernet120 209,210,211,212,213,214,215,216 QSFPDD31 31 400000 -Ethernet124 217,218,219,220,221,222,223,224 QSFPDD32 32 400000 \ No newline at end of file +Ethernet0 33,34,35,36,37,38,39,40 Eth1/1 1 400000 +Ethernet8 41,42,43,44,45,46,47,48 Eth2/1 2 400000 +Ethernet16 49,50,51,52,53,54,55,56 Eth3/1 3 400000 +Ethernet24 57,58,59,60,61,62,63,64 Eth4/1 4 400000 +Ethernet32 65,66,67,68,69,70,71,72 Eth5/1 5 400000 +Ethernet40 73,74,75,76,77,78,79,80 Eth6/1 6 400000 +Ethernet48 81,82,83,84,85,86,87,88 Eth7/1 7 400000 +Ethernet56 89,90,91,92,93,94,95,96 Eth8/1 8 400000 +Ethernet64 1,2,3,4,5,6,7,8 Eth9/1 9 400000 +Ethernet72 9,10,11,12,13,14,15,16 Eth10/1 10 400000 +Ethernet80 17,18,19,20,21,22,23,24 Eth11/1 11 400000 +Ethernet88 25,26,27,28,29,30,31,32 Eth12/1 12 400000 +Ethernet96 97,98,99,100,101,102,103,104 Eth13/1 13 400000 +Ethernet104 105,106,107,108,109,110,111,112 Eth14/1 14 400000 +Ethernet112 113,114,115,116,117,118,119,120 Eth15/1 15 400000 +Ethernet120 121,122,123,124,125,126,127,128 Eth16/1 16 400000 +Ethernet128 129,130,131,132,133,134,135,136 Eth17/1 17 400000 +Ethernet136 137,138,139,140,141,142,143,144 Eth18/1 18 400000 +Ethernet144 145,146,147,148,149,150,151,152 Eth19/1 19 400000 +Ethernet152 153,154,155,156,157,158,159,160 Eth20/1 20 400000 +Ethernet160 225,226,227,228,229,230,231,232 Eth21/1 21 400000 +Ethernet168 233,234,235,236,237,238,239,240 Eth22/1 22 400000 +Ethernet176 241,242,243,244,245,246,247,248 Eth23/1 23 400000 +Ethernet184 249,250,251,252,253,254,255,256 Eth24/1 24 400000 +Ethernet192 161,162,163,164,165,166,167,168 Eth25/1 25 400000 +Ethernet200 169,170,171,172,173,174,175,176 Eth26/1 26 400000 +Ethernet208 177,178,179,180,181,182,183,184 Eth27/1 27 400000 +Ethernet216 185,186,187,188,189,190,191,192 Eth28/1 28 400000 +Ethernet224 193,194,195,196,197,198,199,200 Eth29/1 29 400000 +Ethernet232 201,202,203,204,205,206,207,208 Eth30/1 30 400000 +Ethernet240 209,210,211,212,213,214,215,216 Eth31/1 31 400000 +Ethernet248 217,218,219,220,221,222,223,224 Eth32/1 32 400000 diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai_postinit_cmd.soc b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai_postinit_cmd.soc new file mode 100644 index 000000000000..731625308a5e --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai_postinit_cmd.soc @@ -0,0 +1,2 @@ +modreg ING_MISC_CONFIG INPUT_PRI_TAGGED=1 +modreg ING_MISC_CONFIG INPUT_PRI_UNTAGGED=1 diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm index 400fbdcf7573..3d4cebc5269f 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm @@ -1,5 +1,5 @@ -pbmp_xport_xe.0=0x8111181111c1111811118111181111c111182222 +pbmp_xport_xe.0=0x8ffff8ffffcffff8ffff8ffff8ffffcffff8ffff ccm_dma_enable=0 ccmdma_intr_enable=0 ctr_evict_enable=0 @@ -10,8 +10,6 @@ phy_enable=0 phy_null=1 pll_bypass=1 -init_all_modules=0 - sai_tunnel_global_sip_mask_enable=1 @@ -183,38 +181,38 @@ serdes_core_tx_polarity_flip_physical{209}=0xe9 serdes_core_rx_polarity_flip_physical{217}=0xec serdes_core_tx_polarity_flip_physical{217}=0x68 -dport_map_port_20=1 -dport_map_port_24=2 -dport_map_port_28=3 -dport_map_port_32=4 -dport_map_port_40=5 -dport_map_port_44=6 -dport_map_port_48=7 -dport_map_port_52=8 -dport_map_port_1=9 -dport_map_port_5=10 -dport_map_port_9=11 -dport_map_port_13=12 -dport_map_port_60=13 -dport_map_port_64=14 -dport_map_port_68=15 -dport_map_port_72=16 -dport_map_port_80=17 -dport_map_port_84=18 -dport_map_port_88=19 -dport_map_port_92=20 -dport_map_port_140=21 -dport_map_port_144=22 -dport_map_port_148=23 -dport_map_port_152=24 -dport_map_port_100=25 -dport_map_port_104=26 -dport_map_port_108=27 -dport_map_port_112=28 -dport_map_port_120=29 -dport_map_port_124=30 -dport_map_port_128=31 -dport_map_port_132=32 +#dport_map_port_20=1 +#dport_map_port_24=2 +#dport_map_port_28=3 +#dport_map_port_32=4 +#dport_map_port_40=5 +#dport_map_port_44=6 +#dport_map_port_48=7 +#dport_map_port_52=8 +#dport_map_port_1=9 +#dport_map_port_5=10 +#dport_map_port_9=11 +#dport_map_port_13=12 +#dport_map_port_60=13 +#dport_map_port_64=14 +#dport_map_port_68=15 +#dport_map_port_72=16 +#dport_map_port_80=17 +#dport_map_port_84=18 +#dport_map_port_88=19 +#dport_map_port_92=20 +#dport_map_port_140=21 +#dport_map_port_144=22 +#dport_map_port_148=23 +#dport_map_port_152=24 +#dport_map_port_100=25 +#dport_map_port_104=26 +#dport_map_port_108=27 +#dport_map_port_112=28 +#dport_map_port_120=29 +#dport_map_port_124=30 +#dport_map_port_128=31 +#dport_map_port_132=32 #dport_map_port_38=33 #dport_map_port_118=34 @@ -229,4 +227,4 @@ port_flex_enable=1 #firmware load method, use fast load load_firmware=0x2 - +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc diff --git a/device/celestica/x86_64-cel_silverstone-r0/pcie.yaml b/device/celestica/x86_64-cel_silverstone-r0/pcie.yaml new file mode 100644 index 000000000000..2249ead1a849 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/pcie.yaml @@ -0,0 +1,434 @@ +- 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: '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: '03' + fn: '1' + id: 6f09 + 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: '03' + fn: '2' + id: 6f0a + 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: '03' + fn: '3' + id: 6f0b + 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: 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: 1c + fn: '1' + id: 8c12 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #2 (rev d5)' +- bus: '00' + dev: 1c + fn: '2' + id: 8c14 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #3 (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: '02' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '02' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '02' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '02' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '03' + dev: '00' + fn: '0' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '03' + dev: '00' + fn: '1' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '05' + dev: '00' + fn: '0' + id: b980 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b980 (rev 11)' +- bus: 09 + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: 0a + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: 0b + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- 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: 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/celestica/x86_64-cel_silverstone-r0/platform.json b/device/celestica/x86_64-cel_silverstone-r0/platform.json new file mode 100644 index 000000000000..6dc768bd4622 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/platform.json @@ -0,0 +1,484 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1,1,1,1,1", + "lanes": "33,34,35,36,37,38,39,40", + "breakout_modes": { + "1x400G": ["Eth1/1"], + "2x100G": ["Eth1/1", "Eth1/5"], + "2x40G": ["Eth1/1", "Eth1/5"], + "4x100G": ["Eth1/1", "Eth1/3", "Eth1/5", "Eth1/7"], + "1x100G(2)": ["Eth1/1"], + "1x100G(4)": ["Eth1/1"], + "1x40G(4)": ["Eth1/1"], + "4x25G(4)": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"], + "4x10G(4)": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"] + } + }, + "Ethernet8": { + "index": "2,2,2,2,2,2,2,2", + "lanes": "41,42,43,44,45,46,47,48", + "breakout_modes": { + "1x400G": ["Eth2/1"], + "2x100G": ["Eth2/1", "Eth2/5"], + "2x40G": ["Eth2/1", "Eth2/5"], + "4x100G": ["Eth2/1", "Eth2/3", "Eth2/5", "Eth2/7"], + "1x100G(2)": ["Eth2/1"], + "1x100G(4)": ["Eth2/1"], + "1x40G(4)": ["Eth2/1"], + "4x25G(4)": ["Eth2/1", "Eth2/2", "Eth2/3", "Eth2/4"], + "4x10G(4)": ["Eth2/1", "Eth2/2", "Eth2/3", "Eth2/4"] + } + }, + "Ethernet16": { + "index": "3,3,3,3,3,3,3,3", + "lanes": "49,50,51,52,53,54,55,56", + "breakout_modes": { + "1x400G": ["Eth3/1"], + "2x100G": ["Eth3/1", "Eth3/5"], + "2x40G": ["Eth3/1", "Eth3/5"], + "4x100G": ["Eth3/1", "Eth3/3", "Eth3/5", "Eth3/7"], + "1x100G(2)": ["Eth3/1"], + "1x100G(4)": ["Eth3/1"], + "1x40G(4)": ["Eth3/1"], + "4x25G(4)": ["Eth3/1", "Eth3/2", "Eth3/3", "Eth3/4"], + "4x10G(4)": ["Eth3/1", "Eth3/2", "Eth3/3", "Eth3/4"] + } + }, + "Ethernet24": { + "index": "4,4,4,4,4,4,4,4", + "lanes": "57,58,59,60,61,62,63,64", + "breakout_modes": { + "1x400G": ["Eth4/1"], + "2x100G": ["Eth4/1", "Eth4/5"], + "2x40G": ["Eth4/1", "Eth4/5"], + "4x100G": ["Eth4/1", "Eth4/3", "Eth4/5", "Eth4/7"], + "1x100G(2)": ["Eth4/1"], + "1x100G(4)": ["Eth4/1"], + "1x40G(4)": ["Eth4/1"], + "4x25G(4)": ["Eth4/1", "Eth4/2", "Eth4/3", "Eth4/4"], + "4x10G(4)": ["Eth4/1", "Eth4/2", "Eth4/3", "Eth4/4"] + } + }, + "Ethernet32": { + "index": "5,5,5,5,5,5,5,5", + "lanes": "65,66,67,68,69,70,71,72", + "breakout_modes": { + "1x400G": ["Eth5/1"], + "2x100G": ["Eth5/1", "Eth5/5"], + "2x40G": ["Eth5/1", "Eth5/5"], + "4x100G": ["Eth5/1", "Eth5/3", "Eth5/5", "Eth5/7"], + "1x100G(2)": ["Eth5/1"], + "1x100G(4)": ["Eth5/1"], + "1x40G(4)": ["Eth5/1"], + "4x25G(4)": ["Eth5/1", "Eth5/2", "Eth5/3", "Eth5/4"], + "4x10G(4)": ["Eth5/1", "Eth5/2", "Eth5/3", "Eth5/4"] + } + }, + "Ethernet40": { + "index": "6,6,6,6,6,6,6,6", + "lanes": "73,74,75,76,77,78,79,80", + "breakout_modes": { + "1x400G": ["Eth6/1"], + "2x100G": ["Eth6/1", "Eth6/5"], + "2x40G": ["Eth6/1", "Eth6/5"], + "4x100G": ["Eth6/1", "Eth6/3", "Eth6/5", "Eth6/7"], + "1x100G(2)": ["Eth6/1"], + "1x100G(4)": ["Eth6/1"], + "1x40G(4)": ["Eth6/1"], + "4x25G(4)": ["Eth6/1", "Eth6/2", "Eth6/3", "Eth6/4"], + "4x10G(4)": ["Eth6/1", "Eth6/2", "Eth6/3", "Eth6/4"] + } + }, + "Ethernet48": { + "index": "7,7,7,7,7,7,7,7", + "lanes": "81,82,83,84,85,86,87,88", + "breakout_modes": { + "1x400G": ["Eth7/1"], + "2x100G": ["Eth7/1", "Eth7/5"], + "2x40G": ["Eth7/1", "Eth7/5"], + "4x100G": ["Eth7/1", "Eth7/3", "Eth7/5", "Eth7/7"], + "1x100G(2)": ["Eth7/1"], + "1x100G(4)": ["Eth7/1"], + "1x40G(4)": ["Eth7/1"], + "4x25G(4)": ["Eth7/1", "Eth7/2", "Eth7/3", "Eth7/4"], + "4x10G(4)": ["Eth7/1", "Eth7/2", "Eth7/3", "Eth7/4"] + } + }, + "Ethernet56": { + "index": "8,8,8,8,8,8,8,8", + "lanes": "89,90,91,92,93,94,95,96", + "breakout_modes": { + "1x400G": ["Eth8/1"], + "2x100G": ["Eth8/1", "Eth8/5"], + "2x40G": ["Eth8/1", "Eth8/5"], + "4x100G": ["Eth8/1", "Eth8/3", "Eth8/5", "Eth8/7"], + "1x100G(2)": ["Eth8/1"], + "1x100G(4)": ["Eth8/1"], + "1x40G(4)": ["Eth8/1"], + "4x25G(4)": ["Eth8/1", "Eth8/2", "Eth8/3", "Eth8/4"], + "4x10G(4)": ["Eth8/1", "Eth8/2", "Eth8/3", "Eth8/4"] + } + }, + "Ethernet64": { + "index": "9,9,9,9,9,9,9,9", + "lanes": "1,2,3,4,5,6,7,8", + "breakout_modes": { + "1x400G": ["Eth9/1"], + "2x100G": ["Eth9/1", "Eth9/5"], + "2x40G": ["Eth9/1", "Eth9/5"], + "4x100G": ["Eth9/1", "Eth9/3", "Eth9/5", "Eth9/7"], + "1x100G(2)": ["Eth9/1"], + "1x100G(4)": ["Eth9/1"], + "1x40G(4)": ["Eth9/1"], + "4x25G(4)": ["Eth9/1", "Eth9/2", "Eth9/3", "Eth9/4"], + "4x10G(4)": ["Eth9/1", "Eth9/2", "Eth9/3", "Eth9/4"] + } + }, + "Ethernet72": { + "index": "10,10,10,10,10,10,10,10", + "lanes": "9,10,11,12,13,14,15,16", + "breakout_modes": { + "1x400G": ["Eth10/1"], + "2x100G": ["Eth10/1", "Eth10/5"], + "2x40G": ["Eth10/1", "Eth10/5"], + "4x100G": ["Eth10/1", "Eth10/3", "Eth10/5", "Eth10/7"], + "1x100G(2)": ["Eth10/1"], + "1x100G(4)": ["Eth10/1"], + "1x40G(4)": ["Eth10/1"], + "4x25G(4)": ["Eth10/1", "Eth10/2", "Eth10/3", "Eth10/4"], + "4x10G(4)": ["Eth10/1", "Eth10/2", "Eth10/3", "Eth10/4"] + } + }, + "Ethernet80": { + "index": "11,11,11,11,11,11,11,11", + "lanes": "17,18,19,20,21,22,23,24", + "breakout_modes": { + "1x400G": ["Eth11/1"], + "2x100G": ["Eth11/1", "Eth11/5"], + "2x40G": ["Eth11/1", "Eth11/5"], + "4x100G": ["Eth11/1", "Eth11/3", "Eth11/5", "Eth11/7"], + "1x100G(2)": ["Eth11/1"], + "1x100G(4)": ["Eth11/1"], + "1x40G(4)": ["Eth11/1"], + "4x25G(4)": ["Eth11/1", "Eth11/2", "Eth11/3", "Eth11/4"], + "4x10G(4)": ["Eth11/1", "Eth11/2", "Eth11/3", "Eth11/4"] + } + }, + "Ethernet88": { + "index": "12,12,12,12,12,12,12,12", + "lanes": "25,26,27,28,29,30,31,32", + "breakout_modes": { + "1x400G": ["Eth12/1"], + "2x100G": ["Eth12/1", "Eth12/5"], + "2x40G": ["Eth12/1", "Eth12/5"], + "4x100G": ["Eth12/1", "Eth12/3", "Eth12/5", "Eth12/7"], + "1x100G(2)": ["Eth12/1"], + "1x100G(4)": ["Eth12/1"], + "1x40G(4)": ["Eth12/1"], + "4x25G(4)": ["Eth12/1", "Eth12/2", "Eth12/3", "Eth12/4"], + "4x10G(4)": ["Eth12/1", "Eth12/2", "Eth12/3", "Eth12/4"] + } + }, + "Ethernet96": { + "index": "13,13,13,13,13,13,13,13", + "lanes": "97,98,99,100,101,102,103,104", + "breakout_modes": { + "1x400G": ["Eth13/1"], + "2x100G": ["Eth13/1", "Eth13/5"], + "2x40G": ["Eth13/1", "Eth13/5"], + "4x100G": ["Eth13/1", "Eth13/3", "Eth13/5", "Eth13/7"], + "1x100G(2)": ["Eth13/1"], + "1x100G(4)": ["Eth13/1"], + "1x40G(4)": ["Eth13/1"], + "4x25G(4)": ["Eth13/1", "Eth13/2", "Eth13/3", "Eth13/4"], + "4x10G(4)": ["Eth13/1", "Eth13/2", "Eth13/3", "Eth13/4"] + } + }, + "Ethernet104": { + "index": "14,14,14,14,14,14,14,14", + "lanes": "105,106,107,108,109,110,111,112", + "breakout_modes": { + "1x400G": ["Eth14/1"], + "2x100G": ["Eth14/1", "Eth14/5"], + "2x40G": ["Eth14/1", "Eth14/5"], + "4x100G": ["Eth14/1", "Eth14/3", "Eth14/5", "Eth14/7"], + "1x100G(2)": ["Eth14/1"], + "1x100G(4)": ["Eth14/1"], + "1x40G(4)": ["Eth14/1"], + "4x25G(4)": ["Eth14/1", "Eth14/2", "Eth14/3", "Eth14/4"], + "4x10G(4)": ["Eth14/1", "Eth14/2", "Eth14/3", "Eth14/4"] + } + }, + "Ethernet112": { + "index": "15,15,15,15,15,15,15,15", + "lanes": "113,114,115,116,117,118,119,120", + "breakout_modes": { + "1x400G": ["Eth15/1"], + "2x100G": ["Eth15/1", "Eth15/5"], + "2x40G": ["Eth15/1", "Eth15/5"], + "4x100G": ["Eth15/1", "Eth15/3", "Eth15/5", "Eth15/7"], + "1x100G(2)": ["Eth15/1"], + "1x100G(4)": ["Eth15/1"], + "1x40G(4)": ["Eth15/1"], + "4x25G(4)": ["Eth15/1", "Eth15/2", "Eth15/3", "Eth15/4"], + "4x10G(4)": ["Eth15/1", "Eth15/2", "Eth15/3", "Eth15/4"] + } + }, + "Ethernet120": { + "index": "16,16,16,16,16,16,16,16", + "lanes": "121,122,123,124,125,126,127,128", + "breakout_modes": { + "1x400G": ["Eth16/1"], + "2x100G": ["Eth16/1", "Eth16/5"], + "2x40G": ["Eth16/1", "Eth16/5"], + "4x100G": ["Eth16/1", "Eth16/3", "Eth16/5", "Eth16/7"], + "1x100G(2)": ["Eth16/1"], + "1x100G(4)": ["Eth16/1"], + "1x40G(4)": ["Eth16/1"], + "4x25G(4)": ["Eth16/1", "Eth16/2", "Eth16/3", "Eth16/4"], + "4x10G(4)": ["Eth16/1", "Eth16/2", "Eth16/3", "Eth16/4"] + } + }, + "Ethernet128": { + "index": "17,17,17,17,17,17,17,17", + "lanes": "129,130,131,132,133,134,135,136", + "breakout_modes": { + "1x400G": ["Eth17/1"], + "2x100G": ["Eth17/1", "Eth17/5"], + "2x40G": ["Eth17/1", "Eth17/5"], + "4x100G": ["Eth17/1", "Eth17/3", "Eth17/5", "Eth17/7"], + "1x100G(2)": ["Eth17/1"], + "1x100G(4)": ["Eth17/1"], + "1x40G(4)": ["Eth17/1"], + "4x25G(4)": ["Eth17/1", "Eth17/2", "Eth17/3", "Eth17/4"], + "4x10G(4)": ["Eth17/1", "Eth17/2", "Eth17/3", "Eth17/4"] + } + }, + "Ethernet136": { + "index": "18,18,18,18,18,18,18,18", + "lanes": "137,138,139,140,141,142,143,144", + "breakout_modes": { + "1x400G": ["Eth18/1"], + "2x100G": ["Eth18/1", "Eth18/5"], + "2x40G": ["Eth18/1", "Eth18/5"], + "4x100G": ["Eth18/1", "Eth18/3", "Eth18/5", "Eth18/7"], + "1x100G(2)": ["Eth18/1"], + "1x100G(4)": ["Eth18/1"], + "1x40G(4)": ["Eth18/1"], + "4x25G(4)": ["Eth18/1", "Eth18/2", "Eth18/3", "Eth18/4"], + "4x10G(4)": ["Eth18/1", "Eth18/2", "Eth18/3", "Eth18/4"] + } + }, + "Ethernet144": { + "index": "19,19,19,19,19,19,19,19", + "lanes": "145,146,147,148,149,150,151,152", + "breakout_modes": { + "1x400G": ["Eth19/1"], + "2x100G": ["Eth19/1", "Eth19/5"], + "2x40G": ["Eth19/1", "Eth19/5"], + "4x100G": ["Eth19/1", "Eth19/3", "Eth19/5", "Eth19/7"], + "1x100G(2)": ["Eth19/1"], + "1x100G(4)": ["Eth19/1"], + "1x40G(4)": ["Eth19/1"], + "4x25G(4)": ["Eth19/1", "Eth19/2", "Eth19/3", "Eth19/4"], + "4x10G(4)": ["Eth19/1", "Eth19/2", "Eth19/3", "Eth19/4"] + } + }, + "Ethernet152": { + "index": "20,20,20,20,20,20,20,20", + "lanes": "153,154,155,156,157,158,159,160", + "breakout_modes": { + "1x400G": ["Eth20/1"], + "2x100G": ["Eth20/1", "Eth20/5"], + "2x40G": ["Eth20/1", "Eth20/5"], + "4x100G": ["Eth20/1", "Eth20/3", "Eth20/5", "Eth20/7"], + "1x100G(2)": ["Eth20/1"], + "1x100G(4)": ["Eth20/1"], + "1x40G(4)": ["Eth20/1"], + "4x25G(4)": ["Eth20/1", "Eth20/2", "Eth20/3", "Eth20/4"], + "4x10G(4)": ["Eth20/1", "Eth20/2", "Eth20/3", "Eth20/4"] + } + }, + "Ethernet160": { + "index": "21,21,21,21,21,21,21,21", + "lanes": "225,226,227,228,229,230,231,232", + "breakout_modes": { + "1x400G": ["Eth21/1"], + "2x100G": ["Eth21/1", "Eth21/5"], + "2x40G": ["Eth21/1", "Eth21/5"], + "4x100G": ["Eth21/1", "Eth21/3", "Eth21/5", "Eth21/7"], + "1x100G(2)": ["Eth21/1"], + "1x100G(4)": ["Eth21/1"], + "1x40G(4)": ["Eth21/1"], + "4x25G(4)": ["Eth21/1", "Eth21/2", "Eth21/3", "Eth21/4"], + "4x10G(4)": ["Eth21/1", "Eth21/2", "Eth21/3", "Eth21/4"] + } + }, + "Ethernet168": { + "index": "22,22,22,22,22,22,22,22", + "lanes": "233,234,235,236,237,238,239,240", + "breakout_modes": { + "1x400G": ["Eth22/1"], + "2x100G": ["Eth22/1", "Eth22/5"], + "2x40G": ["Eth22/1", "Eth22/5"], + "4x100G": ["Eth22/1", "Eth22/3", "Eth22/5", "Eth22/7"], + "1x100G(2)": ["Eth22/1"], + "1x100G(4)": ["Eth22/1"], + "1x40G(4)": ["Eth22/1"], + "4x25G(4)": ["Eth22/1", "Eth22/2", "Eth22/3", "Eth22/4"], + "4x10G(4)": ["Eth22/1", "Eth22/2", "Eth22/3", "Eth22/4"] + } + }, + "Ethernet176": { + "index": "23,23,23,23,23,23,23,23", + "lanes": "241,242,243,244,245,246,247,248", + "breakout_modes": { + "1x400G": ["Eth23/1"], + "2x100G": ["Eth23/1", "Eth23/5"], + "2x40G": ["Eth23/1", "Eth23/5"], + "4x100G": ["Eth23/1", "Eth23/3", "Eth23/5", "Eth23/7"], + "1x100G(2)": ["Eth23/1"], + "1x100G(4)": ["Eth23/1"], + "1x40G(4)": ["Eth23/1"], + "4x25G(4)": ["Eth23/1", "Eth23/2", "Eth23/3", "Eth23/4"], + "4x10G(4)": ["Eth23/1", "Eth23/2", "Eth23/3", "Eth23/4"] + } + }, + "Ethernet184": { + "index": "24,24,24,24,24,24,24,24", + "lanes": "249,250,251,252,253,254,255,256", + "breakout_modes": { + "1x400G": ["Eth24/1"], + "2x100G": ["Eth24/1", "Eth24/5"], + "2x40G": ["Eth24/1", "Eth24/5"], + "4x100G": ["Eth24/1", "Eth24/3", "Eth24/5", "Eth24/7"], + "1x100G(2)": ["Eth24/1"], + "1x100G(4)": ["Eth24/1"], + "1x40G(4)": ["Eth24/1"], + "4x25G(4)": ["Eth24/1", "Eth24/2", "Eth24/3", "Eth24/4"], + "4x10G(4)": ["Eth24/1", "Eth24/2", "Eth24/3", "Eth24/4"] + } + }, + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "161,162,163,164,165,166,167,168", + "breakout_modes": { + "1x400G": ["Eth25/1"], + "2x100G": ["Eth25/1", "Eth25/5"], + "2x40G": ["Eth25/1", "Eth25/5"], + "4x100G": ["Eth25/1", "Eth25/3", "Eth25/5", "Eth25/7"], + "1x100G(2)": ["Eth25/1"], + "1x100G(4)": ["Eth25/1"], + "1x40G(4)": ["Eth25/1"], + "4x25G(4)": ["Eth25/1", "Eth25/2", "Eth25/3", "Eth25/4"], + "4x10G(4)": ["Eth25/1", "Eth25/2", "Eth25/3", "Eth25/4"] + } + }, + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "169,170,171,172,173,174,175,176", + "breakout_modes": { + "1x400G": ["Eth26/1"], + "2x100G": ["Eth26/1", "Eth26/5"], + "2x40G": ["Eth26/1", "Eth26/5"], + "4x100G": ["Eth26/1", "Eth26/3", "Eth26/5", "Eth26/7"], + "1x100G(2)": ["Eth26/1"], + "1x100G(4)": ["Eth26/1"], + "1x40G(4)": ["Eth26/1"], + "4x25G(4)": ["Eth26/1", "Eth26/2", "Eth26/3", "Eth26/4"], + "4x10G(4)": ["Eth26/1", "Eth26/2", "Eth26/3", "Eth26/4"] + } + }, + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "177,178,179,180,181,182,183,184", + "breakout_modes": { + "1x400G": ["Eth27/1"], + "2x100G": ["Eth27/1", "Eth27/5"], + "2x40G": ["Eth27/1", "Eth27/5"], + "4x100G": ["Eth27/1", "Eth27/3", "Eth27/5", "Eth27/7"], + "1x100G(2)": ["Eth27/1"], + "1x100G(4)": ["Eth27/1"], + "1x40G(4)": ["Eth27/1"], + "4x25G(4)": ["Eth27/1", "Eth27/2", "Eth27/3", "Eth27/4"], + "4x10G(4)": ["Eth27/1", "Eth27/2", "Eth27/3", "Eth27/4"] + } + }, + "Ethernet216": { + "index": "28,28,28,28,28,28,28,28", + "lanes": "185,186,187,188,189,190,191,192", + "breakout_modes": { + "1x400G": ["Eth28/1"], + "2x100G": ["Eth28/1", "Eth28/5"], + "2x40G": ["Eth28/1", "Eth28/5"], + "4x100G": ["Eth28/1", "Eth28/3", "Eth28/5", "Eth28/7"], + "1x100G(2)": ["Eth28/1"], + "1x100G(4)": ["Eth28/1"], + "1x40G(4)": ["Eth28/1"], + "4x25G(4)": ["Eth28/1", "Eth28/2", "Eth28/3", "Eth28/4"], + "4x10G(4)": ["Eth28/1", "Eth28/2", "Eth28/3", "Eth28/4"] + } + }, + "Ethernet224": { + "index": "29,29,29,29,29,29,29,29", + "lanes": "193,194,195,196,197,198,199,200", + "breakout_modes": { + "1x400G": ["Eth29/1"], + "2x100G": ["Eth29/1", "Eth29/5"], + "2x40G": ["Eth29/1", "Eth29/5"], + "4x100G": ["Eth29/1", "Eth29/3", "Eth29/5", "Eth29/7"], + "1x100G(2)": ["Eth29/1"], + "1x100G(4)": ["Eth29/1"], + "1x40G(4)": ["Eth29/1"], + "4x25G(4)": ["Eth29/1", "Eth29/2", "Eth29/3", "Eth29/4"], + "4x10G(4)": ["Eth29/1", "Eth29/2", "Eth29/3", "Eth29/4"] + } + }, + "Ethernet232": { + "index": "30,30,30,30,30,30,30,30", + "lanes": "201,202,203,204,205,206,207,208", + "breakout_modes": { + "1x400G": ["Eth30/1"], + "2x100G": ["Eth30/1", "Eth30/5"], + "2x40G": ["Eth30/1", "Eth30/5"], + "4x100G": ["Eth30/1", "Eth30/3", "Eth30/5", "Eth30/7"], + "1x100G(2)": ["Eth30/1"], + "1x100G(4)": ["Eth30/1"], + "1x40G(4)": ["Eth30/1"], + "4x25G(4)": ["Eth30/1", "Eth30/2", "Eth30/3", "Eth30/4"], + "4x10G(4)": ["Eth30/1", "Eth30/2", "Eth30/3", "Eth30/4"] + } + }, + "Ethernet240": { + "index": "31,31,31,31,31,31,31,31", + "lanes": "209,210,211,212,213,214,215,216", + "breakout_modes": { + "1x400G": ["Eth31/1"], + "2x100G": ["Eth31/1", "Eth31/5"], + "2x40G": ["Eth31/1", "Eth31/5"], + "4x100G": ["Eth31/1", "Eth31/3", "Eth31/5", "Eth31/7"], + "1x100G(2)": ["Eth31/1"], + "1x100G(4)": ["Eth31/1"], + "1x40G(4)": ["Eth31/1"], + "4x25G(4)": ["Eth31/1", "Eth31/2", "Eth31/3", "Eth31/4"], + "4x10G(4)": ["Eth31/1", "Eth31/2", "Eth31/3", "Eth31/4"] + } + }, + "Ethernet248": { + "index": "32,32,32,32,32,32,32,32", + "lanes": "217,218,219,220,221,222,223,224", + "breakout_modes": { + "1x400G": ["Eth32/1"], + "2x100G": ["Eth32/1", "Eth32/5"], + "2x40G": ["Eth32/1", "Eth32/5"], + "4x100G": ["Eth32/1", "Eth32/3", "Eth32/5", "Eth32/7"], + "1x100G(2)": ["Eth32/1"], + "1x100G(4)": ["Eth32/1"], + "1x40G(4)": ["Eth32/1"], + "4x25G(4)": ["Eth32/1", "Eth32/2", "Eth32/3", "Eth32/4"], + "4x10G(4)": ["Eth32/1", "Eth32/2", "Eth32/3", "Eth32/4"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone-r0/platform_components.json b/device/celestica/x86_64-cel_silverstone-r0/platform_components.json new file mode 100644 index 000000000000..9713fd620c27 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/platform_components.json @@ -0,0 +1,18 @@ +{ + "chassis": { + "Silverstone": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "CPLD FAN": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone-r0/platform_reboot b/device/celestica/x86_64-cel_silverstone-r0/platform_reboot new file mode 100755 index 000000000000..0c84c4d7f536 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/platform_reboot @@ -0,0 +1,6 @@ +#!/bin/bash + +# Set all LEDs to BMC's control +ipmitool raw 0x3a 0x09 0x02 0x01 &> /dev/null + +/usr/local/bin/silverstone_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py index 46684aae0f22..ea2f8cfca969 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py +++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py @@ -1,6 +1,7 @@ import subprocess import sys import re +import os try: from sonic_psu.psu_base import PsuBase @@ -11,8 +12,19 @@ class PsuUtil(PsuBase): """Platform-specific PSUutil class""" + __IPMI_BASE_COMMAND = ["ipmitool", "raw", "0x04", "0x2d"] + __IPMI_CONTAINER_PREFIX = ["docker", "exec", "-ti", "pmon"] + + def __container_prefix(self, cmdlist): + # If running inside container, nothing to prefix. Else, prefix container + # invocation. + if os.environ.get("CONTAINER_NAME") != None: + return cmdlist + + return self.__IPMI_CONTAINER_PREFIX + cmdlist + def __init__(self): - self.ipmi_raw = ["docker", "exec", "-ti", "pmon", "ipmitool", "raw", "0x4", "0x2d", ""] + self.ipmi_raw = self.__container_prefix(self.__IPMI_BASE_COMMAND) self.psu1_id = "0x2f" self.psu2_id = "0x39" PsuBase.__init__(self) @@ -51,8 +63,7 @@ def get_psu_status(self, index): return False psu_id = self.psu1_id if index == 1 else self.psu2_id - self.ipmi_raw[8] = psu_id - res_string = self.run_command(self.ipmi_raw) + res_string = self.run_command(self.ipmi_raw + [psu_id]) status_byte = self.find_value(res_string) if status_byte is None: @@ -76,8 +87,7 @@ def get_psu_presence(self, index): return False psu_id = self.psu1_id if index == 1 else self.psu2_id - self.ipmi_raw[8] = psu_id - res_string = self.run_command(self.ipmi_raw) + res_string = self.run_command(self.ipmi_raw + [psu_id]) status_byte = self.find_value(res_string) if status_byte is None: diff --git a/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json index 94592fa8cebc..f5b2736b13e0 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json +++ b/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json @@ -1,3 +1,5 @@ { - "skip_ledd": true + "skip_ledd": true, + "skip_fancontrol": true, + "skip_xcvrd_cmis_mgr": true } diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py deleted file mode 100644 index d82f3749319c..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -__all__ = ["platform", "chassis"] -from sonic_platform import * diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py deleted file mode 100644 index b6f77cbd3dc9..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py +++ /dev/null @@ -1,131 +0,0 @@ -############################################################################# -# Celestica -# -# Module contains an implementation of SONiC Platform Base API and -# provides the Chassis information which are available in the platform -# -############################################################################# - -import sys -import re -import os -import subprocess -import json - -try: - from sonic_platform_base.chassis_base import ChassisBase - from sonic_platform.component import Component - from sonic_platform.eeprom import Tlv - from sonic_platform.fan import Fan - from sonic_platform.sfp import Sfp - from sonic_platform.psu import Psu - from sonic_platform.thermal import Thermal - from .helper import APIHelper -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -NUM_FAN_TRAY = 7 -NUM_FAN = 2 -NUM_PSU = 2 -NUM_THERMAL = 10 -NUM_SFP = 32 -NUM_COMPONENT = 5 - -IPMI_OEM_NETFN = "0x3A" -IPMI_GET_REBOOT_CAUSE = "0x03 0x00 0x01 0x06" - - -class Chassis(ChassisBase): - """Platform-specific Chassis class""" - - def __init__(self): - self.config_data = {} - ChassisBase.__init__(self) - self._eeprom = Tlv() - self._api_helper = APIHelper() - - for fant_index in range(0, NUM_FAN_TRAY): - for fan_index in range(0, NUM_FAN): - fan = Fan(fant_index, fan_index) - self._fan_list.append(fan) - - for index in range(0, NUM_SFP): - sfp = Sfp(index) - self._sfp_list.append(sfp) - - for index in range(0, NUM_PSU): - psu = Psu(index) - self._psu_list.append(psu) - for index in range(0, NUM_COMPONENT): - component = Component(index) - self._component_list.append(component) - for index in range(0, NUM_THERMAL): - thermal = Thermal(index) - self._thermal_list.append(thermal) - - 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.get_mac() - - def get_serial(self): - """ - Retrieves the hardware serial number for the chassis - Returns: - A string containing the hardware serial number for this chassis. - """ - return self._eeprom.get_serial() - - 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.get_eeprom() - - 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. - """ - - status, raw_cause = self._api_helper.ipmi_raw( - IPMI_OEM_NETFN, IPMI_GET_REBOOT_CAUSE) - hx_cause = raw_cause.split()[0] if status and len( - raw_cause.split()) > 0 else 00 - reboot_cause = { - "00": self.REBOOT_CAUSE_HARDWARE_OTHER, - "11": self.REBOOT_CAUSE_POWER_LOSS, - "22": self.REBOOT_CAUSE_NON_HARDWARE, - "33": self.REBOOT_CAUSE_HARDWARE_OTHER, - "44": self.REBOOT_CAUSE_NON_HARDWARE, - "55": self.REBOOT_CAUSE_NON_HARDWARE, - "66": self.REBOOT_CAUSE_WATCHDOG, - "77": self.REBOOT_CAUSE_NON_HARDWARE - }.get(hx_cause, self.REBOOT_CAUSE_HARDWARE_OTHER) - - description = { - "00": "Unknown reason", - "11": "The last reset is Power on reset", - "22": "The last reset is soft-set CPU warm reset", - "33": "The last reset is soft-set CPU cold reset", - "44": "The last reset is CPU warm reset", - "55": "The last reset is CPU cold reset", - "66": "The last reset is watchdog reset", - "77": "The last reset is power cycle reset" - }.get(hx_cause, "Unknown reason") - - return (reboot_cause, description) diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py deleted file mode 100644 index ba7742c66b60..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py +++ /dev/null @@ -1,118 +0,0 @@ -############################################################################# -# Celestica -# -# Component contains an implementation of SONiC Platform Base API and -# provides the components firmware management function -# -############################################################################# - -import os.path - -try: - from sonic_platform_base.component_base import ComponentBase - from .helper import APIHelper -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -COMPONENT_LIST = [ - ("BIOS", "Basic Input/Output System"), - ("BMC", "Baseboard Management Controller"), - ("SWITCH_CPLD", "Switch board CPLD"), - ("BASE_CPLD", "Base board CPLD"), - ("FPGA", "Field-programmable gate array") -] -SW_CPLD_VER_PATH = "/sys/module/switch_cpld/version" -BASE_CPLD_VER_PATH = "/sys/module/baseboard_lpc/version" -BIOS_VER_PATH = "/sys/class/dmi/id/bios_version" -BMC_VER_CMD1 = ["ipmitool", "mc", "info"] -BMC_VER_CMD2 = ["grep", "Firmware Revision"] -CFUFLASH_FW_UPGRADE_CMD = ["CFUFLASH", "-cd", "-d", "", "-mse", "3", ""] -MEM_PCI_RESOURCE = "/sys/bus/pci/devices/0000:09:00.0/resource0" -FPGA_VER_MEM_OFFSET = 0 -UPGRADE_OPT = { - 'BMC': '1', - 'BIOS': '2', - 'SWITCH_CPLD': '4', - 'BASE_CPLD': '4' -} - - -class Component(ComponentBase): - """Platform-specific Component class""" - - DEVICE_TYPE = "component" - - def __init__(self, component_index): - ComponentBase.__init__(self) - self.index = component_index - self.name = self.get_name() - self._api_helper = APIHelper() - - def __get_bmc_ver(self): - bmc_ver = "Unknown" - status, raw_bmc_data = self._api_helper.run_command(BMC_VER_CMD1, BMC_VER_CMD2) - if status: - bmc_ver_data = raw_bmc_data.split(":") - bmc_ver = bmc_ver_data[-1].strip() if len( - bmc_ver_data) > 1 else bmc_ver - return bmc_ver - - def __get_fpga_ver(self): - fpga_ver = "Unknown" - status, reg_val = self._api_helper.pci_get_value( - MEM_PCI_RESOURCE, FPGA_VER_MEM_OFFSET) - if status: - major = reg_val[0] >> 16 - minor = int(bin(reg_val[0])[16:32], 2) - fpga_ver = '{}.{}'.format(major, minor) - return fpga_ver - - def get_name(self): - """ - Retrieves the name of the component - Returns: - A string containing the name of the component - """ - return COMPONENT_LIST[self.index][0] - - def get_description(self): - """ - Retrieves the description of the component - Returns: - A string containing the description of the component - """ - return COMPONENT_LIST[self.index][1] - - def get_firmware_version(self): - """ - Retrieves the firmware version of module - Returns: - string: The firmware versions of the module - """ - fw_version = { - "BIOS": self._api_helper.read_txt_file(BIOS_VER_PATH), - "BMC": self.__get_bmc_ver(), - "FPGA": self.__get_fpga_ver(), - "SWITCH_CPLD": self._api_helper.read_txt_file(SW_CPLD_VER_PATH), - "BASE_CPLD": self._api_helper.read_txt_file(BASE_CPLD_VER_PATH), - }.get(self.name, "Unknown") - - return fw_version - - def install_firmware(self, image_path): - """ - Install firmware to module - Args: - image_path: A string, path to firmware image - Returns: - A boolean, True if install successfully, False if not - """ - CFUFLASH_FW_UPGRADE_CMD[3] = UPGRADE_OPT.get(self.name) - CFUFLASH_FW_UPGRADE_CMD[6] = image_path - - if not os.path.isfile(image_path): - return False - - # print(install_command) - status = self._api_helper.run_interactive_command(CFUFLASH_FW_UPGRADE_CMD) - return status diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py deleted file mode 100644 index cf3f1a98de20..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py +++ /dev/null @@ -1,117 +0,0 @@ -############################################################################# -# Celestica Silverstone -# -# Platform and model specific eeprom subclass, inherits from the base class, -# and provides the followings: -# - the eeprom format definition -# - specific encoder/decoder if there is special need -############################################################################# - -try: - import glob - import os - import sys - import re - from array import array - - if sys.version_info.major == 3: - from io import StringIO - else: - from cStringIO import StringIO - - from sonic_platform_base.sonic_eeprom import eeprom_dts - from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' -CACHE_FILE = 'syseeprom_cache' -TLV_EEPROM_I2C_BUS = 0 -TLV_EEPROM_I2C_ADDR = 56 - - -class Tlv(eeprom_tlvinfo.TlvInfoDecoder): - - EEPROM_DECODE_HEADLINES = 6 - - def __init__(self): - self._eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-00{1}/eeprom".format( - TLV_EEPROM_I2C_BUS, TLV_EEPROM_I2C_ADDR) - super(Tlv, self).__init__(self._eeprom_path, 0, '', True) - self._eeprom = self._load_eeprom() - - def __parse_output(self, decode_output): - decode_output.replace('\0', '') - lines = decode_output.split('\n') - lines = lines[self.EEPROM_DECODE_HEADLINES:] - _eeprom_info_dict = dict() - - for line in lines: - try: - match = re.search( - '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) - if match is not None: - idx = match.group(1) - value = match.group(3).rstrip('\0') - - _eeprom_info_dict[idx] = value - except: - pass - return _eeprom_info_dict - - def _load_eeprom(self): - original_stdout = sys.stdout - sys.stdout = StringIO() - try: - self.read_eeprom_db() - except: - decode_output = sys.stdout.getvalue() - sys.stdout = original_stdout - return self.__parse_output(decode_output) - - status = self.check_status() - if 'ok' not in status: - return False - - if not os.path.exists(CACHE_ROOT): - try: - os.makedirs(CACHE_ROOT) - except: - pass - - # - # only the eeprom classes that inherit from eeprom_base - # support caching. Others will work normally - # - try: - self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) - except: - pass - - e = self.read_eeprom() - if e is None: - return 0 - - try: - self.update_cache(e) - except: - pass - - self.decode_eeprom(e) - decode_output = sys.stdout.getvalue() - sys.stdout = original_stdout - - (is_valid, valid_crc) = self.is_checksum_valid(e) - if not is_valid: - return False - - return self.__parse_output(decode_output) - - def get_eeprom(self): - return self._eeprom - - def get_serial(self): - return self._eeprom.get('0x23', "Undefined.") - - def get_mac(self): - return self._eeprom.get('0x24', "Undefined.") diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py deleted file mode 100644 index d53de841eeee..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py +++ /dev/null @@ -1,111 +0,0 @@ -import os -import struct -import subprocess -from mmap import * -from sonic_py_common.general import check_output_pipe - -HOST_CHK_CMD = ["docker"] -EMPTY_STRING = "" - - -class APIHelper(): - - def __init__(self): - pass - - def is_host(self): - try: - subprocess.call(HOST_CHK_CMD, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except FileNotFoundError: - return False - return True - - def pci_get_value(self, resource, offset): - status = True - result = "" - try: - fd = os.open(resource, os.O_RDWR) - mm = mmap(fd, 0) - mm.seek(int(offset)) - read_data_stream = mm.read(4) - result = struct.unpack('I', read_data_stream) - except: - status = False - return status, result - - def run_command(self, cmd1_args, cmd2_args): - status = True - result = "" - try: - result = check_output_pipe(cmd1_args, cmd2_args) - except subprocess.CalledProcessError: - status = False - return status, result - - def run_interactive_command(self, cmd): - try: - subprocess.call(cmd) - except: - return False - return True - - def read_txt_file(self, file_path): - try: - with open(file_path, 'r') as fd: - data = fd.read() - return data.strip() - except IOError: - pass - return None - - def ipmi_raw(self, netfn, cmd): - status = True - result = "" - try: - cmd = ["ipmitool", "raw", str(netfn), str(cmd)] - p = subprocess.Popen( - cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - raw_data, err = p.communicate() - if err == '': - result = raw_data.strip() - else: - status = False - except: - status = False - return status, result - - def ipmi_fru_id(self, id, key=None): - status = True - result = "" - cmd1_args = ["ipmitool", "fru", "print", str(id)] - if not key: - try: - p = subprocess.Popen( - cmd1_args, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - raw_data, err = p.communicate() - if err == '': - result = raw_data.strip() - else: - status = False - except: - status = False - else: - cmd2_args = ["grep", str(key)] - status, result = self.run_command(cmd1_args, cmd2_args) - return status, result - - def ipmi_set_ss_thres(self, id, threshold_key, value): - status = True - result = "" - try: - cmd = ["ipmitool", "sensor", "thresh", str(id), str(threshold_key), str(value)] - p = subprocess.Popen( - cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - raw_data, err = p.communicate() - if err == '': - result = raw_data.strip() - else: - status = False - except: - status = False - return status, result diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py deleted file mode 100644 index a6c805d3ca4f..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py +++ /dev/null @@ -1,236 +0,0 @@ -############################################################################# -# Celestica -# -# Module contains an implementation of SONiC Platform Base API and -# provides the PSUs status which are available in the platform -# -############################################################################# - -import os -import re -import math -import sonic_platform - -try: - from sonic_platform_base.psu_base import PsuBase - from .helper import APIHelper - from sonic_platform.fan import Fan -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -PSU_NAME_LIST = ["PSU-1", "PSU-2"] -PSU_NUM_FAN = [1, 1] - -IPMI_SENSOR_NETFN = "0x04" -IPMI_OEM_NETFN = "0x3A" -IPMI_SS_READ_CMD = "0x2D {}" -IPMI_SET_PSU_LED_CMD = "0x07 0x02 {}" -IPMI_GET_PSU_LED_CMD = "0x08 0x02" -IPMI_FRU_MODEL_KEY = "Board Part Number" -IPMI_FRU_SERIAL_KEY = "Board Serial" - -PSU_LED_OFF_CMD = "0x00" -PSU_LED_GREEN_CMD = "0x01" -PSU_LED_AMBER_CMD = "0x02" - -PSU1_FRU_ID = 3 - -SS_READ_OFFSET = 0 - -PSU_VOUT_SS_ID = ["0x36", "0x40"] -PSU_COUT_SS_ID = ["0x37", "0x41"] -PSU_POUT_SS_ID = ["0x38", "0x42"] -PSU_STATUS_REG = ["0x39", "0x2f"] - - -class Psu(PsuBase): - """Platform-specific Psu class""" - - def __init__(self, psu_index): - PsuBase.__init__(self) - self.index = psu_index - for fan_index in range(0, PSU_NUM_FAN[self.index]): - fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) - self._fan_list.append(fan) - self._api_helper = APIHelper() - - def find_value(self, in_string): - result = re.search("^.+ ([0-9a-f]{2}) .+$", in_string) - return result.group(1) if result else result - - def get_voltage(self): - """ - Retrieves current PSU voltage output - Returns: - A float number, the output voltage in volts, - e.g. 12.1 - """ - psu_voltage = 0.0 - psu_vout_key = PSU_VOUT_SS_ID[self.index] - status, raw_ss_read = self._api_helper.ipmi_raw( - IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_vout_key)) - ss_read = raw_ss_read.split()[SS_READ_OFFSET] - # Formula: Rx1x10^-1 - psu_voltage = int(ss_read, 16) * math.pow(10, -1) - - return psu_voltage - - def get_current(self): - """ - Retrieves present electric current supplied by PSU - Returns: - A float number, the electric current in amperes, e.g 15.4 - """ - psu_current = 0.0 - psu_cout_key = PSU_COUT_SS_ID[self.index] - status, raw_ss_read = self._api_helper.ipmi_raw( - IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_cout_key)) - ss_read = raw_ss_read.split()[SS_READ_OFFSET] - # Formula: Rx5x10^-1 - psu_current = int(ss_read, 16) * 5 * math.pow(10, -1) - - return psu_current - - def get_power(self): - """ - Retrieves current energy supplied by PSU - Returns: - A float number, the power in watts, e.g. 302.6 - """ - psu_power = 0.0 - psu_pout_key = PSU_POUT_SS_ID[self.index] - status, raw_ss_read = self._api_helper.ipmi_raw( - IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pout_key)) - ss_read = raw_ss_read.split()[SS_READ_OFFSET] - # Formula: Rx6x10^0 - psu_power = int(ss_read, 16) * 6 - return psu_power - - 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. - """ - return self.get_status() - - 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 - Note: Only support green and off - Returns: - bool: True if status LED state is set successfully, False if not - Note - Set manual - ipmitool raw 0x3a 0x09 0x2 0x0 - """ - led_cmd = { - self.STATUS_LED_COLOR_GREEN: PSU_LED_GREEN_CMD, - self.STATUS_LED_COLOR_AMBER: PSU_LED_AMBER_CMD, - self.STATUS_LED_COLOR_OFF: PSU_LED_OFF_CMD - }.get(color) - - status, set_led = self._api_helper.ipmi_raw( - IPMI_OEM_NETFN, IPMI_SET_PSU_LED_CMD.format(led_cmd)) - set_status_led = False if not status else True - - return set_status_led - - def get_status_led(self): - """ - Gets the state of the PSU status LED - Returns: - A string, one of the predefined STATUS_LED_COLOR_* strings above - """ - status, hx_color = self._api_helper.ipmi_raw( - IPMI_OEM_NETFN, IPMI_GET_PSU_LED_CMD) - - status_led = { - "00": self.STATUS_LED_COLOR_OFF, - "01": self.STATUS_LED_COLOR_GREEN, - "02": self.STATUS_LED_COLOR_AMBER, - }.get(hx_color, self.STATUS_LED_COLOR_OFF) - - return status_led - - def get_name(self): - """ - Retrieves the name of the device - Returns: - string: The name of the device - """ - return PSU_NAME_LIST[self.index] - - def get_presence(self): - """ - Retrieves the presence of the PSU - Returns: - bool: True if PSU is present, False if not - """ - psu_presence = False - psu_pstatus_key = PSU_STATUS_REG[self.index] - status, raw_status_read = self._api_helper.ipmi_raw( - IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pstatus_key)) - status_byte = self.find_value(raw_status_read) - - if status: - presence_int = (int(status_byte, 16) >> 0) & 1 - psu_presence = True if presence_int else False - - return psu_presence - - def get_model(self): - """ - Retrieves the model number (or part number) of the device - Returns: - string: Model/part number of device - """ - model = "Unknown" - ipmi_fru_idx = self.index + PSU1_FRU_ID - status, raw_model = self._api_helper.ipmi_fru_id( - ipmi_fru_idx, IPMI_FRU_MODEL_KEY) - - fru_pn_list = raw_model.split() - if len(fru_pn_list) > 4: - model = fru_pn_list[4] - - return model - - def get_serial(self): - """ - Retrieves the serial number of the device - Returns: - string: Serial number of device - """ - serial = "Unknown" - ipmi_fru_idx = self.index + PSU1_FRU_ID - status, raw_model = self._api_helper.ipmi_fru_id( - ipmi_fru_idx, IPMI_FRU_SERIAL_KEY) - - fru_sr_list = raw_model.split() - if len(fru_sr_list) > 3: - serial = fru_sr_list[3] - - return serial - - def get_status(self): - """ - Retrieves the operational status of the device - Returns: - A boolean value, True if device is operating properly, False if not - """ - psu_status = False - psu_pstatus_key = PSU_STATUS_REG[self.index] - status, raw_status_read = self._api_helper.ipmi_raw( - IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pstatus_key)) - status_byte = self.find_value(raw_status_read) - - if status: - failure_detected = (int(status_byte, 16) >> 1) & 1 - input_lost = (int(status_byte, 16) >> 3) & 1 - psu_status = False if (input_lost or failure_detected) else True - - return psu_status diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py deleted file mode 100644 index 4ad97b42fff3..000000000000 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py +++ /dev/null @@ -1,1467 +0,0 @@ -############################################################################# -# Celestica -# -# Sfp contains an implementation of SONiC Platform Base API and -# provides the sfp device status which are available in the platform -# -############################################################################# - -import time -import subprocess -from ctypes import create_string_buffer - -try: - from sonic_platform_base.sfp_base import SfpBase - from sonic_platform_base.sonic_eeprom import eeprom_dts - 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 - from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId - from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -INFO_OFFSET = 128 -DOM_OFFSET = 0 - -# 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_POWEROVERRIDE_OFFSET = 93 -QSFP_POWEROVERRIDE_WIDTH = 1 -QSFP_POWEROVERRIDE_BIT = 0 -QSFP_POWERSET_BIT = 1 -QSFP_OPTION_VALUE_OFFSET = 192 -QSFP_OPTION_VALUE_WIDTH = 4 -QSFP_MODULE_UPPER_PAGE3_START = 384 -QSFP_MODULE_THRESHOLD_OFFSET = 128 -QSFP_MODULE_THRESHOLD_WIDTH = 24 -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') - -SFP_TYPE = "SFP" -QSFP_TYPE = "QSFP" -OSFP_TYPE = "OSFP" - -PORT_START = 1 -PORT_END = 34 -OSFP_PORT_START = 1 -OSFP_PORT_END = 32 -SFP_PORT_START = 33 -SFP_PORT_END = 34 - -PORT_INFO_PATH = '/sys/devices/platform/cls-xcvr' - - -class Sfp(SfpBase): - """Platform-specific Sfp class""" - - # Path to QSFP sysfs - PLATFORM_ROOT_PATH = "/usr/share/sonic/device" - PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" - HOST_CHK_CMD = ["docker"] - - PLATFORM = "x86_64-cel_silverstone-r0" - HWSKU = "Silverstone" - - def __init__(self, sfp_index): - SfpBase.__init__(self) - # Init index - self.index = sfp_index - self.port_num = self.index + 1 - self.dom_supported = False - self.sfp_type, self.port_name = self.__get_sfp_info() - - # Init eeprom path - eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' - self.port_to_eeprom_mapping = {} - self.port_to_i2c_mapping = { - 1: 10, - 2: 11, - 3: 12, - 4: 13, - 5: 14, - 6: 15, - 7: 16, - 8: 17, - 9: 18, - 10: 19, - 11: 20, - 12: 21, - 13: 22, - 14: 23, - 15: 24, - 16: 25, - 17: 26, - 18: 27, - 19: 28, - 20: 29, - 21: 30, - 22: 31, - 23: 32, - 24: 33, - 25: 34, - 26: 35, - 27: 36, - 28: 37, - 29: 38, - 30: 39, - 31: 40, - 32: 41, - 33: 1, - 34: 2 - } - - for x in range(PORT_START, PORT_END + 1): - port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) - self.port_to_eeprom_mapping[x] = port_eeprom_path - - self.info_dict_keys = ['type', 'vendor_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', 'power_lpmode', 'tx_disable', 'tx_disable_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() - - def __get_sfp_info(self): - port_num = self.index + PORT_START - sfp_type = OSFP_PORT_START - port_name = "Unknown" - - if port_num >= OSFP_PORT_START and port_num <= OSFP_PORT_END: - sfp_type = OSFP_TYPE - port_name = "QSFP" + str(port_num - OSFP_PORT_START + 1) - elif port_num >= SFP_PORT_START and port_num <= SFP_PORT_END: - sfp_type = SFP_TYPE - port_name = "SFP" + str(port_num - SFP_PORT_START + 1) - return sfp_type, port_name - - 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 __is_host(self): - try: - subprocess.call(self.HOST_CHK_CMD, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except FileNotFoundError: - return False - return True - - def __get_path_to_port_config_file(self): - platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) - hwsku_path = "/".join([platform_path, self.HWSKU] - ) if self.__is_host() else self.PMON_HWSKU_PATH - return "/".join([hwsku_path, "port_config.ini"]) - - 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.port_to_eeprom_mapping[self.port_num] - 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(ord(raw[n]))[2:].zfill(2) - except: - pass - finally: - if sysfsfile_eeprom: - sysfsfile_eeprom.close() - - return eeprom_raw - - 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.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_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 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 - vendor_rev |1*255VCHAR |vendor revision 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 - ======================================================================== - """ - 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 - if self.sfp_type == OSFP_TYPE: - offset = 0 - vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP - - sfpi_obj = inf8628InterfaceId() - if sfpi_obj is None: - return None - - sfp_type_raw = self.__read_eeprom_specific_bytes( - (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) - if sfp_type_raw is not None: - sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) - else: - return None - - sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( - (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) - if sfp_vendor_name_raw is not None: - sfp_vendor_name_data = sfpi_obj.parse_vendor_name( - sfp_vendor_name_raw, 0) - else: - return None - - sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( - (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) - if sfp_vendor_pn_raw is not None: - sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( - sfp_vendor_pn_raw, 0) - else: - return None - - sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( - (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) - if sfp_vendor_rev_raw is not None: - sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( - sfp_vendor_rev_raw, 0) - else: - return None - - sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( - (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) - if sfp_vendor_sn_raw is not None: - sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( - sfp_vendor_sn_raw, 0) - else: - return None - - transceiver_info_dict['type'] = sfp_type_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['vendor_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'] = 'N/A' - transceiver_info_dict['vendor_date'] = 'N/A' - transceiver_info_dict['connector'] = 'N/A' - transceiver_info_dict['encoding'] = 'N/A' - transceiver_info_dict['ext_identifier'] = 'N/A' - transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' - transceiver_info_dict['cable_type'] = 'N/A' - transceiver_info_dict['cable_length'] = 'N/A' - transceiver_info_dict['specification_compliance'] = 'N/A' - transceiver_info_dict['nominal_bit_rate'] = 'N/A' - - else: - if self.sfp_type == QSFP_TYPE: - offset = 128 - vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP - cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP - interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP - sfp_type = '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 - cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP - interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP - sfp_type = '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['vendor_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. - ======================================================================== - """ - transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') - - if self.sfp_type == OSFP_TYPE: - pass - - elif self.sfp_type == QSFP_TYPE: - 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 - - 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) - - 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['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. - ======================================================================== - """ - 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 - - dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + SFP_MODULE_THRESHOLD_OFFSET), - SFP_MODULE_THRESHOLD_WIDTH) - 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_reset_status(self): - """ - Retrieves the reset status of SFP - Returns: - A Boolean, True if reset enabled, False if disabled - """ - if not self.dom_supported: - return False - - if self.sfp_type == OSFP_TYPE: - return False - elif self.sfp_type == QSFP_TYPE: - offset = 0 - sfpd_obj = sff8436Dom() - dom_module_monitor_raw = self.__read_eeprom_specific_bytes( - (offset + QSFP_MODULE_MONITOR_OFFSET), QSFP_MODULE_MONITOR_WIDTH) - - if dom_module_monitor_raw is not None: - return True - else: - return False - elif self.sfp_type == SFP_TYPE: - offset = 0 - sfpd_obj = sff8472Dom() - 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: - return True - else: - return False - - 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 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 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 - """ - 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: - 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_disable_data = int(dom_channel_monitor_raw[0], 16) - tx_disable_list.append(tx_disable_data & 0xC0 != 0) - else: - return None - 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 - """ - if self.sfp_type != OSFP_TYPE: - return False - - try: - reg_file = open( - "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"])) - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - - # Read status - content = reg_file.readline().rstrip() - reg_value = int(content) - # low power mode is active high - if reg_value == 0: - return False - - return True - - 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.sfp_type == QSFP_TYPE: - offset = 0 - sfpd_obj = sff8436Dom() - if sfpd_obj is None: - return False - - dom_control_raw = self.__read_eeprom_specific_bytes( - 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']) - else: - return False - - 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() - return transceiver_bulk_status.get("temperature", "N/A") - - 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() - return transceiver_bulk_status.get("voltage", "N/A") - - 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'] - """ - transceiver_bulk_status = self.get_transceiver_bulk_status() - tx1_bs = transceiver_bulk_status.get("tx1bias", "N/A") - tx2_bs = transceiver_bulk_status.get("tx2bias", "N/A") - tx3_bs = transceiver_bulk_status.get("tx3bias", "N/A") - tx4_bs = transceiver_bulk_status.get("tx4bias", "N/A") - tx_bias_list = [tx1_bs, tx2_bs, tx3_bs, tx4_bs] - 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'] - """ - 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 - offset_xcvr = 128 - - 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'] - """ - 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 - offset_xcvr = 128 - - 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 reset(self): - """ - Reset SFP and return all user module settings to their default srate. - Returns: - A boolean, True if successful, False if not - """ - if self.sfp_type != OSFP_TYPE: - return False - - try: - reg_file = open( - "/".join([PORT_INFO_PATH, self.port_name, "qsfp_resetL"]), "w") - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - - # Convert our register value back to a hex string and write back - reg_file.seek(0) - reg_file.write(hex(0)) - reg_file.close() - - # Sleep 1 second to allow it to settle - time.sleep(1) - - # Flip the bit back high and write back to the register to take port out of reset - try: - reg_file = open( - "/".join([PORT_INFO_PATH, self.port_name, "qsfp_resetL"]), "w") - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - - reg_file.seek(0) - reg_file.write(hex(1)) - reg_file.close() - - return True - - 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.sfp_type == QSFP_TYPE: - 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 - sysfsfile_eeprom = open( - self.port_to_eeprom_mapping[self.port_num], "r+b") - sysfsfile_eeprom.seek(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 - 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.sfp_type == QSFP_TYPE: - sysfsfile_eeprom = None - try: - channel_state = self.get_tx_disable_channel() - tx_enable_mask = [0xe, 0xd, 0xb, 0x7] - tx_disable_mask = [0x1, 0x3, 0x7, 0xf] - tx_disable_ctl = channel_state | tx_disable_mask[ - channel] if disable else channel_state & tx_enable_mask[channel] - buffer = create_string_buffer(1) - buffer[0] = chr(tx_disable_ctl) - # Write to eeprom - sysfsfile_eeprom = open( - self.port_to_eeprom_mapping[self.port_num], "r+b") - sysfsfile_eeprom.seek(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 - 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 - """ - if self.sfp_type != OSFP_TYPE: - return False - - try: - reg_file = open( - "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"]), "r+") - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - - content = hex(lpmode) - - reg_file.seek(0) - reg_file.write(content) - reg_file.close() - - return True - - 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.sfp_type == QSFP_TYPE: - 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 - sysfsfile_eeprom = open( - self.port_to_eeprom_mapping[self.port_num], "r+b") - sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_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 - return False - - def get_name(self): - """ - Retrieves the name of the device - Returns: - string: The name of the device - """ - sfputil_helper = SfpUtilHelper() - sfputil_helper.read_porttab_mappings( - self.__get_path_to_port_config_file()) - name = sfputil_helper.logical[self.index] or "Unknown" - return name - - def get_presence(self): - """ - Retrieves the presence of the PSU - Returns: - bool: True if PSU is present, False if not - """ - sysfs_filename = "sfp_modabs" if self.sfp_type == SFP_TYPE else "qsfp_modprsL" - reg_path = "/".join([PORT_INFO_PATH, self.port_name, sysfs_filename]) - - # Read status - try: - reg_file = open(reg_path) - content = reg_file.readline().rstrip() - reg_value = int(content) - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - - # Module present is active low - if reg_value == 0: - return True - - return False - - def get_model(self): - """ - Retrieves the model number (or part number) of the device - Returns: - string: Model/part number of device - """ - transceiver_dom_info_dict = self.get_transceiver_info() - return transceiver_dom_info_dict.get("model", "N/A") - - def get_serial(self): - """ - Retrieves the serial number of the device - Returns: - string: Serial number of device - """ - transceiver_dom_info_dict = self.get_transceiver_info() - return transceiver_dom_info_dict.get("serial", "N/A") - - def get_status(self): - """ - Retrieves the operational status of the device - Returns: - A boolean value, True if device is operating properly, False if not - """ - return self.get_presence() diff --git a/device/celestica/x86_64-cel_silverstone-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_silverstone-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..56fda7de4f5d --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/system_health_monitoring_config.json @@ -0,0 +1,13 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "psu.temperature" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "green_blink_1hz" + } +} diff --git a/device/celestica/x86_64-cel_silverstone-r0/warm-reboot_plugin b/device/celestica/x86_64-cel_silverstone-r0/warm-reboot_plugin new file mode 100755 index 000000000000..22212b5afe13 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/warm-reboot_plugin @@ -0,0 +1,4 @@ +#!/bin/bash + +# Set all LEDs to BMC's control +ipmitool raw 0x3a 0x09 0x02 0x01 &> /dev/null diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers.json.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_def.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_def.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_def.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..44fcf21887a6 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t0.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t1.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/hwsku.json b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/hwsku.json new file mode 100644 index 000000000000..b97d516509ec --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/hwsku.json @@ -0,0 +1,164 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet128": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet136": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet144": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet152": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet160": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet168": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet176": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet184": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet192": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet200": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet208": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet216": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet224": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet232": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet240": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + }, + "Ethernet248": { + "default_brkout_mode": "1x400G", + "autoneg": "off", + "fec": "rs" + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l2/config b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l2/config new file mode 100644 index 000000000000..45a7b84d5032 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l2/config @@ -0,0 +1,3 @@ +l2_mem_entries=139264 +l3_mem_entries=8192 +l3_alpm_enable=0 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l3/config b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l3/config new file mode 100644 index 000000000000..3467c1b39716 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/l3/config @@ -0,0 +1,3 @@ +l2_mem_entries=40000 +l3_mem_entries=40000 +l3_alpm_enable=2 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/pg_profile_lookup.ini b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/pg_profile_lookup.ini new file mode 100644 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 56368 18432 55120 -3 2496 + 25000 5m 56368 18432 55120 -3 2496 + 40000 5m 56368 18432 55120 -3 2496 + 50000 5m 56368 18432 55120 -3 2496 + 100000 5m 56368 18432 55120 -3 2496 + 10000 40m 56368 18432 55120 -3 2496 + 25000 40m 56368 18432 55120 -3 2496 + 40000 40m 56368 18432 55120 -3 2496 + 50000 40m 56368 18432 55120 -3 2496 + 100000 40m 56368 18432 55120 -3 2496 + 10000 300m 56368 18432 55120 -3 2496 + 25000 300m 56368 18432 55120 -3 2496 + 40000 300m 56368 18432 55120 -3 2496 + 50000 300m 56368 18432 55120 -3 2496 + 100000 300m 56368 18432 55120 -3 2496 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/platform-def.json b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/platform-def.json new file mode 100644 index 000000000000..4644f6e4549d --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/platform-def.json @@ -0,0 +1,23 @@ +{ + "fec-mode": { + "Ethernet0-127": { + "1": { + "10000": [ "none", "fc" ], + "25000": [ "none", "fc" ] + }, + "2": { + "20000": [ "none", "fc" ], + "50000": [ "none", "rs" ] + }, + "4": { + "40000": [ "none", "fc" ], + "100000": [ "none", "rs" ] + } + } + }, + "native-port-supported-speeds": { + "Ethernet0-127": { + "4": ["100000","40000"] + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/port_config.ini b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/port_config.ini new file mode 100644 index 000000000000..f7929e6f5c17 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36,37,38,39,40 Eth1/1 1 400000 +Ethernet8 41,42,43,44,45,46,47,48 Eth1/2 2 400000 +Ethernet16 49,50,51,52,53,54,55,56 Eth1/3 3 400000 +Ethernet24 57,58,59,60,61,62,63,64 Eth1/4 4 400000 +Ethernet32 65,66,67,68,69,70,71,72 Eth1/5 5 400000 +Ethernet40 73,74,75,76,77,78,79,80 Eth1/6 6 400000 +Ethernet48 81,82,83,84,85,86,87,88 Eth1/7 7 400000 +Ethernet56 89,90,91,92,93,94,95,96 Eth1/8 8 400000 +Ethernet64 1,2,3,4,5,6,7,8 Eth1/9 9 400000 +Ethernet72 9,10,11,12,13,14,15,16 Eth1/10 10 400000 +Ethernet80 17,18,19,20,21,22,23,24 Eth1/11 11 400000 +Ethernet88 25,26,27,28,29,30,31,32 Eth1/12 12 400000 +Ethernet96 97,98,99,100,101,102,103,104 Eth1/13 13 400000 +Ethernet104 105,106,107,108,109,110,111,112 Eth1/14 14 400000 +Ethernet112 113,114,115,116,117,118,119,120 Eth1/15 15 400000 +Ethernet120 121,122,123,124,125,126,127,128 Eth1/16 16 400000 +Ethernet128 129,130,131,132,133,134,135,136 Eth1/17 17 400000 +Ethernet136 137,138,139,140,141,142,143,144 Eth1/18 18 400000 +Ethernet144 145,146,147,148,149,150,151,152 Eth1/19 19 400000 +Ethernet152 153,154,155,156,157,158,159,160 Eth1/20 20 400000 +Ethernet160 225,226,227,228,229,230,231,232 Eth1/21 21 400000 +Ethernet168 233,234,235,236,237,238,239,240 Eth1/22 22 400000 +Ethernet176 241,242,243,244,245,246,247,248 Eth1/23 23 400000 +Ethernet184 249,250,251,252,253,254,255,256 Eth1/24 24 400000 +Ethernet192 161,162,163,164,165,166,167,168 Eth1/25 25 400000 +Ethernet200 169,170,171,172,173,174,175,176 Eth1/26 26 400000 +Ethernet208 177,178,179,180,181,182,183,184 Eth1/27 27 400000 +Ethernet216 185,186,187,188,189,190,191,192 Eth1/28 28 400000 +Ethernet224 193,194,195,196,197,198,199,200 Eth1/29 29 400000 +Ethernet232 201,202,203,204,205,206,207,208 Eth1/30 30 400000 +Ethernet240 209,210,211,212,213,214,215,216 Eth1/31 31 400000 +Ethernet248 217,218,219,220,221,222,223,224 Eth1/32 32 400000 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/qos.json.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai.profile b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai.profile new file mode 100644 index 000000000000..550bfe181df4 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai_postinit_cmd.soc b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai_postinit_cmd.soc new file mode 100644 index 000000000000..731625308a5e --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/sai_postinit_cmd.soc @@ -0,0 +1,2 @@ +modreg ING_MISC_CONFIG INPUT_PRI_TAGGED=1 +modreg ING_MISC_CONFIG INPUT_PRI_UNTAGGED=1 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/th3-32x400G.config.bcm b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/th3-32x400G.config.bcm new file mode 100644 index 000000000000..f478e2ea85eb --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2/th3-32x400G.config.bcm @@ -0,0 +1,231 @@ +pbmp_xport_xe.0=0x8ffff8ffffcffff8ffff8ffff8ffffcffff9fffe +#pbmp_xport_xe.0=0x8111181111c1111811118111181111c111182222 +ccm_dma_enable=0 +ccmdma_intr_enable=0 +ctr_evict_enable=0 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +phy_enable=0 +phy_null=1 +pll_bypass=1 + +sai_tunnel_global_sip_mask_enable=1 + +port_fec=9 + +#portmap_38=257:10 +#portmap_118=258:10 + + +portmap_20=33:400 +portmap_24=41:400 +portmap_28=49:400 +portmap_32=57:400 +portmap_40=65:400 +portmap_44=73:400 +portmap_48=81:400 +portmap_52=89:400 +portmap_1=1:400 +portmap_5=9:400 +portmap_9=17:400 +portmap_13=25:400 +portmap_60=97:400 +portmap_64=105:400 +portmap_68=113:400 +portmap_72=121:400 +portmap_80=129:400 +portmap_84=137:400 +portmap_88=145:400 +portmap_92=153:400 +portmap_140=225:400 +portmap_144=233:400 +portmap_148=241:400 +portmap_152=249:400 +portmap_100=161:400 +portmap_104=169:400 +portmap_108=177:400 +portmap_112=185:400 +portmap_120=193:400 +portmap_124=201:400 +portmap_128=209:400 +portmap_132=217:400 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + +#dport_map_port_20=1 +#dport_map_port_24=2 +#dport_map_port_28=3 +#dport_map_port_32=4 +#dport_map_port_40=5 +#dport_map_port_44=6 +#dport_map_port_48=7 +#dport_map_port_52=8 +#dport_map_port_1=9 +#dport_map_port_5=10 +#dport_map_port_9=11 +#dport_map_port_13=12 +#dport_map_port_60=13 +#dport_map_port_64=14 +#dport_map_port_68=15 +#dport_map_port_72=16 +#dport_map_port_80=17 +#dport_map_port_84=18 +#dport_map_port_88=19 +#dport_map_port_92=20 +#dport_map_port_140=21 +#dport_map_port_144=22 +#dport_map_port_148=23 +#dport_map_port_152=24 +#dport_map_port_100=25 +#dport_map_port_104=26 +#dport_map_port_108=27 +#dport_map_port_112=28 +#dport_map_port_120=29 +#dport_map_port_124=30 +#dport_map_port_128=31 +#dport_map_port_132=32 +# +#dport_map_port_38=33 +#dport_map_port_118=34 + + + +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 +port_flex_enable=1 + +#firmware load method, use fast load +load_firmware=0x2 + +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers.json.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_def.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_def.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_def.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..44fcf21887a6 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t0.j2 @@ -0,0 +1,45 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t1.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..740cfdf79e96 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "xoff": "4625920", + "size": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "12766208", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "7326924", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"12766208" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/hwsku.json b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/hwsku.json new file mode 100644 index 000000000000..1a6031b4b543 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "4x100G" + }, + "Ethernet8": { + "default_brkout_mode": "4x100G" + }, + "Ethernet16": { + "default_brkout_mode": "4x100G" + }, + "Ethernet24": { + "default_brkout_mode": "4x100G" + }, + "Ethernet32": { + "default_brkout_mode": "4x100G" + }, + "Ethernet40": { + "default_brkout_mode": "4x100G" + }, + "Ethernet48": { + "default_brkout_mode": "4x100G" + }, + "Ethernet56": { + "default_brkout_mode": "4x100G" + }, + "Ethernet64": { + "default_brkout_mode": "4x100G" + }, + "Ethernet72": { + "default_brkout_mode": "4x100G" + }, + "Ethernet80": { + "default_brkout_mode": "4x100G" + }, + "Ethernet88": { + "default_brkout_mode": "4x100G" + }, + "Ethernet96": { + "default_brkout_mode": "4x100G" + }, + "Ethernet104": { + "default_brkout_mode": "4x100G" + }, + "Ethernet112": { + "default_brkout_mode": "4x100G" + }, + "Ethernet120": { + "default_brkout_mode": "4x100G" + }, + "Ethernet128": { + "default_brkout_mode": "4x100G" + }, + "Ethernet136": { + "default_brkout_mode": "4x100G" + }, + "Ethernet144": { + "default_brkout_mode": "4x100G" + }, + "Ethernet152": { + "default_brkout_mode": "4x100G" + }, + "Ethernet160": { + "default_brkout_mode": "4x100G" + }, + "Ethernet168": { + "default_brkout_mode": "4x100G" + }, + "Ethernet176": { + "default_brkout_mode": "4x100G" + }, + "Ethernet184": { + "default_brkout_mode": "4x100G" + }, + "Ethernet192": { + "default_brkout_mode": "4x100G" + }, + "Ethernet200": { + "default_brkout_mode": "4x100G" + }, + "Ethernet208": { + "default_brkout_mode": "4x100G" + }, + "Ethernet216": { + "default_brkout_mode": "4x100G" + }, + "Ethernet224": { + "default_brkout_mode": "4x100G" + }, + "Ethernet232": { + "default_brkout_mode": "4x100G" + }, + "Ethernet240": { + "default_brkout_mode": "4x100G" + }, + "Ethernet248": { + "default_brkout_mode": "4x100G" + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l2/config b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l2/config new file mode 100644 index 000000000000..45a7b84d5032 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l2/config @@ -0,0 +1,3 @@ +l2_mem_entries=139264 +l3_mem_entries=8192 +l3_alpm_enable=0 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l3/config b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l3/config new file mode 100644 index 000000000000..3467c1b39716 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/l3/config @@ -0,0 +1,3 @@ +l2_mem_entries=40000 +l3_mem_entries=40000 +l3_alpm_enable=2 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/pg_profile_lookup.ini b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/pg_profile_lookup.ini new file mode 100644 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 56368 18432 55120 -3 2496 + 25000 5m 56368 18432 55120 -3 2496 + 40000 5m 56368 18432 55120 -3 2496 + 50000 5m 56368 18432 55120 -3 2496 + 100000 5m 56368 18432 55120 -3 2496 + 10000 40m 56368 18432 55120 -3 2496 + 25000 40m 56368 18432 55120 -3 2496 + 40000 40m 56368 18432 55120 -3 2496 + 50000 40m 56368 18432 55120 -3 2496 + 100000 40m 56368 18432 55120 -3 2496 + 10000 300m 56368 18432 55120 -3 2496 + 25000 300m 56368 18432 55120 -3 2496 + 40000 300m 56368 18432 55120 -3 2496 + 50000 300m 56368 18432 55120 -3 2496 + 100000 300m 56368 18432 55120 -3 2496 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/platform-def.json b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/platform-def.json new file mode 100644 index 000000000000..4644f6e4549d --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/platform-def.json @@ -0,0 +1,23 @@ +{ + "fec-mode": { + "Ethernet0-127": { + "1": { + "10000": [ "none", "fc" ], + "25000": [ "none", "fc" ] + }, + "2": { + "20000": [ "none", "fc" ], + "50000": [ "none", "rs" ] + }, + "4": { + "40000": [ "none", "fc" ], + "100000": [ "none", "rs" ] + } + } + }, + "native-port-supported-speeds": { + "Ethernet0-127": { + "4": ["100000","40000"] + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/port_config.ini b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/port_config.ini new file mode 100644 index 000000000000..77deb1931856 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/port_config.ini @@ -0,0 +1,129 @@ +# name lanes alias index speed +Ethernet0 33,34 QSFP1/1 1 100000 +Ethernet2 35,36 QSFP1/2 1 100000 +Ethernet4 37,38 QSFP1/3 1 100000 +Ethernet6 39,40 QSFP1/4 1 100000 +Ethernet8 41,42 QSFP2/1 2 100000 +Ethernet10 43,44 QSFP2/2 2 100000 +Ethernet12 45,46 QSFP2/3 2 100000 +Ethernet14 47,48 QSFP2/4 2 100000 +Ethernet16 49,50 QSFP3/1 3 100000 +Ethernet18 51,52 QSFP3/2 3 100000 +Ethernet20 53,54 QSFP3/3 3 100000 +Ethernet22 55,56 QSFP3/4 3 100000 +Ethernet24 57,58 QSFP4/1 4 100000 +Ethernet26 59,60 QSFP4/2 4 100000 +Ethernet28 61,62 QSFP4/3 4 100000 +Ethernet30 63,64 QSFP4/4 4 100000 +Ethernet32 65,66 QSFP5/1 5 100000 +Ethernet34 67,68 QSFP5/2 5 100000 +Ethernet36 69,70 QSFP5/3 5 100000 +Ethernet38 71,72 QSFP5/4 5 100000 +Ethernet40 73,74 QSFP6/1 6 100000 +Ethernet42 75,76 QSFP6/2 6 100000 +Ethernet44 77,78 QSFP6/3 6 100000 +Ethernet46 79,80 QSFP6/4 6 100000 +Ethernet48 81,82 QSFP7/1 7 100000 +Ethernet50 83,84 QSFP7/2 7 100000 +Ethernet52 85,86 QSFP7/3 7 100000 +Ethernet54 87,88 QSFP7/4 7 100000 +Ethernet56 89,90 QSFP8/1 8 100000 +Ethernet58 91,92 QSFP8/2 8 100000 +Ethernet60 93,94 QSFP8/3 8 100000 +Ethernet62 95,96 QSFP8/4 8 100000 +Ethernet64 1,2 QSFP9/1 9 100000 +Ethernet66 3,4 QSFP9/2 9 100000 +Ethernet68 5,6 QSFP9/3 9 100000 +Ethernet70 7,8 QSFP9/4 9 100000 +Ethernet72 9,10 QSFP10/1 10 100000 +Ethernet74 11,12 QSFP10/2 10 100000 +Ethernet76 13,14 QSFP10/3 10 100000 +Ethernet78 15,16 QSFP10/4 10 100000 +Ethernet80 17,18 QSFP11/1 11 100000 +Ethernet82 19,20 QSFP11/2 11 100000 +Ethernet84 21,22 QSFP11/3 11 100000 +Ethernet86 23,24 QSFP11/4 11 100000 +Ethernet88 25,26 QSFP12/1 12 100000 +Ethernet90 27,28 QSFP12/2 12 100000 +Ethernet92 29,30 QSFP12/3 12 100000 +Ethernet94 31,32 QSFP12/4 12 100000 +Ethernet96 97,98 QSFP13/1 13 100000 +Ethernet98 99,100 QSFP13/2 13 100000 +Ethernet100 101,102 QSFP13/3 13 100000 +Ethernet102 103,104 QSFP13/4 13 100000 +Ethernet104 105,106 QSFP14/1 14 100000 +Ethernet106 107,108 QSFP14/2 14 100000 +Ethernet108 109,110 QSFP14/3 14 100000 +Ethernet110 111,112 QSFP14/4 14 100000 +Ethernet112 113,114 QSFP15/1 15 100000 +Ethernet114 115,116 QSFP15/2 15 100000 +Ethernet116 117,118 QSFP15/3 15 100000 +Ethernet118 119,120 QSFP15/4 15 100000 +Ethernet120 121,122 QSFP16/1 16 100000 +Ethernet122 123,124 QSFP16/2 16 100000 +Ethernet124 125,126 QSFP16/3 16 100000 +Ethernet126 127,128 QSFP16/4 16 100000 +Ethernet128 129,130 QSFP17/1 17 100000 +Ethernet130 131,132 QSFP17/2 17 100000 +Ethernet132 133,134 QSFP17/3 17 100000 +Ethernet134 135,136 QSFP17/4 17 100000 +Ethernet136 137,138 QSFP18/1 18 100000 +Ethernet138 139,140 QSFP18/2 18 100000 +Ethernet140 141,142 QSFP18/3 18 100000 +Ethernet142 143,144 QSFP18/4 18 100000 +Ethernet144 145,146 QSFP19/1 19 100000 +Ethernet146 147,148 QSFP19/2 19 100000 +Ethernet148 149,150 QSFP19/3 19 100000 +Ethernet150 151,152 QSFP19/4 19 100000 +Ethernet152 153,154 QSFP20/1 20 100000 +Ethernet154 155,156 QSFP20/2 20 100000 +Ethernet156 157,158 QSFP20/3 20 100000 +Ethernet158 159,160 QSFP20/4 20 100000 +Ethernet160 225,226 QSFP21/1 21 100000 +Ethernet162 227,228 QSFP21/2 21 100000 +Ethernet164 229,230 QSFP21/3 21 100000 +Ethernet166 231,232 QSFP21/4 21 100000 +Ethernet168 233,234 QSFP22/1 22 100000 +Ethernet170 235,236 QSFP22/2 22 100000 +Ethernet172 237,238 QSFP22/3 22 100000 +Ethernet174 239,240 QSFP22/4 22 100000 +Ethernet176 241,242 QSFP23/1 23 100000 +Ethernet178 243,244 QSFP23/2 23 100000 +Ethernet180 245,246 QSFP23/3 23 100000 +Ethernet182 247,248 QSFP23/4 23 100000 +Ethernet184 249,250 QSFP24/1 24 100000 +Ethernet186 251,252 QSFP24/2 24 100000 +Ethernet188 253,254 QSFP24/3 24 100000 +Ethernet190 255,256 QSFP24/4 24 100000 +Ethernet192 161,162 QSFP25/1 25 100000 +Ethernet194 163,164 QSFP25/2 25 100000 +Ethernet196 165,166 QSFP25/3 25 100000 +Ethernet198 167,168 QSFP25/4 25 100000 +Ethernet200 169,170 QSFP26/1 26 100000 +Ethernet202 171,172 QSFP26/2 26 100000 +Ethernet204 173,174 QSFP26/3 26 100000 +Ethernet206 175,176 QSFP26/4 26 100000 +Ethernet208 177,178 QSFP27/1 27 100000 +Ethernet210 179,180 QSFP27/2 27 100000 +Ethernet212 181,182 QSFP27/3 27 100000 +Ethernet214 183,184 QSFP27/4 27 100000 +Ethernet216 185,186 QSFP28/1 28 100000 +Ethernet218 187,188 QSFP28/2 28 100000 +Ethernet220 189,190 QSFP28/3 28 100000 +Ethernet222 191,192 QSFP28/4 28 100000 +Ethernet224 193,194 QSFP29/1 29 100000 +Ethernet226 195,196 QSFP29/2 29 100000 +Ethernet228 197,198 QSFP29/3 29 100000 +Ethernet230 199,200 QSFP29/4 29 100000 +Ethernet232 201,202 QSFP30/1 30 100000 +Ethernet234 203,204 QSFP30/2 30 100000 +Ethernet236 205,206 QSFP30/3 30 100000 +Ethernet238 207,208 QSFP30/4 30 100000 +Ethernet240 209,210 QSFP31/1 31 100000 +Ethernet242 211,212 QSFP31/2 31 100000 +Ethernet244 213,214 QSFP31/3 31 100000 +Ethernet246 215,216 QSFP31/4 31 100000 +Ethernet248 217,218 QSFP32/1 32 100000 +Ethernet250 219,220 QSFP32/2 32 100000 +Ethernet252 221,222 QSFP32/3 32 100000 +Ethernet254 223,224 QSFP32/4 32 100000 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/qos.json.j2 b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/sai.profile b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/sai.profile new file mode 100644 index 000000000000..483e85c0c1fa --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-128x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/th3-128x100G.config.bcm b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/th3-128x100G.config.bcm new file mode 100644 index 000000000000..2aa1955c10bc --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/Silverstone_v2_128X100G/th3-128x100G.config.bcm @@ -0,0 +1,445 @@ +pbmp_xport_xe.0=0x8ffff8ffffcffff8ffff8ffff8ffffcffff9fffe +ccm_dma_enable=0 +ccmdma_intr_enable=0 +ctr_evict_enable=0 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +phy_enable=0 +phy_null=1 +pll_bypass=1 + +port_fec=3 + +init_all_modules=0 + +sai_tunnel_global_sip_mask_enable=1 + +portmap_20=33:100:2 +portmap_21=35:100:2 +portmap_22=37:100:2 +portmap_23=39:100:2 + +portmap_24=41:100:2 +portmap_25=43:100:2 +portmap_26=45:100:2 +portmap_27=47:100:2 + +portmap_28=49:100:2 +portmap_29=51:100:2 +portmap_30=53:100:2 +portmap_31=55:100:2 + +portmap_32=57:100:2 +portmap_33=59:100:2 +portmap_34=61:100:2 +portmap_35=63:100:2 + +portmap_40=65:100:2 +portmap_41=67:100:2 +portmap_42=69:100:2 +portmap_43=71:100:2 + +portmap_44=73:100:2 +portmap_45=75:100:2 +portmap_46=77:100:2 +portmap_47=79:100:2 + +portmap_48=81:100:2 +portmap_49=83:100:2 +portmap_50=85:100:2 +portmap_51=87:100:2 + +portmap_52=89:100:2 +portmap_53=91:100:2 +portmap_54=93:100:2 +portmap_55=95:100:2 + +portmap_1=1:100:2 +portmap_2=3:100:2 +portmap_3=5:100:2 +portmap_4=7:100:2 + +portmap_5=9:100:2 +portmap_6=11:100:2 +portmap_7=13:100:2 +portmap_8=15:100:2 + +portmap_9=17:100:2 +portmap_10=19:100:2 +portmap_11=21:100:2 +portmap_12=23:100:2 + +portmap_13=25:100:2 +portmap_14=27:100:2 +portmap_15=29:100:2 +portmap_16=31:100:2 + +portmap_60=97:100:2 +portmap_61=99:100:2 +portmap_62=101:100:2 +portmap_63=103:100:2 + +portmap_64=105:100:2 +portmap_65=107:100:2 +portmap_66=109:100:2 +portmap_67=111:100:2 + +portmap_68=113:100:2 +portmap_69=115:100:2 +portmap_70=117:100:2 +portmap_71=119:100:2 + +portmap_72=121:100:2 +portmap_73=123:100:2 +portmap_74=125:100:2 +portmap_75=127:100:2 + +portmap_80=129:100:2 +portmap_81=131:100:2 +portmap_82=133:100:2 +portmap_83=135:100:2 + +portmap_84=137:100:2 +portmap_85=139:100:2 +portmap_86=141:100:2 +portmap_87=143:100:2 + +portmap_88=145:100:2 +portmap_89=147:100:2 +portmap_90=149:100:2 +portmap_91=151:100:2 + +portmap_92=153:100:2 +portmap_93=155:100:2 +portmap_94=157:100:2 +portmap_95=159:100:2 + +portmap_140=225:100:2 +portmap_141=227:100:2 +portmap_142=229:100:2 +portmap_143=231:100:2 + +portmap_144=233:100:2 +portmap_145=235:100:2 +portmap_146=237:100:2 +portmap_147=239:100:2 + +portmap_148=241:100:2 +portmap_149=243:100:2 +portmap_150=245:100:2 +portmap_151=247:100:2 + +portmap_152=249:100:2 +portmap_153=251:100:2 +portmap_154=253:100:2 +portmap_155=255:100:2 + +portmap_100=161:100:2 +portmap_101=163:100:2 +portmap_102=165:100:2 +portmap_103=167:100:2 + +portmap_104=169:100:2 +portmap_105=171:100:2 +portmap_106=173:100:2 +portmap_107=175:100:2 + +portmap_108=177:100:2 +portmap_109=179:100:2 +portmap_110=181:100:2 +portmap_111=183:100:2 + +portmap_112=185:100:2 +portmap_113=187:100:2 +portmap_114=189:100:2 +portmap_115=191:100:2 + +portmap_120=193:100:2 +portmap_121=195:100:2 +portmap_122=197:100:2 +portmap_123=199:100:2 + +portmap_124=201:100:2 +portmap_125=203:100:2 +portmap_126=205:100:2 +portmap_127=207:100:2 + +portmap_128=209:100:2 +portmap_129=211:100:2 +portmap_130=213:100:2 +portmap_131=215:100:2 + +portmap_132=217:100:2 +portmap_133=219:100:2 +portmap_134=221:100:2 +portmap_135=223:100:2 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + + +#dport_map_port_20=1 +#dport_map_port_21=2 +#dport_map_port_22=3 +#dport_map_port_23=4 +#dport_map_port_24=5 +#dport_map_port_25=6 +#dport_map_port_26=7 +#dport_map_port_27=8 +#dport_map_port_28=9 +#dport_map_port_29=10 +#dport_map_port_30=11 +#dport_map_port_31=12 +#dport_map_port_32=13 +#dport_map_port_33=14 +#dport_map_port_34=15 +#dport_map_port_35=16 +#dport_map_port_40=17 +#dport_map_port_41=18 +#dport_map_port_42=19 +#dport_map_port_43=20 +#dport_map_port_44=21 +#dport_map_port_45=22 +#dport_map_port_46=23 +#dport_map_port_47=24 +#dport_map_port_48=25 +#dport_map_port_49=26 +#dport_map_port_50=27 +#dport_map_port_51=28 +#dport_map_port_52=29 +#dport_map_port_53=30 +#dport_map_port_54=31 +#dport_map_port_55=32 +#dport_map_port_1=33 +#dport_map_port_2=34 +#dport_map_port_3=35 +#dport_map_port_4=36 +#dport_map_port_5=37 +#dport_map_port_6=38 +#dport_map_port_7=39 +#dport_map_port_8=40 +#dport_map_port_9=41 +#dport_map_port_10=42 +#dport_map_port_11=43 +#dport_map_port_12=44 +#dport_map_port_13=45 +#dport_map_port_14=46 +#dport_map_port_15=47 +#dport_map_port_16=48 +#dport_map_port_60=49 +#dport_map_port_61=50 +#dport_map_port_62=51 +#dport_map_port_63=52 +#dport_map_port_64=53 +#dport_map_port_65=54 +#dport_map_port_66=55 +#dport_map_port_67=56 +#dport_map_port_68=57 +#dport_map_port_69=58 +#dport_map_port_70=59 +#dport_map_port_71=60 +#dport_map_port_72=61 +#dport_map_port_73=62 +#dport_map_port_74=63 +#dport_map_port_75=64 +#dport_map_port_80=65 +#dport_map_port_81=66 +#dport_map_port_82=67 +#dport_map_port_83=68 +#dport_map_port_84=69 +#dport_map_port_85=70 +#dport_map_port_86=71 +#dport_map_port_87=72 +#dport_map_port_88=73 +#dport_map_port_89=74 +#dport_map_port_90=75 +#dport_map_port_91=76 +#dport_map_port_92=77 +#dport_map_port_93=78 +#dport_map_port_94=79 +#dport_map_port_95=80 +#dport_map_port_140=81 +#dport_map_port_141=82 +#dport_map_port_142=83 +#dport_map_port_143=84 +#dport_map_port_144=85 +#dport_map_port_145=86 +#dport_map_port_146=87 +#dport_map_port_147=88 +#dport_map_port_148=89 +#dport_map_port_149=90 +#dport_map_port_150=91 +#dport_map_port_151=92 +#dport_map_port_152=93 +#dport_map_port_153=94 +#dport_map_port_154=95 +#dport_map_port_155=96 +#dport_map_port_100=97 +#dport_map_port_101=98 +#dport_map_port_102=99 +#dport_map_port_103=100 +#dport_map_port_104=101 +#dport_map_port_105=102 +#dport_map_port_106=103 +#dport_map_port_107=104 +#dport_map_port_108=105 +#dport_map_port_109=106 +#dport_map_port_110=107 +#dport_map_port_111=108 +#dport_map_port_112=109 +#dport_map_port_113=110 +#dport_map_port_114=111 +#dport_map_port_115=112 +#dport_map_port_120=113 +#dport_map_port_121=114 +#dport_map_port_122=115 +#dport_map_port_123=116 +#dport_map_port_124=117 +#dport_map_port_125=118 +#dport_map_port_126=119 +#dport_map_port_127=120 +#dport_map_port_128=121 +#dport_map_port_129=122 +#dport_map_port_130=123 +#dport_map_port_131=124 +#dport_map_port_132=125 +#dport_map_port_133=126 +#dport_map_port_134=127 +#dport_map_port_135=128 + +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 +port_flex_enable=1 + +#firmware load method, use fast load +load_firmware=0x2 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/custom_led.bin b/device/celestica/x86_64-cel_silverstone_v2-r0/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..2424dd07f10358a45fce02612386c336fb9e07e5 GIT binary patch literal 1580 zcmb7@d013c7>D0`?<{C3DpYQv<=ls5N&u!T{Lu80? zB3-m>DQK`4D>0U0Tw1tD*n8CoHP&9$-)k*haYCy;?Fcun5=u(AQArKZG%AoaCBjmf z<0xpfg(f;{sm;!djrA&}^PRhWYU%ROMu(Cby(H3=>LnZzx75E=l%&rPx&B;ViJ-h# zSX}{sary+Ic(h|#f_R#D7)o3Ze@wH|x1!NjUhUY^s0?4qE>S-rD2`<3I>VG@D`k1E z6mN#J(N`=^by0?TCJ2(5f8*{~3cFq50N$jMP+(EaN6F<6{ zN^7FhZ1s%PS!+vDnr)sD`gB3^bUnh8re_=d(i~@$-e$Fu#NqllLDCSNDr>SyrRtR1 z;!SFxK2?yICaD3s*HG7z)IlFF*NK!0t5jG$NjjA_xtGn8pih&lBuQ-_J>D2C)T)%U ziTx{5?ML+iCpI1FoSz342f9SwRnh$usi+b-G}npCtktWse& zRH?8Sn(QiuRd$s@{!jtwqA;-1sIy1u)+&Hbh5nPNj=YZIo&xYXXiNY$S#%b zjSF>kfn4SM$(TFa6F8c8QmcrN?^=na!XmS!BtN08u2qJ@UZE%ug9|skh^04iTuvYPBPNhY63KYDf-6a(Fa7Ax0Ip&ngGgnt z9Cj$f7>*Yoe$q&11cH%V%_v4QhOvxeJQKKvYYA{26PZK?nM`I1S!6SnX-sDZGf_~{ zuwcc8oe0{{mW#NUcC;swC@!G`9qB}8E+rZVUFb?Tx^o#$deD;`g3Mwz*E5H?gt&nl zna54s%q`4k0k?7+3t7ZsZs!h`a3{Ik#ogS)y(}eKk^el z^9#T78^7}hr}>k=_?v(D7nH}T;R$M~V?7(F=SeoQiKlp)%{)T`&(g?qY+)@2muTW;Ug1?<<8}6PfP=ijo4m!_=rnVPcX*e>yvGraa*X#m&If$R fM|_NdqNwr~oPWHj@*WR{pv;S8l*y=thjRH?O__@7xU({k=Z_ zz}b7|ac0iUoH^&rnV}HT3q&-7Bf1dqKmA>LPWd9>r94pszW)=fLHU*cOP&9T{=X~J z`RqFl>~_~LTJ_kpq?a7Q4^$p!B6+1&;?)psA8 z%|NI&)T<_!t9LZG6w%?5(c=i4pUpz0LWu*zE`=&6hg^lxnX)Trj2~1iIcDB$S!O>d z_Xo*!IyNC5S1OfGkM(Fg=n8BJlmy8s2fJzotY34gDo9md#BTMG&@ZXU5;fFU)2jfh zQaAWE2N^a;y}{S7(Bzu&k|}EIc*#^%_Wx0_Pqs?-IkH@$ba<@q`h!%S6@Nq7?ct9M z6uu!-{7>@XAXR=76XY7qw3EyJSPHaR(n6niiQTPNEY5_&CpM`sC_Znwoz;6gEeN_qMM^KR)O%^FnjC#z>6UAP zLZB@u2ig=W`MdmKK$d$HK^7f7atO0yjgs>fG>h_eExTO{<|#8A+6Vt><&^X zxy;dn;OA~nA^M#YD2!)%d^GS;AUSvtvt^3Dq5RBaKKeo6U~qfj)j)T^6#od{M*{jd zFPWr+%H5t%2NRC~g+8dMYKNLrlue{;)ua1w${LT6(YhCHG6igKQl1ImOwSL(c+w ziN5@gU;kB2I?^S+@F{aACH8~X7!|ttgeP65wIB?U5I!}j^UG6{!o1VuW%x^{*4fi%sialXNqN%U zreD)_E6hdv?6%6(krMgkx&^@frdHLO^hC&t?_Lf<*1ks3AmN0e~UU-@i(3_`uXX!xbC5)?0~T-nDu^cJg> z_JHcQsHcxbP{ycwR6%0x-&cR1*8bk{_IIG>BfyQZyT{w#qqTnz+HMfSde+01`YjsG zJ>xW+LDQ+xgvV*xHJT1zsLv_2qx4p!CxQFhfNubv6Wi4Ae|$L?GCpt8D1QvT!bNJb zS);r~qr3&Ruhr6*wXW7` zU7^`CK6-_Jo5IIe){%2t6Nh!nv}Tk{B|m(aPsn3j`R87y6LcllJ?zFRT{T9o{HO(5 zDAZ?#MEy1;$mDWFMQ1yx)#O4|tx;?E8mE#QXXTG;<<_XvxsA)zxIi^H{k&M{RD7(z zJ{M;HcI7S)e^hI=R#ZegDK?Fl@8mNCk#aU2wUhE^r8zM0bP}81KFS-;j^=;cJM!L>JSSQS`{ol32%n`zgs zT~C~tLR7o7UaG;0GApugM8Il{j%HFlNHH6jNj<2Qy*kS3Jvvg;XE}VAM>i0$cY2Hi zS#b)kDBNZb7q@#ji~};Ht+_!O@`aUl_&Ch#IXcS4p$|t5&aZuDp2`}$Gwh9m>~+}> z-oz}xf>z_<9UgtOy_G7tXn$*GZL`Bx_4zTjo+o?%(a_NY+mF3SLb}i3H1i+%_{1!Y zpI6cpIU$!}Rh~@Kt~!c};jD13BHLWtyEZ|Q50RSuMOrUWq@M`8Ad(I$+zvkRr;%C{ z3C{QnrtOlUoZt1<;u(C<`$v1DlS&qNue0Y#u8JRdTO0pT5VS9m`8{{ZhvZdKc7RIn z3S_T*GqBvTc;y_4pZ4i7(ZNAey>~$!?-kI0LG}a#A#%Q-TOM1-GqEUUkTe(B-R@7vAq(a^b@9y!s<;o8D7kcavTc4pM zpKtU&TGxTu^LZ!Qn_#i|s6i{E60Xc8G37Nn$(pfp51^R>sTT`|7EL z3L47--ieZEcR81N7l3N9MnwXnqRQN3o%PMi!=CH`gGRHZK0_heUuo`WX0ZqyBbGfVm`$S0PLc#1N6v@fk$F0`7~_(=EFKz=Vr`2nd^g4d^5 z;`h*v(toVjN`GB8GblRzjx8RF@xl(zS4U)}G8l&Z@<;f@q2W%4EK{U$iC(FemSJ7~ zJj#_bpSW6DiqxS|<`estHu!Sp&BqStM|xt+@0+h_)fbSm#w4UnZZ)|dDFf&hfbJ>a zSy67Un*7li7pam&$7b=o_&j*e%t}0j(rnbc05u;Nr>X|N12`Ym33@NZtGpD^LocNJ zPW5i>F_0xuw(sRb5BAW`|zM)YEUAg1`zv*^*qj4I>+w6FRjkoN1 zDPButaQpDAtHMJ|(Uj!r5GV!k#Gn1xcU6Tviv&(bx$d8mm_R3&pl)oS9 zbcAFsqTdrHUA+2Qf0pj;=3=TEios8+;^8-Ok<6^UHrRog-%f?g*v$JK9hnw)Gg%|y zIrvDO6Nys2ddiBX8`7E=@gUANrWgkclIp9JhOzedX{Q|l{^Hl8slIQ<{fW*IPHHZe z&6|lTE8%gRM9rU~W@+rpr8A{UsRlB6Gt!e|gAJdJTmH33PmG-yxBNFEWsUtEDJG*b zQcOk}-POQ#Q9)AO54rg``))!FD|$cKySt|_Laqy;h=0pec2_B}Fre+5( z4*1+|vB~D;#Zcpq8?9Ae9HVlDql%}<-er%lx?9!xD_W%d71`26kr(gt@KK-G?w!Bv zX2h!UP zF?Xb3e~;-kSzA9UNFNW**DU8_YKFqCQJBUl{tn%}Z7~TBiI?1S+Ue>>(XkR-3>~}I ze{Z*%+&BW0K5E0xzPJ9_o-D{kO%b2?TZ)5k#7TE`=f%|$=j?kQ{yBKOGG&c3iRTl4 zPPLP}()6yrjFUe0{tRWcDM7jr+$;Wd+Sq=CvFT!zVA{tK4KAUwf2R`#lR*2MRI?+r zjE#m84~?#@ch4c$B3RU%eeJZWNpxJHako|Tw|@$$G)VjtZ0_#X=8no9qlDJZ-6{Tw zW=AJl`UWdk_*6UUtk&wdOZX=$_VNjTs_;n?DxPkqy9?Gg&A4^B>GP~PTEVeo7OliVo9TQ#;LQi#dUF-Y^^|zYF~Ao z+f6I-SLh&N7D$*rT2;3|bkFYe+B7LUam?k*d79N(<8VXPjvp)bmuvI%KF%`Pv79IP zy=wBcGzmOr;R?*c25lB9>RX^I1g!Xb!xSN>$F!ViCrkfzn96c~-AxAzT-tiuFsp1% znf0L*@9gwiapszjlrD84tiqh#Om2QURs|h!t`B#vemuGeXFHr>7i_q7?J8lz#=yo+ z8-xw3*ES1**4A~agc|}uxNR2t3G{3m;9P%hR8>{~+M5Hd!DgXh^@a_B8&?bdW}zI_ zY39sX_`hNOs#$?hXv3^CWEwJa714L;$~S0a|0(~9;Ez{lS|k$De;B~x1GQk=VcN|Jyq9)n(vD%)s{dQ9)~h?uw)zLH)qBrr^#WBt-s+ua zTm5|KUn|RcIXT2yE&f)kPW2~eTYV6%CVF@DkZ@~*UYgLAyU*lwf$s27?yj2`o3bd^ zY}r(|3+Dp8i{8}}W-TwMpb@Ui9p-30>q8V%IFW+J8H_=O1qRrm005Xqq7A ziFbRrC|C9sbdA;Z<*_S#oaTSSPRXz{RmLa}j;5uVAAc=cS=dnTE4q}O6n~Jat7lfB zQu6!M-I&UbN7 z@DVln?<0D$z0F085Rq0wyPHd#7%Q*mQ1=bYeHt?3Lhm*$ zJ~3aK3fux5UO!?ckQ~%g#`M%8O^9Y@$2vs2M}-b=ei4n&SMJbX1~X;p)ESw{r1_y| z2c41|V|^rTif6Ew)4Fl&L|RXeMqj`loj{x>-)vv8z4oX7c!omwnxu^EvpCFVq**NH z%>G$(X5THeP@;D~wAi6Cx9l$B7d<&f{`1y()#Nr~J)UhX^W3BTM)re0} z_!(TZxp)}yEtAY}s$!>{M4t&(DFJ!=1vL1fa<@FUs9N6Rw%Rb%zjQwsa|q!U&2kTmbW+10~G0?TpE30?dTEh-@|Um zg7-j)qgXGBa#JTnnjPJqZ;sQfpMr%Au;pR+Z@03{Ox^xX^Yh8Uxr?=1P7i zPFH>|-RFJz{DGVYrF{Ez`HH+>(oNEceYtr#*HJiG;e;+x=i%bkcvf5&m8JEP&Fhl= zj^B9x@P4ynLZsWX`8WxEgNTR0;)}&I>P53L%EA8#6BQs5+r?sCl$eEC(MLJ9Z`odm z#hKUZgk}_salwag5v$8NdH6#YV%2K;Cf3<{xl+^YLVqDf`&XQkvX2$`Ce(#nh!b<8 za^8>qS^iv~xI=D4>@&-6QD_=^F6j_`3eWV%_!*was>`!26p3mif^ovi^0q3X=flLC z9K`cPeA}Gx4#Xn15Knv!jshjNRPQjG&6~&-jHVhm=n>x49HX+P_-S8@qEo){1%q7T zvyrc{`#%|>vg8s&yc-_DX{0|GX?7?<(G1Bs%F5qmRYvNYhdJKtZw(nUWL2v17Lf!8k=z< zcps_zM_$DZg;_DJO7*>>NeiT0i*r!9nmi4OIxpH+PtH|Jw~`h2Tuak*(b?0uf#nX* z_x+Ato^Ot1VFlNWsL6Gz5KJcfpjuHvb(!d z;S#Cg6g=GfdL~84<%@3gPmI(lwn72+Q4qqW{H}?Su!$-zlx#oG>vG4RB1I~(=S6A@ zT6_l;NL^y3e~~L9uCqGt7m}+l-=Jb?R};G&p41 zTLQdBVkreFx(++oNV(mj(YwZxAGyQx$0N2~h$x7YcA3OR#3^?wT*U>_UD&Ob=)?zC z+rNJuRbln2vIZhvL;MF4mRYJkIr8+% znM>T*F9)X#%`c8MLDqf<50j5PObeQ-k-BQQ*^ym!`p6G}FGEQ;RW?lrzF5mo9=Q4dXrXFpenVlLowjl@lIieK+3H`Z z#U0SAkB^JKhsjlAvQy%(soc7UX?YVbDw3y>?as{3`sgTC+!@~v-SB+?vyVTSOSHr< zT_mu-HGvH`0VDh|-?rRc)5a1Ot&sgNA2(Bh*;R`aSh+s93K{<*g!>A**%}@5o4d9U zx#r-zm8j`L_@ForhdYRl6cTM%x9a-lwQbj*ad58>t_^Oi612SL)i+ku33B zgEHqgn+xutN&ams5Uo$|UDoVq8`oW5BJSLd)w^l@WR^OH6BW*sro~~}6SOyFmomxU zW9-K&Ri$iwj9)fSEcVORgv~oCxPg{KwYJ_R^&D1z#!!P_Uush76yn47-MX+{Cz}*M zQldR<=M=x~a26k95suVx=2x)WVzJ?VX{NGHnaiIput-#T=~7O*sQz?;U8hQ z-&SyW(cuCMQY}bv72E7{^>-F<&OGFpc|*KKxzoP0V4}iLH^b9e={OzZr?Y710a$9p zYEZt-4tgaZooQp6{mudcJv$o+-|4>y{TF_x|I3QDo$Y^{eRk2E_JG8C|Ihqbz)w(F zX5Utj4Suq~PjY~tt^+q~G;T69|LUJeSdx)%D{(mUKv((acBhj+8=;a5ps%^;G;qm0 z%ycp~qDblFzm4Ej;W8mMX+&kLjenGHwR6 z)WR_X8Q#g@rDHCfqSClQX7M5PobaTuzmsjFYV!B0p2}lP`wF9Z;NpZ_6rJR!3bWEK zPxMRBz&dCC(gpH-DIe0O;QYWM&NkpHS#%(J0^H^f>Eb7pEpj?}7!ib2-*?ZIfBPQM zC6J?6CegRft+w8Da>uZ_zRN8-WtmH~!XFeMDf+rRoHY=^r$)ttsEr4=Nu8ii_1^6Z zw}|>H-nnP-U3J@iTm?DTNr%b{<-#JHysh4PNrkMBQ{uCfQ{fT&UsIeKxV;WO+(kCI zy}qnSAMc=v1(TKE!?W#So^2)GOU&R9;W(b+oD?zZJH6C(%i>#no0f9rRI*k&bAXOrP_$KHcck zp!NAY{B%H_Xpj`U}_Lpc6U0x8LCp!Mw)W84Y zX1(jwk>!qo{kmzNp{I7LD+tdv7lf-tM}BMne#?zEjRQ7ngH++43VEp;D#5vsixpLFT|6r?{lfTHISf4jBLEX*YqGUB#r`1;HCV`!*$=+z4G2 z>dkIARK^R|OI=ud_9n)qu(&}p)}G*hpe+)^1pl(8ia6q}`aB!(IbD#aZ=4x<+_ay_ z2b;sS@;%F` zZ>E-S>YV|<+T_W|cI2oXhGn z9qwj&CDKxVn`hzxZ>Sf*^gtpw7b?52HH#-hUZv|g66pOb_xXgQ_beo|o;X6O&VowtFbjhdGCKg zdGE?Ct!F6jUHN(|%{(9Dv}u&aHGgjLteGP2ocyfenhDDtQ@qR3-%iW<-aoGluX)DX zZxqd0z**dagpCb|T67_{8)DJp4c+PFuh?lT`jnjRV{5w?EBQ|9%-YgUmVP(Y0`HMw zZ)4A^$rsZ%F0GL{V82bb$$J&tJG-BkS(N=M#1}d4aKW3hHBcWA9oqv2*Xd(w@|iSO zaYCM}tCsL$C-H}|-`JkV_mwfWH$TN~^EUgNs|1{wLA@)T92&}kby(UBpJR+!lyn~_ zEk{Zkn-5)(PF_8%lU#u->oTe0VLh4NxdP>LQO-xw$zd(VazZ(%RC^DCPgjWfi?A%^ zS1eJJo6{Fyr?*JcqgH1(#`Hss)~ZSJatG~XIe}E2f3a^YDdM!F$NdxTE7I)NbsA2Y zhP2BUP|B9n=blPsGff*XuepFlTJd^CSi=et zOf7E~ZdkWoVD+V|Ec5_Qz8dX@8*w^Y+uXW(y|8}ujlm5Y*9SHR*R4Gpq(xg?4QV!$ zy-`Bn*K48NOc2-UL}x#n3caPho}k1(M$g1Xal?@KWHjX~!JQ7%JBg3oi@c+vOxC?|0ORl@d0_llgCi|@q^jZ=n|6DaY>D5BcC)Z`N?lM_AqpEM^& zVm9n9w6t}>5kFNo!oYn`7Vqy2efw7UOUR@DA9rz z+V@|C-qqwqW1vBQE#p)_0u{5JliU*|M41xbM-OW9vat+TSB+MJ2Q~Rayx%+3dwY*A zGRdu%xGqYFqXtO;50{L-x}Oum{2d<4F?P=3cCkGDE*<>uYgBeSc;ftUu2`_u^b*aN ze&G|Vb0kDkl(FPT=@XM#6vm9GMG+#E)|e27KW8CcfTyZ5e}nJzI{AV)b#>t;mk`|_ z!+SioLn&by?;}rrb5N@b-^8icu@-o;IE^OnM}wz&+k3cQOoDZ%#EB8kxsBILogOpz ztd?+6MIOJ4MLM%E=W%dJ8kd`JN)xLyJnl%xH69Vog&o%67Q=)dIE~NO_QRKokQHyo zB8D8c284)6rp4FO>>e5O^-C(BG>@HK_KqwpX7jY!v+%u4Ut3Ji5%=>IK5=e~gwbJa zSEp+*qxX$mS=V0J<+(VTcl`T)PhqELc2s}d;+h_9c2&ft#T$J#`}F8i{~^zmm_e8r zU*fYAwtHOBtmE}Qlf5KbkCObDNifFiP_sB%hqNV@jads67DTzq$x*&?R#aD67MmR> zybu!NoRApgg)i{#^|L{}@adpYI5C(d{A188d^~6oJ{+W7W{a7J_fSH+^7$QJ;yEwv znC`QT^KD5Znv5}uBbjxtP4k0VT|MgRPcVAC93|sNcOYC+d^9G?oiyylniy^!)nS)p|!?&hWh%__oq4cS7 z%&UGejy;zCWN@#TvD3_6?+xI654tEDR@DO^s%ol?Bjq(!O&nEK`PQ`B|JA6PY3;-G zn}c)E?pX2yyctcwM@sb;N#{u~;I+k}GP`U?y!pAM@Nh4$fmcPi5xq$Bax-344Pw!k z!<%lWKf;^d0B@Rk#LNrMM4ZuH;*ud2b!M?$vw(XJU3M3#_OZSjYRz1^~Qg^F3E zHD8Oah6^u}th+kIJj5#hPkne!_Y5~8sm3k^bbdsKW2VC-6}I_uc2?V?wtoFBb+#^? zZcB|?e0Vji7tikR6R)N2jz3!Q@}Myyn)ypP4GC!=O<%p7q!!+4*n_bSEMaYMOXIT3@i-$seMhiIlXX5wLg>lWB^ zBV1`1XLl30OT*?(i-dF&x-WxIYb`y-X|y8{f&$x%{D-^ztn; z>3rbia8t({#XZ<_Ps|`vd++F(B3WQxS|uvCNmKcrIrhgb^d8gr73875RaO~(H{}xs1-kX6uzo*$@DWL~) z9(MAmBxtIX*#pM|{X*I8r42O!QAK$FErMJ!yF{%{Y174auRha@;?2?{Q_K2d@X; zgvhd0}ZaSPl#ni8#Hawti}h^o^u zcc0ElMPjk8EuSy+`iqC&VK3iwlCH!QA`9zf_#HcPjP+c(5%(S+DOqn$_gXKB)Y|48 z@Fb6nCf`a!!s!ISePAPA{gk&gJD&8=K#{cSx@+hoyZc2pU+|D!rO|xoeVS6B=;G}j z-BF8#I3CuSrXh;0Y%Y8dZ>LGI+ilR#e7sSnIN~0axIs{|3-9yjV%f@ootOQ}0>o~f z$DAj6v)u=wIVUZpib-|3aUEXJW*@oBV|e%4La%+1;(o<+F~z;gM49i$yZj;>-eZ0i zgBOF>CN<-4GZTHrI-?Kw-gWtf1Ev95*v|k-~zY- zBESb|0?2?6pbgLo=mK;D_5x(kpXsv=co@L??E;+XdoS=a{r3Yu1YkTI1;ha-013bu zUQB5B3_k*J7l83p0}uf|KqKG`Zwl}bfbkawbOO2n5kNO!FQ5nTJfI(N2oMDv1=xr> z804Y38y1UQ3H;A4O^a0V)H_K)MKg8>g*2ham& zU;u6eWC3Sj0&eD?Eg?Dym|9A-7~rm+eZiay=gzB{zrf>NxJWuDBd~H+^XeOjNV^QU zLAz(T9=8wcH(nnKt;27y88-vtcLn3cTK?KiYcd6`8?N853MannGdb+6$o40RME&@f za3`^M9&n`ZHxk*A=8%8xU-v&d&P|@haXLlh=G%Y8-%kFQsfzD(pwnszna_Vo@&A|k F{{YMu0DAxc literal 0 HcmV?d00001 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/media_settings.json b/device/celestica/x86_64-cel_silverstone_v2-r0/media_settings.json new file mode 100644 index 000000000000..b14bbc45819d --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/media_settings.json @@ -0,0 +1,18024 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-32": { + "Default": { + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000084", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + } + }, + "PORT_MEDIA_SETTINGS": { + "1": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000002", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x0000008c", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x0000008c", + "lane2": "0x00000080", + "lane3": "0x00000070", + "lane4": "0x00000070", + "lane5": "0x00000070", + "lane6": "0x00000070", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xfffffffc", + "lane2": "0xfffffff0", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffe8", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x0000008c", + "lane4": "0x00000084", + "lane5": "0x0000008c", + "lane6": "0x00000084", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff6", + "lane1": "0xfffffff0", + "lane2": "0xfffffff4", + "lane3": "0xfffffff0", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff6" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000084", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xffffffec", + "lane1": "0xfffffff0", + "lane2": "0xfffffff0", + "lane3": "0xfffffff0", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000046", + "lane1": "0x00000048", + "lane2": "0x00000044", + "lane3": "0x00000044", + "lane4": "0x00000046", + "lane5": "0x00000048", + "lane6": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xfffffff0", + "lane3": "0xfffffff0", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xfffffff0", + "lane7": "0xfffffff0" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "2": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000006", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe0", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000080", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000070", + "lane2": "0x00000084", + "lane3": "0x00000088", + "lane4": "0x00000080", + "lane5": "0x00000080", + "lane6": "0x00000070", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xffffffe8", + "lane2": "0xfffffff4", + "lane3": "0xfffffff8", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000080", + "lane4": "0x0000008c", + "lane5": "0x0000006c", + "lane6": "0x00000084", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0x00000000", + "lane3": "0xfffffff4", + "lane4": "0x00000000", + "lane5": "0xfffffff8", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0xfffffffc", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xfffffff4", + "lane4": "0xfffffff8", + "lane5": "0xffffffec", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xffffffec", + "lane4": "0xfffffff0", + "lane5": "0xfffffffa", + "lane6": "0xfffffff0", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003c", + "lane1": "0x00000044", + "lane2": "0x00000046", + "lane3": "0x00000044", + "lane4": "0x0000003c", + "lane5": "0x00000044", + "lane6": "0x00000046", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff0", + "lane4": "0xfffffff0", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff0" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "3": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000002", + "lane6": "0x00000000", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x0000008c", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x0000008c", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000088", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x0000008c", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff8", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffe8", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000084", + "lane2": "0x00000088", + "lane3": "0x00000084", + "lane4": "0x00000068", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff4", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0x00000004", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xffffffec", + "lane2": "0xfffffff4", + "lane3": "0xffffffec", + "lane4": "0xfffffff8", + "lane5": "0xffffffec", + "lane6": "0xfffffff0", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff8", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003c", + "lane1": "0x00000048", + "lane2": "0x00000044", + "lane3": "0x00000044", + "lane4": "0x0000003c", + "lane5": "0x00000048", + "lane6": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff6", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xfffffff4", + "lane6": "0xfffffff6", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "4": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x0000008c", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x00000088", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000088", + "lane3": "0x00000084", + "lane4": "0x0000008c", + "lane5": "0x00000080", + "lane6": "0x00000088", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0xfffffff8", + "lane3": "0xfffffff4", + "lane4": "0xfffffffc", + "lane5": "0xfffffff0", + "lane6": "0xfffffff8", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000084", + "lane4": "0x0000007c", + "lane5": "0x00000080", + "lane6": "0x00000084", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff4", + "lane2": "0xfffffffc", + "lane3": "0xfffffff8", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff0", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xfffffff8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffff8", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000036", + "lane1": "0x00000044", + "lane2": "0x00000044", + "lane3": "0x00000040", + "lane4": "0x00000036", + "lane5": "0x00000044", + "lane6": "0x00000044", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff8", + "lane2": "0xfffffff8", + "lane3": "0xfffffff4", + "lane4": "0xfffffff4", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "5": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x0000008c", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x0000008c", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000090", + "lane2": "0x00000070", + "lane3": "0x00000070", + "lane4": "0x00000088", + "lane5": "0x00000090", + "lane6": "0x00000088", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0x00000000", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xfffffff8", + "lane5": "0x00000000", + "lane6": "0xfffffff8", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000080", + "lane2": "0x00000084", + "lane3": "0x00000084", + "lane4": "0x00000080", + "lane5": "0x0000007c", + "lane6": "0x00000084", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff4", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffff4", + "lane5": "0xfffffff8", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0x00000000", + "lane7": "0xfffffffc" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003c", + "lane1": "0x00000040", + "lane2": "0x0000003c", + "lane3": "0x00000040", + "lane4": "0x0000003c", + "lane5": "0x00000040", + "lane6": "0x0000003c", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff6", + "lane1": "0xfffffff0", + "lane2": "0xfffffff6", + "lane3": "0xfffffff8", + "lane4": "0xfffffff6", + "lane5": "0xfffffff0", + "lane6": "0xfffffff6", + "lane7": "0xfffffff8" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "6": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x0000008c", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000084", + "lane2": "0x00000070", + "lane3": "0x00000090", + "lane4": "0x0000008c", + "lane5": "0x00000080", + "lane6": "0x00000088", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff4", + "lane2": "0xffffffe8", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0xfffffff0", + "lane6": "0xfffffff8", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000080", + "lane4": "0x00000088", + "lane5": "0x00000080", + "lane6": "0x0000007c", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff8", + "lane2": "0xfffffff8", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000036", + "lane1": "0x00000044", + "lane2": "0x0000003c", + "lane3": "0x00000040", + "lane4": "0x00000036", + "lane5": "0x00000044", + "lane6": "0x0000003c", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff6", + "lane1": "0xfffffff0", + "lane2": "0xfffffff6", + "lane3": "0xfffffff8", + "lane4": "0xfffffff6", + "lane5": "0xfffffff0", + "lane6": "0xfffffff6", + "lane7": "0xfffffff8" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "7": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x0000008c", + "lane6": "0x00000090", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x0000008c", + "lane3": "0x00000090", + "lane4": "0x00000070", + "lane5": "0x00000090", + "lane6": "0x00000070", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff8", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0xffffffe8", + "lane5": "0x00000000", + "lane6": "0xffffffe8", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000084", + "lane5": "0x00000080", + "lane6": "0x00000084", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffffc", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0xfffffffc" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xfffffff8", + "lane6": "0xffffffec", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffff8", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003c", + "lane1": "0x0000003c", + "lane2": "0x0000003c", + "lane3": "0x00000038", + "lane4": "0x0000003c", + "lane5": "0x0000003c", + "lane6": "0x0000003c", + "lane7": "0x00000038" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff6", + "lane2": "0xfffffff6", + "lane3": "0xfffffff6", + "lane4": "0xfffffff4", + "lane5": "0xfffffff6", + "lane6": "0xfffffff6", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "8": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x0000008c", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x0000008c", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000084", + "lane4": "0x00000090", + "lane5": "0x00000084", + "lane6": "0x0000008c", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffff4", + "lane4": "0x00000000", + "lane5": "0xfffffff4", + "lane6": "0xfffffffc", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x0000008c", + "lane2": "0x00000080", + "lane3": "0x00000088", + "lane4": "0x00000080", + "lane5": "0x00000084", + "lane6": "0x0000007c", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0x00000000", + "lane2": "0xfffffff8", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000036", + "lane1": "0x00000042", + "lane2": "0x0000003c", + "lane3": "0x0000003c", + "lane4": "0x00000036", + "lane5": "0x00000042", + "lane6": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff6", + "lane3": "0xfffffff6", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff6", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "9": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe0", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000090", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000084", + "lane2": "0x00000070", + "lane3": "0x00000084", + "lane4": "0x00000070", + "lane5": "0x00000070", + "lane6": "0x00000084", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xfffffff4", + "lane2": "0xffffffe8", + "lane3": "0xfffffff4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000084", + "lane2": "0x00000078", + "lane3": "0x00000088", + "lane4": "0x0000008c", + "lane5": "0x0000008c", + "lane6": "0x00000070", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0x00000000", + "lane2": "0xfffffff4", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0xfffffff4", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xffffffec", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff8", + "lane5": "0xfffffff4", + "lane6": "0xfffffff8", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff0", + "lane5": "0xffffffec", + "lane6": "0xfffffff0", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x00000048", + "lane2": "0x00000040", + "lane3": "0x00000044", + "lane4": "0x00000040", + "lane5": "0x00000048", + "lane6": "0x00000040", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "10": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000002", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000090", + "lane2": "0x00000088", + "lane3": "0x0000008c", + "lane4": "0x00000088", + "lane5": "0x0000008c", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000070", + "lane2": "0x00000084", + "lane3": "0x00000088", + "lane4": "0x00000070", + "lane5": "0x00000070", + "lane6": "0x00000070", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xffffffe8", + "lane2": "0xfffffff4", + "lane3": "0xfffffff8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000078", + "lane2": "0x00000070", + "lane3": "0x00000088", + "lane4": "0x00000064", + "lane5": "0x00000088", + "lane6": "0x00000070", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0xfffffffc", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0xfffffffc" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xfffffff0", + "lane5": "0xffffffec", + "lane6": "0xfffffff8", + "lane7": "0xfffffff0" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffff0", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x00000044", + "lane2": "0x00000044", + "lane3": "0x00000046", + "lane4": "0x00000040", + "lane5": "0x00000044", + "lane6": "0x00000044", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff0", + "lane4": "0xfffffff0", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff0" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "11": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000002", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000002" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x0000008c", + "lane2": "0x00000088", + "lane3": "0x0000008c", + "lane4": "0x00000088", + "lane5": "0x00000090", + "lane6": "0x00000090", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000078", + "lane2": "0x00000084", + "lane3": "0x00000070", + "lane4": "0x00000070", + "lane5": "0x00000090", + "lane6": "0x00000070", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffec", + "lane2": "0xfffffff4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0x00000000", + "lane6": "0xffffffe8", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000084", + "lane2": "0x00000088", + "lane3": "0x00000084", + "lane4": "0x00000088", + "lane5": "0x00000080", + "lane6": "0x0000008c", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0x00000000", + "lane3": "0xfffffff8", + "lane4": "0xfffffffc", + "lane5": "0xfffffff4", + "lane6": "0xfffffffc", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xfffffff4", + "lane3": "0xffffffec", + "lane4": "0xfffffff8", + "lane5": "0xffffffec", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffff0", + "lane3": "0xfffffffa", + "lane4": "0xfffffff0", + "lane5": "0xfffffffa", + "lane6": "0xfffffff0", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000044", + "lane1": "0x00000044", + "lane2": "0x00000046", + "lane3": "0x00000040", + "lane4": "0x00000044", + "lane5": "0x00000044", + "lane6": "0x00000046", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff0", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xfffffff4", + "lane6": "0xfffffff0", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "12": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000002" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe0", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x0000008c", + "lane2": "0x0000008c", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x0000008c", + "lane6": "0x0000008c", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000090", + "lane2": "0x00000070", + "lane3": "0x00000090", + "lane4": "0x00000070", + "lane5": "0x00000090", + "lane6": "0x00000084", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0x00000000", + "lane2": "0xffffffe8", + "lane3": "0x00000000", + "lane4": "0xffffffe8", + "lane5": "0x00000000", + "lane6": "0xfffffff4", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffe8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000080", + "lane3": "0x00000080", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffff0", + "lane4": "0xfffffffc", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xffffffec", + "lane6": "0xfffffff0", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xffffffec", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xffffffec" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x00000044", + "lane2": "0x0000003a", + "lane3": "0x0000003c", + "lane4": "0x00000040", + "lane5": "0x00000044", + "lane6": "0x0000003a", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff0", + "lane2": "0xfffffff6", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xfffffff6", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "13": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x00000090", + "lane7": "0x00000094" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000084", + "lane5": "0x00000090", + "lane6": "0x0000008c", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0xfffffff4", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000008", + "lane6": "0x00000008", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffe4", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe0", + "lane6": "0xffffffe0", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000064", + "lane1": "0x00000084", + "lane2": "0x00000074", + "lane3": "0x00000084", + "lane4": "0x00000084", + "lane5": "0x00000078", + "lane6": "0x00000074", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0xfffffff0", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003c", + "lane1": "0x0000003a", + "lane2": "0x00000036", + "lane3": "0x0000003a", + "lane4": "0x0000003c", + "lane5": "0x0000003a", + "lane6": "0x00000036", + "lane7": "0x0000003a" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff6", + "lane2": "0xfffffff8", + "lane3": "0xfffffff6", + "lane4": "0xfffffff8", + "lane5": "0xfffffff6", + "lane6": "0xfffffff8", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "14": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x0000008c", + "lane4": "0x0000008c", + "lane5": "0x00000090", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x0000008c", + "lane2": "0x00000088", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000084", + "lane6": "0x0000008c", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffff8", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0xfffffff4", + "lane6": "0xfffffffc", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000008", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000008", + "lane5": "0x00000004", + "lane6": "0x00000008", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe0", + "lane1": "0xffffffe4", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe0", + "lane5": "0xffffffe0", + "lane6": "0xffffffe0", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000078", + "lane2": "0x00000064", + "lane3": "0x00000084", + "lane4": "0x00000070", + "lane5": "0x00000084", + "lane6": "0x00000080", + "lane7": "0x00000064" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff4", + "lane2": "0xfffffff8", + "lane3": "0x00000000", + "lane4": "0xfffffff8", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000032", + "lane1": "0x00000040", + "lane2": "0x00000034", + "lane3": "0x00000032", + "lane4": "0x00000032", + "lane5": "0x00000040", + "lane6": "0x00000034", + "lane7": "0x00000032" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffff8", + "lane2": "0xfffffff8", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "15": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffe8", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000094", + "lane1": "0x00000090", + "lane2": "0x00000094", + "lane3": "0x00000094", + "lane4": "0x00000090", + "lane5": "0x00000094", + "lane6": "0x00000094", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x0000008c", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000084", + "lane6": "0x00000090", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0xfffffff4", + "lane6": "0x00000000", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000008" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffec", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe0", + "lane6": "0xffffffe4", + "lane7": "0xffffffe0" + }, + "main": { + "lane0": "0x00000068", + "lane1": "0x00000080", + "lane2": "0x00000080", + "lane3": "0x00000078", + "lane4": "0x00000060", + "lane5": "0x00000080", + "lane6": "0x00000078", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000032", + "lane1": "0x00000034", + "lane2": "0x00000030", + "lane3": "0x00000032", + "lane4": "0x00000032", + "lane5": "0x00000034", + "lane6": "0x00000030", + "lane7": "0x00000032" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "16": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffec", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000080", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x00000094", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x0000008c", + "lane2": "0x00000090", + "lane3": "0x0000008c", + "lane4": "0x00000090", + "lane5": "0x0000008c", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000008", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000008", + "lane6": "0x00000004", + "lane7": "0x00000008" + }, + "pre1": { + "lane0": "0xffffffe0", + "lane1": "0xffffffec", + "lane2": "0xffffffe0", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe0", + "lane6": "0xffffffe8", + "lane7": "0xffffffe0" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000064", + "lane2": "0x00000074", + "lane3": "0x00000084", + "lane4": "0x00000088", + "lane5": "0x0000007c", + "lane6": "0x00000068", + "lane7": "0x00000074" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000030", + "lane1": "0x00000032", + "lane2": "0x0000002c", + "lane3": "0x0000002c", + "lane4": "0x00000030", + "lane5": "0x00000032", + "lane6": "0x0000002c", + "lane7": "0x0000002c" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "17": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffe8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000094", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000094", + "lane6": "0x00000090", + "lane7": "0x00000094" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x0000008c", + "lane4": "0x00000090", + "lane5": "0x0000008c", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000008", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000008", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe0", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe0", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000080", + "lane2": "0x00000074", + "lane3": "0x00000080", + "lane4": "0x0000007c", + "lane5": "0x00000080", + "lane6": "0x00000074", + "lane7": "0x00000064" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0xfffffff8", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0xfffffffc", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000036", + "lane1": "0x00000032", + "lane2": "0x00000030", + "lane3": "0x00000030", + "lane4": "0x00000036", + "lane5": "0x00000032", + "lane6": "0x00000030", + "lane7": "0x00000030" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "18": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffe8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000094", + "lane6": "0x00000090", + "lane7": "0x00000094" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x00000090", + "lane4": "0x0000008c", + "lane5": "0x00000090", + "lane6": "0x00000084", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0xfffffff4", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000008", + "lane1": "0x00000004", + "lane2": "0x00000008", + "lane3": "0x00000008", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000008" + }, + "pre1": { + "lane0": "0xffffffe0", + "lane1": "0xffffffe8", + "lane2": "0xffffffe0", + "lane3": "0xffffffe0", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe0" + }, + "main": { + "lane0": "0x00000078", + "lane1": "0x00000078", + "lane2": "0x00000074", + "lane3": "0x00000078", + "lane4": "0x00000080", + "lane5": "0x00000070", + "lane6": "0x00000080", + "lane7": "0x00000078" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000030", + "lane1": "0x00000036", + "lane2": "0x00000032", + "lane3": "0x00000032", + "lane4": "0x00000030", + "lane5": "0x00000036", + "lane6": "0x00000032", + "lane7": "0x00000032" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "19": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000084", + "lane4": "0x00000090", + "lane5": "0x00000088", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffff4", + "lane4": "0x00000000", + "lane5": "0xfffffff8", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000088", + "lane2": "0x00000084", + "lane3": "0x00000088", + "lane4": "0x0000008c", + "lane5": "0x0000008c", + "lane6": "0x00000088", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff8", + "lane2": "0xfffffff8", + "lane3": "0xfffffff8", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0xfffffffc", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000036", + "lane1": "0x00000038", + "lane2": "0x00000032", + "lane3": "0x00000032", + "lane4": "0x00000036", + "lane5": "0x00000038", + "lane6": "0x00000032", + "lane7": "0x00000032" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "20": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x00000090", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000084", + "lane2": "0x00000070", + "lane3": "0x00000084", + "lane4": "0x0000008c", + "lane5": "0x00000090", + "lane6": "0x00000080", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff4", + "lane2": "0xffffffe8", + "lane3": "0xfffffff4", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0xfffffff0", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000084", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0xfffffffc", + "lane2": "0x00000004", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003a", + "lane1": "0x0000003a", + "lane2": "0x00000034", + "lane3": "0x00000036", + "lane4": "0x0000003a", + "lane5": "0x0000003a", + "lane6": "0x00000034", + "lane7": "0x00000036" + }, + "post1": { + "lane0": "0xfffffff6", + "lane1": "0xfffffff6", + "lane2": "0xfffffff8", + "lane3": "0xfffffffc", + "lane4": "0xfffffff6", + "lane5": "0xfffffff6", + "lane6": "0xfffffff8", + "lane7": "0xfffffffc" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x00000044", + "lane4": "0x00000044", + "lane1": "0x00000044", + "lane5": "0x00000044", + "lane2": "0x00000044", + "lane6": "0x00000044", + "lane3": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff8", + "lane4": "0xfffffff8", + "lane1": "0xfffffff8", + "lane5": "0xfffffff8", + "lane2": "0xfffffff8", + "lane6": "0xfffffff8", + "lane3": "0xfffffff8", + "lane7": "0xfffffff8" + } + } + }, + "21": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000006", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe0", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x0000008c", + "lane2": "0x00000088", + "lane3": "0x00000090", + "lane4": "0x00000088", + "lane5": "0x00000080", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000088", + "lane2": "0x00000084", + "lane3": "0x00000084", + "lane4": "0x00000070", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff8", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffe8", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000088", + "lane2": "0x0000008c", + "lane3": "0x00000080", + "lane4": "0x0000008c", + "lane5": "0x0000008c", + "lane6": "0x00000084", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffff8", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffff8", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff8", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffff8", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000048", + "lane1": "0x00000044", + "lane2": "0x00000044", + "lane3": "0x00000040", + "lane4": "0x00000048", + "lane5": "0x00000044", + "lane6": "0x00000044", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff0", + "lane2": "0xfffffff4", + "lane3": "0xfffffff6", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xfffffff4", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "22": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000002", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x0000008c", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000070", + "lane4": "0x00000084", + "lane5": "0x00000088", + "lane6": "0x00000084", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xffffffe8", + "lane4": "0xfffffff4", + "lane5": "0xfffffff8", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000084", + "lane2": "0x0000008c", + "lane3": "0x0000008c", + "lane4": "0x0000007c", + "lane5": "0x00000080", + "lane6": "0x0000007c", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffff8", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffffc", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xffffffec", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff8", + "lane5": "0xfffffff4", + "lane6": "0xfffffff0", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffffa", + "lane2": "0xfffffff0", + "lane3": "0xffffffec", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xfffffffa", + "lane7": "0xffffffec" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000044", + "lane1": "0x00000044", + "lane2": "0x00000042", + "lane3": "0x00000044", + "lane4": "0x00000044", + "lane5": "0x00000044", + "lane6": "0x00000042", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff0", + "lane2": "0xfffffff0", + "lane3": "0xfffffff0", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xfffffff0", + "lane7": "0xfffffff0" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "23": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000002", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x0000008c", + "lane2": "0x00000088", + "lane3": "0x0000008c", + "lane4": "0x00000088", + "lane5": "0x0000008c", + "lane6": "0x00000088", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000070", + "lane4": "0x00000084", + "lane5": "0x00000070", + "lane6": "0x00000084", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xffffffe8", + "lane4": "0xfffffff4", + "lane5": "0xffffffe8", + "lane6": "0xfffffff4", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffe8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000080", + "lane2": "0x0000007c", + "lane3": "0x00000084", + "lane4": "0x00000080", + "lane5": "0x0000007c", + "lane6": "0x00000080", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff8", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffff8", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff8", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xfffffff0", + "lane5": "0xffffffec", + "lane6": "0xfffffff0", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000048", + "lane1": "0x00000042", + "lane2": "0x00000044", + "lane3": "0x00000044", + "lane4": "0x00000048", + "lane5": "0x00000042", + "lane6": "0x00000044", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xffffffec", + "lane1": "0xfffffff6", + "lane2": "0xfffffff4", + "lane3": "0xfffffff6", + "lane4": "0xffffffec", + "lane5": "0xfffffff6", + "lane6": "0xfffffff4", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "24": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000002", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x0000008c", + "lane2": "0x0000008c", + "lane3": "0x0000008c", + "lane4": "0x0000008c", + "lane5": "0x00000088", + "lane6": "0x0000008c", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000090", + "lane2": "0x00000070", + "lane3": "0x00000070", + "lane4": "0x00000070", + "lane5": "0x00000084", + "lane6": "0x00000070", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0x00000000", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xfffffff4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffe8", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000074", + "lane1": "0x00000088", + "lane2": "0x00000090", + "lane3": "0x00000088", + "lane4": "0x00000084", + "lane5": "0x0000008c", + "lane6": "0x00000084", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffffc", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffff4", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0xfffffffc" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xfffffff0", + "lane7": "0xffffffec" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x00000048", + "lane2": "0x00000040", + "lane3": "0x00000044", + "lane4": "0x00000040", + "lane5": "0x00000048", + "lane6": "0x00000040", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff4", + "lane2": "0xfffffff6", + "lane3": "0xfffffff4", + "lane4": "0xfffffff0", + "lane5": "0xfffffff4", + "lane6": "0xfffffff6", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "25": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x0000008c", + "lane2": "0x0000008c", + "lane3": "0x0000008c", + "lane4": "0x0000008c", + "lane5": "0x00000090", + "lane6": "0x0000008c", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x00000070", + "lane4": "0x0000008c", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0xffffffe8", + "lane4": "0xfffffffc", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000084", + "lane2": "0x00000088", + "lane3": "0x00000084", + "lane4": "0x00000088", + "lane5": "0x00000084", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff8", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xfffffff8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffff8", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000042", + "lane1": "0x0000003c", + "lane2": "0x00000042", + "lane3": "0x0000003a", + "lane4": "0x00000042", + "lane5": "0x0000003c", + "lane6": "0x00000042", + "lane7": "0x0000003a" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff8", + "lane3": "0xfffffff6", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff8", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "26": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x0000008c", + "lane2": "0x0000008c", + "lane3": "0x00000090", + "lane4": "0x00000090", + "lane5": "0x00000090", + "lane6": "0x0000008c", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000090", + "lane2": "0x00000070", + "lane3": "0x00000090", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x00000088", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0x00000000", + "lane2": "0xffffffe8", + "lane3": "0x00000000", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff8", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffe8", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000088", + "lane2": "0x00000084", + "lane3": "0x0000008c", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff8", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xfffffff8", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffff8", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000044", + "lane1": "0x00000042", + "lane2": "0x00000038", + "lane3": "0x0000003c", + "lane4": "0x00000044", + "lane5": "0x00000042", + "lane6": "0x00000038", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff6", + "lane2": "0xfffffff6", + "lane3": "0xfffffff8", + "lane4": "0xfffffff0", + "lane5": "0xfffffff6", + "lane6": "0xfffffff6", + "lane7": "0xfffffff8" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "27": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000090", + "lane2": "0x0000008c", + "lane3": "0x00000090", + "lane4": "0x00000088", + "lane5": "0x0000008c", + "lane6": "0x0000008c", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x0000008c", + "lane2": "0x00000070", + "lane3": "0x00000070", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000084", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffffc", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffe8", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000080", + "lane2": "0x00000074", + "lane3": "0x00000088", + "lane4": "0x0000008c", + "lane5": "0x00000088", + "lane6": "0x00000080", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff8", + "lane2": "0xfffffff4", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0xfffffff8", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0xfffffffc", + "lane1": "0x00000004", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0xfffffffc", + "lane6": "0x00000004", + "lane7": "0x00000004" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xfffffff8", + "lane6": "0xffffffec", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffff8", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x00000044", + "lane2": "0x00000040", + "lane3": "0x00000040", + "lane4": "0x00000040", + "lane5": "0x00000044", + "lane6": "0x00000040", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff0", + "lane2": "0xfffffff8", + "lane3": "0xfffffff8", + "lane4": "0xfffffff4", + "lane5": "0xfffffff0", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "28": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000090", + "lane1": "0x00000090", + "lane2": "0x00000090", + "lane3": "0x0000008c", + "lane4": "0x0000008c", + "lane5": "0x00000090", + "lane6": "0x00000090", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000070", + "lane2": "0x00000070", + "lane3": "0x00000070", + "lane4": "0x00000084", + "lane5": "0x00000070", + "lane6": "0x00000088", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xfffffff4", + "lane5": "0xffffffe8", + "lane6": "0xfffffff8", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000084", + "lane2": "0x00000080", + "lane3": "0x00000080", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x00000080", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff8", + "lane2": "0xfffffff4", + "lane3": "0xfffffff8", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffff4", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffffa", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x0000003e", + "lane1": "0x00000044", + "lane2": "0x00000040", + "lane3": "0x0000003c", + "lane4": "0x0000003e", + "lane5": "0x00000044", + "lane6": "0x00000040", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffff6", + "lane1": "0xfffffff8", + "lane2": "0xfffffff8", + "lane3": "0xfffffff8", + "lane4": "0xfffffff6", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "29": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000006", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe0", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe8", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000090", + "lane2": "0x00000080", + "lane3": "0x0000008c", + "lane4": "0x00000088", + "lane5": "0x00000090", + "lane6": "0x00000088", + "lane7": "0x00000090" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000080", + "lane2": "0x0000008c", + "lane3": "0x00000088", + "lane4": "0x0000008c", + "lane5": "0x00000080", + "lane6": "0x00000088", + "lane7": "0x00000070" + }, + "post1": { + "lane0": "0xfffffff8", + "lane1": "0xfffffff0", + "lane2": "0xfffffffc", + "lane3": "0xfffffff8", + "lane4": "0xfffffffc", + "lane5": "0xfffffff0", + "lane6": "0xfffffff8", + "lane7": "0xffffffe8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000080", + "lane2": "0x00000080", + "lane3": "0x0000007c", + "lane4": "0x00000070", + "lane5": "0x0000008c", + "lane6": "0x00000088", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff8", + "lane2": "0xfffffffc", + "lane3": "0xfffffff8", + "lane4": "0xfffffff8", + "lane5": "0x00000000", + "lane6": "0xfffffffc", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0xfffffffc", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xffffffec", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffff0", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffffa", + "lane7": "0xfffffff8" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000044", + "lane1": "0x00000040", + "lane2": "0x0000003c", + "lane3": "0x00000040", + "lane4": "0x00000044", + "lane5": "0x00000040", + "lane6": "0x0000003c", + "lane7": "0x00000040" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff8", + "lane2": "0xfffffff4", + "lane3": "0xfffffff8", + "lane4": "0xfffffff0", + "lane5": "0xfffffff8", + "lane6": "0xfffffff4", + "lane7": "0xfffffff8" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "30": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000000", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe0", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x0000008c", + "lane1": "0x00000088", + "lane2": "0x0000008c", + "lane3": "0x00000084", + "lane4": "0x00000090", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000090", + "lane2": "0x00000070", + "lane3": "0x0000008c", + "lane4": "0x00000084", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000084" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0x00000000", + "lane2": "0xffffffe8", + "lane3": "0xfffffffc", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000080", + "lane1": "0x00000088", + "lane2": "0x00000084", + "lane3": "0x00000088", + "lane4": "0x00000080", + "lane5": "0x00000088", + "lane6": "0x0000008c", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0x00000000", + "lane2": "0xfffffff8", + "lane3": "0x00000000", + "lane4": "0xfffffff4", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0x00000004", + "lane5": "0x00000000", + "lane6": "0x00000004", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xffffffec", + "lane4": "0xfffffff8", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xfffffff0" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffffa", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff0", + "lane5": "0xfffffffa", + "lane6": "0xfffffffa", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x00000044", + "lane2": "0x00000040", + "lane3": "0x00000044", + "lane4": "0x00000040", + "lane5": "0x00000044", + "lane6": "0x00000040", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff4", + "lane2": "0xfffffff4", + "lane3": "0xfffffff4", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x00000046", + "lane4": "0x00000046", + "lane1": "0x00000046", + "lane5": "0x00000046", + "lane2": "0x00000046", + "lane6": "0x00000046", + "lane3": "0x00000046", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff4", + "lane4": "0xfffffff4", + "lane1": "0xfffffff4", + "lane5": "0xfffffff4", + "lane2": "0xfffffff4", + "lane6": "0xfffffff4", + "lane3": "0xfffffff4", + "lane7": "0xfffffff4" + } + } + }, + "31": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000002", + "lane1": "0x00000002", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000002", + "lane6": "0x00000004", + "lane7": "0x00000002" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x0000008c", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe8", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000070", + "lane2": "0x00000070", + "lane3": "0x00000070", + "lane4": "0x00000084", + "lane5": "0x00000070", + "lane6": "0x00000080", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0xfffffff4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe8", + "lane3": "0xffffffe8", + "lane4": "0xfffffff4", + "lane5": "0xffffffe8", + "lane6": "0xfffffff0", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe8", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffe8", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000078", + "lane2": "0x00000080", + "lane3": "0x00000084", + "lane4": "0x00000080", + "lane5": "0x00000078", + "lane6": "0x0000007c", + "lane7": "0x00000080" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0xfffffff4", + "lane2": "0xfffffffc", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0xfffffff0", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff8", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xfffffff8", + "lane5": "0xfffffff8", + "lane6": "0xfffffff8", + "lane7": "0xfffffff8" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffffa", + "lane2": "0xfffffffa", + "lane3": "0xfffffffa", + "lane4": "0xfffffff0", + "lane5": "0xfffffff0", + "lane6": "0xfffffff0", + "lane7": "0xfffffff0" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000048", + "lane1": "0x00000046", + "lane2": "0x00000040", + "lane3": "0x00000044", + "lane4": "0x00000048", + "lane5": "0x00000046", + "lane6": "0x00000040", + "lane7": "0x00000044" + }, + "post1": { + "lane0": "0xffffffec", + "lane1": "0xfffffff4", + "lane2": "0xfffffff0", + "lane3": "0xfffffff6", + "lane4": "0xffffffec", + "lane5": "0xfffffff4", + "lane6": "0xfffffff0", + "lane7": "0xfffffff6" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + }, + "32": { + "50000-copper-1.0M": { + "pre2": { + "lane0": "0x00000002", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000002", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe4", + "lane2": "0xffffffe4", + "lane3": "0xffffffe4", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe4", + "lane7": "0xffffffe4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000088", + "lane2": "0x00000088", + "lane3": "0x00000088", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-2.0M": { + "pre2": { + "lane0": "0x00000004", + "lane1": "0x00000000", + "lane2": "0x00000004", + "lane3": "0x00000000", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xffffffe4", + "lane1": "0xffffffe8", + "lane2": "0xffffffe4", + "lane3": "0xffffffe8", + "lane4": "0xffffffe4", + "lane5": "0xffffffe4", + "lane6": "0xffffffe8", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000070", + "lane1": "0x00000080", + "lane2": "0x00000070", + "lane3": "0x00000090", + "lane4": "0x00000070", + "lane5": "0x00000070", + "lane6": "0x00000080", + "lane7": "0x0000008c" + }, + "post1": { + "lane0": "0xffffffe8", + "lane1": "0xfffffff0", + "lane2": "0xffffffe8", + "lane3": "0x00000000", + "lane4": "0xffffffe8", + "lane5": "0xffffffe8", + "lane6": "0xfffffff0", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-copper-3.0M": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0x00000004", + "lane3": "0x00000004", + "lane4": "0x00000004", + "lane5": "0x00000004", + "lane6": "0x00000004", + "lane7": "0x00000004" + }, + "pre1": { + "lane0": "0xffffffec", + "lane1": "0xffffffec", + "lane2": "0xffffffec", + "lane3": "0xffffffec", + "lane4": "0xffffffec", + "lane5": "0xffffffe8", + "lane6": "0xffffffec", + "lane7": "0xffffffe8" + }, + "main": { + "lane0": "0x00000084", + "lane1": "0x00000080", + "lane2": "0x00000084", + "lane3": "0x00000088", + "lane4": "0x00000080", + "lane5": "0x00000084", + "lane6": "0x00000084", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0x00000000", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0xfffffffc" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000004", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "50000-optical": { + "pre2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + }, + "pre1": { + "lane0": "0xfffffff4", + "lane1": "0xfffffff0", + "lane2": "0xfffffff0", + "lane3": "0xffffffec", + "lane4": "0xfffffff4", + "lane5": "0xfffffff4", + "lane6": "0xfffffff4", + "lane7": "0xfffffff4" + }, + "main": { + "lane0": "0x00000088", + "lane1": "0x00000084", + "lane2": "0x00000084", + "lane3": "0x00000084", + "lane4": "0x00000088", + "lane5": "0x00000088", + "lane6": "0x00000088", + "lane7": "0x00000088" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xfffffff0", + "lane2": "0xfffffff0", + "lane3": "0xfffffff4", + "lane4": "0xffffffec", + "lane5": "0xffffffec", + "lane6": "0xffffffec", + "lane7": "0xffffffec" + }, + "post2": { + "lane0": "0x00000000", + "lane1": "0x00000000", + "lane2": "0x00000000", + "lane3": "0x00000000", + "lane4": "0x00000000", + "lane5": "0x00000000", + "lane6": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-1.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-2.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-3.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-copper-5.0M": { + "pre1": { + "lane0": "0xffffffec", + "lane4": "0xffffffec", + "lane1": "0xffffffec", + "lane5": "0xffffffec", + "lane2": "0xffffffec", + "lane6": "0xffffffec", + "lane3": "0xffffffec", + "lane7": "0xffffffec" + }, + "main": { + "lane0": "0x00000069", + "lane4": "0x00000069", + "lane1": "0x00000069", + "lane5": "0x00000069", + "lane2": "0x00000069", + "lane6": "0x00000069", + "lane3": "0x00000069", + "lane7": "0x00000069" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "25000-optical": { + "pre1": { + "lane0": "0xfffffffc", + "lane1": "0xfffffffc", + "lane2": "0xfffffffc", + "lane3": "0xfffffffc", + "lane4": "0xfffffffc", + "lane5": "0xfffffffc", + "lane6": "0xfffffffc", + "lane7": "0xfffffffc" + }, + "main": { + "lane0": "0x00000040", + "lane1": "0x0000004e", + "lane2": "0x00000044", + "lane3": "0x00000046", + "lane4": "0x00000040", + "lane5": "0x0000004e", + "lane6": "0x00000044", + "lane7": "0x00000046" + }, + "post1": { + "lane0": "0xfffffff0", + "lane1": "0xffffffec", + "lane2": "0xfffffff4", + "lane3": "0xfffffff0", + "lane4": "0xfffffff0", + "lane5": "0xffffffec", + "lane6": "0xfffffff4", + "lane7": "0xfffffff0" + } + }, + "10000-copper-1.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-2.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000001e", + "lane4": "0x0000001e", + "lane1": "0x0000001e", + "lane5": "0x0000001e", + "lane2": "0x0000001e", + "lane6": "0x0000001e", + "lane3": "0x0000001e", + "lane7": "0x0000001e" + }, + "post1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + } + }, + "10000-copper-3.0M": { + "pre1": { + "lane0": "0x00000000", + "lane4": "0x00000000", + "lane1": "0x00000000", + "lane5": "0x00000000", + "lane2": "0x00000000", + "lane6": "0x00000000", + "lane3": "0x00000000", + "lane7": "0x00000000" + }, + "main": { + "lane0": "0x0000003c", + "lane4": "0x0000003c", + "lane1": "0x0000003c", + "lane5": "0x0000003c", + "lane2": "0x0000003c", + "lane6": "0x0000003c", + "lane3": "0x0000003c", + "lane7": "0x0000003c" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-5.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-copper-7.0M": { + "pre1": { + "lane0": "0xfffffffa", + "lane4": "0xfffffffa", + "lane1": "0xfffffffa", + "lane5": "0xfffffffa", + "lane2": "0xfffffffa", + "lane6": "0xfffffffa", + "lane3": "0xfffffffa", + "lane7": "0xfffffffa" + }, + "main": { + "lane0": "0x00000057", + "lane4": "0x00000057", + "lane1": "0x00000057", + "lane5": "0x00000057", + "lane2": "0x00000057", + "lane6": "0x00000057", + "lane3": "0x00000057", + "lane7": "0x00000057" + }, + "post1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + } + }, + "10000-optical": { + "pre1": { + "lane0": "0xfffffffe", + "lane4": "0xfffffffe", + "lane1": "0xfffffffe", + "lane5": "0xfffffffe", + "lane2": "0xfffffffe", + "lane6": "0xfffffffe", + "lane3": "0xfffffffe", + "lane7": "0xfffffffe" + }, + "main": { + "lane0": "0x0000004a", + "lane4": "0x0000004a", + "lane1": "0x0000004a", + "lane5": "0x0000004a", + "lane2": "0x0000004a", + "lane6": "0x0000004a", + "lane3": "0x0000004a", + "lane7": "0x0000004a" + }, + "post1": { + "lane0": "0xfffffff2", + "lane4": "0xfffffff2", + "lane1": "0xfffffff2", + "lane5": "0xfffffff2", + "lane2": "0xfffffff2", + "lane6": "0xfffffff2", + "lane3": "0xfffffff2", + "lane7": "0xfffffff2" + } + } + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/pcie.yaml b/device/celestica/x86_64-cel_silverstone_v2-r0/pcie.yaml new file mode 100644 index 000000000000..0a4fcfbb29da --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/pcie.yaml @@ -0,0 +1,35 @@ +- bus: '00' + dev: '1f' + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller (rev 05)' + +- 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: '06' + dev: '00' + fn: '0' + id: b980 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b980 (rev 11)' + +- bus: '0f' + dev: '00' + fn: '0' + id: 1533 + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)' + +- bus: '10' + dev: '00' + fn: '0' + id: 7021 + name: 'Memory controller: Xilinx Corporation Device 7021' diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pd-plugin.json b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pd-plugin.json new file mode 100644 index 000000000000..e17bdf2aee33 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pd-plugin.json @@ -0,0 +1,188 @@ +{ + "XCVR": + { + "xcvr_present": { + "i2c": + { + "valmap-QSFP-DD": {"0": true,"1": false}, + "valmap-SFP+": { "0": true, "1": false} + } + } + }, + + "PSU": + { + "name": + { + "1": "PSU 1", + "2": "PSU 2" + }, + "fan_name": + { + "1": + { + "1": "PSU 1 Fan 1" + }, + "2": + { + "1": "PSU 2 Fan 1" + } + + }, + "thermal_name": + { + "1": "PSU 1 Temp1", + "2": "PSU 2 Temp1" + }, + "psu_present": + { + "bmc": + { + "valmap": {"1":true, "0":false} + }, + "i2c": + { + "valmap": {"1":true, "0": false} + } + }, + "psu_fan_dir": + { + "bmc": + { + "valmap": {"1":"INTAKE", "0":"EXHAUST"} + }, + "i2c": + { + "valmap": + { + "TDPS-1500AB-A 6":"EXHAUST", + "SAC1500D12AA":"EXHAUST", + "TDPS-1500AB-6 B":"EXHAUST", + "TDPS-1500AB-6 D":"EXHAUST", + "TDPS-1500AB-6 E":"EXHAUST", + "SAC1500D12RA":"INTAKE", + "TDPS-1500AB-6 C":"INTAKE", + "TDPS-1500AB-7 C":"INTAKE" + } + } + }, + "psu_led_color": + { + "colmap": {"green":"green", "red":"red"} + }, + "psu_power_good": + { + "bmc": + { + "valmap": {"1":true} + }, + "i2c": + { + "valmap": {"1":true, "0": false} + } + }, + "PSU_FAN_MAX_SPEED":"29000" + }, + + "FAN": + { + "drawer_name": + { + "1": "Drawer 1", + "2": "Drawer 2", + "3": "Drawer 3", + "4": "Drawer 4", + "5": "Drawer 5", + "6": "Drawer 6", + "7": "Drawer 7" + }, + "name": + { + "1": + { + "1": "Fan 1 Front", + "2": "Fan 1 Rear" + }, + "2": + { + "1": "Fan 2 Front", + "2": "Fan 2 Rear" + }, + "3": + { + "1": "Fan 3 Front", + "2": "Fan 3 Rear" + }, + "4": + { + "1": "Fan 4 Front", + "2": "Fan 4 Rear" + }, + "5": + { + "1": "Fan 5 Front", + "2": "Fan 5 Rear" + }, + "6": + { + "1": "Fan 6 Front", + "2": "Fan 6 Rear" + }, + "7": + { + "1": "Fan 7 Front", + "2": "Fan 7 Rear" + } + }, + "direction": + { + "bmc": + { + "valmap": {"1":"INTAKE", "0":"EXHAUST"} + }, + "i2c": + { + "valmap": {"0":"INTAKE", "1":"EXHAUST"} + } + + }, + + "present": + { + "i2c": + { + "valmap": {"0":true, "1":false} + }, + "bmc": + { + "valmap": {"0":true, "1":false} + } + }, + + "FAN_MAX_RPM_SPEED": + { + "INTAKE": {"0": "32000", "1": "28000"}, + "EXHAUST": {"0": "32000", "1": "30200"} + }, + "pwm_to_duty_cycle": "lambda pwm: ((pwm*100)/255)", + "duty_cycle_to_pwm": "lambda dc: ((dc*255)/100)" + }, + + "THERMAL": + { + "NONE_BMC": + { + "temp1_high_threshold": + { + "PSU1_TEMP1": {"B2F": "116", "F2B": "116"}, + "PSU2_TEMP1": {"B2F": "116", "F2B": "116"}, + "TEMP_FB_U17": {"B2F": "56", "F2B": "N/A"}, + "TEMP_SW_U16": {"B2F": "N/A", "F2B": "59"}, + "XP0R8V_Temp": {"B2F": "125", "F2B": "125"}, + "VDD_CORE_Temp": {"B2F": "125", "F2B": "125"}, + "XP3R3V_L_Temp": {"B2F": "125", "F2B": "125"}, + "XP3R3V_R_Temp": {"B2F": "125", "F2B": "125"} + } + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-bmc b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-bmc new file mode 100644 index 000000000000..87647bff54f9 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-bmc @@ -0,0 +1,2114 @@ +{ +"PLATFORM": +{ + "num_psus": 2, + "num_fantrays": 7, + "num_fans_pertray": 2, + "num_ports": 34, + "num_temps": 14, + "num_component": 11, + "bmc_present": "True", + "pddf_dev_types": + { + "description":" - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld" + ], + "PSU": + [ + "psu_eeprom", + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl", + "fan_eeprom" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ], + "FPGAPCIE": + [ + "fpgapci" + ] + }, + "std_kos": + [ + "lpc_ich", + "i2c-dev", + "ipmi_devintf", + "ipmi_si", + "i2c_mux_pca954x", + "optoe", + "at24", + "i2c-i801" + ], + "pddf_kos": + [ + "pddf_client_module", + "pddf_cpld_module", + "pddf_cpld_driver", + "pddf_mux_module", + "pddf_led_module", + "pddf_fpgai2c_module", + "pddf_fpgai2c_driver", + "pddf_fpgapci_driver", + "pddf_fpgapci_module", + "pddf_xcvr_module", + "pddf_xcvr_driver_module" + ], + "custom_kos": + [ + "pddf_custom_fpga_algo", + "pddf_custom_wdt" + ] + }, + + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + {"dev_name":"i2c-0", "dev":"SMBUS0"}, + {"dev_name":"pcie-0", "dev":"PCIE0"} + ] + } + }, + + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"} + ] + } + }, + + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x56", "dev_type": "24c64"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "PCIE0": + { + "dev_info": {"device_type": "PCIE", "device_name": "PCIE0", "device_parent": "SYSTEM"}, + "i2c": + { + "DEVICES": + [ + {"dev": "FPGAPCIE0"} + ] + } + }, + + "FPGAPCIE0": + { + "dev_info": {"device_type": "FPGAPCIE", "device_name": "FPGAPCIE0", "device_parent": "PCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x0"}, + "dev_attr": {"vendor_id":"0x10EE", "device_id": "0x7021", "virt_bus": "0x64", "data_base_offset":"0x0", + "data_size":"0x25000", "i2c_ch_base_offset":"0x00010000", "i2c_ch_size":"0x1000", "virt_i2c_ch":"0xf"}, + "channel": + [ + {"chn":"9", "dev":"CPLD_S1"}, + {"chn":"9", "dev":"CPLD_S2"}, + {"chn":"10", "dev":"MUX1"}, + {"chn":"10", "dev":"MUX2"}, + {"chn":"10", "dev":"MUX3"}, + {"chn":"10", "dev":"MUX4"}, + {"chn":"11", "dev":"PORT33"}, + {"chn":"12", "dev":"PORT34"} + ] + } + }, + + "CPLD_S1": + { + "dev_info": {"device_type":"CPLD", "device_name":"CPLD_S1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6C", "dev_addr":"0x30", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_S2": + { + "dev_info": {"device_type":"CPLD", "device_name":"CPLD_S2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6C", "dev_addr":"0x31", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "MUX1": + { + "dev_info": {"device_type":"MUX", "device_name":"MUX1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x73", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x2", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT16"}, + {"chn":"1", "dev":"PORT13"}, + {"chn":"2", "dev":"PORT12"}, + {"chn":"3", "dev":"PORT10"}, + {"chn":"4", "dev":"PORT9"}, + {"chn":"5", "dev":"PORT14"}, + {"chn":"6", "dev":"PORT11"}, + {"chn":"7", "dev":"PORT7"} + ] + } + }, + + "MUX2": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0xa", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT20"}, + {"chn":"1", "dev":"PORT17"}, + {"chn":"2", "dev":"PORT22"}, + {"chn":"3", "dev":"PORT25"}, + {"chn":"4", "dev":"PORT19"}, + {"chn":"5", "dev":"PORT21"}, + {"chn":"6", "dev":"PORT24"}, + {"chn":"7", "dev":"PORT18"} + ] + } + }, + + "MUX3": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX3", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x71", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x12", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT3"}, + {"chn":"1", "dev":"PORT4"}, + {"chn":"2", "dev":"PORT1"}, + {"chn":"3", "dev":"PORT2"}, + {"chn":"4", "dev":"PORT8"}, + {"chn":"5", "dev":"PORT6"}, + {"chn":"6", "dev":"PORT5"}, + {"chn":"7", "dev":"PORT15"} + ] + } + }, + + "MUX4": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX4", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x70", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x1a", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT27"}, + {"chn":"1", "dev":"PORT32"}, + {"chn":"2", "dev":"PORT29"}, + {"chn":"3", "dev":"PORT31"}, + {"chn":"4", "dev":"PORT30"}, + {"chn":"5", "dev":"PORT23"}, + {"chn":"6", "dev":"PORT26"}, + {"chn":"7", "dev":"PORT28"} + ] + } + }, + + "PORT1": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT1", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"1"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT1-EEPROM" }, + {"itf":"control", "dev":"PORT1-CTRL" } + ] + } + }, + "PORT1-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT1-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": {"parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT1-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT1-CTRL", "device_parent":"MUX3", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": {"parent_bus":"0x13", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT2": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT2", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"2"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT2-EEPROM" }, + {"itf":"control", "dev":"PORT2-CTRL" } + ] + } + }, + "PORT2-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT2-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": {"parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT2-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT2-CTRL", "device_parent":"MUX3", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": {"parent_bus":"0x14", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + + "PORT3": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT3", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"3"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT3-EEPROM" }, + {"itf":"control", "dev":"PORT3-CTRL" } + ] + } + }, + "PORT3-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT3-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": {"parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT3-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT3-CTRL", "device_parent":"MUX3", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": {"parent_bus":"0x11", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT4": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT4", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"4"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT4-EEPROM" }, + {"itf":"control", "dev":"PORT4-CTRL" } + ] + } + }, + "PORT4-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT4-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": {"parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT4-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT4-CTRL", "device_parent":"MUX3", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": {"parent_bus":"0x12", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT5": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT5", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"5"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT5-EEPROM" }, + {"itf":"control", "dev":"PORT5-CTRL" } + ] + } + }, + "PORT5-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT5-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": {"parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT5-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT5-CTRL", "device_parent":"MUX3", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": {"parent_bus":"0x17", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT6": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT6", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"6"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT6-EEPROM" }, + {"itf":"control", "dev":"PORT6-CTRL" } + ] + } + }, + "PORT6-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT6-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": {"parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT6-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT6-CTRL", "device_parent":"MUX3", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": {"parent_bus":"0x16", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT7": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT7", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"7"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT7-EEPROM" }, + {"itf":"control", "dev":"PORT7-CTRL" } + ] + } + }, + "PORT7-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT7-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": {"parent_bus":"0x8", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT7-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT7-CTRL", "device_parent":"MUX1", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": {"parent_bus":"0x8", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT8": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT8", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"8"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT8-EEPROM" }, + {"itf":"control", "dev":"PORT8-CTRL" } + ] + } + }, + "PORT8-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT8-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": {"parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT8-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT8-CTRL", "device_parent":"MUX3", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": {"parent_bus":"0x15", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT9": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT9", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"9"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT9-EEPROM" }, + {"itf":"control", "dev":"PORT9-CTRL" } + ] + } + }, + "PORT9-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT9-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": {"parent_bus":"0x5", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT9-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT9-CTRL", "device_parent":"MUX1", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": {"parent_bus":"0x5", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT10": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT10", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"10"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT10-EEPROM" }, + {"itf":"control", "dev":"PORT10-CTRL" } + ] + } + }, + "PORT10-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT10-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": {"parent_bus":"0x4", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT10-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT10-CTRL", "device_parent":"MUX1", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": {"parent_bus":"0x4", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT11": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT11", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"11"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT11-EEPROM" }, + {"itf":"control", "dev":"PORT11-CTRL" } + ] + } + }, + "PORT11-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT11-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": {"parent_bus":"0x7", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT11-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT11-CTRL", "device_parent":"MUX1", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": {"parent_bus":"0x7", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT12": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT12", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"12"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT12-EEPROM" }, + {"itf":"control", "dev":"PORT12-CTRL" } + ] + } + }, + "PORT12-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT12-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": {"parent_bus":"0x3", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT12-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT12-CTRL", "device_parent":"MUX1", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": {"parent_bus":"0x3", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT13": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT13", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"13"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT13-EEPROM" }, + {"itf":"control", "dev":"PORT13-CTRL" } + ] + } + }, + "PORT13-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT13-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT13-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT13-CTRL", "device_parent":"MUX1", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT14": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT14", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"14"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT14-EEPROM" }, + {"itf":"control", "dev":"PORT14-CTRL" } + ] + } + }, + "PORT14-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT14-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT14-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT14-CTRL", "device_parent":"MUX1", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT15": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT15", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"15"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT15-EEPROM" }, + {"itf":"control", "dev":"PORT15-CTRL" } + ] + } + }, + "PORT15-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT15-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": {"parent_bus":"0x18", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT15-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT15-CTRL", "device_parent":"MUX3", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": {"parent_bus":"0x18", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT16": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT16", "device_parent":"MUX1"}, + "dev_attr": {"dev_idx":"16"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT16-EEPROM" }, + {"itf":"control", "dev":"PORT16-CTRL" } + ] + } + }, + "PORT16-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT16-EEPROM", "device_parent":"MUX1", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT16-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT16-CTRL", "device_parent":"MUX1", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT17": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT17", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"17"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT17-EEPROM" }, + {"itf":"control", "dev":"PORT17-CTRL" } + ] + } + }, + "PORT17-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT17-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": {"parent_bus":"0xa", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT17-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT17-CTRL", "device_parent":"MUX2", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": {"parent_bus":"0xa", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT18": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT18", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"18"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT18-EEPROM" }, + {"itf":"control", "dev":"PORT18-CTRL" } + ] + } + }, + "PORT18-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT18-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": {"parent_bus":"0x10", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT18-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT18-CTRL", "device_parent":"MUX2", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": {"parent_bus":"0x10", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT19": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT19", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"19"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT19-EEPROM" }, + {"itf":"control", "dev":"PORT19-CTRL" } + ] + } + }, + "PORT19-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT19-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": {"parent_bus":"0xd", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT19-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT19-CTRL", "device_parent":"MUX2", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": {"parent_bus":"0xd", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT20": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT20", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"20"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT20-EEPROM" }, + {"itf":"control", "dev":"PORT20-CTRL" } + ] + } + }, + "PORT20-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT20-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": {"parent_bus":"0x9", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT20-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT20-CTRL", "device_parent":"MUX2", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": {"parent_bus":"0x9", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT21": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT21", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"21"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT21-EEPROM" }, + {"itf":"control", "dev":"PORT21-CTRL" } + ] + } + }, + "PORT21-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT21-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": {"parent_bus":"0xe", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT21-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT21-CTRL", "device_parent":"MUX2", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": {"parent_bus":"0xe", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT22": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT22", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"22"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT22-EEPROM" }, + {"itf":"control", "dev":"PORT22-CTRL" } + ] + } + }, + "PORT22-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT22-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": {"parent_bus":"0xb", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT22-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT22-CTRL", "device_parent":"MUX2", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": {"parent_bus":"0xb", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT23": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT23", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"23"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT23-EEPROM" }, + {"itf":"control", "dev":"PORT23-CTRL" } + ] + } + }, + "PORT23-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT23-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1e", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT23-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT23-CTRL", "device_parent":"MUX4", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1e", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT24": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT24", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"24"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT24-EEPROM" }, + {"itf":"control", "dev":"PORT24-CTRL" } + ] + } + }, + "PORT24-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT24-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": {"parent_bus":"0xf", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT24-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT24-CTRL", "device_parent":"MUX2", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": {"parent_bus":"0xf", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT25": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT25", "device_parent":"MUX2"}, + "dev_attr": {"dev_idx":"25"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT25-EEPROM" }, + {"itf":"control", "dev":"PORT25-CTRL" } + ] + } + }, + "PORT25-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT25-EEPROM", "device_parent":"MUX2", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": {"parent_bus":"0xc", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT25-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT25-CTRL", "device_parent":"MUX2", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": {"parent_bus":"0xc", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT26": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT26", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"26"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT26-EEPROM" }, + {"itf":"control", "dev":"PORT26-CTRL" } + ] + } + }, + "PORT26-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT26-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1f", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT26-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT26-CTRL", "device_parent":"MUX4", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1f", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT27": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT27", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"27"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT27-EEPROM" }, + {"itf":"control", "dev":"PORT27-CTRL" } + ] + } + }, + "PORT27-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT27-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": {"parent_bus":"0x19", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT27-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT27-CTRL", "device_parent":"MUX4", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": {"parent_bus":"0x19", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT28": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT28", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"28"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT28-EEPROM" }, + {"itf":"control", "dev":"PORT28-CTRL" } + ] + } + }, + "PORT28-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT28-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": {"parent_bus":"0x20", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT28-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT28-CTRL", "device_parent":"MUX4", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": {"parent_bus":"0x20", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT29": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT29", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"29"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT29-EEPROM" }, + {"itf":"control", "dev":"PORT29-CTRL" } + ] + } + }, + "PORT29-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT29-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1b", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT29-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT29-CTRL", "device_parent":"MUX4", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1b", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT30": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT30", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"30"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT30-EEPROM" }, + {"itf":"control", "dev":"PORT30-CTRL" } + ] + } + }, + "PORT30-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT30-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1d", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + + "PORT30-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT30-CTRL", "device_parent":"MUX4", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1d", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT31": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT31", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"31"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT31-EEPROM" }, + {"itf":"control", "dev":"PORT31-CTRL" } + ] + } + }, + "PORT31-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT31-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1c", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT31-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT31-CTRL", "device_parent":"MUX4", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1c", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT32": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT32", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"32"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT32-EEPROM" }, + {"itf":"control", "dev":"PORT32-CTRL" } + ] + } + }, + "PORT32-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT32-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1a", "dev_addr":"0x50", "dev_type":"optoe3"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT32-CTRL": + { + "dev_info": {"device_type":"pci", "device_name":"PORT32-CTRL", "device_parent":"MUX4", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1a", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT33": + { + "dev_info": {"device_type":"SFP+", "device_name":"PORT33", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"dev_idx":"33"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT33-EEPROM"}, + {"itf":"control", "dev":"PORT33-CTRL"} + ] + } + }, + "PORT33-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT33-EEPROM", "device_parent":"FPGAPCIE0", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6E", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT33-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT33-CTRL", "device_parent":"FPGAPCIE0", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6E", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"}, + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x00", "attr_cmpval":"0x00", "attr_len":"1"} + ] + } + }, + + "PORT34": + { + "dev_info": {"device_type":"SFP+", "device_name":"PORT34", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"dev_idx":"34"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT34-EEPROM" }, + {"itf":"control", "dev":"PORT34-CTRL" } + ] + } + }, + "PORT34-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT34-EEPROM", "device_parent":"FPGAPCIE0", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6F", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT34-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT34-CTRL", "device_parent":"FPGAPCIE0", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6F", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + { "attr_name":"xcvr_present", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"}, + { "attr_name":"xcvr_txfault", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + { "attr_name":"xcvr_txdisable", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + { "attr_name":"xcvr_rxlos", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x00", "attr_cmpval":"0x00", "attr_len":"1"} + ] + } + }, + + "PSU1": + { + "dev_info": {"device_type":"PSU"}, + "dev_attr": {"dev_idx":"0", "num_psu_fans": "1"}, + "bmc": { + "ipmitool": { + "attr_list": + [ + {"attr_name":"psu_present", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x3A", "raw": "1", "type":"raw", "offset":"2", "mask":"0x01"}, + {"attr_name":"psu_power_good", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x3A", "type":"raw", "raw": "1", "offset":"2", "mask":"0x0F"}, + {"attr_name":"psu_model_name", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Board Part Number", "separator":": ","field_pos":"2"}, + {"attr_name":"psu_serial_num", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Board Serial", "separator":": ","field_pos":"2"}, + {"attr_name":"psu_mfr_id", "bmc_cmd":"ipmitool fru print 3", "raw": "0", "field_name":"Board Mfg", "separator":": ", "field_pos":"2"}, + {"attr_name":"psu_fan_dir", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x07", "type": "raw","raw": "1"}, + {"attr_name":"psu_p_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x30", "type": "raw", "raw": "1", "offset":"0", "multiplier":"6000000"}, + {"attr_name":"psu_v_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2E", "type": "raw", "raw":"1", "offset":"0", "multiplier":"100"}, + {"attr_name":"psu_i_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2F", "type": "raw", "raw":"1", "offset":"0", "multiplier":"500"}, + {"attr_name":"psu_p_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2A", "type": "raw", "raw": "1", "offset":"0", "multiplier":"6000000"}, + {"attr_name":"psu_v_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x28", "type": "raw", "raw":"1", "offset":"0", "multiplier":"100"}, + {"attr_name":"psu_i_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x29", "type": "raw", "raw":"1", "offset":"0", "multiplier":"500"}, + {"attr_name":"psu_fan1_speed_rpm", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2B", "type": "raw", "raw":"1", "offset":"0", "multiplier": "200"}, + {"attr_name":"psu_temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2C", "type": "raw", "raw":"1", "offset":"0", "multiplier":"1000"}, + {"attr_name":"psu_temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x2C", "type": "raw", "raw":"1", "offset":"5", "multiplier":"1"}, + {"attr_name":"psu_v_out_max", "bmc_cmd":"ipmitool raw 0x04 0x27 0x2E", "type": "raw", "raw":"1", "offset":"5", "multiplier":"100"}, + {"attr_name":"psu_v_out_min", "bmc_cmd":"ipmitool raw 0x04 0x27 0x2E", "type": "raw", "raw":"1", "offset":"2", "multiplier":"100"}, + {"attr_name":"psu_p_out_max", "bmc_cmd":"ipmitool raw 0x04 0x27 0x30", "type": "raw", "raw":"1", "offset":"1", "multiplier":"6000"} + ] + } + } + }, + + "PSU2": + { + "dev_info": {"device_type":"PSU"}, + "dev_attr": {"dev_idx":"1", "num_psu_fans": "1"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"psu_present", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x3B", "raw": "1", "type":"raw", "offset":"2", "mask":"0x01"}, + {"attr_name":"psu_power_good", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x3B", "type":"raw", "raw": "1", "offset":"2", "mask":"0x0F"}, + {"attr_name":"psu_model_name", "bmc_cmd":"ipmitool fru print 4", "raw": "0", "field_name":"Board Part Number", "separator":": ","field_pos":"2"}, + {"attr_name":"psu_serial_num", "bmc_cmd":"ipmitool fru print 4", "raw": "0", "field_name":"Board Serial", "separator":": ","field_pos":"2"}, + {"attr_name":"psu_mfr_id", "bmc_cmd":"ipmitool fru print 4", "raw": "0", "field_name":"Board Mfg", "separator":": ", "field_pos":"2"}, + {"attr_name":"psu_fan_dir", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x07", "type": "raw", "raw": "1"}, + {"attr_name":"psu_p_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x39", "type": "raw", "raw": "1", "offset":"0", "multiplier":"6000000"}, + {"attr_name":"psu_v_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x37", "type": "raw", "raw":"1", "offset":"0", "multiplier":"100"}, + {"attr_name":"psu_i_out", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x38", "type": "raw", "raw":"1", "offset":"0", "multiplier":"500"}, + {"attr_name":"psu_p_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x33", "type": "raw", "raw": "1", "offset":"0", "multiplier":"6000000"}, + {"attr_name":"psu_v_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x31", "type": "raw", "raw":"1", "offset":"0", "multiplier":"100"}, + {"attr_name":"psu_i_in", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x32", "type": "raw", "raw":"1", "offset":"0", "multiplier":"500"}, + {"attr_name":"psu_fan1_speed_rpm", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x34", "type": "raw", "raw":"1", "offset":"0", "multiplier": "200"}, + {"attr_name":"psu_temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x35", "type": "raw", "raw":"1", "offset":"0", "multiplier":"1000"}, + {"attr_name":"psu_temp1_high_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x35", "type": "raw", "raw":"1", "offset":"5", "multiplier":"1"}, + {"attr_name":"psu_v_out_max", "bmc_cmd":"ipmitool raw 0x04 0x27 0x37", "type": "raw", "raw":"1", "offset":"5", "multiplier":"100"}, + {"attr_name":"psu_v_out_min", "bmc_cmd":"ipmitool raw 0x04 0x27 0x37", "type": "raw", "raw":"1", "offset":"2", "multiplier":"100"}, + {"attr_name":"psu_p_out_max", "bmc_cmd":"ipmitool raw 0x04 0x27 0x39", "type": "raw", "raw":"1", "offset":"1", "multiplier":"6000"} + ] + } + } + }, + + "FAN-CTRL": + { + "dev_info": {"device_type":"FAN"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"fan1_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x00", "type":"raw", "raw":"1"}, + {"attr_name":"fan2_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x00", "type":"raw", "raw":"1"}, + {"attr_name":"fan3_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x01", "type":"raw", "raw":"1"}, + {"attr_name":"fan4_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x01", "type":"raw", "raw":"1"}, + {"attr_name":"fan5_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x02", "type":"raw", "raw":"1"}, + {"attr_name":"fan6_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x02", "type":"raw", "raw":"1"}, + {"attr_name":"fan7_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x03", "type":"raw", "raw":"1"}, + {"attr_name":"fan8_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x03", "type":"raw", "raw":"1"}, + {"attr_name":"fan9_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x04", "type":"raw", "raw":"1"}, + {"attr_name":"fan10_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x04", "type":"raw", "raw":"1"}, + {"attr_name":"fan11_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x05", "type":"raw", "raw":"1"}, + {"attr_name":"fan12_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x05", "type":"raw", "raw":"1"}, + {"attr_name":"fan13_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x06", "type":"raw", "raw":"1"}, + {"attr_name":"fan14_present", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x03 0x06", "type":"raw", "raw":"1"}, + {"attr_name":"fan1_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x00", "type":"raw", "raw": "1"}, + {"attr_name":"fan2_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x00", "type":"raw", "raw": "1"}, + {"attr_name":"fan3_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x01", "type":"raw", "raw": "1"}, + {"attr_name":"fan4_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x01", "type":"raw", "raw": "1"}, + {"attr_name":"fan5_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x02", "type":"raw", "raw": "1"}, + {"attr_name":"fan6_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x02", "type":"raw", "raw": "1"}, + {"attr_name":"fan7_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x03", "type":"raw", "raw": "1"}, + {"attr_name":"fan8_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x03", "type":"raw", "raw": "1"}, + {"attr_name":"fan9_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x04", "type":"raw", "raw": "1"}, + {"attr_name":"fan10_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x04", "type":"raw", "raw": "1"}, + {"attr_name":"fan11_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x05", "type":"raw", "raw": "1"}, + {"attr_name":"fan12_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x05", "type":"raw", "raw": "1"}, + {"attr_name":"fan13_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x06", "type":"raw", "raw": "1"}, + {"attr_name":"fan14_direction", "bmc_cmd":"ipmitool raw 0x3a 0x62 0x06", "type":"raw", "raw": "1"}, + {"attr_name":"fan1_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 00", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan2_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 00", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan3_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 01", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan4_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 01", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan5_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 02", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan6_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 02", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan7_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 03", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan8_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 03", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan9_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 04", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan10_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 04", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan11_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 05", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan12_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 05", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan13_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 06", "raw":"1", "type": "raw", "offset":"0", "multiplier": "150"}, + {"attr_name":"fan14_input", "bmc_cmd":"ipmitool raw 0x3a 0x26 0x04 06", "raw":"1", "type": "raw", "offset":"1", "multiplier": "150"}, + {"attr_name":"fan1_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x22", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan2_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x22", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan3_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x32", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan4_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x32", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan5_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x42", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan6_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x42", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan7_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x52", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan8_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x52", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan9_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x62", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan10_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x62", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan11_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x72", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan12_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x72", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan13_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x82", "raw":"1", "type":"mask", "mask":"0xff"}, + {"attr_name":"fan14_pwm", "bmc_cmd":"ipmitool raw 0x3a 0x64 0x02 0x01 0x82", "raw":"1", "type":"mask", "mask":"0xff"} + ] + } + } + }, + + "TEMP1": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"PSU 1 Temp2"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2D", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x2D", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP2": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"PSU 1 Temp3"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x6A", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x6A", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP3": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"PSU 2 Temp2"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x36", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x36", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP4": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"PSU 2 Temp3"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x6B", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x6B", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP5": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"CPU Internal Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x5", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x5", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP6": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"ASIC Internal Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x6", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x6", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP7": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"Fanboard Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x2", "type": "raw", "raw":"1", "offset":"0"} + ] + } + } + }, + "TEMP8": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"Switchboard Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x4", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x4", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP9": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"MP2975 3.3v Chip Right Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x68", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x68", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP10": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"MP2975 3.3v Chip Left Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x69", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x69", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP11": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"TPS536C7 Chip Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x66", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x66", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP12": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"MP2975 0.8v Chip Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x67", "type": "raw", "raw":"1", "offset":"0"}, + {"attr_name":"temp1_high_crit_threshold", "bmc_cmd":"ipmitool raw 0x04 0x27 0x67", "type": "raw", "raw":"1", "offset":"5"} + ] + } + } + }, + "TEMP13": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"Fanboard Center Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x67", "type": "raw", "raw":"1", "offset":"0"} + ] + } + } + }, + "TEMP14": + { + "dev_info": {"device_type":"TEMP_SENSOR"}, + "dev_attr": {"display_name":"Switchboard Left Temp"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"temp1_input", "bmc_cmd":"ipmitool raw 0x04 0x2D 0x3", "type": "raw", "raw":"1", "offset":"0"} + ] + } + } + }, + + "SYS_LED": + { + "dev_info": {"device_type":"LED", "device_name":"SYS_LED"}, + "dev_attr": {"index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "2"}, + {"attr_name":"amber_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "3"}, + {"attr_name":"green_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "4"}, + {"attr_name":"green_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "5"}, + {"attr_name":"amber_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "6"}, + {"attr_name":"alternate_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "7"}, + {"attr_name":"alternate_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x00", "raw": "1", "type":"raw", "value": "8"} + ] + } + } + }, + "ALARM_LED": + { + "dev_info": {"device_type":"LED", "device_name":"ALARM_LED"}, + "dev_attr": {"index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "2"}, + {"attr_name":"amber_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "3"}, + {"attr_name":"green_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "4"}, + {"attr_name":"green_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "5"}, + {"attr_name":"amber_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "6"}, + {"attr_name":"alternate_blink_1hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "7"}, + {"attr_name":"alternate_blink_4hz", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x01", "raw": "1", "type":"raw", "value": "8"} + ] + } + } + }, + "FANTRAY1_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY1_LED"}, + "dev_attr": {"index":"0", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x04", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x04", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x04", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + }, + "FANTRAY2_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY2_LED"}, + "dev_attr": {"index":"1", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x05", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x05", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x05", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + }, + "FANTRAY3_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY3_LED"}, + "dev_attr": {"index":"2", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x06", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x06", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x06", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + }, + "FANTRAY4_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY4_LED"}, + "dev_attr": {"index":"3", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x07", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x07", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x07", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + }, + "FANTRAY5_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY5_LED"}, + "dev_attr": {"index":"4", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x08", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x08", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x08", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + }, + "FANTRAY6_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY6_LED"}, + "dev_attr": {"index":"5", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x09", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x09", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x09", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + }, + "FANTRAY7_LED": + { + "dev_info": {"device_type":"LED", "device_name":"FANTRAY7_LED"}, + "dev_attr": {"index":"6", "flag": "ro"}, + "bmc": { + "ipmitool" : { + "attr_list": + [ + {"attr_name":"off", "bmc_cmd":"ipmitool raw 0x3a 0x39 0x01 0x0a", "raw": "1", "type":"raw", "value": "0"}, + {"attr_name":"green", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x0a", "raw": "1", "type":"raw", "value": "1"}, + {"attr_name":"amber", "bmc_cmd":"ipmitool raw 0x3A 0x39 0x01 0x0a", "raw": "1", "type":"raw", "value": "2"} + ] + } + } + } +} + diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-nonebmc b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-nonebmc new file mode 100644 index 000000000000..f58c32095338 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf/pddf-device.json-nonebmc @@ -0,0 +1,2058 @@ +{ +"PLATFORM": +{ + "num_psus": 2, + "num_fantrays": 7, + "num_fans_pertray": 2, + "num_ports": 34, + "num_temps": 6, + "num_component": 8, + "bmc_present": "False", + "pddf_dev_types": + { + "description":" - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", + "CPLD": + [ + "i2c_cpld", + "cpld_eeprom" + ], + "PSU": + [ + "psu_pmbus" + ], + "FAN": + [ + "fan_ctrl", + "fan_eeprom", + "fan_cpld" + ], + "PORT_MODULE": + [ + "pddf_xcvr" + ], + "FPGAPCIE": + [ + "fpgapci" + ] + }, + "std_kos": + [ + "lpc_ich", + "i2c-dev", + "ipmi_devintf", + "i2c_mux_pca954x", + "optoe", + "at24", + "i2c-i801" + ], + "pddf_kos": + [ + "pddf_client_module", + "pddf_psu_module", + "pddf_cpld_module", + "pddf_cpld_driver", + "pddf_mux_module", + "pddf_fpgai2c_module", + "pddf_fpgai2c_driver", + "pddf_fpgapci_driver", + "pddf_fpgapci_module", + "pddf_xcvr_module", + "pddf_xcvr_driver_module", + "pddf_fan_module" + ], + "custom_kos": + [ + "pddf_custom_led_module", + "pddf_custom_wdt", + "pddf_custom_fpga_algo", + "pddf_custom_fan_driver_module", + "pddf_custom_psu_driver_module", + "tps536c7" + ] + }, + + "SYSTEM": + { + "dev_info": {"device_type":"CPU", "device_name":"ROOT_COMPLEX", "device_parent":null}, + "i2c": + { + "CONTROLLERS": + [ + {"dev_name":"i2c-0", "dev":"SMBUS0"}, + {"dev_name":"pcie-0", "dev":"PCIE0"} + ] + } + }, + + "SMBUS0": + { + "dev_info": {"device_type": "SMBUS", "device_name": "SMBUS0", "device_parent": "SYSTEM"}, + "i2c": + { + "topo_info": {"dev_addr": "0x0"}, + "DEVICES": + [ + {"dev": "EEPROM1"} + ] + } + }, + + "EEPROM1": + { + "dev_info": {"device_type": "EEPROM", "device_name": "EEPROM1", "device_parent": "SMBUS0"}, + "i2c": + { + "topo_info": {"parent_bus": "0x0", "dev_addr": "0x56", "dev_type": "24c64"}, + "dev_attr": {"access_mode": "BLOCK"}, + "attr_list": [ + {"attr_name": "eeprom"} + ] + } + }, + + "PCIE0": + { + "dev_info": {"device_type": "PCIE", "device_name": "PCIE0", "device_parent": "SYSTEM"}, + "i2c": + { + "DEVICES": + [ + {"dev": "FPGAPCIE0"} + ] + } + }, + + "FPGAPCIE0": + { + "dev_info": {"device_type": "FPGAPCIE", "device_name": "FPGAPCIE0", "device_parent": "PCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x0"}, + "dev_attr": {"vendor_id":"0x10EE", "device_id": "0x7021", "virt_bus": "0x64", "data_base_offset":"0x0", + "data_size":"0x25000", "i2c_ch_base_offset":"0x00010000", "i2c_ch_size":"0x1000", "virt_i2c_ch":"0xf"}, + "channel": + [ + {"chn":"1", "dev":"CPLD_B"}, + {"chn":"3", "dev":"TEMP1"}, + {"chn":"4", "dev":"TEMP2"}, + {"chn":"4", "dev":"TEMP3"}, + {"chn":"4", "dev":"TEMP4"}, + {"chn":"5", "dev":"CPLD_COME"}, + {"chn":"6", "dev":"MUX1"}, + {"chn":"7", "dev":"TEMP5"}, + {"chn":"8", "dev":"MUX2"}, + {"chn":"8", "dev":"FAN_CPLD"}, + {"chn":"8", "dev":"FAN-CTRL"}, + {"chn":"9", "dev":"CPLD_S1"}, + {"chn":"9", "dev":"CPLD_S2"}, + {"chn":"10", "dev":"MUX3"}, + {"chn":"10", "dev":"MUX4"}, + {"chn":"10", "dev":"MUX5"}, + {"chn":"10", "dev":"MUX6"}, + {"chn":"11", "dev":"PORT33"}, + {"chn":"12", "dev":"PORT34"} + ] + } + }, + + "CPLD_B": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD_B", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x64", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_COME": + { + "dev_info": { "device_type":"CPLD", "device_name":"CPLD_COME", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x68", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "FAN_CPLD": + { + "dev_info": { "device_type":"CPLD", "device_name":"FAN_CPLD", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6B", "dev_addr":"0x0d", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_S1": + { + "dev_info": {"device_type":"CPLD", "device_name":"CPLD_S1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6C", "dev_addr":"0x30", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "CPLD_S2": + { + "dev_info": {"device_type":"CPLD", "device_name":"CPLD_S2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6C", "dev_addr":"0x31", "dev_type":"i2c_cpld"}, + "dev_attr":{} + } + }, + + "MUX1": + { + "dev_info": {"device_type":"MUX", "device_name":"MUX1", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x69", "dev_addr":"0x70", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x01", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PSU1"}, + {"chn":"1", "dev":"PSU2"} + ] + } + }, + "MUX2": + { + "dev_info": {"device_type":"MUX", "device_name":"MUX2", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6B", "dev_addr":"0x77", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x09", "idle_state": "-2"}, + "channel": + [ + {"chn":"7", "dev":"TEMP6"} + ] + } + }, + "MUX3": + { + "dev_info": {"device_type":"MUX", "device_name":"MUX3", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x73", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x11", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT16"}, + {"chn":"1", "dev":"PORT13"}, + {"chn":"2", "dev":"PORT12"}, + {"chn":"3", "dev":"PORT10"}, + {"chn":"4", "dev":"PORT9"}, + {"chn":"5", "dev":"PORT14"}, + {"chn":"6", "dev":"PORT11"}, + {"chn":"7", "dev":"PORT7"} + ] + } + }, + "MUX4": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX4", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x72", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x19", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT20"}, + {"chn":"1", "dev":"PORT17"}, + {"chn":"2", "dev":"PORT22"}, + {"chn":"3", "dev":"PORT25"}, + {"chn":"4", "dev":"PORT19"}, + {"chn":"5", "dev":"PORT21"}, + {"chn":"6", "dev":"PORT24"}, + {"chn":"7", "dev":"PORT18"} + ] + } + }, + "MUX5": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX5", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x71", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x21", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT3"}, + {"chn":"1", "dev":"PORT4"}, + {"chn":"2", "dev":"PORT1"}, + {"chn":"3", "dev":"PORT2"}, + {"chn":"4", "dev":"PORT8"}, + {"chn":"5", "dev":"PORT6"}, + {"chn":"6", "dev":"PORT5"}, + {"chn":"7", "dev":"PORT15"} + ] + } + }, + "MUX6": + { + "dev_info": { "device_type":"MUX", "device_name":"MUX6", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6D", "dev_addr":"0x70", "dev_type":"pca9548"}, + "dev_attr": {"virt_bus":"0x29", "idle_state": "-2"}, + "channel": + [ + {"chn":"0", "dev":"PORT27"}, + {"chn":"1", "dev":"PORT32"}, + {"chn":"2", "dev":"PORT29"}, + {"chn":"3", "dev":"PORT31"}, + {"chn":"4", "dev":"PORT30"}, + {"chn":"5", "dev":"PORT23"}, + {"chn":"6", "dev":"PORT26"}, + {"chn":"7", "dev":"PORT28"} + ] + } + }, + + "PORT1": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT1", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"1"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT1-EEPROM" }, + {"itf":"control", "dev":"PORT1-CTRL" } + ] + } + }, + "PORT1-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT1-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": {"parent_bus":"0x23", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT1-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT1-CTRL", "device_parent":"MUX5", "virt_parent":"PORT1"}, + "i2c": + { + "topo_info": {"parent_bus":"0x23", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x10", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT2": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT2", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"2"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT2-EEPROM" }, + {"itf":"control", "dev":"PORT2-CTRL" } + ] + } + }, + "PORT2-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT2-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": {"parent_bus":"0x24", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT2-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT2-CTRL", "device_parent":"MUX5", "virt_parent":"PORT2"}, + "i2c": + { + "topo_info": {"parent_bus":"0x24", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x11", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT3": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT3", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"3"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT3-EEPROM" }, + {"itf":"control", "dev":"PORT3-CTRL" } + ] + } + }, + "PORT3-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT3-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": {"parent_bus":"0x21", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT3-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT3-CTRL", "device_parent":"MUX5", "virt_parent":"PORT3"}, + "i2c": + { + "topo_info": {"parent_bus":"0x21", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x12", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT4": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT4", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"4"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT4-EEPROM" }, + {"itf":"control", "dev":"PORT4-CTRL" } + ] + } + }, + "PORT4-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT4-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": {"parent_bus":"0x22", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT4-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT4-CTRL", "device_parent":"MUX5", "virt_parent":"PORT4"}, + "i2c": + { + "topo_info": {"parent_bus":"0x22", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x13", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT5": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT5", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"5"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT5-EEPROM" }, + {"itf":"control", "dev":"PORT5-CTRL" } + ] + } + }, + "PORT5-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT5-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": {"parent_bus":"0x27", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT5-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT5-CTRL", "device_parent":"MUX5", "virt_parent":"PORT5"}, + "i2c": + { + "topo_info": {"parent_bus":"0x27", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x14", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT6": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT6", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"6"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT6-EEPROM" }, + {"itf":"control", "dev":"PORT6-CTRL" } + ] + } + }, + "PORT6-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT6-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": {"parent_bus":"0x26", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT6-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT6-CTRL", "device_parent":"MUX5", "virt_parent":"PORT6"}, + "i2c": + { + "topo_info": {"parent_bus":"0x26", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x15", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT7": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT7", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"7"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT7-EEPROM" }, + {"itf":"control", "dev":"PORT7-CTRL" } + ] + } + }, + "PORT7-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT7-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": {"parent_bus":"0x18", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT7-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT7-CTRL", "device_parent":"MUX3", "virt_parent":"PORT7"}, + "i2c": + { + "topo_info": {"parent_bus":"0x18", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x16", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT8": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT8", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"8"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT8-EEPROM" }, + {"itf":"control", "dev":"PORT8-CTRL" } + ] + } + }, + "PORT8-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT8-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": {"parent_bus":"0x25", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT8-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT8-CTRL", "device_parent":"MUX5", "virt_parent":"PORT8"}, + "i2c": + { + "topo_info": {"parent_bus":"0x25", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x17", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT9": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT9", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"9"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT9-EEPROM" }, + {"itf":"control", "dev":"PORT9-CTRL" } + ] + } + }, + "PORT9-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT9-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": {"parent_bus":"0x15", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT9-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT9-CTRL", "device_parent":"MUX3", "virt_parent":"PORT9"}, + "i2c": + { + "topo_info": {"parent_bus":"0x15", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x18", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT10": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT10", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"10"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT10-EEPROM" }, + {"itf":"control", "dev":"PORT10-CTRL" } + ] + } + }, + "PORT10-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT10-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": {"parent_bus":"0x14", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT10-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT10-CTRL", "device_parent":"MUX3", "virt_parent":"PORT10"}, + "i2c": + { + "topo_info": {"parent_bus":"0x14", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x19", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT11": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT11", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"11"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT11-EEPROM" }, + {"itf":"control", "dev":"PORT11-CTRL" } + ] + } + }, + "PORT11-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT11-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": {"parent_bus":"0x17", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT11-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT11-CTRL", "device_parent":"MUX3", "virt_parent":"PORT11"}, + "i2c": + { + "topo_info": {"parent_bus":"0x17", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1a", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT12": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT12", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"12"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT12-EEPROM" }, + {"itf":"control", "dev":"PORT12-CTRL" } + ] + } + }, + "PORT12-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT12-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": {"parent_bus":"0x13", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT12-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT12-CTRL", "device_parent":"MUX3", "virt_parent":"PORT12"}, + "i2c": + { + "topo_info": {"parent_bus":"0x13", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1b", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT13": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT13", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"13"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT13-EEPROM" }, + {"itf":"control", "dev":"PORT13-CTRL" } + ] + } + }, + "PORT13-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT13-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": {"parent_bus":"0x12", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT13-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT13-CTRL", "device_parent":"MUX3", "virt_parent":"PORT13"}, + "i2c": + { + "topo_info": {"parent_bus":"0x12", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1c", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT14": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT14", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"14"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT14-EEPROM" }, + {"itf":"control", "dev":"PORT14-CTRL" } + ] + } + }, + "PORT14-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT14-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": {"parent_bus":"0x16", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT14-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT14-CTRL", "device_parent":"MUX3", "virt_parent":"PORT14"}, + "i2c": + { + "topo_info": {"parent_bus":"0x16", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1d", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT15": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT15", "device_parent":"MUX5"}, + "dev_attr": {"dev_idx":"15"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT15-EEPROM" }, + {"itf":"control", "dev":"PORT15-CTRL" } + ] + } + }, + "PORT15-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT15-EEPROM", "device_parent":"MUX5", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": {"parent_bus":"0x28", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT15-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT15-CTRL", "device_parent":"MUX5", "virt_parent":"PORT15"}, + "i2c": + { + "topo_info": {"parent_bus":"0x28", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1e", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT16": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT16", "device_parent":"MUX3"}, + "dev_attr": {"dev_idx":"16"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT16-EEPROM" }, + {"itf":"control", "dev":"PORT16-CTRL" } + ] + } + }, + "PORT16-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT16-EEPROM", "device_parent":"MUX3", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": {"parent_bus":"0x11", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT16-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT16-CTRL", "device_parent":"MUX3", "virt_parent":"PORT16"}, + "i2c": + { + "topo_info": {"parent_bus":"0x11", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x30", "attr_devtype":"cpld", "attr_devname":"CPLD_S1", "attr_offset":"0x1f", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT17": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT17", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"17"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT17-EEPROM" }, + {"itf":"control", "dev":"PORT17-CTRL" } + ] + } + }, + "PORT17-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT17-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1a", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT17-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT17-CTRL", "device_parent":"MUX4", "virt_parent":"PORT17"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1a", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x10", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT18": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT18", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"18"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT18-EEPROM" }, + {"itf":"control", "dev":"PORT18-CTRL" } + ] + } + }, + "PORT18-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT18-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": {"parent_bus":"0x20", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT18-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT18-CTRL", "device_parent":"MUX4", "virt_parent":"PORT18"}, + "i2c": + { + "topo_info": {"parent_bus":"0x20", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x11", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT19": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT19", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"19"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT19-EEPROM" }, + {"itf":"control", "dev":"PORT19-CTRL" } + ] + } + }, + "PORT19-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT19-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1d", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT19-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT19-CTRL", "device_parent":"MUX4", "virt_parent":"PORT19"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1d", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x12", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT20": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT20", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"20"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT20-EEPROM" }, + {"itf":"control", "dev":"PORT20-CTRL" } + ] + } + }, + "PORT20-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT20-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": {"parent_bus":"0x19", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT20-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT20-CTRL", "device_parent":"MUX4", "virt_parent":"PORT20"}, + "i2c": + { + "topo_info": {"parent_bus":"0x19", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x13", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT21": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT21", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"21"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT21-EEPROM" }, + {"itf":"control", "dev":"PORT21-CTRL" } + ] + } + }, + "PORT21-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT21-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1e", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT21-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT21-CTRL", "device_parent":"MUX4", "virt_parent":"PORT21"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1e", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x14", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT22": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT22", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"22"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT22-EEPROM" }, + {"itf":"control", "dev":"PORT22-CTRL" } + ] + } + }, + "PORT22-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT22-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1b", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT22-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT22-CTRL", "device_parent":"MUX4", "virt_parent":"PORT22"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1b", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x15", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT23": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT23", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"23"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT23-EEPROM" }, + {"itf":"control", "dev":"PORT23-CTRL" } + ] + } + }, + "PORT23-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT23-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2e", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT23-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT23-CTRL", "device_parent":"MUX6", "virt_parent":"PORT23"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2e", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x16", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT24": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT24", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"24"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT24-EEPROM" }, + {"itf":"control", "dev":"PORT24-CTRL" } + ] + } + }, + "PORT24-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT24-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1f", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT24-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT24-CTRL", "device_parent":"MUX4", "virt_parent":"PORT24"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1f", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x17", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT25": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT25", "device_parent":"MUX4"}, + "dev_attr": {"dev_idx":"25"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT25-EEPROM" }, + {"itf":"control", "dev":"PORT25-CTRL" } + ] + } + }, + "PORT25-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT25-EEPROM", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1c", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT25-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT25-CTRL", "device_parent":"MUX4", "virt_parent":"PORT25"}, + "i2c": + { + "topo_info": {"parent_bus":"0x1c", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x18", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT26": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT26", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"26"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT26-EEPROM" }, + {"itf":"control", "dev":"PORT26-CTRL" } + ] + } + }, + "PORT26-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT26-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2f", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT26-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT26-CTRL", "device_parent":"MUX6", "virt_parent":"PORT26"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2f", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x19", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT27": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT27", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"27"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT27-EEPROM" }, + {"itf":"control", "dev":"PORT27-CTRL" } + ] + } + }, + "PORT27-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT27-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": {"parent_bus":"0x29", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT27-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT27-CTRL", "device_parent":"MUX6", "virt_parent":"PORT27"}, + "i2c": + { + "topo_info": {"parent_bus":"0x29", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1a", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT28": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT28", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"28"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT28-EEPROM" }, + {"itf":"control", "dev":"PORT28-CTRL" } + ] + } + }, + "PORT28-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT28-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": {"parent_bus":"0x30", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT28-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT28-CTRL", "device_parent":"MUX6", "virt_parent":"PORT28"}, + "i2c": + { + "topo_info": {"parent_bus":"0x30", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1b", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT29": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT29", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"29"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT29-EEPROM" }, + {"itf":"control", "dev":"PORT29-CTRL" } + ] + } + }, + "PORT29-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT29-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2b", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT29-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT29-CTRL", "device_parent":"MUX6", "virt_parent":"PORT29"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2b", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1c", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT30": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT30", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"30"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT30-EEPROM" }, + {"itf":"control", "dev":"PORT30-CTRL" } + ] + } + }, + "PORT30-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT30-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2d", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + + "PORT30-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT30-CTRL", "device_parent":"MUX6", "virt_parent":"PORT30"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2d", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1d", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT31": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT31", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"31"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT31-EEPROM" }, + {"itf":"control", "dev":"PORT31-CTRL" } + ] + } + }, + "PORT31-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT31-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2c", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT31-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT31-CTRL", "device_parent":"MUX6", "virt_parent":"PORT31"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2c", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1e", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT32": + { + "dev_info": {"device_type":"QSFP-DD", "device_name":"PORT32", "device_parent":"MUX6"}, + "dev_attr": {"dev_idx":"32"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT32-EEPROM" }, + {"itf":"control", "dev":"PORT32-CTRL" } + ] + } + }, + "PORT32-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT32-EEPROM", "device_parent":"MUX6", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2a", "dev_addr":"0x50", "dev_type":"optoe1"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT32-CTRL": + { + "dev_info": {"device_type":"pci", "device_name":"PORT32-CTRL", "device_parent":"MUX6", "virt_parent":"PORT32"}, + "i2c": + { + "topo_info": {"parent_bus":"0x2a", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x06", "attr_cmpval":"0x40", "attr_len":"1"}, + {"attr_name":"xcvr_reset", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_lpmode", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_intr_status", "attr_devaddr":"0x31", "attr_devtype":"cpld", "attr_devname":"CPLD_S2", "attr_offset":"0x1f", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"} + ] + } + }, + + "PORT33": + { + "dev_info": {"device_type":"SFP+", "device_name":"PORT33", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"dev_idx":"33"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT33-EEPROM"}, + {"itf":"control", "dev":"PORT33-CTRL"} + ] + } + }, + "PORT33-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT33-EEPROM", "device_parent":"FPGAPCIE0", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6E", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT33-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT33-CTRL", "device_parent":"FPGAPCIE0", "virt_parent":"PORT33"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6E", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"}, + {"attr_name":"xcvr_txfault", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_txdisable", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_rxlos", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x04", "attr_mask":"0x00", "attr_cmpval":"0x00", "attr_len":"1"} + ] + } + }, + "PORT34": + { + "dev_info": {"device_type":"SFP+", "device_name":"PORT34", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"dev_idx":"34"}, + "i2c": + { + "interface": + [ + {"itf":"eeprom", "dev":"PORT34-EEPROM" }, + {"itf":"control", "dev":"PORT34-CTRL" } + ] + } + }, + "PORT34-EEPROM": + { + "dev_info": {"device_type":"", "device_name":"PORT34-EEPROM", "device_parent":"FPGAPCIE0", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6F", "dev_addr":"0x50", "dev_type":"optoe2"}, + "attr_list": + [ + {"attr_name":"eeprom"} + ] + } + }, + "PORT34-CTRL": + { + "dev_info": {"device_type":"", "device_name":"PORT34-CTRL", "device_parent":"FPGAPCIE0", "virt_parent":"PORT34"}, + "i2c": + { + "topo_info": {"parent_bus":"0x6F", "dev_addr":"0x66", "dev_type":"pddf_xcvr"}, + "attr_list": + [ + {"attr_name":"xcvr_present", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x01", "attr_cmpval":"0x02", "attr_len":"1"}, + {"attr_name":"xcvr_txfault", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x02", "attr_cmpval":"0x04", "attr_len":"1"}, + {"attr_name":"xcvr_txdisable", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x03", "attr_cmpval":"0x08", "attr_len":"1"}, + {"attr_name":"xcvr_rxlos", "attr_devaddr":"0x1000", "attr_devtype":"fpgapci", "attr_devname":"FPGAPCIE0", "attr_offset":"0x08", "attr_mask":"0x00", "attr_cmpval":"0x00", "attr_len":"1"} + ] + } + }, + + "PSU1": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU1", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"1", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + {"itf":"pmbus", "dev":"PSU1-PMBUS"} + + ] + } + }, + + "PSU1-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU1-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU1"}, + "i2c": + { + "topo_info":{ "parent_bus":"0x1", "dev_addr":"0x58", "dev_type":"psu_pmbus"}, + "attr_list": + [ + {"attr_name":"psu_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x08", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_power_good", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x02", "attr_cmpval":"0x02", "attr_len":"1"}, + {"attr_name":"psu_model_name", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_serial_num", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"13"}, + {"attr_name":"psu_mfr_id", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0x00", "attr_len":"7"}, + {"attr_name":"psu_fan_dir", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x97", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_in", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_min", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + + "PSU2": + { + "dev_info": { "device_type":"PSU", "device_name":"PSU2", "device_parent":"MUX1"}, + "dev_attr": { "dev_idx":"2", "num_psu_fans": "1"}, + "i2c": + { + "interface": + [ + {"itf":"pmbus", "dev":"PSU2-PMBUS"} + + ] + } + }, + + "PSU2-PMBUS": + { + "dev_info": { "device_type":"PSU-PMBUS", "device_name":"PSU2-PMBUS", "device_parent":"MUX1", "virt_parent":"PSU2"}, + "i2c": + { + "topo_info":{ "parent_bus":"0x2", "dev_addr":"0x59", "dev_type":"psu_pmbus"}, + "attr_list": + [ + {"attr_name":"psu_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x04", "attr_cmpval":"0x00", "attr_len":"1"}, + {"attr_name":"psu_power_good", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "attr_offset":"0x60", "attr_mask":"0x01", "attr_cmpval":"0x01", "attr_len":"1"}, + {"attr_name":"psu_model_name", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_serial_num", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13"}, + {"attr_name":"psu_mfr_id", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x99", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"7"}, + {"attr_name":"psu_fan_dir", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x9a", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"17"}, + {"attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8b", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x97", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x88", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_i_in", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x89", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8e", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xc0", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_v_out_min", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + {"attr_name":"psu_p_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + ] + } + }, + + "FAN-CTRL": + { + "dev_info": { "device_type":"FAN", "device_name":"FAN-CTRL", "device_parent":"FPGAPCIE0"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6B", "dev_addr":"0x66", "dev_type":"fan_cpld"}, + "dev_attr": { "num_fantrays":"7"}, + "attr_list": + [ + {"attr_name":"fan1_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x20", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan2_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x21", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan3_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x30", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan4_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x31", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan5_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x40", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan6_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x41", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan7_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x50", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan8_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x51", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan9_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x60", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan10_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x61", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan11_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x70", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan12_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x71", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan13_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x80", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan14_input", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x81", "attr_mask":"0xff", "attr_len":"1", "attr_mult":"150", "attr_is_divisor":0}, + {"attr_name":"fan1_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x22", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan2_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x22", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan3_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x32", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan4_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x32", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan5_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x42", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan6_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x42", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan7_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x52", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan8_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x52", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan9_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x62", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan10_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x62", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan11_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x72", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan12_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x72", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan13_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x82", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan14_pwm", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x82", "attr_mask":"0xff", "attr_cmpval": "0x00","attr_len":"1"}, + {"attr_name":"fan1_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x26", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan2_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x26", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan3_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x36", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan4_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x36", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan5_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x46", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan6_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x46", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan7_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x56", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan8_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x56", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan9_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x66", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan10_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x66", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan11_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x76", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan12_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x76", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan13_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x86", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan14_direction", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x86", "attr_mask":"0xff", "attr_cmpval": "0xfe", "attr_len":"1"}, + {"attr_name":"fan1_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x26", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan2_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x26", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan3_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x36", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan4_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x36", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan5_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x46", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan6_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x46", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan7_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x56", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan8_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x56", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan9_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x66", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan10_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x66", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan11_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x76", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan12_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x76", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan13_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x86", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"}, + {"attr_name":"fan14_present", "attr_devaddr":"0x0d", "attr_devtype":"cpld", "attr_devname":"FAN_CPLD", "attr_offset":"0x86", "attr_mask":"0x00", "attr_cmpval": "0x01", "attr_len":"1"} + ] + } + }, + + "TEMP1": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP1", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"VDD_CORE_Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x66", "dev_addr":"0x6c", "dev_type":"tps536c7"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP2": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP2", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"XP3R3V_L_Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x67", "dev_addr":"0x76", "dev_type":"mp2975"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP3": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP3", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"XP3R3V_R_Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x67", "dev_addr":"0x7b", "dev_type":"mp2975"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP4": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP4", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"XP0R8V_Temp"}, + "i2c": + { + "topo_info": { "parent_bus":"0x67", "dev_addr":"0x70", "dev_type":"mp2975"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP5": + { + "dev_info": {"device_type":"TEMP_SENSOR","device_name":"TEMP5", "device_parent":"FPGAPCIE0"}, + "dev_attr": {"display_name":"TEMP_SW_U16"}, + "i2c": + { + "topo_info": { "parent_bus":"0x6A", "dev_addr":"0x49", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + "TEMP6": + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP6", "device_parent":"MUX2"}, + "dev_attr": { "display_name":"TEMP_FB_U17"}, + "i2c": + { + "topo_info": { "parent_bus":"0x10", "dev_addr":"0x49", "dev_type":"lm75"}, + "attr_list": + [ + {"attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + {"attr_name": "temp1_max_hyst"}, + {"attr_name": "temp1_input"} + ] + } + }, + + + "SYS_LED": + { + "dev_info": {"device_type":"LED", "device_name":"SYS_LED"}, + "dev_attr": {"index":"0"}, + "i2c": { + "attr_list": + [ + {"attr_name":"green", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"green", "value":"0x10", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"}, + {"attr_name":"amber", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"amber", "value":"0x20", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"}, + {"attr_name":"green_blink", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"green_blink", "value":"0x02", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"}, + {"attr_name":"off", "attr_devtype":"cpld", "attr_devname":"CPLD_B", "bits":"5:0","descr":"off", "value":"0x33", "swpld_addr":"0x0d", "swpld_addr_offset":"0x62"} + ] + } + }, + "FANTRAY1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"0"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x24"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x24"} + ] + } + }, + "FANTRAY2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"1"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x34"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x34"} + ] + } + }, + "FANTRAY3_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"2"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x44"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x44"} + ] + } + }, + "FANTRAY4_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"3"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x54"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x54"} + ] + } + }, + "FANTRAY5_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"4"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x64"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x64"} + ] + } + }, + "FANTRAY6_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"5"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x74"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x74"} + ] + } + }, + "FANTRAY7_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FANTRAY_LED"}, + "dev_attr": { "index":"6"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Green","value":"0x01","swpld_addr":"0x0d","swpld_addr_offset":"0x84"}, + {"attr_name":"amber","attr_devtype":"cpld","attr_devname":"FAN_CPLD","bits":"1:0","descr":"Amber","value":"0x02","swpld_addr":"0x0d","swpld_addr_offset":"0x84"} + ] + } + } +} + diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/pddf_support b/device/celestica/x86_64-cel_silverstone_v2-r0/pddf_support new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/platform.json b/device/celestica/x86_64-cel_silverstone_v2-r0/platform.json new file mode 100644 index 000000000000..da5f089819ab --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/platform.json @@ -0,0 +1,914 @@ +{ + "chassis": { + "name": "Silverstone_v2", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "components": [ + { + "name": "BIOS" + }, + { + "name": "ONIE" + }, + { + "name": "BMC" + }, + { + "name": "FPGA" + }, + { + "name": "CPLD COMe" + }, + { + "name": "CPLD BASE" + }, + { + "name": "CPLD SW1" + }, + { + "name": "CPLD SW2" + }, + { + "name": "CPLD FAN" + }, + { + "name": "ASIC PCIe" + }, + { + "name": "SSD" + } + ], + "fans": [ + { + "name": "Fantray1_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray1_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray2_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray2_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray3_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray3_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray4_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray4_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray5_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray5_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray6_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray6_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray7_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray7_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ], + "fan_drawers": [ + { + "name": "Fantray1", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray1_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray1_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + }, + { + "name": "Fantray2", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray2_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray2_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + }, + { + "name": "Fantray3", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray3_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray3_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + }, + { + "name": "Fantray4", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray4_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray4_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + }, + { + "name": "Fantray5", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray5_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray5_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + }, + { + "name": "Fantray6", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray6_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray6_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + }, + { + "name": "Fantray7", + "status_led": { + "controllable": true, + "colors": [ + "green", + "amber", + "off" + ] + }, + "fans": [ + { + "name": "Fantray7_1", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + }, + { + "name": "Fantray7_2", + "status_led": { + "controllable": false + }, + "speed": { + "controllable": false + } + } + ] + } + ], + "psus": [ + { + "name": "PSU 1", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU1_FAN1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "PSU 2", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU2_FAN1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + } + ] + }, + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1,1,1,1,1", + "lanes": "33,34,35,36,37,38,39,40", + "breakout_modes": { + "1x400G": ["Eth1/1"], + "2x100G": ["Eth1/1", "Eth1/5"], + "2x40G": ["Eth1/1", "Eth1/5"], + "4x100G": ["Eth1/1", "Eth1/3", "Eth1/5", "Eth1/7"], + "1x100G(2)": ["Eth1/1"], + "1x100G(4)": ["Eth1/1"], + "1x40G(4)": ["Eth1/1"], + "4x25G(4)": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"], + "4x10G(4)": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"] + } + }, + "Ethernet8": { + "index": "2,2,2,2,2,2,2,2", + "lanes": "41,42,43,44,45,46,47,48", + "breakout_modes": { + "1x400G": ["Eth2/1"], + "2x100G": ["Eth2/1", "Eth2/5"], + "2x40G": ["Eth2/1", "Eth2/5"], + "4x100G": ["Eth2/1", "Eth2/3", "Eth2/5", "Eth2/7"], + "1x100G(2)": ["Eth2/1"], + "1x100G(4)": ["Eth2/1"], + "1x40G(4)": ["Eth2/1"], + "4x25G(4)": ["Eth2/1", "Eth2/2", "Eth2/3", "Eth2/4"], + "4x10G(4)": ["Eth2/1", "Eth2/2", "Eth2/3", "Eth2/4"] + } + }, + "Ethernet16": { + "index": "3,3,3,3,3,3,3,3", + "lanes": "49,50,51,52,53,54,55,56", + "breakout_modes": { + "1x400G": ["Eth3/1"], + "2x100G": ["Eth3/1", "Eth3/5"], + "2x40G": ["Eth3/1", "Eth3/5"], + "4x100G": ["Eth3/1", "Eth3/3", "Eth3/5", "Eth3/7"], + "1x100G(2)": ["Eth3/1"], + "1x100G(4)": ["Eth3/1"], + "1x40G(4)": ["Eth3/1"], + "4x25G(4)": ["Eth3/1", "Eth3/2", "Eth3/3", "Eth3/4"], + "4x10G(4)": ["Eth3/1", "Eth3/2", "Eth3/3", "Eth3/4"] + } + }, + "Ethernet24": { + "index": "4,4,4,4,4,4,4,4", + "lanes": "57,58,59,60,61,62,63,64", + "breakout_modes": { + "1x400G": ["Eth4/1"], + "2x100G": ["Eth4/1", "Eth4/5"], + "2x40G": ["Eth4/1", "Eth4/5"], + "4x100G": ["Eth4/1", "Eth4/3", "Eth4/5", "Eth4/7"], + "1x100G(2)": ["Eth4/1"], + "1x100G(4)": ["Eth4/1"], + "1x40G(4)": ["Eth4/1"], + "4x25G(4)": ["Eth4/1", "Eth4/2", "Eth4/3", "Eth4/4"], + "4x10G(4)": ["Eth4/1", "Eth4/2", "Eth4/3", "Eth4/4"] + } + }, + "Ethernet32": { + "index": "5,5,5,5,5,5,5,5", + "lanes": "65,66,67,68,69,70,71,72", + "breakout_modes": { + "1x400G": ["Eth5/1"], + "2x100G": ["Eth5/1", "Eth5/5"], + "2x40G": ["Eth5/1", "Eth5/5"], + "4x100G": ["Eth5/1", "Eth5/3", "Eth5/5", "Eth5/7"], + "1x100G(2)": ["Eth5/1"], + "1x100G(4)": ["Eth5/1"], + "1x40G(4)": ["Eth5/1"], + "4x25G(4)": ["Eth5/1", "Eth5/2", "Eth5/3", "Eth5/4"], + "4x10G(4)": ["Eth5/1", "Eth5/2", "Eth5/3", "Eth5/4"] + } + }, + "Ethernet40": { + "index": "6,6,6,6,6,6,6,6", + "lanes": "73,74,75,76,77,78,79,80", + "breakout_modes": { + "1x400G": ["Eth6/1"], + "2x100G": ["Eth6/1", "Eth6/5"], + "2x40G": ["Eth6/1", "Eth6/5"], + "4x100G": ["Eth6/1", "Eth6/3", "Eth6/5", "Eth6/7"], + "1x100G(2)": ["Eth6/1"], + "1x100G(4)": ["Eth6/1"], + "1x40G(4)": ["Eth6/1"], + "4x25G(4)": ["Eth6/1", "Eth6/2", "Eth6/3", "Eth6/4"], + "4x10G(4)": ["Eth6/1", "Eth6/2", "Eth6/3", "Eth6/4"] + } + }, + "Ethernet48": { + "index": "7,7,7,7,7,7,7,7", + "lanes": "81,82,83,84,85,86,87,88", + "breakout_modes": { + "1x400G": ["Eth7/1"], + "2x100G": ["Eth7/1", "Eth7/5"], + "2x40G": ["Eth7/1", "Eth7/5"], + "4x100G": ["Eth7/1", "Eth7/3", "Eth7/5", "Eth7/7"], + "1x100G(2)": ["Eth7/1"], + "1x100G(4)": ["Eth7/1"], + "1x40G(4)": ["Eth7/1"], + "4x25G(4)": ["Eth7/1", "Eth7/2", "Eth7/3", "Eth7/4"], + "4x10G(4)": ["Eth7/1", "Eth7/2", "Eth7/3", "Eth7/4"] + } + }, + "Ethernet56": { + "index": "8,8,8,8,8,8,8,8", + "lanes": "89,90,91,92,93,94,95,96", + "breakout_modes": { + "1x400G": ["Eth8/1"], + "2x100G": ["Eth8/1", "Eth8/5"], + "2x40G": ["Eth8/1", "Eth8/5"], + "4x100G": ["Eth8/1", "Eth8/3", "Eth8/5", "Eth8/7"], + "1x100G(2)": ["Eth8/1"], + "1x100G(4)": ["Eth8/1"], + "1x40G(4)": ["Eth8/1"], + "4x25G(4)": ["Eth8/1", "Eth8/2", "Eth8/3", "Eth8/4"], + "4x10G(4)": ["Eth8/1", "Eth8/2", "Eth8/3", "Eth8/4"] + } + }, + "Ethernet64": { + "index": "9,9,9,9,9,9,9,9", + "lanes": "1,2,3,4,5,6,7,8", + "breakout_modes": { + "1x400G": ["Eth9/1"], + "2x100G": ["Eth9/1", "Eth9/5"], + "2x40G": ["Eth9/1", "Eth9/5"], + "4x100G": ["Eth9/1", "Eth9/3", "Eth9/5", "Eth9/7"], + "1x100G(2)": ["Eth9/1"], + "1x100G(4)": ["Eth9/1"], + "1x40G(4)": ["Eth9/1"], + "4x25G(4)": ["Eth9/1", "Eth9/2", "Eth9/3", "Eth9/4"], + "4x10G(4)": ["Eth9/1", "Eth9/2", "Eth9/3", "Eth9/4"] + } + }, + "Ethernet72": { + "index": "10,10,10,10,10,10,10,10", + "lanes": "9,10,11,12,13,14,15,16", + "breakout_modes": { + "1x400G": ["Eth10/1"], + "2x100G": ["Eth10/1", "Eth10/5"], + "2x40G": ["Eth10/1", "Eth10/5"], + "4x100G": ["Eth10/1", "Eth10/3", "Eth10/5", "Eth10/7"], + "1x100G(2)": ["Eth10/1"], + "1x100G(4)": ["Eth10/1"], + "1x40G(4)": ["Eth10/1"], + "4x25G(4)": ["Eth10/1", "Eth10/2", "Eth10/3", "Eth10/4"], + "4x10G(4)": ["Eth10/1", "Eth10/2", "Eth10/3", "Eth10/4"] + } + }, + "Ethernet80": { + "index": "11,11,11,11,11,11,11,11", + "lanes": "17,18,19,20,21,22,23,24", + "breakout_modes": { + "1x400G": ["Eth11/1"], + "2x100G": ["Eth11/1", "Eth11/5"], + "2x40G": ["Eth11/1", "Eth11/5"], + "4x100G": ["Eth11/1", "Eth11/3", "Eth11/5", "Eth11/7"], + "1x100G(2)": ["Eth11/1"], + "1x100G(4)": ["Eth11/1"], + "1x40G(4)": ["Eth11/1"], + "4x25G(4)": ["Eth11/1", "Eth11/2", "Eth11/3", "Eth11/4"], + "4x10G(4)": ["Eth11/1", "Eth11/2", "Eth11/3", "Eth11/4"] + } + }, + "Ethernet88": { + "index": "12,12,12,12,12,12,12,12", + "lanes": "25,26,27,28,29,30,31,32", + "breakout_modes": { + "1x400G": ["Eth12/1"], + "2x100G": ["Eth12/1", "Eth12/5"], + "2x40G": ["Eth12/1", "Eth12/5"], + "4x100G": ["Eth12/1", "Eth12/3", "Eth12/5", "Eth12/7"], + "1x100G(2)": ["Eth12/1"], + "1x100G(4)": ["Eth12/1"], + "1x40G(4)": ["Eth12/1"], + "4x25G(4)": ["Eth12/1", "Eth12/2", "Eth12/3", "Eth12/4"], + "4x10G(4)": ["Eth12/1", "Eth12/2", "Eth12/3", "Eth12/4"] + } + }, + "Ethernet96": { + "index": "13,13,13,13,13,13,13,13", + "lanes": "97,98,99,100,101,102,103,104", + "breakout_modes": { + "1x400G": ["Eth13/1"], + "2x100G": ["Eth13/1", "Eth13/5"], + "2x40G": ["Eth13/1", "Eth13/5"], + "4x100G": ["Eth13/1", "Eth13/3", "Eth13/5", "Eth13/7"], + "1x100G(2)": ["Eth13/1"], + "1x100G(4)": ["Eth13/1"], + "1x40G(4)": ["Eth13/1"], + "4x25G(4)": ["Eth13/1", "Eth13/2", "Eth13/3", "Eth13/4"], + "4x10G(4)": ["Eth13/1", "Eth13/2", "Eth13/3", "Eth13/4"] + } + }, + "Ethernet104": { + "index": "14,14,14,14,14,14,14,14", + "lanes": "105,106,107,108,109,110,111,112", + "breakout_modes": { + "1x400G": ["Eth14/1"], + "2x100G": ["Eth14/1", "Eth14/5"], + "2x40G": ["Eth14/1", "Eth14/5"], + "4x100G": ["Eth14/1", "Eth14/3", "Eth14/5", "Eth14/7"], + "1x100G(2)": ["Eth14/1"], + "1x100G(4)": ["Eth14/1"], + "1x40G(4)": ["Eth14/1"], + "4x25G(4)": ["Eth14/1", "Eth14/2", "Eth14/3", "Eth14/4"], + "4x10G(4)": ["Eth14/1", "Eth14/2", "Eth14/3", "Eth14/4"] + } + }, + "Ethernet112": { + "index": "15,15,15,15,15,15,15,15", + "lanes": "113,114,115,116,117,118,119,120", + "breakout_modes": { + "1x400G": ["Eth15/1"], + "2x100G": ["Eth15/1", "Eth15/5"], + "2x40G": ["Eth15/1", "Eth15/5"], + "4x100G": ["Eth15/1", "Eth15/3", "Eth15/5", "Eth15/7"], + "1x100G(2)": ["Eth15/1"], + "1x100G(4)": ["Eth15/1"], + "1x40G(4)": ["Eth15/1"], + "4x25G(4)": ["Eth15/1", "Eth15/2", "Eth15/3", "Eth15/4"], + "4x10G(4)": ["Eth15/1", "Eth15/2", "Eth15/3", "Eth15/4"] + } + }, + "Ethernet120": { + "index": "16,16,16,16,16,16,16,16", + "lanes": "121,122,123,124,125,126,127,128", + "breakout_modes": { + "1x400G": ["Eth16/1"], + "2x100G": ["Eth16/1", "Eth16/5"], + "2x40G": ["Eth16/1", "Eth16/5"], + "4x100G": ["Eth16/1", "Eth16/3", "Eth16/5", "Eth16/7"], + "1x100G(2)": ["Eth16/1"], + "1x100G(4)": ["Eth16/1"], + "1x40G(4)": ["Eth16/1"], + "4x25G(4)": ["Eth16/1", "Eth16/2", "Eth16/3", "Eth16/4"], + "4x10G(4)": ["Eth16/1", "Eth16/2", "Eth16/3", "Eth16/4"] + } + }, + "Ethernet128": { + "index": "17,17,17,17,17,17,17,17", + "lanes": "129,130,131,132,133,134,135,136", + "breakout_modes": { + "1x400G": ["Eth17/1"], + "2x100G": ["Eth17/1", "Eth17/5"], + "2x40G": ["Eth17/1", "Eth17/5"], + "4x100G": ["Eth17/1", "Eth17/3", "Eth17/5", "Eth17/7"], + "1x100G(2)": ["Eth17/1"], + "1x100G(4)": ["Eth17/1"], + "1x40G(4)": ["Eth17/1"], + "4x25G(4)": ["Eth17/1", "Eth17/2", "Eth17/3", "Eth17/4"], + "4x10G(4)": ["Eth17/1", "Eth17/2", "Eth17/3", "Eth17/4"] + } + }, + "Ethernet136": { + "index": "18,18,18,18,18,18,18,18", + "lanes": "137,138,139,140,141,142,143,144", + "breakout_modes": { + "1x400G": ["Eth18/1"], + "2x100G": ["Eth18/1", "Eth18/5"], + "2x40G": ["Eth18/1", "Eth18/5"], + "4x100G": ["Eth18/1", "Eth18/3", "Eth18/5", "Eth18/7"], + "1x100G(2)": ["Eth18/1"], + "1x100G(4)": ["Eth18/1"], + "1x40G(4)": ["Eth18/1"], + "4x25G(4)": ["Eth18/1", "Eth18/2", "Eth18/3", "Eth18/4"], + "4x10G(4)": ["Eth18/1", "Eth18/2", "Eth18/3", "Eth18/4"] + } + }, + "Ethernet144": { + "index": "19,19,19,19,19,19,19,19", + "lanes": "145,146,147,148,149,150,151,152", + "breakout_modes": { + "1x400G": ["Eth19/1"], + "2x100G": ["Eth19/1", "Eth19/5"], + "2x40G": ["Eth19/1", "Eth19/5"], + "4x100G": ["Eth19/1", "Eth19/3", "Eth19/5", "Eth19/7"], + "1x100G(2)": ["Eth19/1"], + "1x100G(4)": ["Eth19/1"], + "1x40G(4)": ["Eth19/1"], + "4x25G(4)": ["Eth19/1", "Eth19/2", "Eth19/3", "Eth19/4"], + "4x10G(4)": ["Eth19/1", "Eth19/2", "Eth19/3", "Eth19/4"] + } + }, + "Ethernet152": { + "index": "20,20,20,20,20,20,20,20", + "lanes": "153,154,155,156,157,158,159,160", + "breakout_modes": { + "1x400G": ["Eth20/1"], + "2x100G": ["Eth20/1", "Eth20/5"], + "2x40G": ["Eth20/1", "Eth20/5"], + "4x100G": ["Eth20/1", "Eth20/3", "Eth20/5", "Eth20/7"], + "1x100G(2)": ["Eth20/1"], + "1x100G(4)": ["Eth20/1"], + "1x40G(4)": ["Eth20/1"], + "4x25G(4)": ["Eth20/1", "Eth20/2", "Eth20/3", "Eth20/4"], + "4x10G(4)": ["Eth20/1", "Eth20/2", "Eth20/3", "Eth20/4"] + } + }, + "Ethernet160": { + "index": "21,21,21,21,21,21,21,21", + "lanes": "225,226,227,228,229,230,231,232", + "breakout_modes": { + "1x400G": ["Eth21/1"], + "2x100G": ["Eth21/1", "Eth21/5"], + "2x40G": ["Eth21/1", "Eth21/5"], + "4x100G": ["Eth21/1", "Eth21/3", "Eth21/5", "Eth21/7"], + "1x100G(2)": ["Eth21/1"], + "1x100G(4)": ["Eth21/1"], + "1x40G(4)": ["Eth21/1"], + "4x25G(4)": ["Eth21/1", "Eth21/2", "Eth21/3", "Eth21/4"], + "4x10G(4)": ["Eth21/1", "Eth21/2", "Eth21/3", "Eth21/4"] + } + }, + "Ethernet168": { + "index": "22,22,22,22,22,22,22,22", + "lanes": "233,234,235,236,237,238,239,240", + "breakout_modes": { + "1x400G": ["Eth22/1"], + "2x100G": ["Eth22/1", "Eth22/5"], + "2x40G": ["Eth22/1", "Eth22/5"], + "4x100G": ["Eth22/1", "Eth22/3", "Eth22/5", "Eth22/7"], + "1x100G(2)": ["Eth22/1"], + "1x100G(4)": ["Eth22/1"], + "1x40G(4)": ["Eth22/1"], + "4x25G(4)": ["Eth22/1", "Eth22/2", "Eth22/3", "Eth22/4"], + "4x10G(4)": ["Eth22/1", "Eth22/2", "Eth22/3", "Eth22/4"] + } + }, + "Ethernet176": { + "index": "23,23,23,23,23,23,23,23", + "lanes": "241,242,243,244,245,246,247,248", + "breakout_modes": { + "1x400G": ["Eth23/1"], + "2x100G": ["Eth23/1", "Eth23/5"], + "2x40G": ["Eth23/1", "Eth23/5"], + "4x100G": ["Eth23/1", "Eth23/3", "Eth23/5", "Eth23/7"], + "1x100G(2)": ["Eth23/1"], + "1x100G(4)": ["Eth23/1"], + "1x40G(4)": ["Eth23/1"], + "4x25G(4)": ["Eth23/1", "Eth23/2", "Eth23/3", "Eth23/4"], + "4x10G(4)": ["Eth23/1", "Eth23/2", "Eth23/3", "Eth23/4"] + } + }, + "Ethernet184": { + "index": "24,24,24,24,24,24,24,24", + "lanes": "249,250,251,252,253,254,255,256", + "breakout_modes": { + "1x400G": ["Eth24/1"], + "2x100G": ["Eth24/1", "Eth24/5"], + "2x40G": ["Eth24/1", "Eth24/5"], + "4x100G": ["Eth24/1", "Eth24/3", "Eth24/5", "Eth24/7"], + "1x100G(2)": ["Eth24/1"], + "1x100G(4)": ["Eth24/1"], + "1x40G(4)": ["Eth24/1"], + "4x25G(4)": ["Eth24/1", "Eth24/2", "Eth24/3", "Eth24/4"], + "4x10G(4)": ["Eth24/1", "Eth24/2", "Eth24/3", "Eth24/4"] + } + }, + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "161,162,163,164,165,166,167,168", + "breakout_modes": { + "1x400G": ["Eth25/1"], + "2x100G": ["Eth25/1", "Eth25/5"], + "2x40G": ["Eth25/1", "Eth25/5"], + "4x100G": ["Eth25/1", "Eth25/3", "Eth25/5", "Eth25/7"], + "1x100G(2)": ["Eth25/1"], + "1x100G(4)": ["Eth25/1"], + "1x40G(4)": ["Eth25/1"], + "4x25G(4)": ["Eth25/1", "Eth25/2", "Eth25/3", "Eth25/4"], + "4x10G(4)": ["Eth25/1", "Eth25/2", "Eth25/3", "Eth25/4"] + } + }, + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "169,170,171,172,173,174,175,176", + "breakout_modes": { + "1x400G": ["Eth26/1"], + "2x100G": ["Eth26/1", "Eth26/5"], + "2x40G": ["Eth26/1", "Eth26/5"], + "4x100G": ["Eth26/1", "Eth26/3", "Eth26/5", "Eth26/7"], + "1x100G(2)": ["Eth26/1"], + "1x100G(4)": ["Eth26/1"], + "1x40G(4)": ["Eth26/1"], + "4x25G(4)": ["Eth26/1", "Eth26/2", "Eth26/3", "Eth26/4"], + "4x10G(4)": ["Eth26/1", "Eth26/2", "Eth26/3", "Eth26/4"] + } + }, + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "177,178,179,180,181,182,183,184", + "breakout_modes": { + "1x400G": ["Eth27/1"], + "2x100G": ["Eth27/1", "Eth27/5"], + "2x40G": ["Eth27/1", "Eth27/5"], + "4x100G": ["Eth27/1", "Eth27/3", "Eth27/5", "Eth27/7"], + "1x100G(2)": ["Eth27/1"], + "1x100G(4)": ["Eth27/1"], + "1x40G(4)": ["Eth27/1"], + "4x25G(4)": ["Eth27/1", "Eth27/2", "Eth27/3", "Eth27/4"], + "4x10G(4)": ["Eth27/1", "Eth27/2", "Eth27/3", "Eth27/4"] + } + }, + "Ethernet216": { + "index": "28,28,28,28,28,28,28,28", + "lanes": "185,186,187,188,189,190,191,192", + "breakout_modes": { + "1x400G": ["Eth28/1"], + "2x100G": ["Eth28/1", "Eth28/5"], + "2x40G": ["Eth28/1", "Eth28/5"], + "4x100G": ["Eth28/1", "Eth28/3", "Eth28/5", "Eth28/7"], + "1x100G(2)": ["Eth28/1"], + "1x100G(4)": ["Eth28/1"], + "1x40G(4)": ["Eth28/1"], + "4x25G(4)": ["Eth28/1", "Eth28/2", "Eth28/3", "Eth28/4"], + "4x10G(4)": ["Eth28/1", "Eth28/2", "Eth28/3", "Eth28/4"] + } + }, + "Ethernet224": { + "index": "29,29,29,29,29,29,29,29", + "lanes": "193,194,195,196,197,198,199,200", + "breakout_modes": { + "1x400G": ["Eth29/1"], + "2x100G": ["Eth29/1", "Eth29/5"], + "2x40G": ["Eth29/1", "Eth29/5"], + "4x100G": ["Eth29/1", "Eth29/3", "Eth29/5", "Eth29/7"], + "1x100G(2)": ["Eth29/1"], + "1x100G(4)": ["Eth29/1"], + "1x40G(4)": ["Eth29/1"], + "4x25G(4)": ["Eth29/1", "Eth29/2", "Eth29/3", "Eth29/4"], + "4x10G(4)": ["Eth29/1", "Eth29/2", "Eth29/3", "Eth29/4"] + } + }, + "Ethernet232": { + "index": "30,30,30,30,30,30,30,30", + "lanes": "201,202,203,204,205,206,207,208", + "breakout_modes": { + "1x400G": ["Eth30/1"], + "2x100G": ["Eth30/1", "Eth30/5"], + "2x40G": ["Eth30/1", "Eth30/5"], + "4x100G": ["Eth30/1", "Eth30/3", "Eth30/5", "Eth30/7"], + "1x100G(2)": ["Eth30/1"], + "1x100G(4)": ["Eth30/1"], + "1x40G(4)": ["Eth30/1"], + "4x25G(4)": ["Eth30/1", "Eth30/2", "Eth30/3", "Eth30/4"], + "4x10G(4)": ["Eth30/1", "Eth30/2", "Eth30/3", "Eth30/4"] + } + }, + "Ethernet240": { + "index": "31,31,31,31,31,31,31,31", + "lanes": "209,210,211,212,213,214,215,216", + "breakout_modes": { + "1x400G": ["Eth31/1"], + "2x100G": ["Eth31/1", "Eth31/5"], + "2x40G": ["Eth31/1", "Eth31/5"], + "4x100G": ["Eth31/1", "Eth31/3", "Eth31/5", "Eth31/7"], + "1x100G(2)": ["Eth31/1"], + "1x100G(4)": ["Eth31/1"], + "1x40G(4)": ["Eth31/1"], + "4x25G(4)": ["Eth31/1", "Eth31/2", "Eth31/3", "Eth31/4"], + "4x10G(4)": ["Eth31/1", "Eth31/2", "Eth31/3", "Eth31/4"] + } + }, + "Ethernet248": { + "index": "32,32,32,32,32,32,32,32", + "lanes": "217,218,219,220,221,222,223,224", + "breakout_modes": { + "1x400G": ["Eth32/1"], + "2x100G": ["Eth32/1", "Eth32/5"], + "2x40G": ["Eth32/1", "Eth32/5"], + "4x100G": ["Eth32/1", "Eth32/3", "Eth32/5", "Eth32/7"], + "1x100G(2)": ["Eth32/1"], + "1x100G(4)": ["Eth32/1"], + "1x40G(4)": ["Eth32/1"], + "4x25G(4)": ["Eth32/1", "Eth32/2", "Eth32/3", "Eth32/4"], + "4x10G(4)": ["Eth32/1", "Eth32/2", "Eth32/3", "Eth32/4"] + } + } + } + +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/platform_asic b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-bmc b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-bmc new file mode 100644 index 000000000000..8a187b11ffe0 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-bmc @@ -0,0 +1,19 @@ +{ + "chassis": { + "DS4000-R 02": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "CPLD FAN": {}, + "ASIC PCIe": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-nonebmc b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-nonebmc new file mode 100644 index 000000000000..528b0c4dcbfb --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_components.json-nonebmc @@ -0,0 +1,18 @@ +{ + "chassis": { + "DS4000": { + "component": { + "BIOS": {}, + "ONIE": {}, + "BMC": {}, + "FPGA": {}, + "CPLD COMe": {}, + "CPLD BASE": {}, + "CPLD SW1": {}, + "CPLD SW2": {}, + "CPLD FAN": {}, + "SSD": {} + } + } + } +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/platform_env.conf b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_env.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/platform_reboot b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_reboot new file mode 100755 index 000000000000..a3eef1d10ee2 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/platform_reboot @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/local/bin/silverstone_v2_platform_shutdown.sh system diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/eeprom.py new file mode 100644 index 000000000000..03bdb5262f2c --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Celestica Silverstone-v2 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError 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/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/psuutil.py new file mode 100644 index 000000000000..1b91409e82d7 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/psuutil.py @@ -0,0 +1,85 @@ +import os.path +import subprocess +import sys +import re + +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): + self.ipmi_sensor = "ipmitool sensor" + PsuBase.__init__(self) + + def run_command(self, command): + ret, data = subprocess.getstatusoutput(command) + if ret != 0: + sys.exit(ret) + else: + return data + + def find_value(self, grep_string): + result = re.search(".+\| (0x\d{2})\d{2}\|.+", grep_string) + if result: + return result.group(1) + else: + return result + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + grep_key = "PSUL_Status" if index == 1 else "PSUR_Status" + grep_string = self.run_command(self.ipmi_sensor + ' | grep ' + grep_key) + status_byte = self.find_value(grep_string) + + if status_byte is None: + return False + + failure_detected = (int(status_byte, 16) >> 1) & 1 + input_lost = (int(status_byte, 16) >> 3) & 1 + if failure_detected or input_lost: + return False + else: + return True + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + grep_key = "PSUL_Status" if index == 1 else "PSUR_Status" + grep_string = self.run_command(self.ipmi_sensor + ' | grep ' + grep_key) + status_byte = self.find_value(grep_string) + + if status_byte is None: + return False + + presence = (int(status_byte, 16) >> 0) & 1 + if presence: + return True + else: + return False diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/sfputil.py new file mode 100755 index 000000000000..7dd0ab18ae28 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/sfputil.py @@ -0,0 +1,179 @@ +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 33 + QSFP_PORT_START = 1 + QSFP_PORT_END = 32 + + EEPROM_OFFSET = 1 + PORT_INFO_PATH = '/sys/class/silverstonev2_fpga' + + _port_name = "" + _port_to_eeprom_mapping = {} + _port_to_i2cbus_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def port_to_i2cbus_mapping(self): + return self._port_to_i2cbus_mapping + + def get_port_name(self, port_num): + if port_num in self.qsfp_ports: + self._port_name = "QSFP" + str(port_num - self.QSFP_PORT_START + 1) + else: + self._port_name = "SFP" + str(port_num) + return self._port_name + + # 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.DOM_EEPROM_ADDR, 256) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + + for x in range(self.PORT_START, self.PORT_END+1): + self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET) + self.port_to_eeprom_mapping[x] = eeprom_path.format( + x + self.EEPROM_OFFSET) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + + # Check for invalid port_num + if port_num not in list(range(self.port_start, self.port_end + 1)): + return False + + # Get path for access port presence status + port_name = self.get_port_name(port_num) + sysfs_filename = "qsfp_modprs" if port_num in self.qsfp_ports else "sfp_modabs" + reg_path = "/".join([self.PORT_INFO_PATH, port_name, sysfs_filename]) + + # Read status + try: + reg_file = open(reg_path) + content = reg_file.readline().rstrip() + reg_value = int(content) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Module present is active low + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + try: + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_lpmode"]), "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Read status + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # ModPrsL is active low + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + try: + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_lpmode"]), "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = hex(lpmode) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid QSFP port_num + if port_num not in self.qsfp_ports: + return False + + try: + port_name = self.get_port_name(port_num) + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(0)) + reg_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + # Flip the bit back high and write back to the register to take port out of reset + try: + reg_file = open( + "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_file.seek(0) + reg_file.write(hex(1)) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + """ + TBD: When the feature request. + """ + raise NotImplementedError diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/ssd_util.py b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/ssd_util.py new file mode 100644 index 000000000000..374f13a684cd --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/plugins/ssd_util.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*-# + +# @Time : 2023/3/17 16:42 +# @Mail : J_Talong@163.com yajiang@celestica.com +# @Author : jiang tao + +from sonic_platform_base.sonic_ssd.ssd_base import SsdBase +from subprocess import Popen, PIPE +from re import findall +from os.path import exists + +NOT_AVAILABLE = "N/A" + + +class SsdUtil(SsdBase): + + def __init__(self, disk_dev): + """ + Constructor + Args: + disk_dev: Linux device name to get parameters for + """ + + super().__init__(disk_dev) + if not isinstance(disk_dev, str): + raise TypeError("disk dev type wrong {}".format(type(disk_dev))) + + if not exists(disk_dev): + raise RuntimeError("disk dev {} not found".format(disk_dev)) + + self.model = NOT_AVAILABLE + self.serial = NOT_AVAILABLE + self.firmware = NOT_AVAILABLE + self.temperature = NOT_AVAILABLE + self.health = NOT_AVAILABLE + + inno_disk = ["iSmart", "-d", disk_dev] + self.ssd_info = self._execute_shell(inno_disk) + + self.model = self._parse_re(r'Model Name:\s*(.+?)\n', self.ssd_info) + self.serial = self._parse_re(r'Serial Number:\s*(.+?)\n', self.ssd_info) + self.firmware = self._parse_re(r'FW Version:\s*(.+?)\n', self.ssd_info) + self.temperature = self._parse_re(r'Temperature\s*\[\s*(.+?)\]', self.ssd_info) + self.health = self._parse_re(r'Health:\s*(.+?)', self.ssd_info) + + @staticmethod + def _execute_shell(cmd): + process = Popen(cmd, universal_newlines=True, stdout=PIPE) + output, _ = process.communicate() + return output + + @staticmethod + def _parse_re(pattern, buffer): + res_list = findall(pattern, buffer) + return res_list[0] if res_list else NOT_AVAILABLE + + def get_health(self): + """ + Retrieves current disk health in percentages + Returns: + A float number of current ssd health + e.g. 83.5 + """ + return self.health + + def get_temperature(self): + """ + Retrieves current disk temperature in Celsius + Returns: + A float number of current temperature in Celsius + e.g. 40.1 + """ + return self.temperature + + def get_model(self): + """ + Retrieves model for the given disk device + Returns: + A string holding disk model as provided by the manufacturer + """ + return self.model + + def get_firmware(self): + """ + Retrieves firmware version for the given disk device + Returns: + A string holding disk firmware version as provided by the manufacturer + """ + return self.firmware + + def get_serial(self): + """ + Retrieves serial number for the given disk device + Returns: + A string holding disk serial number as provided by the manufacturer + """ + return self.serial + + def get_vendor_output(self): + """ + Retrieves vendor specific data for the given disk device + Returns: + A string holding some vendor specific disk information + """ + return self.ssd_info diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_silverstone_v2-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..9a1f92753051 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true, + "skip_fancontrol": true +} diff --git a/device/celestica/x86_64-cel_silverstone_v2-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_silverstone_v2-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..5661a0d21396 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone_v2-r0/system_health_monitoring_config.json @@ -0,0 +1,16 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature", + "PSU 1 Fan 1", + "PSU 2 Fan 1" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "alternate_blink_4hz" + } +} diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 4e86423bd7e8..b620c911cda6 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -54,7 +54,11 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(CEL_DX010_PLATFORM_MODULE) \ $(CEL_HALIBURTON_PLATFORM_MODULE) \ $(CEL_SEASTONE2_PLATFORM_MODULE) \ - $(CEL_BELGITE_PLATFORM_MODULE) \ + $(CEL_DS3000_PLATFORM_MODULE) \ + $(CEL_DS1000_PLATFORM_MODULE) \ + $(CEL_QUESTONE2_PLATFORM_MODULE) \ + $(CEL_SILVERSTONE_V2_PLATFORM_MODULE) \ + $(CEL_DS2000_PLATFORM_MODULE) \ $(DELTA_AG9032V1_PLATFORM_MODULE) \ $(DELTA_AG9064_PLATFORM_MODULE) \ $(DELTA_AG5648_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-cel.mk b/platform/broadcom/platform-modules-cel.mk index b25aeb7c0900..2db8560b8bf3 100644 --- a/platform/broadcom/platform-modules-cel.mk +++ b/platform/broadcom/platform-modules-cel.mk @@ -1,16 +1,24 @@ # Celestica DX010 and Haliburton Platform modules -CEL_DX010_PLATFORM_MODULE_VERSION = 0.9 -CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9 -CEL_SEASTONE2_PLATFORM_MODULE_VERSION = 0.9 -CEL_SILVERSTONE_PLATFORM_MODULE_VERSION = 0.9 -CEL_BELGITE_PLATFORM_MODULE_VERSION = 0.9 +CEL_DX010_PLATFORM_MODULE_VERSION = 1.0 +CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 1.0 +CEL_SEASTONE2_PLATFORM_MODULE_VERSION = 1.0 +CEL_SILVERSTONE_PLATFORM_MODULE_VERSION = 1.0 +CEL_DS1000_PLATFORM_MODULE_VERSION = 1.0 +CEL_QUESTONE2_PLATFORM_MODULE_VERSION = 1.0 +CEL_DS3000_PLATFORM_MODULE_VERSION = 1.0 +CEL_SILVERSTONE_V2_PLATFORM_MODULE_VERSION = 1.0 +CEL_DS2000_PLATFORM_MODULE_VERSION = 1.0 export CEL_DX010_PLATFORM_MODULE_VERSION export CEL_HALIBURTON_PLATFORM_MODULE_VERSION export CEL_SEASTONE2_PLATFORM_MODULE_VERSION export CEL_SILVERSTONE_PLATFORM_MODULE_VERSION -export CEL_BELGITE_PLATFORM_MODULE_VERSION +export CEL_DS1000_PLATFORM_MODULE_VERSION +export CEL_QUESTONE2_PLATFORM_MODULE_VERSION +export CEL_DS3000_PLATFORM_MODULE_VERSION +export CEL_SILVERSTONE_V2_PLATFORM_MODULE_VERSION +export CEL_DS2000_PLATFORM_MODULE_VERSION CEL_DX010_PLATFORM_MODULE = platform-modules-dx010_$(CEL_DX010_PLATFORM_MODULE_VERSION)_amd64.deb $(CEL_DX010_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cel @@ -30,6 +38,22 @@ CEL_SILVERSTONE_PLATFORM_MODULE = platform-modules-silverstone_$(CEL_SILVERSTONE $(CEL_SILVERSTONE_PLATFORM_MODULE)_PLATFORM = x86_64-cel_silverstone-r0 $(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SILVERSTONE_PLATFORM_MODULE))) -CEL_BELGITE_PLATFORM_MODULE = platform-modules-belgite_$(CEL_BELGITE_PLATFORM_MODULE_VERSION)_amd64.deb -$(CEL_BELGITE_PLATFORM_MODULE)_PLATFORM = x86_64-cel_belgite-r0 -$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_BELGITE_PLATFORM_MODULE))) +CEL_DS1000_PLATFORM_MODULE = platform-modules-ds1000_$(CEL_DS1000_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_DS1000_PLATFORM_MODULE)_PLATFORM = x86_64-cel_ds1000-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_DS1000_PLATFORM_MODULE))) + +CEL_QUESTONE2_PLATFORM_MODULE = platform-modules-questone2_$(CEL_QUESTONE2_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_QUESTONE2_PLATFORM_MODULE)_PLATFORM = x86_64-cel_questone_2-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_QUESTONE2_PLATFORM_MODULE))) + +CEL_DS3000_PLATFORM_MODULE = platform-modules-ds3000_$(CEL_DS3000_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_DS3000_PLATFORM_MODULE)_PLATFORM = x86_64-cel_ds3000-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_DS3000_PLATFORM_MODULE))) + +CEL_SILVERSTONE_V2_PLATFORM_MODULE = platform-modules-silverstone-v2_$(CEL_SILVERSTONE_V2_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_SILVERSTONE_V2_PLATFORM_MODULE)_PLATFORM = x86_64-cel_silverstone_v2-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SILVERSTONE_V2_PLATFORM_MODULE))) + +CEL_DS2000_PLATFORM_MODULE = platform-modules-ds2000_$(CEL_DS2000_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_DS2000_PLATFORM_MODULE)_PLATFORM = x86_64-cel_ds2000-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_DS2000_PLATFORM_MODULE))) diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan.py deleted file mode 100644 index 5ece7e980980..000000000000 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan.py +++ /dev/null @@ -1,93 +0,0 @@ -try: - from sonic_platform_pddf_base.pddf_fan import PddfFan - import subprocess -except ImportError as e: - raise ImportError(str(e) + "- required module not found") -# ------------------------------------------------------------------ -# HISTORY: -# 5/1/2022 (A.D.) -# add function:set_status_led, -# Solve the problem that when a fan is pulled out, the Fan LED on the front panel is still green Issue-#11525 -# ------------------------------------------------------------------ - - -class Fan(PddfFan): - """PDDF Platform-Specific Fan class""" - - def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): - # idx is 0-based - PddfFan.__init__(self, tray_idx, fan_idx, pddf_data, pddf_plugin_data, is_psu_fan, psu_index) - - - 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 - """ - # Fix the speed vairance to 10 percent. If it changes based on platforms, overwrite - # this value in derived pddf fan class - return 20 - - def get_presence(self): - if self.is_psu_fan: - #For PSU, FAN must be present when PSU is present - try: - cmd = ['i2cget', '-y', '-f', '0x2', '0x32', '0x41'] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) - data = p.communicate() - status = int(data[0].strip(), 16) - if (self.fans_psu_index == 1 and (status & 0x10) == 0) or \ - (self.fans_psu_index == 2 and (status & 0x20) == 0): - return True - except (IOError, ValueError): - pass - - return False - else: - #Overwirte the PDDF Common since the FANs on Belgite are all Fixed and present - return True - - def get_direction(self): - """ - Retrieves the direction of fan - - Returns: - A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST - depending on fan direction - """ - if self.is_psu_fan: - # Belgite PSU module only has EXHAUST fan - return "EXHAUST" - else: - return super().get_direction() - - def get_status_led(self): - """ - Gets the state of the fan status LED - - Returns: - A string, one of the predefined STATUS_LED_COLOR_* strings above - """ - if self.is_psu_fan: - return "N/A" - else: - return super().get_status_led() - - def set_status_led(self, color): - """ - Sets the state of the fan module status LED - - Args: - color: A string representing the color with which to set the - fan module status LED - - Returns: - bool: True if status LED state is set successfully, False if not - """ - if self.is_psu_fan: - return False - else: - return super().set_status_led(color) diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/sfp.py deleted file mode 100644 index a216a37afcf8..000000000000 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/sfp.py +++ /dev/null @@ -1,15 +0,0 @@ -try: - from sonic_platform_pddf_base.pddf_sfp import PddfSfp -except ImportError as e: - raise ImportError (str(e) + "- required module not found") - - -class Sfp(PddfSfp): - """ - PDDF Platform-Specific Sfp class - """ - - def __init__(self, index, pddf_data=None, pddf_plugin_data=None): - PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) - - # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/thermal.py deleted file mode 100644 index 7dd294fb8475..000000000000 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/thermal.py +++ /dev/null @@ -1,111 +0,0 @@ -try: - from sonic_platform_pddf_base.pddf_thermal import PddfThermal -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - - - -class Thermal(PddfThermal): - """PDDF Platform-Specific Thermal class""" - - def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): - PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index) - self.minimum_thermal = self.get_temperature() - self.maximum_thermal = self.get_temperature() - # Provide the functions/variables below for which implementation is to be overwritten - - 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 - """ - return 0.001 - - 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 - """ - - return 100.000 - - 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 - - return 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 - - return self.maximum_thermal - - def get_presence(self): - """ - Retrieves the presence of the PSU - 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 device - Returns: - string: Model/part number of device - """ - return "N/A" - - def get_serial(self): - """ - Retrieves the serial number of the device - Returns: - string: Serial number of device - """ - return "N/A" - - def get_status(self): - """ - Retrieves the operational status of the device - Returns: - A boolean value, True if device is operating properly, False if not - """ - if not self.get_presence(): - return False - - return True - - def is_replaceable(self): - """ - Retrieves whether thermal module is replaceable - Returns: - A boolean value, True if replaceable, False if not - """ - return False - - def get_position_in_parent(self): - """ - Retrieves the thermal position information - Returns: - A int value, 0 represent ASIC thermal, 1 represent CPU thermal info - """ - return 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_post_device_create.sh b/platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_post_device_create.sh deleted file mode 100755 index 436cf61d6dbe..000000000000 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_post_device_create.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -# Set U60 shutdown threhold 80 -sudo i2cset -y -f 6 0x49 0x3 0x4e 0x00 i -sleep 0.1 -sudo i2cset -y -f 6 0x49 0x1 0x2 -sleep 0.1 -#Set LM75 shutdown enable -sudo i2cset -y -f 2 0x32 0x45 0x1 - -# set sys led green status -sudo i2cset -y -f 2 0x32 0x43 0xec - -echo -2 | tee /sys/bus/i2c/drivers/pca954x/*-00*/idle_state diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/utils/belgite_pddf_monitor.py b/platform/broadcom/sonic-platform-modules-cel/belgite/utils/belgite_pddf_monitor.py deleted file mode 100755 index 5ce0469a0ddf..000000000000 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/utils/belgite_pddf_monitor.py +++ /dev/null @@ -1,272 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) Celestica Technology Corporation -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ------------------------------------------------------------------ -# HISTORY: -# 9/16/2021 (A.D.) -# ------------------------------------------------------------------ - -try: - import sys - import getopt - import logging - import logging.config - import time # this is only being used as part of the example - import signal - import math - from sonic_platform import platform - from sonic_py_common.general import getstatusoutput_noshell -except ImportError as e: - raise ImportError('%s - required module not found' % str(e)) - -# Deafults -FUNCTION_NAME = 'cel_belgite_monitor' -DUTY_MAX = 100 -FAN_NUMBER = 3 -SENSOR_NUMBER = 4 -CPU_CORE_TEMP = r"/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp1_input" - - -class cel_belgite_monitor(object): - """ - Make a class we can use to capture stdout and sterr in the log - """ - # static temp var - _ori_temp = 0 - _new_perc = DUTY_MAX / 2 - syslog = logging.getLogger("[" + FUNCTION_NAME + "]") - init_fan_temperature = [0, 0, 0, 0] - - def __init__(self, log_file, log_level): - """Needs a logger and a logger level.""" - formatter = logging.Formatter('%(name)s %(message)s') - sys_handler = logging.handlers.SysLogHandler(address='/dev/log') - sys_handler.setFormatter(formatter) - sys_handler.ident = 'common' - self.syslog.setLevel(logging.WARNING) - self.syslog.addHandler(sys_handler) - self.platform_chassis_obj = platform.Platform().get_chassis() - # set up logging to file - logging.basicConfig( - filename=log_file, - filemode='w', - level=log_level, - format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', - datefmt='%H:%M:%S' - ) - - # set up logging to console - if log_level == logging.DEBUG: - console = logging.StreamHandler() - console.setLevel(log_level) - formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') - console.setFormatter(formatter) - logging.getLogger('').addHandler(console) - logging.debug('SET. logfile:%s / loglevel:%d' % (log_file, log_level)) - - def get_all_temperature(self): - """ - return: all temperature - """ - all_temperature_list = list() - for sensor_index in range(SENSOR_NUMBER): - temp = self.platform_chassis_obj.get_thermal(sensor_index).get_temperature() - if temp is None or str(temp).strip() == "": - return False - temp = temp*1000 - all_temperature_list.append(temp) - u4_temperature = all_temperature_list[0] - u7_temperature = all_temperature_list[1] - # default CPU temperature 70 - cpu_temperature = 70000 - try: - with open(CPU_CORE_TEMP, "r") as f: - cpu_temperature = float(f.read().strip()) - except Exception as E: - logging.debug('Error: %s' % E) - u60_temperature = all_temperature_list[3] - return [u4_temperature, u7_temperature, cpu_temperature, u60_temperature] - - def get_fan_speed_by_temperature(self, temp_list): - fan1_direction = self.platform_chassis_obj.get_fan(0).get_direction() - logging.debug('INFO: fan direction: %s' % str(fan1_direction)) - all_temp = self.get_all_temperature() - logging.debug('INFO: all_temp: %s' % str(all_temp)) - # B2F=intake: U7 temperature, F2B-EXHAUST: U4 temperature - a = 1 if fan1_direction.lower() == "intake" else 0 - sensor_temp = all_temp[a] - cup_temp = all_temp[2] - u60_temp = all_temp[3] - logging.debug('sensor_temp:%d cup_temp:%d u60_temp:%d' % (sensor_temp, cup_temp, u60_temp)) - update_temp_sensor, update_temp_cpu, update_temp_u60 = True, True, True - if all_temp[a] - temp_list[a] < 0: - update_temp_sensor = False - if cup_temp - temp_list[2] < 0: - update_temp_cpu = False - if u60_temp - temp_list[3] < 0: - update_temp_u60 = False - - # U4 U7 - if not update_temp_sensor: # temperature down - b = math.trunc(1400/13) - if sensor_temp <= 32000: - sensor_temp_speed = 40 - elif sensor_temp >= 45000: - sensor_temp_speed = 100 - else: - sensor_temp_speed = int(math.trunc(60 / 13) * math.trunc(sensor_temp / 1000) - b) - else: # temperature up - b = math.trunc(1580 / 13) - if sensor_temp <= 35000: - sensor_temp_speed = 40 - elif sensor_temp >= 48000: - sensor_temp_speed = 100 - else: - sensor_temp_speed = int(math.trunc(60/13) * math.trunc(sensor_temp/1000) - b) - - # CPU - if not update_temp_cpu: # temperature down - b = 228 - if cup_temp <= 67000: - cpu_temp_speed = 40 - elif cup_temp >= 82000: - cpu_temp_speed = 100 - else: - cpu_temp_speed = int(4 * (cup_temp / 1000) - b) - else: # temperature up - b = 240 - if cup_temp <= 70000: - cpu_temp_speed = 40 - elif cup_temp >= 85000: - cpu_temp_speed = 100 - else: - cpu_temp_speed = int(4 * (cup_temp / 1000) - b) - - # U60 - if not update_temp_u60: # temperature down - b = 168 - if u60_temp <= 52000: - u60_temp_speed = 40 - elif u60_temp >= 67000: - u60_temp_speed = 100 - else: - u60_temp_speed = int(4 * (u60_temp / 1000) - b) - else: # temperature up - b = 180 - if u60_temp <= 55000: - u60_temp_speed = 40 - elif u60_temp >= 70000: - u60_temp_speed = 100 - else: - u60_temp_speed = int(4 * (u60_temp / 1000) - b) - return max([sensor_temp_speed, cpu_temp_speed, u60_temp_speed]) - - def manage_fans(self): - fan_presence_list = [True, True, True] # whether fan is absent or not - for fan_index in range(FAN_NUMBER): - if not self.platform_chassis_obj.get_fan(fan_index).get_presence() or not \ - self.platform_chassis_obj.get_fan(fan_index).get_status(): - fan_presence_list[fan_index] = False - logging.debug('self.platform_chassis_obj.get_fan(fan_index).get_presence():%s' - % str(self.platform_chassis_obj.get_fan(fan_index).get_presence())) - logging.debug('self.platform_chassis_obj.get_fan(fan_index).get_status():%s' - % str(self.platform_chassis_obj.get_fan(fan_index).get_status())) - else: - fan_presence_list[fan_index] = True - - fans_inserted_num = FAN_NUMBER - fan_presence_list.count(False) - if fans_inserted_num == 0: # all fans broken, power off - self.syslog.critical("No fans inserted. Severe overheating hazard. " - "Please insert Fans immediately or power off the device\n") - - # power off - elif fans_inserted_num in [1, 2]: # 1 or 2 present, full speed - self._new_perc = DUTY_MAX - else: # 3 fans normal, manage the fans follow thermal policy - self._new_perc = self.get_fan_speed_by_temperature(self.init_fan_temperature) - logging.debug('INFO: 3 fans inserted: self._new_perc: %s' % str(self._new_perc)) - self.init_fan_temperature = self.get_all_temperature() - - for i in range(FAN_NUMBER): - aa = self.platform_chassis_obj.get_fan(i).get_speed() - logging.debug("INFO: Get before setting fan speed: %s" % aa) - if self._new_perc < 40: - self._new_perc = 40 - if self._new_perc > 100: - self._new_perc = 100 - set_stat = self.platform_chassis_obj.get_fan(i).set_speed(self._new_perc) - if set_stat is True: - logging.debug('INFO: PASS. set_fan%d_duty_cycle (%d)' % (i, self._new_perc)) - else: - logging.debug('INFO: FAIL. set_fan%d_duty_cycle (%d)' % (i, self._new_perc)) - - -def handler(signum, frame): - platform_chassis = platform.Platform().get_chassis() - for _ in range(FAN_NUMBER): - set_stat = platform_chassis.get_fan(_).set_speed(DUTY_MAX) - if set_stat is True: - logging.debug('INFO:Cause signal %d, set fan speed max.' % signum) - else: - logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)' % DUTY_MAX) - # Enable the CPLD Heartbeat back - status, output = getstatusoutput_noshell(["i2cset", "-f", "-y", "75", "0x40", "0x22", "0x00"]) - if status == 0: - logging.debug('INFO: CPLD Heartbeat check is enabled back') - sys.exit(0) - - -def main(argv): - global test_temp - - log_file = '/home/admin/%s.log' % FUNCTION_NAME - log_level = logging.INFO - if len(sys.argv) != 1: - try: - opts, args = getopt.getopt(argv, 'hdlt:', ['lfile=']) - except getopt.GetoptError: - print('Usage: %s [-d] [-l ]' % sys.argv[0]) - return 0 - for opt, arg in opts: - if opt == '-h': - print('Usage: %s [-d] [-l ]' % sys.argv[0]) - return 0 - elif opt in ('-d', '--debug'): - log_level = logging.DEBUG - elif opt in ('-l', '--lfile'): - log_file = arg - - if sys.argv[1] == '-t': - if len(sys.argv) != 6: - print("temp test, need input 4 temp") - return 0 - - signal.signal(signal.SIGINT, handler) - signal.signal(signal.SIGTERM, handler) - # Disaable the CPLD Heartbeat check to control Fan speed from CPU via ADT7470 - getstatusoutput_noshell(['i2cset', '-f', '-y', '2', '0x32', '0x30', '0x01']) - - monitor = cel_belgite_monitor(log_file, log_level) - - # Loop forever, doing something useful hopefully: - while True: - monitor.manage_fans() - time.sleep(10) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/changelog b/platform/broadcom/sonic-platform-modules-cel/debian/changelog index aa89b4df6329..42f4d07630e7 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/changelog +++ b/platform/broadcom/sonic-platform-modules-cel/debian/changelog @@ -1,3 +1,12 @@ +sonic-cel-platform-modules (1.0) unstable; urgency=low + + * Add questone2 platform module. + * V2 platforms DS4000, DS3000, DS2000 + * Rename Belgite to DS1000 + * Hardened platform bug fixes + + -- Jemston Fernando Wed, 12 Jun 2024 15:00:00 +0530 + sonic-cel-platform-modules (0.9) unstable; urgency=low * Add haliburton platform module. diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/control b/platform/broadcom/sonic-platform-modules-cel/debian/control index 0dd6eb76e00e..4a05b4821de3 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/control +++ b/platform/broadcom/sonic-platform-modules-cel/debian/control @@ -26,7 +26,27 @@ Architecture: amd64 Depends: linux-image-6.1.0-11-2-amd64-unsigned Description: kernel modules for platform devices such as led, sfp. -Package: platform-modules-belgite +Package: platform-modules-ds1000 +Architecture: amd64 +Depends: linux-image-6.1.0-11-2-amd64-unsigned +Description: kernel modules for platform devices such as led, sfp + +Package: platform-modules-questone2 +Architecture: amd64 +Depends: linux-image-6.1.0-11-2-amd64-unsigned +Description: kernel modules for platform devices such as led, sfp + +Package: platform-modules-ds3000 +Architecture: amd64 +Depends: linux-image-6.1.0-11-2-amd64-unsigned +Description: kernel modules for platform devices such as led, sfp + +Package: platform-modules-silverstone-v2 +Architecture: amd64 +Depends: linux-image-6.1.0-11-2-amd64-unsigned +Description: kernel modules for platform devices such as led, sfp + +Package: platform-modules-ds2000 Architecture: amd64 Depends: linux-image-6.1.0-11-2-amd64-unsigned Description: kernel modules for platform devices such as led, sfp diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.install deleted file mode 100644 index 6f9f8f267ed9..000000000000 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.install +++ /dev/null @@ -1,7 +0,0 @@ -belgite/systemd/pddf-platform-init.service etc/systemd/system -belgite/service/belgite-pddf-platform-monitor.service lib/systemd/system -belgite/scripts/pddf_pre_driver_install.sh usr/local/bin -belgite/scripts/pddf_post_device_create.sh usr/local/bin -belgite/utils/belgite_pddf_monitor.py usr/local/bin -belgite/pddf/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_belgite-r0/pddf -services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.install new file mode 100644 index 000000000000..24a75dfe8240 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.install @@ -0,0 +1,8 @@ +ds1000/systemd/pddf-platform-init.service etc/systemd/system +ds1000/service/ds1000-fan-control.service lib/systemd/system +ds1000/scripts/pddf_pre_driver_install.sh usr/local/bin +ds1000/scripts/pddf_post_device_create.sh usr/local/bin +ds1000/scripts/ds1000_platform_shutdown.sh usr/local/bin +ds1000/utils/ds1000_fanctld.py usr/local/bin +ds1000/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_ds1000-r0/pddf +services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.postinst similarity index 56% rename from platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.postinst rename to platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.postinst index 4abd671baec9..1b038ebcc32a 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-belgite.postinst +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds1000.postinst @@ -1,6 +1,6 @@ depmod -a /usr/local/bin/platform_api_mgnt.sh install systemctl enable pddf-platform-init.service +systemctl enable ds1000-fan-control.service systemctl start pddf-platform-init.service -systemctl enable belgite-pddf-platform-monitor.service -systemctl start belgite-pddf-platform-monitor.service +systemctl start ds1000-fan-control.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.install new file mode 100644 index 000000000000..e7a40d21a66f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.install @@ -0,0 +1,12 @@ +ds2000/scripts/ds2000_platform_shutdown.sh usr/local/bin +ds2000/scripts/pddf_pre_driver_install.sh usr/local/bin +ds2000/scripts/pddf_post_device_create.sh usr/local/bin +ds2000/scripts/pre_pddf_init.sh usr/local/bin +ds2000/scripts/sensors usr/bin +ds2000/scripts/platform_sensors.py usr/local/bin +ds2000/systemd/pddf-platform-init.service etc/systemd/system +ds2000/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_ds2000-r0/pddf +ds2000/scripts/pddf_pre_driver_install.sh usr/local/bin +ds2000/systemd/ds2000-pddf-platform-monitor.service lib/systemd/system +ds2000/utils/pddf_fan_control_sensor_refresh.py usr/local/bin +ds2000/utils/FanControl usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.postinst new file mode 100644 index 000000000000..b517026a66a6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds2000.postinst @@ -0,0 +1,7 @@ +depmod -a + +systemctl enable pddf-platform-init.service +systemctl start pddf-platform-init.service + +systemctl enable ds2000-pddf-platform-monitor.service +systemctl start ds2000-pddf-platform-monitor.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.install new file mode 100644 index 000000000000..1ea62240a8b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.install @@ -0,0 +1,11 @@ +ds3000/systemd/pddf-platform-init.service etc/systemd/system +ds3000/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_ds3000-r0/pddf +ds3000/scripts/pre_pddf_init.sh usr/local/bin +ds3000/scripts/sensors usr/bin +ds3000/scripts/platform_sensors.py usr/local/bin +ds3000/scripts/ds3000_platform_shutdown.sh usr/local/bin +ds3000/scripts/pddf_pre_driver_install.sh usr/local/bin +ds3000/scripts/pddf_post_device_create.sh usr/local/bin +ds3000/utils/afulnx_64 usr/local/bin +ds3000/utils/fpga_prog usr/local/bin +ds3000/utils/ispvm usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.postinst new file mode 100644 index 000000000000..f8b021b6248a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-ds3000.postinst @@ -0,0 +1,4 @@ +depmod -a + +systemctl enable pddf-platform-init.service +systemctl start pddf-platform-init.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init index fab61467da72..6e643e524d51 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init @@ -40,8 +40,14 @@ fi case "$1" in start) echo -n "Setting up board... " - + modprobe i2c-i801 + modprobe i2c-isch + modprobe i2c-ismt modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-gpio + modprobe i2c-mux-pca954x force-deselect-on-exit=1 modprobe dx010_wdt modprobe leds-dx010 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init index aff8503d7543..9a5bcdac4776 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init @@ -35,6 +35,15 @@ case "$1" in start) echo -n "Setting up board... " + modprobe i2c-i801 + modprobe i2c-isch + modprobe i2c-ismt + modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-gpio + modprobe i2c-mux-pca954x + modprobe smc modprobe hlx_gpio_ich modprobe dps200 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.init new file mode 100644 index 000000000000..a32be9dd97d8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.init @@ -0,0 +1,97 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: $portmap +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup questone2 board. +### END INIT INFO + + +case "$1" in +start) + echo -n "Setting up board... " + + # Loads kernel modules + modprobe i2c-ismt + modprobe i2c-i801 + modprobe i2c-isch + modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-gpio + modprobe i2c-mux-pca954x + modprobe 8021q + + modprobe questone2_baseboard_cpld + modprobe questone2_switchboard + modprobe mc24lc64t + modprobe optoe + modprobe sff_8436_eeprom + + # Add driver to support TLV - EEPROM + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + echo -n "/sys/bus/i2c/devices/i2c-${devnum}" > /tmp/eeprom_path.txt + break + fi + done + + # One platform support two hwskus, auto select the correct hwsku + # If label is not either Questone-II or Questone-IIA, then Questone-IIA is used by default + hwsku_file="/usr/share/sonic/device/x86_64-cel_questone_2-r0/default_sku" + if [ ! -f $hwsku_file ]; then + platform_path="/usr/share/sonic/device/x86_64-cel_questone_2-r0" + + sleep 1 # Wait for EEPROM driver initialization + hwsku=$(decode-syseeprom | grep "Label" | awk '{print $5}') + + cd ${platform_path} + if [ x$hwsku = x"Questone-II" ];then + echo "Questone_2 t1" > $hwsku_file + ln -sf ./Questone_2/platform.json platform.json + ln -sf ./Questone_2/platform_components.json platform_components.json + ln -sf ./Questone_2/custom_led.bin custom_led.bin + else + echo "Questone_2A t1" > $hwsku_file + ln -sf ./Questone_2A/platform.json platform.json + ln -sf ./Questone_2A/platform_components.json platform_components.json + ln -sf ./Questone_2A/custom_led.bin custom_led.bin + fi + fi + + # SONiC LED control policy + ipmitool raw 0x3a 0x0f 0x02 0x00 + # Set status led to green blinking 1Hz to indicate NOS take control + ipmitool raw 0x3a 0x0a 0x00 0x06 + # Set Alarm LED off + ipmitool raw 0x3a 0x0c 0x00 0x03 0x63 0x00 + # PSU and FAN LED are in default controlled by CPLD + + echo "done." + ;; + +stop) + if [ -f /tmp/eeprom_path.txt ]; then + echo 0x56 > `cat /tmp/eeprom_path.txt`/delete_device + fi + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-questone2 {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.install new file mode 100644 index 000000000000..b08bfe00d4c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.install @@ -0,0 +1,9 @@ +questone2/cfg/questone2-modules.conf etc/modules-load.d +questone2/cfg/questone2-modprobe.conf etc/modprobe.d +questone2/systemd/platform-modules-questone2.service lib/systemd/system +questone2/cfg/pid_config_questone2.ini usr/local/etc +questone2/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_questone_2-r0 +questone2/scripts/questone2_platform_shutdown.sh usr/local/bin +questone2/scripts/sensors usr/bin +questone2/scripts/platform_sensors.py usr/local/bin +services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.postinst new file mode 100644 index 000000000000..7a7371851fd0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-questone2.postinst @@ -0,0 +1,6 @@ +depmod -a + +/usr/local/bin/platform_api_mgnt.sh install + +systemctl enable platform-modules-questone2.service +systemctl start platform-modules-questone2.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init index 977cdac06000..75edea4c0066 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init @@ -16,6 +16,16 @@ start) echo -n "Setting up board... " # Add driver to support HW + modprobe i2c-ismt + modprobe i2c-i801 + modprobe i2c-isch + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-gpio + modprobe i2c-mux-pca954x + modprobe ipmi_devintf + modprobe ipmi_si + modprobe i2c-dev modprobe ipmi_devintf modprobe ipmi_si @@ -28,14 +38,27 @@ start) devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` if [[ $devname == 'SMBus iSMT adapter at '* ]]; then echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-${devnum}/new_device - break + echo -n "/sys/bus/i2c/devices/i2c-${devnum}" > /tmp/eeprom_path.txt + break fi done + sleep 1 + # SONiC LED control policy + ipmitool raw 0x3a 0x0f 0x02 0x00 + # Set status led to green blinking 1Hz to indicate NOS take control + ipmitool raw 0x3a 0x0a 0x00 0x06 + # Set Alarm LED off + ipmitool raw 0x3a 0x0c 0x00 0x03 0x63 0x00 + # PSU is in default controlled by CPLD + echo "done." ;; stop) + if [ -f /tmp/eeprom_path.txt ]; then + echo 0x56 > `cat /tmp/eeprom_path.txt`/delete_device + fi echo "done." ;; diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install index 31fc4fd3bd6d..08923fedaf6a 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install @@ -1,4 +1,7 @@ seastone2/cfg/seastone2-modules.conf etc/modules-load.d seastone2/systemd/platform-modules-seastone2.service lib/systemd/system seastone2/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_seastone_2-r0 +seastone2/scripts/seastone2_platform_shutdown.sh usr/local/bin +seastone2/scripts/sensors usr/bin +seastone2/scripts/platform_sensors.py usr/local/bin services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst index f232a2cac59d..fc5257b98494 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst @@ -1,5 +1,6 @@ depmod -a -systemctl enable platform-modules-seastone2.service -systemctl start platform-modules-seastone2.service /usr/local/bin/platform_api_mgnt.sh install + +systemctl enable platform-modules-seastone2.service +systemctl start platform-modules-seastone2.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.install new file mode 100644 index 000000000000..15e497039647 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.install @@ -0,0 +1,13 @@ +silverstone-v2/systemd/pddf-platform-init.service etc/systemd/system +silverstone-v2/service/silverstone-v2-pddf-platform-monitor.service lib/systemd/system +silverstone-v2/scripts/silverstone_v2_platform_shutdown.sh usr/local/bin +silverstone-v2/scripts/pddf_pre_driver_install.sh usr/local/bin +silverstone-v2/scripts/pddf_post_device_create.sh usr/local/bin +silverstone-v2/scripts/pre_pddf_init.py usr/local/bin +silverstone-v2/scripts/sensors usr/bin +silverstone-v2/scripts/platform_sensors.py usr/local/bin +silverstone-v2/utils/pddf_fan_control_sensor_refresh.py usr/local/bin +silverstone-v2/utils/pddf_sensor_list_refresh.py usr/local/bin +silverstone-v2/utils/FanControl usr/local/bin +silverstone-v2/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_silverstone_v2-r0/pddf +services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.postinst new file mode 100644 index 000000000000..aa8cac74fd80 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone-v2.postinst @@ -0,0 +1,6 @@ +depmod -a +/usr/local/bin/platform_api_mgnt.sh install +systemctl enable silverstone-v2-pddf-platform-monitor.service +systemctl start silverstone-v2-pddf-platform-monitor.service +systemctl enable pddf-platform-init.service +systemctl start pddf-platform-init.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init index eb003599ec61..38895aff2b3b 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init @@ -11,30 +11,105 @@ # Short-Description: Setup SilverStone board. ### END INIT INFO - case "$1" in start) echo -n "Setting up board... " + modprobe i2c-i801 + modprobe i2c-isch + modprobe i2c-ismt + modprobe i2c-mux + modprobe i2c-smbus + modprobe coretemp + modprobe ipmi_devintf + modprobe ipmi_si + modprobe i2c-dev - modprobe baseboard-lpc - modprobe switchboard - modprobe mc24lc64t modprobe ipmi_devintf + modprobe baseboard-lpc + modprobe cls-i2c-mux-pca954x + modprobe cls-switchboard + modprobe xcvr-cls + modprobe switch_cpld - # Instantiate TLV EEPROM device on I801 bus + sleep 1 + + for i in {0..3} + do + echo -2 > /sys/devices/pci0000:00/0000:00:1c.0/0000:09:00.0/ocores-i2c.3/i2c-3/3-007$i/idle_state + done + + # Instantiate TLV EEPROM device on I801 bus devname=`cat /sys/bus/i2c/devices/i2c-0/name` if [[ $devname == 'SMBus I801 adapter at '* ]]; then echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/new_device fi + + # Clear system cache decode-syseeprom --init 2> /dev/null & + sleep 1 + + # Attach switchboard CPLD i2c device + echo switch_cpld 0x30 > /sys/bus/i2c/devices/i2c-4/new_device + + # Attach optical Module EEPROM + # use optoe2 for SFP+. + for i in {1..2} + do + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-$i/new_device + done + + # use optoe3 for QSFP-DD. + for i in {10..41} + do + echo optoe3 0x50 > /sys/bus/i2c/devices/i2c-$i/new_device + done + + # SONiC LED control policy + ## Disable BMC LED control + ipmitool raw 0x3a 0x09 0x02 0x00 + ## Set status led to green blinking 1Hz to indicate NOS take control + ipmitool raw 0x3a 0x03 0x00 0x02 0x62 0xdd + ## Set Alarm LED off + ipmitool raw 0x3a 0x03 0x00 0x02 0x63 0xff + ## Set PSU HW control + ipmitool raw 0x3a 0x03 0x00 0x02 0x61 0x10 + ## Set FAN HW control + ipmitool raw 0x3a 0x03 0x00 0x02 0x65 0x10 + /bin/sh /usr/local/bin/platform_api_mgnt.sh init echo "done." ;; stop) + #TLV eeprom + if [ -d /sys/bus/i2c/devices/i2c-0/0-0056 ]; then + echo 0x56 > /sys/bus/i2c/devices/i2c-0/delete_device + fi + + #switchcpld i2c + if [ -d /sys/bus/i2c/devices/i2c-4/4-0030 ]; then + echo 0x30 > /sys/bus/i2c/devices/i2c-4/delete_device + fi + + #sfp+ module + for i in {1..2} + do + if [ -d /sys/bus/i2c/devices/i2c-$i/$i-0050 ]; then + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/delete_device + fi + done + + #qsfp-DD + for i in {10..41} + do + if [ -d /sys/bus/i2c/devices/i2c-$i/$i-0050 ]; then + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/delete_device + fi + done + echo "done." ;; @@ -48,4 +123,4 @@ force-reload|restart) ;; esac -exit 0 \ No newline at end of file +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install index 73fa4b90a4fc..0a973ed8d678 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install @@ -1,5 +1,6 @@ silverstone/scripts/sensors usr/bin silverstone/scripts/platform_sensors.py usr/local/bin +silverstone/scripts/silverstone_platform_shutdown.sh usr/local/bin silverstone/cfg/silverstone-modules.conf etc/modules-load.d silverstone/systemd/platform-modules-silverstone.service lib/systemd/system silverstone/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-cel_silverstone-r0 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst index feb9cf45c219..f5dfe16c0bbb 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst @@ -1,5 +1,6 @@ depmod -a -systemctl enable platform-modules-silverstone.service -systemctl start platform-modules-silverstone.service /usr/local/bin/platform_api_mgnt.sh install + +systemctl enable platform-modules-silverstone.service +systemctl start platform-modules-silverstone.service diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/rules b/platform/broadcom/sonic-platform-modules-cel/debian/rules index 7c81e2496f1d..bcbcdcfd3e7c 100755 --- a/platform/broadcom/sonic-platform-modules-cel/debian/rules +++ b/platform/broadcom/sonic-platform-modules-cel/debian/rules @@ -6,7 +6,8 @@ export KBUILD_EXTRA_SYMBOLS := /sonic/platform/pddf/i2c/Module.symvers.PDDF KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= dx010 haliburton silverstone seastone2 belgite + +MODULE_DIRS:= dx010 haliburton silverstone seastone2 ds1000 questone2 silverstone-v2 ds2000 ds3000 %: dh $@ @@ -14,22 +15,13 @@ MODULE_DIRS:= dx010 haliburton silverstone seastone2 belgite override_dh_auto_build: (for mod in $(MODULE_DIRS); do \ make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ - if [ $$mod = "seastone2" ]; then \ - cd $(MOD_SRC_DIR)/services/platform_api; \ - python3 -m build --wheel --no-isolation --outdir $(MOD_SRC_DIR)/$${mod}/modules; \ - continue; \ + if [ -d $(MOD_SRC_DIR)/$${mod}/pddf ]; then \ + cd $(MOD_SRC_DIR)/$${mod}/pddf; \ + else \ + cd $(MOD_SRC_DIR)/$${mod}; \ fi; \ - if [ $$mod = "belgite" ]; then \ - cd $(MOD_SRC_DIR); \ - if [ -d $(MOD_SRC_DIR)/$${mod}/pddf ]; then \ - cd $(MOD_SRC_DIR)/$${mod}/pddf; \ - python3 -m build --wheel --no-isolation --outdir $(MOD_SRC_DIR)/$${mod}/pddf; \ - echo "Finished making pddf whl package for $$mod"; \ - fi; \ - continue; \ - fi; \ - cd $(MOD_SRC_DIR)/$${mod}; \ - python3 -m build --wheel --no-isolation --outdir $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + echo "Finished making sonic_platform whl package for $$mod"; \ done) override_dh_auto_install: @@ -46,7 +38,5 @@ override_dh_clean: dh_clean (for mod in $(MODULE_DIRS); do \ make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ - if [ -f $(MOD_SRC_DIR)/$${mod}/pddf/*.whl ]; then \ - rm -f $(MOD_SRC_DIR)/$${mod}/pddf/*.whl; \ - fi; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ done) diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/ds1000/modules/Makefile similarity index 100% rename from platform/broadcom/sonic-platform-modules-cel/belgite/modules/Makefile rename to platform/broadcom/sonic-platform-modules-cel/ds1000/modules/Makefile diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/ds1000/modules/mc24lc64t.c similarity index 100% rename from platform/broadcom/sonic-platform-modules-cel/belgite/modules/mc24lc64t.c rename to platform/broadcom/sonic-platform-modules-cel/ds1000/modules/mc24lc64t.c diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/modules/pddf_custom_psu.c b/platform/broadcom/sonic-platform-modules-cel/ds1000/modules/pddf_custom_psu.c similarity index 100% rename from platform/broadcom/sonic-platform-modules-cel/belgite/modules/pddf_custom_psu.c rename to platform/broadcom/sonic-platform-modules-cel/ds1000/modules/pddf_custom_psu.c diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/modules/pddf_custom_wdt.c b/platform/broadcom/sonic-platform-modules-cel/ds1000/modules/pddf_custom_wdt.c new file mode 100644 index 000000000000..77e8ff7d44a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/modules/pddf_custom_wdt.c @@ -0,0 +1,734 @@ +/*************************************************************************** + * Copyright (C) 2021 Celestica Corp * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_CONTROL_BASE 0xA100 +#define TEST_SCRATCH_REG 0xA101 +#define REBOOT_CAUSE_REG 0xA105 +#define WDT_SET_TIMER_H_BIT_REG 0xA161 +#define WDT_SET_TIMER_M_BIT_REG 0xA162 +#define WDT_SET_TIMER_L_BIT_REG 0xA163 +#define WDT_TIMER_H_BIT_REG 0xA164 +#define WDT_TIMER_M_BIT_REG 0xA165 +#define WDT_TIMER_L_BIT_REG 0xA166 +#define WDT_ENABLE_REG 0xA167 +#define WDT_FEED_REG 0xA168 +#define WDT_PUNCH_REG 0xA169 +#define WDT_START_FEED 0x01 +#define WDT_STOP_FEED 0x00 + +#define POWER_CYCLE_RESET 0x00 +#define POWER_ON_RESET 0x11 +#define SOFT_SET_WARM_RESET 0x22 +#define SOFT_SET_COLD_RESET 0x33 +#define CPU_WARM_RESET 0x44 +#define CPU_COLD_RESET 0x55 +#define CPU_GPIO_WARM_RESET 0x66 +#define WDT_RESET 0x77 +#define CPU_OVERLOAD_RESET 0x88 +#define INSUFFICIENT_FAN_SPEED_RESET 0xAA + + +#define MAX_TIMER_VALUE 0xffffff +#define DEFUALT_TIMER_VALUE 180000 /* 180s */ +#define WDT_ENABLE 0x01 +#define WDT_DISABLE 0x00 +#define WDT_RESTART 0x00 +#define DRV_NAME "cpld_wdt" +#define DRV_VERSION "1.0.0" +#define DEV_NAME "cpld_wdt" + +struct wdt_data { + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + int timeout; + int timer_val; + char caused_reboot; /* last reboot was by the watchdog */ + struct resource *res; +}; + +struct cpld_wdt_private { + struct platform_device *pdev; + struct watchdog_device wddev; + struct cdev cdev; + struct miscdevice mdev; + bool suspended; + struct wdt_data wdat; +}; + +//struct class *cpld_wdt; +static const int max_timeout = MAX_TIMER_VALUE; + +static int timeout = DEFUALT_TIMER_VALUE; /* default 180s */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Start watchdog timer on module load with" + " given initial timeout(unit: ms)." + " Zero (default) disables this feature."); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0644); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int watchdog_get_timeleft(struct cpld_wdt_private *wdt) +{ + int time = 0; + + mutex_lock(&wdt->wdat.lock); + + time = inb(WDT_TIMER_H_BIT_REG); + time = time << 8 | inb(WDT_TIMER_M_BIT_REG); + time = time << 8 | inb(WDT_TIMER_L_BIT_REG); + time = time/1000; + mutex_unlock(&wdt->wdat.lock); + + return time; +} +static int watchdog_get_timeout(struct cpld_wdt_private *wdt) +{ + int timeout = 0; + if(!wdt) + return -EINVAL; + + mutex_lock(&wdt->wdat.lock); + timeout = inb(WDT_SET_TIMER_H_BIT_REG); + timeout = timeout << 8 | inb(WDT_SET_TIMER_M_BIT_REG); + timeout = timeout << 8 | inb(WDT_SET_TIMER_L_BIT_REG); + timeout=timeout/1000; + mutex_unlock(&wdt->wdat.lock); + + return timeout; +} +static int watchdog_set_timeout(struct cpld_wdt_private *wdt, unsigned int timeout) +{ + unsigned char val = 0; + if(!wdt) + return -EINVAL; + + if (timeout <= 0 + || timeout > max_timeout) { + pr_err("watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&wdt->wdat.lock); + + wdt->wdat.timeout = timeout; + if (timeout > MAX_TIMER_VALUE) { + wdt->wdat.timer_val = MAX_TIMER_VALUE; + } else { + wdt->wdat.timer_val = timeout; + } + /* Set timer value */ + //pr_crit("Watchdog Timeout:0x%06x\n", wdt->wdat.timer_val); + + outb((wdt->wdat.timer_val >> 16) & 0xff, WDT_SET_TIMER_H_BIT_REG); + outb((wdt->wdat.timer_val >> 8) & 0xff, WDT_SET_TIMER_M_BIT_REG); + outb(wdt->wdat.timer_val & 0xff, WDT_SET_TIMER_L_BIT_REG); + + mutex_unlock(&wdt->wdat.lock); + + return 0; +} + +static int watchdog_ping(struct cpld_wdt_private *wdt) +{ + if(!wdt) + return -EINVAL; + + mutex_lock(&wdt->wdat.lock); + + /* start feed watchdog */ + outb(WDT_START_FEED, WDT_FEED_REG); + /* stop feed watchdog */ + outb(WDT_STOP_FEED, WDT_FEED_REG); + + mutex_unlock(&wdt->wdat.lock); + + return 0; +} + +static void watchdog_keepalive(struct cpld_wdt_private *wdt) +{ + unsigned char val = 0; + if(!wdt) + return; + + mutex_lock(&wdt->wdat.lock); + + val = inb(WDT_FEED_REG); + + val &= 0x1; + + val = ~val; + + val &= 0x1; + /* start feed watchdog */ + outb(val, WDT_FEED_REG); + + mutex_unlock(&wdt->wdat.lock); + return; +} + +static int watchdog_start(struct cpld_wdt_private *wdt) +{ + if(!wdt) + return -EINVAL; + + /* Make sure we don't die as soon as the watchdog is enabled below */ + //watchdog_keepalive(); + mutex_lock(&wdt->wdat.lock); + outb(WDT_ENABLE, WDT_ENABLE_REG); + outb(WDT_RESTART, WDT_PUNCH_REG); + mutex_unlock(&wdt->wdat.lock); + + return 0; +} + +static int watchdog_stop(struct cpld_wdt_private *wdt) +{ + if(!wdt) + return -EINVAL; + + mutex_lock(&wdt->wdat.lock); + outb(WDT_DISABLE, WDT_ENABLE_REG); + mutex_unlock(&wdt->wdat.lock); + + return 0; +} + +static char watchdog_get_reason(struct cpld_wdt_private *p) +{ + char status = 0; + + if (!p) + return -1; + mutex_lock(&p->wdat.lock); + status = inb(REBOOT_CAUSE_REG); + mutex_unlock(&p->wdat.lock); + + return status; +} + +static bool watchdog_is_running(struct cpld_wdt_private *wdt) +{ + /* + * if we fail to determine the watchdog's status assume it to be + * running to be on the safe side + */ + + bool is_running = true; + + mutex_lock(&wdt->wdat.lock); + is_running = inb(WDT_ENABLE_REG); + mutex_unlock(&wdt->wdat.lock); + + return is_running; +} + +static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = DRV_NAME, +}; + +static ssize_t identity_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + if(!wdt) + return -EINVAL; + return sprintf(buf, "%s\n", wdt->wdat.ident.identity); +} + +static DEVICE_ATTR_RO(identity); + + +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + bool state = watchdog_is_running(wdt); + if(true == state) + return sprintf(buf, "active\n"); + else + return sprintf(buf, "inactive\n"); +} + +static DEVICE_ATTR_RO(state); + +static ssize_t status_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + unsigned int status; + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + if(!wdt) + return -EINVAL; + + return sprintf(buf, "0x%x\n", status); +} + +static DEVICE_ATTR_RO(status); + +static ssize_t reason_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char bootstatus; + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + if(!wdt) + return -EINVAL; + + bootstatus = watchdog_get_reason(wdt); + + return sprintf(buf, "0x%02x\n", bootstatus); +} + +static DEVICE_ATTR_RO(reason); + +static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + unsigned int timeleft; + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + if(!wdt) + return -EINVAL; + + timeleft = watchdog_get_timeleft(wdt); + + return sprintf(buf, "%u\n", timeleft); + +} + +static DEVICE_ATTR_RO(timeleft); + + +static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + unsigned int timeout; + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + if(!wdt) + return -EINVAL; + + timeout = watchdog_get_timeout(wdt); + + return sprintf(buf, "%u\n", timeout); +} +static DEVICE_ATTR_RO(timeout); + + +static struct attribute *wdt_attrs[] = { + &dev_attr_state.attr, + &dev_attr_identity.attr, + &dev_attr_status.attr, + &dev_attr_reason.attr, + &dev_attr_timeleft.attr, + &dev_attr_timeout.attr, + NULL, +}; + +static const struct attribute_group wdt_group = { + .attrs = wdt_attrs, +}; + +static int watchdog_open(struct inode *inode, struct file *file) +{ + struct cpld_wdt_private *wdt; + + wdt = container_of(file->private_data, struct cpld_wdt_private, mdev); + + /* If the watchdog is alive we don't need to start it again */ + + if (test_and_set_bit(0, &wdt->wdat.opened)) + return -EBUSY; + + //watchdog_start(wdt); + + if (nowayout) + __module_get(THIS_MODULE); + + wdt->wdat.expect_close = 0; + + + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + struct cpld_wdt_private *p; + p = container_of(file->private_data, struct cpld_wdt_private, mdev); + + if(!p) + return -EINVAL; + + clear_bit(0, &p->wdat.opened); + + if (!p->wdat.expect_close) { + //watchdog_keepalive(p); + //pr_crit("Unexpected close, Not stopping watchdog!\n"); + } else if (!nowayout) { + //pr_crit("Cpld Watchdog Stopped!\n"); + watchdog_stop(p); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct cpld_wdt_private *p; + p = container_of(file->private_data, struct cpld_wdt_private, mdev); + + if(!p) + return -EINVAL; + + + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&p->wdat.lock); + p->wdat.expect_close = expect_close; + mutex_unlock(&p->wdat.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(p); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + unsigned int val; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + struct cpld_wdt_private *p; + p = container_of(file->private_data, struct cpld_wdt_private, mdev); + if(!p) + return -EINVAL; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &p->wdat.ident, + sizeof(p->wdat.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_is_running(p); + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + //status = watchdog_get_bootstatus(p); + return put_user(status, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)){ + return -EFAULT; + } + + if (new_options & WDIOS_DISABLECARD){ + return watchdog_stop(p); + } + + if (new_options & WDIOS_ENABLECARD){ + return watchdog_start(p); + } + + return 0; + + case WDIOC_KEEPALIVE: + watchdog_keepalive(p); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + new_timeout = new_timeout*1000; + if (watchdog_set_timeout(p, new_timeout)) + return -EINVAL; + + val = watchdog_get_timeout(p); + return put_user(val, uarg.i); + case WDIOC_GETTIMEOUT: + val = watchdog_get_timeout(p); + return put_user(val, uarg.i); + + case WDIOC_GETTIMELEFT: + val = watchdog_get_timeleft(p); + return put_user(val, uarg.i); + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + //watchdog_stop(p); + + pr_err("CPLD Watchdog did not Stop!\n"); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + //.minor = WATCHDOG_MINOR, + .name = DEV_NAME, + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int cpld_wdt_probe(struct platform_device *pdev) +{ + int wdt_reboot_cause, err = 0; + unsigned char ver = 0; + struct device *dev = &pdev->dev; + + struct cpld_wdt_private *p; + + p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + + mutex_init(&(p->wdat.lock)); + + p->wdat.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING + | WDIOC_GETTIMELEFT; + + snprintf(p->wdat.ident.identity, + sizeof(p->wdat.ident.identity), "%s", DRV_NAME); + + wdt_reboot_cause = inb(REBOOT_CAUSE_REG); // REBOOT_CAUSE + p->wdat.caused_reboot = wdt_reboot_cause; + ver = inb(WDT_CONTROL_BASE); + pr_info("Watchdog CPLD Version:0x%02x\n", + ver); + + if (timeout) { + if (timeout <= 0 + || timeout > max_timeout) { + pr_err("starting timeout out of range\n"); + err = -EINVAL; + return err; + } + + //watchdog_start(p); + + + if (timeout > MAX_TIMER_VALUE) { + watchdog_set_timeout(p, MAX_TIMER_VALUE); + } else { + watchdog_set_timeout(p, timeout); + } + + if (nowayout) + __module_get(THIS_MODULE); + + pr_info("watchdog started with initial timeout of %u Second(s)\n", + timeout/1000); + } + + err = watchdog_set_timeout(p, timeout); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + p->mdev = watchdog_miscdev; + err = misc_register(&p->mdev); + if (err) { + pr_err("cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + return err;; + } + + /*p->wdat.res = platform_get_resource(pdev, IORESOURCE_IO, WDT_CONTROL_BASE); + if (!p->wdat.res) + return -ENODEV; + + if (!devm_request_region(dev, p->wdat.res->start, + resource_size(p->wdat.res), + pdev->name)) { + return -EBUSY; + } + */ + err = sysfs_create_group(&pdev->dev.kobj, &wdt_group); + if (err) { + printk(KERN_ERR "Cannot create sysfs for cpld_wdt.\n"); + return err; + } + + platform_set_drvdata(pdev, p); + dev_set_drvdata(dev, p); + + pr_info("initialized. sec (nowayout=%d)\n", + nowayout); + + return 0; +} + +static int cpld_wdt_remove(struct platform_device *pdev) +{ + struct cpld_wdt_private *p = platform_get_drvdata(pdev); + + if (p) { + sysfs_remove_group(&pdev->dev.kobj, &wdt_group); + misc_deregister(&p->mdev); + unregister_reboot_notifier(&watchdog_notifier); + } + return 0; +} + +static struct platform_driver cpld_wdt_driver = { + .probe = cpld_wdt_probe, + .remove = cpld_wdt_remove, + .driver = { + .name = DRV_NAME, + }, +}; + +static struct resource cpld_wdt_resources[] = { + { + .start = 0xA100, + .end = 0xA1F2, + .flags = IORESOURCE_IO, + }, +}; + +static void wdt_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cpld_wdt_dev = { + .name = DRV_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cpld_wdt_resources), + .resource = cpld_wdt_resources, + .dev = { + .release = wdt_dev_release, + } +}; + +static int __init cpld_wdt_init_module(void) +{ + int err = 0; + + err = platform_device_register(&cpld_wdt_dev); + err += platform_driver_register(&cpld_wdt_driver); + if(err < 0) + pr_info("Platform Device/Driver Register Failed. err:%d\n", err); + + pr_info("CPLD WatchDog Timer Driver v%s\n", DRV_VERSION); + return err; +} + +static void __exit cpld_wdt_cleanup_module(void) +{ + platform_driver_unregister(&cpld_wdt_driver); + platform_device_unregister(&cpld_wdt_dev); + pr_info("Watchdog Module Unloaded\n"); +} + +module_init(cpld_wdt_init_module); +module_exit(cpld_wdt_cleanup_module); + + +MODULE_DESCRIPTION("Cpld Watchdog Driver"); +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Nicholas "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/setup.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/setup.py new file mode 100644 index 000000000000..db095d23534a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/setup.py @@ -0,0 +1,27 @@ +import os +from setuptools import setup +os.listdir + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Celestica Platforms based on PDDF', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + packages=['sonic_platform'], + 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.9', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/__init__.py new file mode 100644 index 000000000000..d3c24cb008dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import platform diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/chassis.py similarity index 71% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/chassis.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/chassis.py index ed2e339461ac..e325c0af5569 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/chassis.py @@ -5,21 +5,24 @@ ############################################################################# import os import time +import sys +import subprocess +import re try: from sonic_platform_pddf_base.pddf_chassis import PddfChassis from sonic_platform_pddf_base.pddf_eeprom import PddfEeprom from sonic_platform_base.chassis_base import ChassisBase - from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.thermal import Thermal from sonic_platform.watchdog import Watchdog - import sys - import subprocess from sonic_py_common import device_info from sonic_platform_base.sfp_base import SfpBase except ImportError as e: raise ImportError(str(e) + "- required module not found") -NUM_COMPONENT = 2 +NUM_COMPONENTS = 4 +NUM_SENSORS = 4 +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" class Chassis(PddfChassis): """ @@ -31,17 +34,23 @@ def __init__(self, pddf_data=None, pddf_plugin_data=None): PddfChassis.__init__(self, pddf_data, pddf_plugin_data) (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + self._watchdog = None + self._airflow_direction = None self.__initialize_components() - self.sfp_port_list = list(range(49, 56+1)) - for port_idx in self.sfp_port_list: - present = self.get_sfp(port_idx).get_presence() - self.sfp_status_dict[port_idx] = '1' if present else '0' + for sfp in self._sfp_list: + present = sfp.get_presence() + self.sfp_status_dict[sfp.index] = '1' if present else '0' + + # PDDF doesn't support CPU internal temperature sensor + # Hence it is created from chassis init override and + # handled appropriately in thermal APIs + self._thermal_list.append(Thermal(NUM_SENSORS)) def __initialize_components(self): from sonic_platform.component import Component - for index in range(0, NUM_COMPONENT): + for index in range(0, NUM_COMPONENTS): component = Component(index) self._component_list.append(component) @@ -99,12 +108,18 @@ def get_reboot_cause(self): with open("/sys/devices/platform/cpld_wdt/reason", "r") as f: hw_reboot_cause = f.read().strip() - if hw_reboot_cause == "0x77": + if hw_reboot_cause == "0x99": + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'NPU overload reset' + elif hw_reboot_cause == "0x88": + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'CPU overload reset' + elif hw_reboot_cause == "0x77": reboot_cause = self.REBOOT_CAUSE_WATCHDOG description = 'Hardware Watchdog Reset' elif hw_reboot_cause == "0x66": reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER - description = 'GPIO Request Warm Reset' + description = 'GPIO Warm Reset' elif hw_reboot_cause == "0x55": reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'CPU Cold Reset' @@ -112,19 +127,34 @@ def get_reboot_cause(self): reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = 'CPU Warm Reset' elif hw_reboot_cause == "0x33": - reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Soft-Set Cold Reset' elif hw_reboot_cause == "0x22": - reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Soft-Set Warm Reset' elif hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_POWER_LOSS - description = 'Power Loss' + description = 'Power Loss' + elif hw_reboot_cause == "0x00": + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Cold Powercycle' + if os.path.isfile(HW_REBOOT_CAUSE_FILE): + with open(HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + if match is not None: + if match.group(1) == 'temp_fatal': + description = 'Fatal temperature trip [Time:{}]'.format(match.group(2)) + elif match.group(1) == 'temp_critical': + description = 'Critical temperature reboot [Time:{}]'.format(match.group(2)) + elif match.group(1) == 'system': + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'System cold reboot' else: reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = 'Unkown Reason' - return (reboot_cause, description) + return (reboot_cause, description) def get_revision(self): version_str = self._eeprom.revision_str() @@ -133,23 +163,20 @@ def get_revision(self): return str(bytearray(version_str, 'ascii')[0]) return version_str - + @staticmethod def get_position_in_parent(): return -1 - + @staticmethod def is_replaceable(): return False def set_status_led(self, color): - color_dict = { - 'green': "STATUS_LED_COLOR_GREEN", - 'red': "STATUS_LED_COLOR_AMBER", - 'amber': "STATUS_LED_COLOR_AMBER", - 'off': "STATUS_LED_COLOR_OFF" - } - return self.set_system_led("SYS_LED", color_dict.get(color, "STATUS_LED_COLOR_OFF")) + if color == self.get_system_led("SYS_LED"): + return True + + return self.set_system_led("SYS_LED", color) def get_status_led(self): return self.get_system_led("SYS_LED") @@ -224,13 +251,14 @@ def get_change_event(self, timeout=0): time_period = timeout/float(1000) #Convert msecs to secs while time.time() < (start_time + time_period) or timeout == 0: - for port_idx in self.sfp_port_list: + for sfp in self._sfp_list: + port_idx = sfp.index if self.sfp_status_dict[port_idx] == SFP_REMOVED and \ - self.get_sfp(port_idx).get_presence() == SFP_PRESENT: + sfp.get_presence() == SFP_PRESENT: sfp_dict[port_idx] = SFP_INSERTED self.sfp_status_dict[port_idx] = SFP_INSERTED elif self.sfp_status_dict[port_idx] == SFP_INSERTED and \ - self.get_sfp(port_idx).get_presence() == SFP_ABSENT: + sfp.get_presence() == SFP_ABSENT: sfp_dict[port_idx] = SFP_REMOVED self.sfp_status_dict[port_idx] = SFP_REMOVED @@ -240,3 +268,21 @@ def get_change_event(self, timeout=0): time.sleep(0.5) return True, {'sfp':{}} # Timeout + + def get_airflow_direction(self): + if self._airflow_direction == None: + try: + vendor_extn = self._eeprom.get_vendor_extn() + airflow_type = vendor_extn.split()[2][2:4] # Either 0xFB or 0xBF + if airflow_type == 'FB': + direction = 'exhaust' + elif airflow_type == 'BF': + direction = 'intake' + else: + direction = 'N/A' + except (AttributeError, IndexError): + direction = 'N/A' + + self._airflow_direction = direction + + return self._airflow_direction diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/component.py similarity index 52% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/component.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/component.py index 3b68c5759b5a..23efdbda441a 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/component.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/component.py @@ -1,128 +1,168 @@ -#!/usr/bin/env python - -############################################################################# -# Celestica -# -# Component contains an implementation of SONiC Platform Base API and -# provides the components firmware management function -# -############################################################################# - -import subprocess -import time - -try: - from sonic_platform_base.component_base import ComponentBase - #from helper import APIHelper -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -SWCPLD_VERSION_PATH = ['i2cget', '-y', '-f', '2', '0x32', '0'] -BIOS_VERSION_PATH = ['dmidecode', '-s', 'bios-version'] -COMPONENT_NAME_LIST = ["SWCPLD", "BIOS"] -COMPONENT_DES_LIST = ["Used for managing the chassis and SFP+ ports (49-56)", - "Basic Input/Output System"] - - -class Component(ComponentBase): - """Platform-specific Component class""" - - DEVICE_TYPE = "component" - - def __init__(self, component_index): - ComponentBase.__init__(self) - self.index = component_index - self.name = self.get_name() - - def __get_bios_version(self): - # Retrieves the BIOS firmware version - version = "N/A" - - try: - p = subprocess.Popen(BIOS_VERSION_PATH, stdout=subprocess.PIPE, universal_newlines=True) - data = p.communicate() - version = data[0].strip() - except IOError: - pass - - return version - - def __get_cpld_version(self): - version = "N/A" - try: - p = subprocess.Popen(SWCPLD_VERSION_PATH, stdout=subprocess.PIPE, universal_newlines=True) - data = p.communicate() - ver = int(data[0].strip(), 16) - version = "{0}.{1}".format(ver >> 4, ver & 0x0F) - except (IOError, ValueError): - pass - - return version - - def get_name(self): - """ - Retrieves the name of the component - Returns: - A string containing the name of the component - """ - return COMPONENT_NAME_LIST[self.index] - - def get_description(self): - """ - Retrieves the description of the component - Returns: - A string containing the description of the component - """ - return COMPONENT_DES_LIST[self.index] - - def get_firmware_version(self): - """ - Retrieves the firmware version of module - Returns: - string: The firmware versions of the module - """ - fw_version = None - - if self.name == "BIOS": - fw_version = self.__get_bios_version() - elif "CPLD" in self.name: - fw_version = self.__get_cpld_version() - - return fw_version - - def install_firmware(self, image_path): - """ - Install firmware to module - Args: - image_path: A string, path to firmware image - Returns: - A boolean, True if install successfully, False if not - """ - return False - - def update_firmware(self, image_path): - return False - - def get_available_firmware_version(self, image_path): - return 'N/A' - - def get_firmware_update_notification(self, image_path): - return "None" - - def get_model(self): - return 'N/A' - - def get_position_in_parent(self): - return -1 - - def get_presence(self): - return True - - def get_serial(self): - return 'N/A' - - def get_status(self): - return True - - def is_replaceable(self): - return False +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import subprocess +import re + +try: + from sonic_platform_base.component_base import ComponentBase + #from helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +COMPONENT_NAME = 0 +COMPONENT_DESC = 1 +COMPONENT_VER_CMD = 2 +COMPONENT_VER_FN = 3 +BIOS_VERSION_CMD = ['dmidecode', '-s', 'bios-version'] +ONIE_VERSION_CMD = ['cat', '/host/machine.conf'] +SWCPLD_VERSION_CMD = ['i2cget', '-y', '-f', '2', '0x32', '0'] +SSD_VERSION_CMD = ['smartctl', '-i', '/dev/sda'] + + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + self.component_list = [["BIOS", "Basic Input/Output System", BIOS_VERSION_CMD, self.__get_cmd_output],\ + ["ONIE", "Open Network Install Environment", ONIE_VERSION_CMD, self.__get_onie_version],\ + ["CPLD SW", "CPLD for board functions, watchdog and port control SFP(49-56)", SWCPLD_VERSION_CMD, self.__get_cpld_version],\ + ["SSD", "Solid State Drive - {}", SSD_VERSION_CMD, self.__get_ssd_version]] + + ComponentBase.__init__(self) + self.index = component_index + self.name = self.get_name() + + def __get_cmd_output(self): + cmd = self.component_list[self.index][COMPONENT_VER_CMD] + version = "N/A" + + try: + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) + data = p.communicate() + version = data[0].strip() + except IOError: + pass + + return version + + def __get_onie_version(self): + version = "N/A" + + ret = re.search(r"(?<=onie_version=).+[^\n]", self.__get_cmd_output()) + if ret != None: + version = ret.group(0) + + return version + + def __get_ssd_version(self): + version = "N/A" + + ret = re.search(r"Firmware Version: +(.*)[^\\]", self.__get_cmd_output()) + if ret != None: + try: + version = ret.group(1) + except (IndexError): + pass + + return version + + def __get_cpld_version(self): + version = "N/A" + + try: + ver = int(self.__get_cmd_output(), 16) + version = "{0}.{1}".format(ver >> 4, ver & 0x0F) + except (ValueError): + pass + + return version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.component_list[self.index][COMPONENT_NAME] + + def __get_ssd_desc(self, desc_format): + description = "N/A" + + ret = re.search(r"Device Model: +(.*)[^\\]", self.__get_cmd_output()) + if ret != None: + try: + description = desc_format.format(ret.group(1)) + except (IndexError): + pass + + return description + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + # For SSD get the model name from device + if self.get_name() == "SSD": + return self.__get_ssd_desc(self.component_list[self.index][COMPONENT_DESC]) + + return self.component_list[self.index][COMPONENT_DESC] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + fw_version = self.component_list[self.index][COMPONENT_VER_FN]() + + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + return False + + def update_firmware(self, image_path): + return False + + def get_available_firmware_version(self, image_path): + return 'N/A' + + def get_firmware_update_notification(self, image_path): + return "None" + + def get_model(self): + return 'N/A' + + def get_position_in_parent(self): + return -1 + + def get_presence(self): + return True + + def get_serial(self): + return 'N/A' + + def get_status(self): + return True + + def is_replaceable(self): + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/eeprom.py similarity index 81% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/eeprom.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/eeprom.py index bc1ef6420b68..5379db32a5a0 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/eeprom.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/eeprom.py @@ -6,7 +6,7 @@ class Eeprom(PddfEeprom): - _TLV_DISPLAY_VENDOR_EXT = True + _TLV_DISPLAY_VENDOR_EXT = True _TLV_INFO_MAX_LEN = 256 pddf_obj = {} plugin_data = {} @@ -58,18 +58,11 @@ def __init__(self, pddf_data=None, pddf_plugin_data=None): else: name, value = self.decoder(None, tlv) - self.eeprom_tlv_dict[code] = value + self.eeprom_tlv_dict[code] = value.strip() if (eeprom[tlv_index]) == self._TLV_CODE_CRC_32: break tlv_index += (eeprom[tlv_index+1]) + 2 - def vendor_ext_str(self): - """ - :return: the direction of fan(FB or BF, string) - """ - (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_VENDOR_EXT) - if not is_valid: - return "N/A" - return str(hex(int(results[2][2]))).replace("0x", "").upper() - # Provide the functions/variables below for which implementation is to be overwritten + def get_vendor_extn(self): + return self.eeprom_tlv_dict.get('0xFD', 'N/A') diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan.py new file mode 100644 index 000000000000..3a71e9723900 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan.py @@ -0,0 +1,153 @@ +try: + from sonic_platform_pddf_base.pddf_fan import PddfFan + import subprocess +except ImportError as e: + raise ImportError(str(e) + "- required module not found") +# ------------------------------------------------------------------ +# HISTORY: +# 5/1/2022 (A.D.) +# add function:set_status_led, +# Solve the problem that when a fan is pulled out, the Fan LED on the front panel is still green Issue-#11525 +# ------------------------------------------------------------------ + +MIN_SPEED = 40 # Percentage + +class Fan(PddfFan): + """PDDF Platform-Specific Fan class""" + + def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): + # idx is 0-based + PddfFan.__init__(self, tray_idx, fan_idx, pddf_data, pddf_plugin_data, is_psu_fan, psu_index) + + self.max_speed_rpm = 28600 #Max RPM from FAN spec + + # Remap LED color READ and OFF to AMBER as they are unsupported + self.STATUS_LED_COLOR_RED = "amber" + self.STATUS_LED_COLOR_OFF = "amber" + + def get_presence(self): + if not self.is_psu_fan: + # FANs on Ds1000 are all Fixed and present + return True + + #For PSU, FAN must be present when PSU is present + try: + cmd = ['i2cget', '-y', '-f', '0x2', '0x32', '0x41'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) + data = p.communicate() + status = int(data[0].strip(), 16) + if (self.fans_psu_index == 1 and (status & 0x10) == 0) or \ + (self.fans_psu_index == 2 and (status & 0x20) == 0): + return True + except (IOError, ValueError): + pass + + def get_status(self): + if not self.is_psu_fan: + if not self.get_presence(): + return False + + # FANs must not be operated below MIN_SPEED + target_speed = self.get_target_speed() + if target_speed < MIN_SPEED: + return False + + # FANs target speed and actual speed must + # be within specified tolerance limits + current_speed = self.get_speed() + speed_tolerance = self.get_speed_tolerance() + if abs(target_speed - current_speed) > speed_tolerance: + return False + + return True + + return super().get_status() + + # Override get_speed as PDDF retrieves the speed from the + # set PWM value which is actually the target fan speed + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan: + return super().get_speed() + + # Percentage of current FAN speed against the max FAN speed + return round(super().get_speed_rpm() * 100 / self.max_speed_rpm) + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + if self.is_psu_fan: + # Ds1000 PSU module only has EXHAUST fan + return "exhaust" + + return super().get_direction() + + def get_status_led(self): + """ + Gets the state of the fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.is_psu_fan: + return "N/A" + + return super().get_status_led() + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + + Args: + color: A string representing the color with which to set the + fan module status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + if self.is_psu_fan: + return False + + if self.get_status_led() == color: + return True + + return super().set_status_led(color) + + def get_name(self): + if self.is_psu_fan: + return "PSU {} Fan {}".format(self.fans_psu_index, self.fan_index) + else: + return "Fan {}".format(self.fantray_index) + + def is_under_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_min_th = target_speed * (1 - float(speed_tolerance) / 100) + if speed < speed_min_th: + return True + else: + return False + + def is_over_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_max_th = target_speed * (1 + float(speed_tolerance) / 100) + if speed > speed_max_th: + return True + else: + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan_drawer.py similarity index 91% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan_drawer.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan_drawer.py index ac80aad4b1eb..beec44630406 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/fan_drawer.py @@ -6,7 +6,7 @@ ############################################################################# try: - from sonic_platform_pddf_base.pddf_fan_drawer import PddfFanDrawer + from sonic_platform_pddf_base.pddf_fan_drawer import PddfFanDrawer except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -16,8 +16,8 @@ class FanDrawer(PddfFanDrawer): def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None): # idx is 0-based PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data) - - + + def set_status_led(self, color): return self._fan_list[0].set_status_led(color) @@ -31,3 +31,6 @@ def get_serial(self): def get_model(self): model = "Unknown" return model + + def get_name(self): + return "Drawer {0}".format(self.fantray_index) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/pcie.py new file mode 100644 index 000000000000..0f8bc0830384 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/pcie.py @@ -0,0 +1,15 @@ +# +# pcie_base.py +# +# Abstract base class for implementing platform-specific +# PCIE functionality for SONiC +# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +class Pcie(PcieUtil): + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/platform.py similarity index 100% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/platform.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/platform.py diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/psu.py similarity index 61% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/psu.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/psu.py index f1047bed740a..a3a7f6da8f34 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/psu.py @@ -6,12 +6,12 @@ class Psu(PddfPsu): """PDDF Platform-Specific PSU class""" - + PLATFORM_PSU_CAPACITY = 550 def __init__(self, index, pddf_data=None, pddf_plugin_data=None): PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) - + # Provide the functions/variables below for which implementation is to be overwritten def get_capacity(self): """ @@ -71,3 +71,38 @@ def get_voltage_low_threshold(self): e.g. 12.1 """ return 11.4 + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + # When AC power is not plugged into one of the PSU, the FAN of + # that PSU is driven using the power from the alternate PSU and + # because of this the PSU VOUT might read a small voltage value + # and it is misleading. Therefore the PSU VOUT is fetched from + # HW only when PSU status is OK + if self.get_status(): + return super().get_voltage() + + return 0.0 + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + # In Ds1000 PSU LED is controlled by the PSU firmware, so soft + # simulating the LED in a generic way based on the PSU status + if self.get_presence(): + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_AMBER + + return "N/A" diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/sfp.py new file mode 100644 index 000000000000..9187edb1fdf3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/sfp.py @@ -0,0 +1,36 @@ +try: + from sonic_platform_pddf_base.pddf_sfp import PddfSfp +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class Sfp(PddfSfp): + """ + PDDF Platform-Specific Sfp class + """ + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + self.index = index+1 + PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + Returns: + String that represents the current error descriptions of vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + return self.SFP_STATUS_OK + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + SFP+ don't support reset, so raise the error of NotImplemented + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/thermal.py new file mode 100644 index 000000000000..b17dfa4457df --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/thermal.py @@ -0,0 +1,105 @@ +try: + from sonic_platform_pddf_base.pddf_thermal import PddfThermal +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +import subprocess + +HIGH_THRESHOLD = 0 +LOW_THRESHOLD = 1 +HIGH_CRIT_THRESHOLD = 2 +LOW_CRIT_THRESHOLD = 3 + +NUM_SENSORS = 4 +CPU_SENSOR_STR = "CPU Internal Temp" +thermal_limits = { + # : , , , + 'Front Right Temp': [50.0, None, None, None], + 'Front Left Temp': [50.0, None, None, None], + 'Rear Right Temp': [50.0, None, None, None], + 'ASIC External Temp': [100.0, None, 105.0, None], + CPU_SENSOR_STR: [88.0, None, 91.0, None] +} + +class Thermal(PddfThermal): + """PDDF Platform-Specific Thermal class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): + # PDDF doesn't support CPU internal temperature sensor + # Hence it is created from chassis init override and + # handled appropriately in thermal APIs + self.thermal_index = index + 1 + self.is_psu_thermal = is_psu_thermal + if self.thermal_index <= NUM_SENSORS: + PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index) + # Provide the functions/variables below for which implementation is to be overwritten + + def get_name(self): + if self.thermal_index <= NUM_SENSORS: + return super().get_name() + + return CPU_SENSOR_STR + + def get_temperature(self): + if self.thermal_index <= NUM_SENSORS: + return super().get_temperature() + + temperature = 0.0 + cmd = ['cat', '/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp1_input'] + try: + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) + data = p.communicate() + temperature = int(data[0].strip())/1000.0 + except (IOError, ValueError): + pass + + return temperature + + def get_low_threshold(self): + thermal_limit = thermal_limits.get(self.get_name(), None) + if thermal_limit != None: + return thermal_limit[LOW_THRESHOLD] + + return None + + def __get_psu_high_threshold(self): + thermal_limit = None + try: + cmd = ['i2cget', '-y', '-f', '4', str(0x58 + (self.thermals_psu_index - 1)), '0x51', 'w'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) + data = p.communicate() + thermal_limit = int(data[0].strip(), 16) + except (IOError, ValueError): + pass + + return thermal_limit + + def get_high_threshold(self): + if self.is_psu_thermal: + return self.__get_psu_high_threshold() + + thermal_limit = thermal_limits.get(self.get_name(), None) + if thermal_limit != None: + return thermal_limit[HIGH_THRESHOLD] + + return None + + def get_low_critical_threshold(self): + thermal_limit = thermal_limits.get(self.get_name(), None) + if thermal_limit != None: + return thermal_limit[LOW_CRIT_THRESHOLD] + + return None + + def get_high_critical_threshold(self): + thermal_limit = thermal_limits.get(self.get_name(), None) + if thermal_limit != None: + return thermal_limit[HIGH_CRIT_THRESHOLD] + + return None + + def set_high_threshold(self, temperature): + raise NotImplementedError + + def set_low_threshold(self, temperature): + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/watchdog.py similarity index 98% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/watchdog.py rename to platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/watchdog.py index 7973e8a3cfad..d43e1d74f5e3 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/watchdog.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/pddf/sonic_platform/watchdog.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################# -# +# # Watchdog contains an implementation of SONiC Platform Base Watchdog API # ############################################################################# @@ -55,14 +55,14 @@ class CpldWatchdog(WatchdogBase): watchdog = None def __init__(self): global watchdog - self.status_path = "/sys/devices/platform/cpld_wdt/status" - self.state_path = "/sys/devices/platform/cpld_wdt/state" - self.timeout_path = "/sys/devices/platform/cpld_wdt/timeout" + self.status_path = "/sys/devices/platform/cpld_wdt/status" + self.state_path = "/sys/devices/platform/cpld_wdt/state" + self.timeout_path = "/sys/devices/platform/cpld_wdt/timeout" # Set default value with open("/sys/devices/platform/cpld_wdt/state", "r") as fd: txt = fd.read() - state = txt.strip() - self.armed = True if state == "active" else False + state = txt.strip() + self.armed = True if state == "active" else False self.timeout = DEFAULT_TIMEOUT if not watchdog: watchdog = os.open("/dev/cpld_wdt", os.O_RDWR) @@ -160,7 +160,7 @@ def arm(self, seconds): else: self._enable() self.armed = True - + ret = self.timeout except IOError as e: pass @@ -226,4 +226,3 @@ def __init__(self): CpldWatchdog.__init__(self) # Provide the functions/variables below for which implementation is to be overwritten - diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/ds1000_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/ds1000_platform_shutdown.sh new file mode 100755 index 000000000000..a1ea8ccbe4ae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/ds1000_platform_shutdown.sh @@ -0,0 +1,26 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +# CPLD CPU cold power-cycle +i2cset -f -y 2 0x32 0x18 0x0 + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_post_device_create.sh b/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_post_device_create.sh new file mode 100755 index 000000000000..9fd8364e23b6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_post_device_create.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Enable FAN WDT +sudo i2cset -y -f 2 0x32 0x30 0x01 + +# Set all FAN speed to 100% +sudo i2cset -y -f 2 0x32 0x32 0xff +sudo i2cset -y -f 2 0x32 0x36 0xff +sudo i2cset -y -f 2 0x32 0x3a 0xff + +# Set FAN LED status to GREEN +sudo i2cset -y -f 2 0x32 0x33 0x2 +sudo i2cset -y -f 2 0x32 0x37 0x2 +sudo i2cset -y -f 2 0x32 0x3b 0x2 + +# Set Alarm LED status to OFF, since it is unused in SONiC +sudo i2cset -y -f 2 0x32 0x44 0x00 + +# Set SYS LED status to GREEN +sudo i2cset -y -f 2 0x32 0x43 0xec + +echo -2 | tee /sys/bus/i2c/drivers/pca954x/*-00*/idle_state diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_pre_driver_install.sh b/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_pre_driver_install.sh similarity index 70% rename from platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_pre_driver_install.sh rename to platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_pre_driver_install.sh index 2b37a5d5f6ff..39b055c1e55a 100755 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/scripts/pddf_pre_driver_install.sh +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/scripts/pddf_pre_driver_install.sh @@ -1,5 +1,5 @@ #!/bin/bash -modprobe -r i2c_ismt +modprobe -r i2c_ismt sleep 0.1 modprobe -r i2c-i801 sleep 0.1 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/service/ds1000-fan-control.service b/platform/broadcom/sonic-platform-modules-cel/ds1000/service/ds1000-fan-control.service new file mode 100644 index 000000000000..7269080b53bc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/service/ds1000-fan-control.service @@ -0,0 +1,17 @@ +[Unit] +Description=Ds1000 Fan Control service +After=pddf-platform-init.service +Requires=pddf-platform-init.service +BindsTo=pddf-platform-init.service + +[Service] +Type=simple +ExecStart=/usr/local/bin/ds1000_fanctld.py +KillSignal=SIGTERM +SuccessExitStatus=0 + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/systemd/pddf-platform-init.service b/platform/broadcom/sonic-platform-modules-cel/ds1000/systemd/pddf-platform-init.service new file mode 100644 index 000000000000..becd98ea602e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/systemd/pddf-platform-init.service @@ -0,0 +1,15 @@ +[Unit] +Description=PDDF module and device initialization service +Before=pmon.service watchdog-control.service ds1000-fan-control.service +Before=opennsl-modules.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/pddf_util.py install +ExecStop=/usr/local/bin/pddf_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +WantedBy=opennsl-modules.service diff --git a/platform/broadcom/sonic-platform-modules-cel/ds1000/utils/ds1000_fanctld.py b/platform/broadcom/sonic-platform-modules-cel/ds1000/utils/ds1000_fanctld.py new file mode 100755 index 000000000000..9955568ac237 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds1000/utils/ds1000_fanctld.py @@ -0,0 +1,346 @@ +#!/usr/bin/python3 +# +# Copyright (C) Celestica Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# 9/16/2021 (A.D.) +# ------------------------------------------------------------------ + +try: + import os + import sys + import getopt + import subprocess + import re + import time + import signal + from sonic_platform import platform + from sonic_py_common import daemon_base +except ImportError as e: + raise ImportError('%s - required module not found' % repr(e)) + +# Constants +NOMINAL_TEMP = 30 # degree C +MODULE_NAME = 'ds1000fanctld' +SP_LOW_TEMP = 0 +SP_HIGH_TEMP = 1 +SP_CRITICAL_TEMP = 2 +SP_FATAL_TEMP = 3 +SP_REF_TEMP = 4 +SP_FAN_SPEED = 5 +SP_VALIDATE = 6 + +# Daemon control platform specific constants +PDDF_INIT_WAIT = 30 #secs +POLL_INTERVAL = 10 #secs +CRITICAL_DURATION = 120 #secs +CRITICAL_LOG_INTERVAL = 20 #every 'n' secs +FAN_DUTY_MIN = 40 # percentage +FAN_DUTY_MAX = 100 #percentage +TEMP_HYST = 3 # degree C +NUM_FANS = 3 + +# Validation functions +def valid_if_exhaust(fan_dir): + if fan_dir == "EXHAUST": + return True + + return False + +def valid_if_intake(fan_dir): + if fan_dir == "INTAKE": + return True + + return False + +def valid_always(fan_dir): + return True + +def valid_never(fan_dir): + return False + +# Core data for Thermal FAN speed evaluation +# {: [low_temp, high_temp, critical_temp, fatal_temp, current_temp, fanspeed, validate_function]} +SENSOR_PARAM = { + 'Front Right Temp': [34, 47, None, None, NOMINAL_TEMP, FAN_DUTY_MIN, valid_if_exhaust], + 'Front Left Temp': [None, None, None, None, NOMINAL_TEMP, FAN_DUTY_MIN, valid_never], + 'Rear Right Temp': [34, 47, None, None, NOMINAL_TEMP, FAN_DUTY_MIN, valid_if_intake], + 'ASIC External Temp': [54, 69, 105, 110, NOMINAL_TEMP, FAN_DUTY_MIN, valid_always], + 'CPU Internal Temp': [69, 84, 91, 94, NOMINAL_TEMP, FAN_DUTY_MIN, valid_always] +} + +class Ds1000FanControl(daemon_base.DaemonBase): + global MODULE_NAME + global SENSOR_PARAM + + def __init__(self, log_level): + + str_to_log_level = { + 'ERROR' : self.LOG_PRIORITY_ERROR, \ + 'WARNING' : self.LOG_PRIORITY_WARNING, \ + 'NOTICE': self.LOG_PRIORITY_NOTICE, \ + 'INFO': self.LOG_PRIORITY_INFO, \ + 'DEBUG': self.LOG_PRIORITY_DEBUG + } + self.fan_list = [] + self.thermal_list = [] + + super(Ds1000FanControl, self).__init__(MODULE_NAME) + if log_level is not None: + self.set_min_log_priority(str_to_log_level.get(log_level)) + self.log_info("Forcing to loglevel {}".format(log_level)) + self.log_info("Starting up...") + + self.log_debug("Waiting {} secs for PDDF driver initialization".format(PDDF_INIT_WAIT)) + time.sleep(PDDF_INIT_WAIT) + + try: + self.critical_period = 0 + self.platform_chassis = platform.Platform().get_chassis() + + # Fetch FAN info + self.fan_list = self.platform_chassis.get_all_fans() + if len(self.fan_list) != NUM_FANS: + self.log_error("Fans detected({}) is not same as expected({}), so exiting..."\ + .format(len(self.fan_list), NUM_FANS)) + sys.exit(1) + + self.fan_dir = self.fan_list[0].get_direction() + self.log_debug("Fans direction is {}".format(self.fan_dir)) + + # Fetch THERMAL info + self.thermal_list = self.platform_chassis.get_all_thermals() + if len(self.thermal_list) != len(SENSOR_PARAM): + self.log_error("Thermals detected({}) is not same as expected({}), so exiting..."\ + .format(len(self.thermal_list), len(SENSOR_PARAM))) + sys.exit(1) + + # Initialize the thermal temperature dict + # {: [thermal_temp, fanspeed]} + for thermal in self.thermal_list: + thermal_name = thermal.get_name() + SENSOR_PARAM[thermal_name][SP_REF_TEMP] = thermal.get_temperature() + + except Exception as e: + self.log_error("Failed to init Ds1000FanControl due to {}, so exiting...".format(repr(e))) + sys.exit(1) + + # Signal handler + def signal_handler(self, sig, frame): + if sig == signal.SIGHUP: + self.log_notice("Caught SIGHUP - ignoring...") + elif sig == signal.SIGINT: + self.log_warning("Caught SIGINT - Setting all FAN speed to max({}%) and exiting... ".format(FAN_DUTY_MAX)) + self.set_all_fan_speed(FAN_DUTY_MAX) + sys.exit(0) + elif sig == signal.SIGTERM: + self.log_warning("Caught SIGTERM - Setting all FAN speed to max({}%) and exiting... ".format(FAN_DUTY_MAX)) + self.set_all_fan_speed(FAN_DUTY_MAX) + sys.exit(0) + else: + self.log_notice("Caught unhandled signal '" + sig + "'") + + + @staticmethod + def is_fan_operational(fan): + if fan.get_presence() and fan.get_status(): + return True + + return False + + @staticmethod + def get_speed_from_min_max(cur_temp, min_temp, max_temp, min_speed, max_speed): + if cur_temp <= min_temp: + speed = min_speed + elif cur_temp >= max_temp: + speed = max_speed + else: + multiplier = (max_speed - min_speed) / (max_temp - min_temp) + speed = int(((cur_temp - min_temp) * multiplier) + min_speed) + + return speed + + def thermal_shutdown(self, reason): + cmd = ['/usr/local/bin/ds1000_platform_shutdown.sh', reason] + + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) + proc.communicate() + if proc.returncode == 0: + return True + else: + self.log_error("Thermal {} shutdown failed with errorno {}"\ + .format(reason, proc.returncode)) + return False + + def get_fan_speed_from_thermals(self): + prominent_speed = FAN_DUTY_MIN + is_critical = False + + for thermal in self.thermal_list: + speed = prominent_speed + thermal_name = thermal.get_name() + thermal_temp = thermal.get_temperature() + thermal_info = SENSOR_PARAM[thermal_name] + thermal_ref = thermal_info[SP_REF_TEMP] + thermal_low = thermal_info[SP_LOW_TEMP] + thermal_high = thermal_info[SP_HIGH_TEMP] + thermal_critical = thermal_info[SP_CRITICAL_TEMP] + thermal_fatal = thermal_info[SP_FATAL_TEMP] + + if thermal_info[SP_VALIDATE](self.fan_dir): + self.log_debug("{} temperature is {}C".format(thermal_name, thermal_temp)) + if thermal_temp <= thermal_low: + SENSOR_PARAM[thermal_name][SP_REF_TEMP] = thermal_low + speed = FAN_DUTY_MIN + elif thermal_temp >= thermal_high: + SENSOR_PARAM[thermal_name][SP_REF_TEMP] = thermal_high + speed = FAN_DUTY_MAX + if thermal_fatal and thermal_temp >= thermal_fatal: + # Double check since immediate cold power-cycle + # is an expensive operation in field + if thermal.get_temperature() >= thermal_fatal: + self.log_warning("'{}' temperature ({}C) hit fatal limit ({}C)."\ + " Triggering immediate cold power-cycle"\ + .format(thermal_name, thermal_temp, thermal_fatal)) + self.thermal_shutdown('temp_fatal') + sys.exit(0) + else: + self.log_warning("'{}' temperature ({}C) hit fatal limit ({}C) intermittently"\ + .format(thermal_name, thermal_temp, thermal_fatal)) + elif thermal_critical and thermal_temp >= thermal_critical: + if self.critical_period < CRITICAL_DURATION: + if self.critical_period % CRITICAL_LOG_INTERVAL == 0: + self.log_warning("'{}' temperature ({}C) hit critical limit ({}C)."\ + " Triggering cold power-cycle in {} seconds"\ + .format(thermal_name, thermal_temp, thermal_critical,\ + (CRITICAL_DURATION - self.critical_period))) + is_critical = True + else: + self.log_warning("'{}' temperature ({}C) is in critical limit ({}C) for more"\ + " than {} seconds. Triggering cold power-cycle now"\ + .format(thermal_name, thermal_temp, thermal_critical,\ + CRITICAL_DURATION)) + self.thermal_shutdown('temp_critical') + sys.exit(0) + + else: + if thermal_temp > thermal_ref: + SENSOR_PARAM[thermal_name][SP_REF_TEMP] = thermal_temp + speed = self.get_speed_from_min_max(thermal_temp, thermal_low, thermal_high,\ + FAN_DUTY_MIN, FAN_DUTY_MAX) + elif thermal_ref - thermal_temp >= TEMP_HYST: + SENSOR_PARAM[thermal_name][SP_REF_TEMP] = thermal_temp + 1 + speed = self.get_speed_from_min_max(thermal_temp + 1, thermal_low, thermal_high,\ + FAN_DUTY_MIN, FAN_DUTY_MAX) + else: + speed = SENSOR_PARAM[thermal_name][SP_FAN_SPEED] + + self.log_debug("{} thermal speed is {}%".format(thermal_name, speed)) + SENSOR_PARAM[thermal_name][SP_FAN_SPEED] = speed + prominent_speed = max(prominent_speed, speed) + + if is_critical: + self.critical_period = self.critical_period + POLL_INTERVAL + elif self.critical_period > 0: + self.critical_period = 0 + self.log_notice("All thermals are now below critical limit."\ + " System cold power-cycle is now cancelled") + + self.log_debug("Prominent thermal speed is {}%".format(prominent_speed)) + + return prominent_speed + + def set_all_fan_speed(self, speed): + for fan in self.fan_list: + fan_name = fan.get_name() + try: + if fan.set_speed(speed): + self.log_debug("Set {} speed to {}%".format(fan_name, speed)) + else: + self.log_error("Set '{}' to speed {}% failed".format(fan_name, speed)) + except Exception as e: + self.log_error("Set '{}' to speed {}% failed due to {}".format(fan_name, speed, repr(e))) + + return False + + def run(self): + while True: + num_good_fans = 0 + dir_mismatch = False + for fan in self.fan_list: + if self.is_fan_operational(fan): + num_good_fans = num_good_fans + 1 + else: + self.log_notice("FAN '{}' is broken or not inserted".format(fan.get_name())) + + if self.fan_dir is None: + self.fan_dir = fan.get_direction() + elif self.fan_dir != fan.get_direction(): + dir_mismatch = True + self.log_debug("{} FANs are operational, there is{}direction mismatch"\ + .format('All' if num_good_fans == len(self.fan_list) else num_good_fans, + ' ' if dir_mismatch else ' no ')) + + # Always evaluate the thermals irrespective of the FAN state + speed = self.get_fan_speed_from_thermals() + + if dir_mismatch: + self.log_warning("Some FANs have incompatible direction. Please replace FANs immediately") + else: + if num_good_fans == len(self.fan_list): # Good FANs is equal to number of FANs + self.set_all_fan_speed(speed) + else: + if not num_good_fans: # None of the FANs are operational + self.log_warning("Overheating hazard!! All FANs are broken or not inserted") + else: + self.log_warning("Some FANs are broken or not inserted") + self.set_all_fan_speed(FAN_DUTY_MAX) + + time.sleep(POLL_INTERVAL) + +def main(argv): + log_level = None + valid_log_levels = ['ERROR', 'WARNING', 'NOTICE', 'INFO', 'DEBUG'] + + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv, 'hdl', ['log-level=']) + except getopt.GetoptError: + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + sys.exit(1) + for opt, arg in opts: + if opt == '-h': + print('Usage: %s [-d] [-l ]\nlog_level - ERROR, WARNING, NOTICE, INFO, DEBUG' % sys.argv[0]) + sys.exit(1) + elif opt in ('-l', '--log-level'): + if log_level not in valid_log_levels: + print('Invalid log level %s' % arg) + sys.exit(1) + elif opt == '-d': + log_level = 'DEBUG' + + fanctl = Ds1000FanControl(log_level) + + fanctl.log_debug("Start daemon main loop") + # Loop forever, doing something useful hopefully: + fanctl.run() + fanctl.log_debug("Stop daemon main loop") + + sys.exit(0) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/classes/__init__.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/Makefile new file mode 100644 index 000000000000..51583c9fbbce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/Makefile @@ -0,0 +1,5 @@ +TARGET:= pddf_custom_psu_driver_module +$(TARGET)-objs := ./psu_driver/pddf_psu_api.o ./psu_driver/pddf_psu_driver.o + +obj-m := $(TARGET).o +obj-m += mc24lc64t.o pddf_custom_fpga_algo.o pddf_custom_fpga_extend.o lpc_basecpld.o diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/lpc_basecpld.c b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/lpc_basecpld.c new file mode 100644 index 000000000000..f925b5d84564 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/lpc_basecpld.c @@ -0,0 +1,720 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * lpc_basecpld.c - The CPLD driver for the Base Board of ds2000 + * The driver implement sysfs to access CPLD register on the baseboard of ds2000 via LPC bus. + * + * Author: Nicholas Wu /Oscar Xu + * Copyright (C) 2022-2024 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "sys_cpld" +/** + * CPLD register address for read and write. + */ +#define VERSION_ADDR 0xA100 +#define SCRATCH_ADDR 0xA101 +#define PSU_LED_ADDR 0xA161 +#define SYS_LED_ADDR 0xA162 +#define ALARM_LED_ADDR 0xA163 +#define FAN_LED_ADDR 0xA165 +#define COME_CPLD_VER_ADDR 0xA1E0 + +#define CPLD_REGISTER_SIZE 0xFF + +/* LED CTRL */ + +enum FAN_LED { + fan_led_amb = 1, + fan_led_grn, + fan_led_off, + fan_led_auto = 0x10 +} fan_led; + +enum SYS_LED { + sys_led_both = 0, + sys_led_grn, + sys_led_amb, + sys_led_off +} sys_led; + +enum PWR_LED { + pwr_led_amb = 1, + pwr_led_grn, + pwr_led_off, + pwr_led_auto = 0x10 +} pwr_led; + +enum ALARM_LED { + alarm_led_both = 0, + alarm_led_grn, + alarm_led_amb, + alarm_led_off +} alarm_led; + +enum LED_CTRL { + led_on = 0, + led_blk_1hz, + led_blk_4hz, + led_off +} led_ctrl; + +#define LED_OFF "off" +#define LED_GREEN "green" +#define LED_AMBER "amber" +#define LED_HZ_GBNK "grn_bnk_1hz" +#define LED_HZ_ABNK "amb_bnk_1hz" +#define LED_QHZ_GBNK "grn_bnk_4hz" +#define LED_QHZ_ABNK "amb_bnk_4hz" +#define LED_HZ_GABNK "grn_amb_1hz" +#define LED_QHZ_GABNK "grn_amb_4hz" + +struct cpld_b_data { + struct mutex cpld_lock; + uint16_t read_addr; +}; + +struct cpld_b_data *cpld_data; + +/** + * Read the value from scratch register as hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t scratch_show(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf, "0x%2.2x\n", data); +} + +/** + * Set scratch register with specific hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t scratch_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int ret = 0; + unsigned long data; + + mutex_lock(&cpld_data->cpld_lock); + ret = kstrtoul(buf, 0, &data); + if (ret != 0) { + mutex_unlock(&cpld_data->cpld_lock); + return ret; + } + outb(data, SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +/* CPLD version attributes */ +static ssize_t version_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len = 0; + unsigned char value = 0; + + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + value = inb(VERSION_ADDR); + len = sprintf(buf, "%d.%d\n", value >> 4, value & 0x0F); + mutex_unlock(&cpld_data->cpld_lock); + + return len; +} + + +static ssize_t getreg_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + int ret = 0; + unsigned long addr; + + ret = kstrtoul(buf, 0, &addr); + if (ret != 0) { + return ret; + } + cpld_data->read_addr = addr; + + return count; +} + +static ssize_t getreg_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len = 0; + + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n", inb(cpld_data->read_addr)); + mutex_unlock(&cpld_data->cpld_lock); + + return len; +} + +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + int ret = 0; + unsigned long addr; + unsigned long value; + char *tok; + char clone[20]; + char *pclone = clone; + + strscpy(clone, buf,sizeof(clone)); + + mutex_lock(&cpld_data->cpld_lock); + tok = strsep((char **)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + ret = kstrtoul(tok, 0, &addr); + if (ret != 0) { + mutex_unlock(&cpld_data->cpld_lock); + return ret; + } + + tok = strsep((char **)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + ret = kstrtoul(tok, 0, &value); + if (ret != 0) { + mutex_unlock(&cpld_data->cpld_lock); + return ret; + } + outb(value, addr); + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +/** + * Read all CPLD register in binary mode. + * @return number of byte read. + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i = 0; + ssize_t status; + + mutex_lock(&cpld_data->cpld_lock); +begin: + if (i < count) { + buf[i++] = inb(VERSION_ADDR + off); + off++; + msleep(1); + goto begin; + } + status = count; + mutex_unlock(&cpld_data->cpld_lock); + + return status; +} + +/** + * @brief Show status led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return led state - off/on/blink + */ +static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + unsigned char color = 0; + unsigned char control = 0; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + color = (data & 0x30) >> 4; + control = (data & 0x3); + + switch(color){ + case sys_led_both: + if ( control == led_blk_1hz){ + return sprintf(buf, "%s\n", LED_HZ_GABNK); + }else if(control == led_blk_4hz){ + return sprintf(buf, "%s\n", LED_QHZ_GABNK); + }else{ + break; + } + case sys_led_amb: + if ( control == led_blk_1hz){ + return sprintf(buf, "%s\n", LED_HZ_ABNK); + }else if(control == led_blk_4hz){ + return sprintf(buf, "%s\n", LED_QHZ_ABNK); + }else if(control == led_on){ + return sprintf(buf, "%s\n", LED_AMBER); + }else{ + break; + } + case sys_led_grn: + if ( control == led_blk_1hz){ + return sprintf(buf, "%s\n", LED_HZ_GBNK); + }else if(control == led_blk_4hz){ + return sprintf(buf, "%s\n", LED_QHZ_GBNK); + }else if(control == led_on){ + return sprintf(buf, "%s\n", LED_GREEN); + }else{ + break; + } + default: + break; + } + + return sprintf(buf, "%s\n", LED_OFF); +} + +/** + * @brief Set the status led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value - off/on/blink + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char data; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + if(sysfs_streq(buf, LED_OFF)){ + data &= 0xCC; + data |= sys_led_off << 4; + data |= led_off; + }else if(sysfs_streq(buf, LED_GREEN)){ + data &= 0xCC; + data |= sys_led_grn << 4; + data |= led_on; + }else if(sysfs_streq(buf, LED_AMBER)){ + data &= 0xCC; + data |= sys_led_amb << 4; + data |= led_on; + }else if(sysfs_streq(buf, LED_HZ_GBNK)){ + data &= 0xCC; + data |= sys_led_grn << 4; + data |= led_blk_1hz; + }else if(sysfs_streq(buf, LED_HZ_ABNK)){ + data &= 0xCC; + data |= sys_led_amb << 4; + data |= led_blk_1hz; + }else if(sysfs_streq(buf, LED_QHZ_GBNK)){ + data &= 0xCC; + data |= sys_led_grn << 4; + data |= led_blk_4hz; + }else if(sysfs_streq(buf, LED_QHZ_ABNK)){ + data &= 0xCC; + data |= sys_led_amb << 4; + data |= led_blk_4hz; + }else if(sysfs_streq(buf, LED_HZ_GABNK)){ + data &= 0xCC; + data |= sys_led_both << 4; + data |= led_blk_1hz; + }else if(sysfs_streq(buf, LED_QHZ_GABNK)){ + data &= 0xCC; + data |= sys_led_both << 4; + data |= led_blk_4hz; + }else{ + count = -EINVAL; + } + + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +/** + * @brief Show alarm led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return led state - off/on/blink + */ +static ssize_t alarm_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + unsigned char color = 0; + unsigned char control = 0; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(ALARM_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + color = (data & 0x30) >> 4; + control = (data & 0x3); + + switch(color){ + case alarm_led_both: + if ( control == led_blk_1hz){ + return sprintf(buf, "%s\n", LED_HZ_GABNK); + }else if(control == led_blk_4hz){ + return sprintf(buf, "%s\n", LED_QHZ_GABNK); + }else{ + break; + } + case alarm_led_amb: + if ( control == led_blk_1hz){ + return sprintf(buf, "%s\n", LED_HZ_ABNK); + }else if(control == led_blk_4hz){ + return sprintf(buf, "%s\n", LED_QHZ_ABNK); + }else if(control == led_on){ + return sprintf(buf, "%s\n", LED_AMBER); + }else{ + break; + } + case alarm_led_grn: + if ( control == led_blk_1hz){ + return sprintf(buf, "%s\n", LED_HZ_GBNK); + }else if(control == led_blk_4hz){ + return sprintf(buf, "%s\n", LED_QHZ_GBNK); + }else if(control == led_on){ + return sprintf(buf, "%s\n", LED_GREEN); + }else{ + break; + } + default: + break; + } + + return sprintf(buf, "%s\n", LED_OFF); +} + +/** + * @brief Set the alarm led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value - off/on/blink + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t alarm_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char data; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(ALARM_LED_ADDR); + if(sysfs_streq(buf, LED_OFF)){ + data &= 0xCC; + data |= alarm_led_off << 4; + data |= led_off; + }else if(sysfs_streq(buf, LED_GREEN)){ + data &= 0xCC; + data |= alarm_led_grn << 4; + data |= led_on; + }else if(sysfs_streq(buf, LED_AMBER)){ + data &= 0xCC; + data |= alarm_led_amb << 4; + data |= led_on; + }else if(sysfs_streq(buf, LED_HZ_GBNK)){ + data &= 0xCC; + data |= alarm_led_grn << 4; + data |= led_blk_1hz; + }else if(sysfs_streq(buf, LED_HZ_ABNK)){ + data &= 0xCC; + data |= alarm_led_amb << 4; + data |= led_blk_1hz; + }else if(sysfs_streq(buf, LED_QHZ_GBNK)){ + data &= 0xCC; + data |= alarm_led_grn << 4; + data |= led_blk_4hz; + }else if(sysfs_streq(buf, LED_QHZ_ABNK)){ + data &= 0xCC; + data |= alarm_led_amb << 4; + data |= led_blk_4hz; + }else if(sysfs_streq(buf, LED_HZ_GABNK)){ + data &= 0xCC; + data |= alarm_led_both << 4; + data |= led_blk_1hz; + }else if(sysfs_streq(buf, LED_QHZ_GABNK)){ + data &= 0xCC; + data |= alarm_led_both << 4; + data |= led_blk_4hz; + + }else{ + count = -EINVAL; + } + + outb(data, ALARM_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +static ssize_t pwr_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + if ((data & 0x10) != 0) + { + return sprintf(buf, "%s\n", "auto"); + } + data = data & 0x3; + return sprintf(buf, "%s\n", + data == pwr_led_grn ? "green" : data == pwr_led_amb ? "amber" : "off"); +} + + +static ssize_t pwr_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status, data; + + if (sysfs_streq(buf, "off")) { + led_status = pwr_led_off; + } else if (sysfs_streq(buf, "green")) { + led_status = pwr_led_grn; + } else if (sysfs_streq(buf, "amber")) { + led_status = pwr_led_amb; + } else if (sysfs_streq(buf, "auto")) { + led_status = pwr_led_auto; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_LED_ADDR); + /* Set bit 4 as 0 to control pwrled by software */ + data = data & ~(0x13); + data = data | led_status; + outb(data, PSU_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + + mutex_lock(&cpld_data->cpld_lock); + data = inb(FAN_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + if ((data & 0x10) != 0) + { + return sprintf(buf, "%s\n", "auto"); + } + data = data & 0x3; + return sprintf(buf, "%s\n", + data == fan_led_grn ? "green" : data == fan_led_amb ? "amber" : "off"); +} + + +static ssize_t fan_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status, data; + + if (sysfs_streq(buf, "off")) { + led_status = fan_led_off; + } else if (sysfs_streq(buf, "green")) { + led_status = fan_led_grn; + } else if (sysfs_streq(buf, "amber")) { + led_status = fan_led_amb; + } else if (sysfs_streq(buf, "auto")) { + led_status = fan_led_auto; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(FAN_LED_ADDR); + /* Set bit 4 as 0 to control fanled by software */ + data = data & ~(0x13); + data = data | led_status; + outb(data, FAN_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +/* COME CPLD version attributes */ +static ssize_t come_cpld_version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = -EIO; + // COME CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n",inb(COME_CPLD_VER_ADDR)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} + +static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE); +static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RW(scratch); +static DEVICE_ATTR_RW(getreg); +static DEVICE_ATTR_WO(setreg); +static DEVICE_ATTR_RW(sys_led); +static DEVICE_ATTR_RW(alarm_led); +static DEVICE_ATTR_RW(pwr_led); +static DEVICE_ATTR_RW(fan_led); +static DEVICE_ATTR_RO(come_cpld_version); + +static struct attribute *cpld_b_attrs[] = { + &dev_attr_version.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_sys_led.attr, + &dev_attr_alarm_led.attr, + &dev_attr_pwr_led.attr, + &dev_attr_fan_led.attr, + &dev_attr_come_cpld_version.attr, + NULL, +}; + +static struct bin_attribute *cpld_b_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute_group cpld_b_attrs_grp = { + .attrs = cpld_b_attrs, + .bin_attrs = cpld_b_bin_attrs, +}; + +static struct resource cpld_b_resources[] = { + { + .start = 0xA100, + .end = 0xA1FF, + .flags = IORESOURCE_IO, + }, +}; + +static void cpld_b_dev_release(struct device *dev) +{ + return; +} + +static struct platform_device cpld_b_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cpld_b_resources), + .resource = cpld_b_resources, + .dev = { + .release = cpld_b_dev_release, + } +}; + +static int cpld_b_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int err = 0; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_b_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + cpld_data->read_addr = VERSION_ADDR; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "Specified Resource Not Available...\n"); + return -ENODEV; + } + + err = sysfs_create_group(&pdev->dev.kobj, &cpld_b_attrs_grp); + if (err) { + dev_err(&pdev->dev, "Cannot create sysfs for baseboard CPLD\n"); + return err; + } + return 0; +} + +static int cpld_b_drv_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &cpld_b_attrs_grp); + return 0; +} + +static struct platform_driver cpld_b_drv = { + .probe = cpld_b_drv_probe, + .remove = __exit_p(cpld_b_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cpld_b_init(void) +{ + // Register platform device and platform driver + platform_device_register(&cpld_b_dev); + platform_driver_register(&cpld_b_drv); + return 0; +} + +void cpld_b_exit(void) +{ + // Unregister platform device and platform driver + platform_driver_unregister(&cpld_b_drv); + platform_device_unregister(&cpld_b_dev); +} + +module_init(cpld_b_init); +module_exit(cpld_b_exit); + + +MODULE_AUTHOR("Celestica Inc."); +MODULE_DESCRIPTION("LPC CPLD baseboard driver"); +MODULE_VERSION("0.0.2"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/mc24lc64t.c new file mode 100644 index 000000000000..4603b3d41065 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/mc24lc64t.c @@ -0,0 +1,171 @@ +/* + * mc24lc64t.c - driver for Microchip 24LC64T + * + * Copyright (C) 2017 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes. + +struct mc24lc64t_data { + struct mutex update_lock; +}; + +static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, read_time, i = 0; + int status; + + mutex_lock(&drvdata->update_lock); + + if (i2c_smbus_write_byte_data(client, off>>8, off)) + { + status = -EIO; + goto exit; + } + + msleep(1); + +begin: + + if (i < count) + { + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + do { + read_time = jiffies; + + status = i2c_smbus_read_byte(client); + if (status >= 0) + { + buf[i++] = status; + goto begin; + } + } while (time_before(read_time, timeout)); + + status = -ETIMEDOUT; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + + return status; +} + +static ssize_t mc24lc64t_write (struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count){ + + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, write_time, i = 0; + int status; + u16 value; + + mutex_lock(&drvdata->update_lock); + +begin: + if (i < count){ + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + value = (buf[i] << 8)| off; + do { + write_time = jiffies; + status = i2c_smbus_write_word_data(client, off>>8, value); + if (status >= 0) + { + // increase offset + off++; + // increase buffer index + i++; + goto begin; + } + } while (time_before(write_time, timeout)); + status = -ETIMEDOUT; + goto exit; + } + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + return status; +} + +static struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUGO, + }, + .size = EEPROM_SIZE, + .read = mc24lc64t_read, + .write = mc24lc64t_write, +}; + +static int mc24lc64t_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct mc24lc64t_data *drvdata; + int err; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA + | I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + + if (!(drvdata = devm_kzalloc(&client->dev, + sizeof(struct mc24lc64t_data), GFP_KERNEL))) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + + return err; +} + +static void mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); +} + +static const struct i2c_device_id mc24lc64t_id[] = { + { "24lc64t", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mc24lc64t_id); + +static struct i2c_driver mc24lc64t_driver = { + .driver = { + .name = "mc24lc64t", + .owner = THIS_MODULE, + }, + .probe = mc24lc64t_probe, + .remove = mc24lc64t_remove, + .id_table = mc24lc64t_id, +}; + +module_i2c_driver(mc24lc64t_driver); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Microchip 24LC64T Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_algo.c b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_algo.c new file mode 100644 index 000000000000..32ed875df587 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_algo.c @@ -0,0 +1,631 @@ +/* +* +* Licensed under the GNU General Public License Version 2 +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +/* +* pddf_xilinx_device_7021_algo.c +* Description: +* A sample i2c driver algorithms for Xilinx Corporation Device 7021 FPGA adapters +* +*********************************************************************************/ +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../pddf/i2c/modules/include/pddf_i2c_algo.h" + +#define DEBUG 0 + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#define XIIC_MSB_OFFSET 0 +#define XIIC_REG_OFFSET (0x100 + XIIC_MSB_OFFSET) + +/* + * Register offsets in bytes from RegisterBase. Three is added to the + * base offset to access LSB (IBM style) of the word + */ +#define XIIC_CR_REG_OFFSET (0x00 + XIIC_REG_OFFSET) /* Control Register */ +#define XIIC_SR_REG_OFFSET (0x04 + XIIC_REG_OFFSET) /* Status Register */ +#define XIIC_DTR_REG_OFFSET (0x08 + XIIC_REG_OFFSET) /* Data Tx Register */ +#define XIIC_DRR_REG_OFFSET (0x0C + XIIC_REG_OFFSET) /* Data Rx Register */ +#define XIIC_ADR_REG_OFFSET (0x10 + XIIC_REG_OFFSET) /* Address Register */ +#define XIIC_TFO_REG_OFFSET (0x14 + XIIC_REG_OFFSET) /* Tx FIFO Occupancy */ +#define XIIC_RFO_REG_OFFSET (0x18 + XIIC_REG_OFFSET) /* Rx FIFO Occupancy */ +#define XIIC_TBA_REG_OFFSET (0x1C + XIIC_REG_OFFSET) /* 10 Bit Address reg */ +#define XIIC_RFD_REG_OFFSET (0x20 + XIIC_REG_OFFSET) /* Rx FIFO Depth reg */ +#define XIIC_GPO_REG_OFFSET (0x24 + XIIC_REG_OFFSET) /* Output Register */ + +/* Control Register masks */ +#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */ +#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */ +#define XIIC_CR_MSMS_MASK 0x04 /* Master starts Txing=1 */ +#define XIIC_CR_DIR_IS_TX_MASK 0x08 /* Dir of tx. Txing=1 */ +#define XIIC_CR_NO_ACK_MASK 0x10 /* Tx Ack. NO ack = 1 */ +#define XIIC_CR_REPEATED_START_MASK 0x20 /* Repeated start = 1 */ +#define XIIC_CR_GENERAL_CALL_MASK 0x40 /* Gen Call enabled = 1 */ + +/* Status Register masks */ +#define XIIC_SR_GEN_CALL_MASK 0x01 /* 1=a mstr issued a GC */ +#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x02 /* 1=when addr as slave */ +#define XIIC_SR_BUS_BUSY_MASK 0x04 /* 1 = bus is busy */ +#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x08 /* 1=Dir: mstr <-- slave */ +#define XIIC_SR_TX_FIFO_FULL_MASK 0x10 /* 1 = Tx FIFO full */ +#define XIIC_SR_RX_FIFO_FULL_MASK 0x20 /* 1 = Rx FIFO full */ +#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x40 /* 1 = Rx FIFO empty */ +#define XIIC_SR_TX_FIFO_EMPTY_MASK 0x80 /* 1 = Tx FIFO empty */ + +/* Interrupt Status Register masks Interrupt occurs when... */ +#define XIIC_INTR_ARB_LOST_MASK 0x01 /* 1 = arbitration lost */ +#define XIIC_INTR_TX_ERROR_MASK 0x02 /* 1=Tx error/msg complete */ +#define XIIC_INTR_TX_EMPTY_MASK 0x04 /* 1 = Tx FIFO/reg empty */ +#define XIIC_INTR_RX_FULL_MASK 0x08 /* 1=Rx FIFO/reg=OCY level */ +#define XIIC_INTR_BNB_MASK 0x10 /* 1 = Bus not busy */ +#define XIIC_INTR_AAS_MASK 0x20 /* 1 = when addr as slave */ +#define XIIC_INTR_NAAS_MASK 0x40 /* 1 = not addr as slave */ +#define XIIC_INTR_TX_HALF_MASK 0x80 /* 1 = TX FIFO half empty */ + +/* The following constants specify the depth of the FIFOs */ +#define IIC_RX_FIFO_DEPTH 16 /* Rx fifo capacity */ +#define IIC_TX_FIFO_DEPTH 16 /* Tx fifo capacity */ + +/* + * Tx Fifo upper bit masks. + */ +#define XIIC_TX_DYN_START_MASK 0x0100 /* 1 = Set dynamic start */ +#define XIIC_TX_DYN_STOP_MASK 0x0200 /* 1 = Set dynamic stop */ + +/* + * The following constants define the register offsets for the Interrupt + * registers. There are some holes in the memory map for reserved addresses + * to allow other registers to be added and still match the memory map of the + * interrupt controller registers + */ +#define XIIC_IISR_OFFSET 0x20 /* Interrupt Status Register */ +#define XIIC_RESETR_OFFSET 0x40 /* Reset Register */ + +#define XIIC_RESET_MASK 0xAUL + +#define XIIC_PM_TIMEOUT 1000 /* ms */ +/* timeout waiting for the controller to respond */ +#define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000)) + +struct fpgalogic_i2c { + void __iomem *base; + u32 reg_shift; + u32 reg_io_width; + wait_queue_head_t wait; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + int ip_clock_khz; + int bus_clock_khz; + void (*reg_set)(struct fpgalogic_i2c *i2c, int reg, u8 value); + u8 (*reg_get)(struct fpgalogic_i2c *i2c, int reg); + u32 timeout; + struct mutex lock; +}; +static struct fpgalogic_i2c fpgalogic_i2c[I2C_PCI_MAX_BUS]; +extern void __iomem * fpga_ctl_addr; +extern int (*ptr_fpgapci_read)(uint32_t); +extern int (*ptr_fpgapci_write)(uint32_t, uint32_t); +extern int (*pddf_i2c_pci_add_numbered_bus)(struct i2c_adapter *, int); +static int xiic_reinit(struct fpgalogic_i2c *i2c); + +void i2c_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * i2c_release_mutex - release mutex + */ +void i2c_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static inline void xiic_setreg32(struct fpgalogic_i2c *i2c, int reg, int value) +{ + (void)iowrite32(value, i2c->base + reg); +} + +static inline int xiic_getreg32(struct fpgalogic_i2c *i2c, int reg) +{ + u32 ret; + + ret = ioread32(i2c->base + reg); + + return ret; +} + +static inline void xiic_irq_clr(struct fpgalogic_i2c *i2c, u32 mask) +{ + u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + + xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); +} + +static int xiic_clear_rx_fifo(struct fpgalogic_i2c *i2c) +{ + u8 sr; + unsigned long timeout; + + timeout = jiffies + XIIC_I2C_TIMEOUT; + for (sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); + !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); + sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET)) { + xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + if (time_after(jiffies, timeout)) { + printk("Failed to clear rx fifo\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +/** + * Wait until something change in a given register + * @i2c: ocores I2C device instance + * @reg: register to query + * @mask: bitmask to apply on register value + * @val: expected result + * @timeout: timeout in jiffies + * + * Timeout is necessary to avoid to stay here forever when the chip + * does not answer correctly. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int poll_wait(struct fpgalogic_i2c *i2c, + int reg, u8 mask, u8 val, + const unsigned long timeout) +{ + unsigned long j; + u8 status = 0; + + j = jiffies + timeout; + while (1) { + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, reg); + mutex_unlock(&i2c->lock); + if ((status & mask) == val) + break; + if (time_after(jiffies, j)) + return -ETIMEDOUT; + cpu_relax(); + cond_resched(); + } + return 0; +} + +/** + * Wait until is possible to process some data + * @i2c: ocores I2C device instance + * + * Used when the device is in polling mode (interrupts disabled). + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_poll_wait(struct fpgalogic_i2c *i2c) +{ + u8 mask = 0, status = 0; + int err = 0; + int val = 0; + int tmp = 0; + mutex_lock(&i2c->lock); + if (i2c->state == STATE_DONE) { + /* transfer is over */ + mask = XIIC_SR_BUS_BUSY_MASK; + } else if (i2c->state == STATE_WRITE || i2c->state == STATE_START){ + /* on going transfer */ + if (0 == i2c->msg->len){ + mask = XIIC_INTR_TX_ERROR_MASK; + } else { + mask = XIIC_SR_TX_FIFO_FULL_MASK; + } + } + else if (i2c->state == STATE_READ){ + /* on going receive */ + mask = XIIC_SR_TX_FIFO_EMPTY_MASK | XIIC_SR_RX_FIFO_EMPTY_MASK; + } + mutex_unlock(&i2c->lock); + // printk("Wait for: 0x%x\n", mask); + + /* + * once we are here we expect to get the expected result immediately + * so if after 50ms we timeout then something is broken. + */ + + if (1 == i2c->nmsgs && 0 == i2c->msg->len && i2c->state == STATE_START && !(i2c->msg->flags & I2C_M_RD)) { /* for i2cdetect I2C_SMBUS_QUICK mode*/ + err = poll_wait(i2c, XIIC_IISR_OFFSET, mask, mask, msecs_to_jiffies(50)); + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); + mutex_unlock(&i2c->lock); + if (0 != err) { /* AXI IIC as an transceiver , if ever an XIIC_INTR_TX_ERROR_MASK interrupt happens, means no such i2c device */ + err = 0; + } else { + err = -ETIMEDOUT; + } + } + else { + if (mask & XIIC_SR_TX_FIFO_EMPTY_MASK){ + err = poll_wait(i2c, XIIC_SR_REG_OFFSET, mask, XIIC_SR_TX_FIFO_EMPTY_MASK, msecs_to_jiffies(50)); + mask &= ~XIIC_SR_TX_FIFO_EMPTY_MASK; + } + if (0 == err){ + err = poll_wait(i2c, XIIC_SR_REG_OFFSET, mask, 0, msecs_to_jiffies(50)); + } + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + + if ((status & XIIC_INTR_ARB_LOST_MASK) || + ((status & XIIC_INTR_TX_ERROR_MASK) && + !(status & XIIC_INTR_RX_FULL_MASK) && + !(i2c->msg->flags & I2C_M_RD))) { /* AXI IIC as an transceiver , if ever an XIIC_INTR_TX_ERROR_MASK interrupt happens, return */ + err = -ETIMEDOUT; + + if (status & XIIC_INTR_ARB_LOST_MASK) { + val = xiic_getreg32(i2c, XIIC_CR_REG_OFFSET); + tmp = XIIC_CR_MSMS_MASK; + val &=(~tmp); + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, val); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, XIIC_INTR_ARB_LOST_MASK); + printk("%s: TRANSFER STATUS ERROR, ISR: bit 0x%x happens\n", + __func__, XIIC_INTR_ARB_LOST_MASK); + } + if (status & XIIC_INTR_TX_ERROR_MASK) { + int sta = 0; + int cr = 0; + sta = xiic_getreg32(i2c,XIIC_SR_REG_OFFSET); + cr = xiic_getreg32(i2c,XIIC_CR_REG_OFFSET); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, XIIC_INTR_TX_ERROR_MASK); + printk("%s: TRANSFER STATUS ERROR, ISR: bit 0x%x happens; SR: bit 0x%x; CR: bit 0x%x\n", + __func__, status, sta, cr); + } + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + (void)xiic_reinit(i2c); + mutex_unlock(&i2c->lock); + return err; + } + mutex_unlock(&i2c->lock); + } + + return err; +} + +static void ocores_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + //unsigned long flags; + u16 val; + + /* + * If we spin here because we are in timeout, so we are going + * to be in STATE_ERROR. See ocores_process_timeout() + */ + mutex_lock(&i2c->lock); + // printk("STATE: %d\n", i2c->state); + + if (i2c->state == STATE_START) { + i2c->state =(msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + /* if it's the time sequence is 'start bit + address + read bit + stop bit' */ + if (i2c->state == STATE_READ){ + /* it's the last message so we include dynamic stop bit with length */ + val = msg->len | XIIC_TX_DYN_STOP_MASK; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, val); + goto out; + } + } + if (i2c->state == STATE_READ){ + /* suit for I2C_FUNC_SMBUS_BLOCK_DATA */ + if (msg->flags & I2C_M_RECV_LEN) { + msg->len = xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + msg->flags &= ~I2C_M_RECV_LEN; + msg->buf[i2c->pos++] = msg->len; + } + else { + msg->buf[i2c->pos++] = xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + } + } else if (i2c->state == STATE_WRITE){ + /* if it reaches the last byte data to be sent */ + if ((i2c->pos == msg->len - 1) && (i2c->nmsgs == 1)){ + val = msg->buf[i2c->pos++] | XIIC_TX_DYN_STOP_MASK; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, val); + i2c->state = STATE_DONE; + goto out; + /* if it is not the last byte data to be sent */ + } else if (i2c->pos < msg->len) { + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, msg->buf[i2c->pos++]); + goto out; + } + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->pos = 0; + if (i2c->nmsgs) { + i2c->msg++; + msg = i2c->msg; + if (!(msg->flags & I2C_M_NOSTART)) /* send start? */{ + i2c->state = STATE_START; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK); + goto out; + } + } else { /* end? */ + i2c->state = STATE_DONE; + goto out; + } + } + +out: + mutex_unlock(&i2c->lock); + return ; +} + + +static int fpgai2c_poll(struct fpgalogic_i2c *i2c, + struct i2c_msg *msgs, int num) +{ + int ret = 0; + // u8 ctrl; + + mutex_lock(&i2c->lock); + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + /* Set receive Fifo depth to maximum (zero based). */ + xiic_setreg32(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + + /* Reset Tx Fifo. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + + /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); + + /* set i2c clock as 100Hz. */ + //xiic_setreg32(i2c, 0x13c, 0x7C); + + /* make sure RX fifo is empty */ + ret = xiic_clear_rx_fifo(i2c); + if (ret){ + mutex_unlock(&i2c->lock); + return ret; + } + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + // printk("STATE: %d\n", i2c->state); + + if (msgs->len == 0 && num == 1){ /* suit for i2cdetect time sequence */ + u8 status = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + xiic_irq_clr(i2c, status); + /* send out the 1st byte data and stop bit */ + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msgs) | XIIC_TX_DYN_START_MASK | XIIC_TX_DYN_STOP_MASK); + } else { + /* send out the 1st byte data */ + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msgs) | XIIC_TX_DYN_START_MASK); + } + mutex_unlock(&i2c->lock); + while (1) { + int err; + + err = ocores_poll_wait(i2c); + if (err) { + i2c->state = STATE_ERROR; + break; + }else if (i2c->state == STATE_DONE){ + break; + } + ocores_process(i2c); + } + + return (i2c->state == STATE_DONE) ? num : -EIO; +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int err = -EIO; + u8 retry = 0, max_retry = 0; + + if( ( (1 == msgs->len && (msgs->flags & I2C_M_RD)) || (0 == msgs->len && !(msgs->flags & I2C_M_RD)) ) && num == 1 ) /* I2C_SMBUS_QUICK or I2C_SMBUS_BYTE */ + max_retry = 1; + else + max_retry = 5; // retry 5 times if receive a NACK or other errors + while( (-EIO == err) && (retry < max_retry)) + { + err = fpgai2c_poll(i2c, msgs, num); + retry++; + } + + return err; + +} + +static u32 fpgai2c_func(struct i2c_adapter *adap) +{ +/* a typical full-I2C adapter would use the following */ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm fpgai2c_algorithm= { + .master_xfer = fpgai2c_xfer, /*write I2C messages */ + .functionality = fpgai2c_func, /* what the adapter supports */ +}; + +static int xiic_reinit(struct fpgalogic_i2c *i2c) +{ + int ret; + int val = 0; + + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + + /* Set receive Fifo depth to maximum (zero based). */ + xiic_setreg32(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + + /* Reset Tx Fifo. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + + /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ + val |= XIIC_CR_ENABLE_DEVICE_MASK; + //val |= XIIC_CR_TX_FIFO_RESET_MASK; + //val |= XIIC_CR_MSMS_MASK; + val |= XIIC_CR_DIR_IS_TX_MASK; + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, val); + + /* make sure RX fifo is empty */ + ret = xiic_clear_rx_fifo(i2c); + if (ret) + return ret; + + return 0; +} + +static int fpgai2c_init(struct fpgalogic_i2c *i2c) +{ + // int prescale; + // int diff; + // u8 ctrl; + int ret; + + + //i2c->reg_set = xiic_setreg32; + //i2c->reg_get = xiic_getreg32; + + ret = xiic_reinit(i2c); + if (ret < 0) { + printk("Cannot xiic_reinit\n"); + return ret; + } + + /* Initialize interrupt handlers if not already done */ + init_waitqueue_head(&i2c->wait); + return 0; +} + +static int adap_data_init(struct i2c_adapter *adap, int i2c_ch_index) +{ + struct fpgapci_devdata *pci_privdata = 0; + pci_privdata = (struct fpgapci_devdata*) dev_get_drvdata(adap->dev.parent); + + if (pci_privdata == 0) { + printk("[%s]: ERROR pci_privdata is 0\n", __FUNCTION__); + return -1; + } +#if DEBUG + pddf_dbg(FPGA, KERN_INFO "[%s] index: [%d] fpga_data__base_addr:0x%0x8lx" + " fpgapci_bar_len:0x%08lx fpga_i2c_ch_base_addr:0x%08lx ch_size=0x%x supported_i2c_ch=%d", + __FUNCTION__, i2c_ch_index, pci_privdata->fpga_data_base_addr, + pci_privdata->bar_length, pci_privdata->fpga_i2c_ch_base_addr, + pci_privdata->fpga_i2c_ch_size, pci_privdata->max_fpga_i2c_ch); +#endif + if (i2c_ch_index >= pci_privdata->max_fpga_i2c_ch || pci_privdata->max_fpga_i2c_ch > I2C_PCI_MAX_BUS) { + printk("[%s]: ERROR i2c_ch_index=%d max_ch_index=%d out of range: %d\n", + __FUNCTION__, i2c_ch_index, pci_privdata->max_fpga_i2c_ch, I2C_PCI_MAX_BUS); + return -1; + } +#ifdef __STDC_LIB_EXT1__ + memset_s(&fpgalogic_i2c[i2c_ch_index], sizeof(fpgalogic_i2c[0]), 0, sizeof(fpgalogic_i2c[0])); +#else + memset(&fpgalogic_i2c[i2c_ch_index], 0, sizeof(fpgalogic_i2c[0])); +#endif + + fpgalogic_i2c[i2c_ch_index].base = pci_privdata->fpga_i2c_ch_base_addr + + i2c_ch_index* pci_privdata->fpga_i2c_ch_size; + mutex_init(&fpgalogic_i2c[i2c_ch_index].lock); + fpgai2c_init(&fpgalogic_i2c[i2c_ch_index]); + + + adap->algo_data = &fpgalogic_i2c[i2c_ch_index]; + i2c_set_adapdata(adap, &fpgalogic_i2c[i2c_ch_index]); + return 0; +} + +static int pddf_i2c_pci_add_numbered_bus_default (struct i2c_adapter *adap, int i2c_ch_index) +{ + int ret = 0; + + adap_data_init(adap, i2c_ch_index); + adap->algo = &fpgai2c_algorithm; + + ret = i2c_add_numbered_adapter(adap); + return ret; +} + +/* + * FPGAPCI APIs + */ +int board_i2c_fpgapci_read(uint32_t offset) +{ + int data; + data=ioread32(fpga_ctl_addr+offset); + return data; +} + + +int board_i2c_fpgapci_write(uint32_t offset, uint32_t value) +{ + iowrite32(value, fpga_ctl_addr+offset); + return (0); +} + + +static int __init pddf_xilinx_device_7021_algo_init(void) +{ + pddf_dbg(FPGA, KERN_INFO "[%s]\n", __FUNCTION__); + pddf_i2c_pci_add_numbered_bus = pddf_i2c_pci_add_numbered_bus_default; + ptr_fpgapci_read = board_i2c_fpgapci_read; + ptr_fpgapci_write = board_i2c_fpgapci_write; + return 0; +} + +static void __exit pddf_xilinx_device_7021_algo_exit(void) +{ + pddf_dbg(FPGA, KERN_INFO "[%s]\n", __FUNCTION__); + + pddf_i2c_pci_add_numbered_bus = NULL; + ptr_fpgapci_read = NULL; + ptr_fpgapci_write = NULL; + return; +} + + +module_init (pddf_xilinx_device_7021_algo_init); +module_exit (pddf_xilinx_device_7021_algo_exit); +MODULE_DESCRIPTION("Xilinx Corporation Device 7021 FPGAPCIe I2C-Bus algorithm"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_extend.c b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_extend.c new file mode 100644 index 000000000000..4ea09f09404f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pddf_custom_fpga_extend.c @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * fpga-cls.c - front panel port control. + * + * Copyright (C) 2019 Celestica Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../../../../pddf/i2c/modules/include/pddf_i2c_algo.h" + +#define FPGA_VERSION_ADDR 0x0000 +#define FPGA_SCRATCH_ADDR 0x0004 +#define FPGA_BCM_TEMP_ADDR 0x001c +#define FPGA_BCM_TEMP_LOW_ADDR 0x0078 +#define FPGA_BCM_TEMP_HIGH_ADDR 0x0080 +#define FPGA_REG_SPACE_SIZE 0x2000 + + +/* + * fpga_priv - port fpga private data + * @dev: device for reference + * @base: virtual base address + * @num_ports: number of front panel ports + * @fp_devs: list of front panel port devices + */ +struct fpga_priv { + void __iomem *base; + struct mutex fpga_lock; // For FPGA internal lock + void __iomem * fpga_read_addr; +}; + +extern void __iomem * fpga_ctl_addr; + +/** + * Show the value of the register set by 'set_fpga_reg_address' + * If the address is not set by 'set_fpga_reg_address' first, + * The version register is selected by default. + * @param buf register value in hextring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + // read data from the address + uint32_t data; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + data = ioread32(fpga->fpga_read_addr); + return sprintf(buf, "0x%8.8x\n", data); +} +/** + * Store the register address + * @param buf address wanted to be read value of + * @return number of bytes stored, or an error code + */ +static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t addr; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + addr = (uint32_t)strtoul(buf, &last, 16); + if (addr == 0 && buf == last) { + return -EINVAL; + } + fpga->fpga_read_addr = fpga->base + addr; + return count; +} +/** + * Show value of fpga scratch register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + + return sprintf(buf, "0x%8.8x\n", ioread32(fpga->base + FPGA_SCRATCH_ADDR) & 0xffffffff); +} +/** + * Store value of fpga scratch register + * @param buf scratch register value passing from user space + * @return number of bytes stored, or an error code + */ +static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t data; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + data = (uint32_t)strtoul(buf, &last, 16); + if (data == 0 && buf == last) { + return -EINVAL; + } + iowrite32(data, fpga->base + FPGA_SCRATCH_ADDR); + return count; +} + +/** + * Show value of fpga version register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_version(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + + return sprintf(buf, "0x%8.8x\n", ioread32(fpga->base + FPGA_VERSION_ADDR) & 0xffffffff); +} + + +/** + * Store a value in a specific register address + * @param buf the value and address in format '0xhhhh 0xhhhhhhhh' + * @return number of bytes sent by user space, or an error code + */ +static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // register are 4 bytes + uint32_t addr; + uint32_t value; + uint32_t mode = 8; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + strscpy(clone, buf, count); + mutex_lock(&fpga->fpga_lock); + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + addr = (uint32_t)strtoul(tok, &last, 16); + if (addr == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + value = (uint32_t)strtoul(tok, &last, 16); + if (value == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mode = 32; + } else { + mode = (uint32_t)strtoul(tok, &last, 10); + if (mode == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + } + if (mode == 32) { + iowrite32(value, fpga->base + addr); + } else if (mode == 8) { + iowrite8(value, fpga->base + addr); + } else { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + mutex_unlock(&fpga->fpga_lock); + return count; +} + +/** + * Read all FPGA register in binary mode. + * @param buf Raw transceivers port startus and control register values + * @return number of bytes read, or an error code + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i = 0; + ssize_t status; + u8 read_reg; + struct device *dev = kobj_to_dev(kobj); + struct fpga_priv *fpga = dev_get_drvdata(dev); + + if ( off + count > FPGA_REG_SPACE_SIZE ) { + return -EINVAL; + } + mutex_lock(&fpga->fpga_lock); + while (i < count) { + read_reg = ioread8(fpga->base + off + i); + buf[i++] = read_reg; + } + status = count; + mutex_unlock(&fpga->fpga_lock); + return status; +} + +/** + * Show value of fpga bcm switch internal temp sensor register calculated by FPGA + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_bcm_temp_fpga(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + uint32_t reg_val = ioread32(fpga->base + FPGA_BCM_TEMP_ADDR) & 0x3ffff; + + return sprintf(buf, "0x%08x\n", reg_val); +} + +/** + * Show value of fpga bcm switch internal temp sensor register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_bcm_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + u8 low_byte = ioread32(fpga->base + FPGA_BCM_TEMP_LOW_ADDR) & 0xff; + u8 high_byte = ioread32(fpga->base + FPGA_BCM_TEMP_HIGH_ADDR) & 0xff; + + return sprintf(buf, "0x%02x%02x\n", high_byte, low_byte); +} + +/* FPGA attributes */ +static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address); +static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value); +static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch); +static DEVICE_ATTR( version, 0400, get_fpga_version, NULL); +static DEVICE_ATTR( bcm_temp_fpga, 0400, get_fpga_bcm_temp_fpga, NULL); +static DEVICE_ATTR( bcm_temp, 0400, get_fpga_bcm_temp, NULL); +static BIN_ATTR_RO( dump, FPGA_REG_SPACE_SIZE); + +static struct bin_attribute *fpga_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute *fpga_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_scratch.attr, + &dev_attr_version.attr, + &dev_attr_bcm_temp_fpga.attr, + &dev_attr_bcm_temp.attr, + &dev_attr_setreg.attr, + NULL, +}; + +static struct attribute_group fpga_attr_grp = { + .attrs = fpga_attrs, + .bin_attrs = fpga_bin_attrs, +}; + + +static int cls_fpga_probe(struct platform_device *pdev) +{ + struct fpga_priv *fpga; + int ret = -ENOMEM; + + if (!fpga_ctl_addr){ + printk(KERN_WARNING, "fpga_ctl_addr is null"); + return ret; + } + + fpga = devm_kzalloc(&pdev->dev, sizeof(struct fpga_priv), GFP_KERNEL); + if (!fpga){ + ret = -ENOMEM; + goto err_exit; + } + + mutex_init(&fpga->fpga_lock); + dev_set_drvdata(&pdev->dev, fpga); + fpga->base = fpga_ctl_addr; + + printk("FPGA version: 0x%x\n", ioread32(fpga->base + FPGA_VERSION_ADDR)); + + ret = sysfs_create_group(&pdev->dev.kobj, &fpga_attr_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create FPGA system sysfs attributes\n"); + goto err_remove_fpga; + } + + return 0; + +err_remove_fpga: + sysfs_remove_group(&pdev->dev.kobj, &fpga_attr_grp); +mem_unmap: + iounmap(fpga->base); +err_exit: + return ret; +} + +static int cls_fpga_remove(struct platform_device *pdev) +{ + struct fpga_priv *fpga = dev_get_drvdata(&pdev->dev); + + sysfs_remove_group(&pdev->dev.kobj, &fpga_attr_grp); + iounmap(fpga->base); + return 0; +} + +static void fpga_dev_release( struct device * dev) +{ + return; +} +static struct resource cls_fpga_resources[] = { + { + .start = NULL, + .end = NULL, + .flags = IORESOURCE_IO, + }, +}; + +static struct platform_device cls_fpga_dev = { + .name = "fpga_sysfs", + .id = -1, + .num_resources = ARRAY_SIZE(cls_fpga_resources), + .resource = cls_fpga_resources, + .dev = { + .release = fpga_dev_release, + } +}; + +static struct platform_driver cls_fpga_driver = { + .probe = cls_fpga_probe, + .remove = cls_fpga_remove, + .driver = { + .name = "fpga_sysfs", + }, +}; + +static int __init drv_init(void) +{ + int rc = 0; + + rc = platform_device_register(&cls_fpga_dev); + rc += platform_driver_register(&cls_fpga_driver); + printk("fpga drv_init:%d\n", rc); + return rc; +} + +static void __exit drv_exit(void) +{ + platform_driver_unregister(&cls_fpga_driver); + platform_device_unregister(&cls_fpga_dev); + printk("fpga drv_exit.\n"); +} + +module_init(drv_init); +module_exit(drv_exit); + +MODULE_AUTHOR("Nicholas Wu"); +MODULE_DESCRIPTION("Celestica fpga access/control driver"); +MODULE_VERSION("2.0.0"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:cls-fpga"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pmbus.h new file mode 100644 index 000000000000..cb6dbe29c0bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/pmbus.h @@ -0,0 +1,504 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + */ + +#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_WRITE_PROTECT = 0x10, + + 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, + + PMBUS_MFR_VIN_MIN = 0xA0, + PMBUS_MFR_VIN_MAX = 0xA1, + PMBUS_MFR_IIN_MAX = 0xA2, + PMBUS_MFR_PIN_MAX = 0xA3, + PMBUS_MFR_VOUT_MIN = 0xA4, + PMBUS_MFR_VOUT_MAX = 0xA5, + PMBUS_MFR_IOUT_MAX = 0xA6, + PMBUS_MFR_POUT_MAX = 0xA7, + + PMBUS_IC_DEVICE_ID = 0xAD, + PMBUS_IC_DEVICE_REV = 0xAE, + + PMBUS_MFR_MAX_TEMP_1 = 0xC0, + PMBUS_MFR_MAX_TEMP_2 = 0xC1, + PMBUS_MFR_MAX_TEMP_3 = 0xC2, + +/* + * 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, + + /* + * RPM and PWM Fan control + * + * Drivers wanting to expose PWM control must define the behaviour of + * PMBUS_VIRT_PWM_[1-4] and PMBUS_VIRT_PWM_ENABLE_[1-4] in the + * {read,write}_word_data callback. + * + * pmbus core provides a default implementation for + * PMBUS_VIRT_FAN_TARGET_[1-4]. + * + * TARGET, PWM and PWM_ENABLE members must be defined sequentially; + * pmbus core uses the difference between the provided register and + * it's _1 counterpart to calculate the FAN/PWM ID. + */ + PMBUS_VIRT_FAN_TARGET_1, + PMBUS_VIRT_FAN_TARGET_2, + PMBUS_VIRT_FAN_TARGET_3, + PMBUS_VIRT_FAN_TARGET_4, + PMBUS_VIRT_PWM_1, + PMBUS_VIRT_PWM_2, + PMBUS_VIRT_PWM_3, + PMBUS_VIRT_PWM_4, + PMBUS_VIRT_PWM_ENABLE_1, + PMBUS_VIRT_PWM_ENABLE_2, + PMBUS_VIRT_PWM_ENABLE_3, + PMBUS_VIRT_PWM_ENABLE_4, + + /* Samples for average + * + * Drivers wanting to expose functionality for changing the number of + * samples used for average values should implement support in + * {read,write}_word_data callback for either PMBUS_VIRT_SAMPLES if it + * applies to all types of measurements, or any number of specific + * PMBUS_VIRT_*_SAMPLES registers to allow for individual control. + */ + PMBUS_VIRT_SAMPLES, + PMBUS_VIRT_IN_SAMPLES, + PMBUS_VIRT_CURR_SAMPLES, + PMBUS_VIRT_POWER_SAMPLES, + PMBUS_VIRT_TEMP_SAMPLES, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * WRITE_PROTECT + */ +#define PB_WP_ALL BIT(7) /* all but WRITE_PROTECT */ +#define PB_WP_OP BIT(6) /* all but WP, OPERATION, PAGE */ +#define PB_WP_VOUT BIT(5) /* all but WP, OPERATION, PAGE, VOUT, ON_OFF */ + +#define PB_WP_ANY (PB_WP_ALL | PB_WP_OP | PB_WP_VOUT) + +/* + * 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) + +enum pmbus_fan_mode { percent = 0, rpm }; + +/* + * 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_VIN_OFF BIT(3) +#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_PWM, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ +#define PMBUS_PHASES 10 /* Maximum number of phases per page */ + +/* 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) +#define PMBUS_HAVE_PWM12 BIT(20) +#define PMBUS_HAVE_PWM34 BIT(21) +#define PMBUS_HAVE_SAMPLES BIT(22) + +#define PMBUS_PHASE_VIRTUAL BIT(30) /* Phases on this page are virtual */ +#define PMBUS_PAGE_VIRTUAL BIT(31) /* Page is virtual */ + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + u8 phases[PMBUS_PAGES]; /* Number of phases per page */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version[PMBUS_PAGES]; /* vrm version per page */ + /* + * 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 */ + u32 pfunc[PMBUS_PHASES];/* Functionality, per phase */ + /* + * 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 phase, + 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; + + /* custom attributes */ + const struct attribute_group **groups; +}; + +/* 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, int page, int phase); +int pmbus_read_word_data(struct i2c_client *client, int page, int phase, + u8 reg); +int pmbus_write_word_data(struct i2c_client *client, int 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, struct pmbus_driver_info *info); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); +int pmbus_get_fan_rate_device(struct i2c_client *client, int page, int id, + enum pmbus_fan_mode mode); +int pmbus_get_fan_rate_cached(struct i2c_client *client, int page, int id, + enum pmbus_fan_mode mode); +int pmbus_update_fan(struct i2c_client *client, int page, int id, + u8 config, u8 mask, u16 command); +struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.c b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.c new file mode 100644 index 000000000000..338417125569 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.c @@ -0,0 +1,478 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description of various APIs related to PSU component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_psu_defs.h" +#include "pddf_psu_driver.h" + + +#define PSU_REG_VOUT_MODE 0x20 +#define PSU_REG_READ_VOUT 0x8b + +/*#define PSU_DEBUG*/ +#ifdef PSU_DEBUG +#define psu_dbg(...) printk(__VA_ARGS__) +#else +#define psu_dbg(...) +#endif + + +void get_psu_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + case PSU_V_OUT: + strscpy(str, "in3_input", ATTR_NAME_LEN); + break; + case PSU_I_OUT: + strscpy(str, "curr2_input", ATTR_NAME_LEN); + break; + case PSU_P_OUT: + strscpy(str, "power2_input", ATTR_NAME_LEN); + break; + case PSU_FAN1_SPEED: + strscpy(str, "fan1_input", ATTR_NAME_LEN); + break; + case PSU_TEMP1_INPUT: + strscpy(str, "temp1_input", ATTR_NAME_LEN); + break; + default: + break; + } + + return; +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static u8 psu_get_vout_mode(struct i2c_client *client) +{ + u8 status = 0, retry = 10; + uint8_t offset = PSU_REG_VOUT_MODE; + + while (retry) + { + status = i2c_smbus_read_byte_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + printk(KERN_ERR "%s: Get PSU Vout mode failed\n", __func__); + return 0; + } + else + { + /*printk(KERN_ERR "%s: vout_mode reg value 0x%x\n", __func__, status);*/ + return status; + } +} + +static u16 psu_get_v_out(struct i2c_client *client) +{ + u16 status = 0, retry = 10; + uint8_t offset = PSU_REG_READ_VOUT; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + printk(KERN_ERR "%s: Get PSU Vout failed\n", __func__); + return 0; + } + else + { + /*printk(KERN_ERR "%s: vout reg value 0x%x\n", __func__, status);*/ + return status; + } +} + +int psu_update_hw(struct device *dev, struct psu_attr_info *info, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + + +int psu_update_attr(struct device *dev, struct psu_attr_info *data, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data=NULL; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) + { + dev_dbg(&client->dev, "Starting update for %s\n", data->name); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: pre_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: post_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return 0; +} + +ssize_t psu_show_default(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); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i, status=0; + u16 value = 0; + u8 vout_mode = 0; + int exponent, mantissa; + int multiplier = 1000; + char new_str[ATTR_NAME_LEN] = ""; + PSU_SYSFS_ATTR_DATA *ptr = NULL; + + for (i=0;inum_attr;i++) + { + ptr = (PSU_SYSFS_ATTR_DATA *)pdata->psu_attrs[i].access_data; + get_psu_duplicate_sysfs(ptr->index , new_str); + if ( strcmp(attr->dev_attr.attr.name, pdata->psu_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0 ) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + strscpy(new_str, "", ATTR_NAME_LEN); + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) + { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + psu_update_attr(dev, sysfs_attr_info, usr_data); + + switch(attr->index) + { + case PSU_PRESENT: + case PSU_POWER_GOOD: + status = sysfs_attr_info->val.intval; + return sprintf(buf, "%d\n", status); + break; + case PSU_MODEL_NAME: + case PSU_MFR_ID: + case PSU_SERIAL_NUM: + case PSU_FAN_DIR: + return sprintf(buf, "%s\n", sysfs_attr_info->val.strval); + break; + case PSU_V_OUT: + value = psu_get_v_out(client); + vout_mode = psu_get_vout_mode(client); + if ((vout_mode >> 5) == 0) + exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f); + else + exponent = 0; + + mantissa = value; + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + + case PSU_V_OUT_MIN: + case PSU_V_OUT_MAX: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + vout_mode = psu_get_vout_mode(client); + if ((vout_mode >> 5) == 0) + exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f); + else + exponent = 0; + mantissa = two_complement_to_int(value & 0xffff, 16, 0xffff); + + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + case PSU_I_OUT: + case PSU_V_IN: + case PSU_I_IN: + case PSU_P_OUT_MAX: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + case PSU_P_IN: + case PSU_P_OUT: + multiplier = 1000000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + case PSU_FAN1_SPEED: + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent)); + else + return sprintf(buf, "%d\n", (mantissa) / (1 << -exponent)); + + break; + case PSU_TEMP1_INPUT: + case PSU_TEMP1_HIGH_THRESHOLD: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + default: + printk(KERN_ERR "%s: Unable to find attribute index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t psu_store_default(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 psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->psu_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + /*No write attributes for now in PSU*/ + default: + goto exit; + } + + psu_update_hw(dev, sysfs_attr_info, usr_data); + +exit: + return count; +} + +extern int board_i2c_cpld_read_new(unsigned short cpld_addr, char *name, u8 reg); +int sonic_i2c_get_psu_byte_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0; + int val = 0; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + + + if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0) + { + val = board_i2c_cpld_read_new(adata->devaddr, adata->devname, adata->offset); + if (val < 0){ + return val; + } + padata->val.intval = ((val & adata->mask) == adata->cmpval); + psu_dbg(KERN_ERR "%s: byte_value = 0x%x\n", __FUNCTION__, padata->val.intval); + } + + return status; +} + +int sonic_i2c_get_psu_block_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char buf[32]=""; //temporary placeholder for block data + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, buf); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + buf[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read block of data from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + buf[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strscpy(padata->val.strval, buf+1, data_len-1); + else + strscpy(padata->val.strval, buf, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, buf block: %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_word_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read a word from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: word value : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.h b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.h new file mode 100644 index 000000000000..24e4ea02e7ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_api.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * PSU driver related api declarations + */ + +#ifndef __PDDF_PSU_API_H__ +#define __PDDF_PSU_API_H__ + +extern void get_psu_duplicate_sysfs(int idx, char *str); +extern ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +extern int sonic_i2c_get_psu_byte_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_block_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_word_default(void *client, PSU_DATA_ATTR *adata, void *data); + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_defs.h b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_defs.h new file mode 100644 index 000000000000..60e81a9f5878 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_defs.h @@ -0,0 +1,90 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description: + * Platform PSU defines/structures header file + */ + +#ifndef __PDDF_PSU_DEFS_H__ +#define __PDDF_PSU_DEFS_H__ + + +#define MAX_NUM_PSU 5 +#define MAX_PSU_ATTRS 32 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct PSU_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum psu_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute + char devname[DEV_TYPE_LEN]; // Name of the device from where this sysfs attr is read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + void *access_data; + +}PSU_DATA_ATTR; + +typedef struct PSU_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, PSU_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, PSU_DATA_ATTR *adata, void *data); + void *data; +} PSU_SYSFS_ATTR_DATA; + +typedef struct PSU_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + PSU_SYSFS_ATTR_DATA *a_ptr; +} PSU_SYSFS_ATTR_DATA_ENTRY; + + +/* PSU CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */ +typedef struct PSU_DATA +{ + int idx; // psu index + int num_psu_fans; + PSU_DATA_ATTR psu_attr; + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR psu_attrs[MAX_PSU_ATTRS]; +}PSU_DATA; + +typedef struct PSU_PDATA +{ + int idx; // psu index + int num_psu_fans; // num of fans supported by the PSU + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR *psu_attrs; +}PSU_PDATA; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.c b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.c new file mode 100644 index 000000000000..fa5d31a0866a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.c @@ -0,0 +1,398 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * A pddf kernel module driver for PSU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_driver.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_api.h" + + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +struct pddf_ops_t pddf_psu_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = NULL, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_psu_ops); + + +PSU_SYSFS_ATTR_DATA access_psu_present = {PSU_PRESENT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_byte_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_present); + +PSU_SYSFS_ATTR_DATA access_psu_model_name = {PSU_MODEL_NAME, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_model_name); + +PSU_SYSFS_ATTR_DATA access_psu_power_good = {PSU_POWER_GOOD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_byte_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_power_good); + +PSU_SYSFS_ATTR_DATA access_psu_mfr_id = {PSU_MFR_ID, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_mfr_id); + +PSU_SYSFS_ATTR_DATA access_psu_serial_num = {PSU_SERIAL_NUM, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_serial_num); + +PSU_SYSFS_ATTR_DATA access_psu_fan_dir = {PSU_FAN_DIR, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan_dir); + +PSU_SYSFS_ATTR_DATA access_psu_v_out = {PSU_V_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out); + +PSU_SYSFS_ATTR_DATA access_psu_v_out_min = {PSU_V_OUT_MIN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out_min); + +PSU_SYSFS_ATTR_DATA access_psu_v_out_max = {PSU_V_OUT_MAX, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out_max); + +PSU_SYSFS_ATTR_DATA access_psu_i_out = {PSU_I_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out = {PSU_P_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out_max = {PSU_P_OUT_MAX, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out_max); + +PSU_SYSFS_ATTR_DATA access_psu_fan1_speed_rpm = {PSU_FAN1_SPEED, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan1_speed_rpm); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_input = {PSU_TEMP1_INPUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_input); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_high_threshold = {PSU_TEMP1_HIGH_THRESHOLD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_high_threshold); + +PSU_SYSFS_ATTR_DATA access_psu_v_in = {PSU_V_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_in); + +PSU_SYSFS_ATTR_DATA access_psu_i_in = {PSU_I_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_in); + +PSU_SYSFS_ATTR_DATA access_psu_p_in = {PSU_P_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_in); + +PSU_SYSFS_ATTR_DATA_ENTRY psu_sysfs_attr_data_tbl[]= +{ + { "psu_present", &access_psu_present}, + { "psu_model_name", &access_psu_model_name}, + { "psu_power_good" , &access_psu_power_good}, + { "psu_mfr_id" , &access_psu_mfr_id}, + { "psu_serial_num" , &access_psu_serial_num}, + { "psu_fan_dir" , &access_psu_fan_dir}, + { "psu_v_out" , &access_psu_v_out}, + { "psu_v_out_min" , &access_psu_v_out_min}, + { "psu_v_out_max" , &access_psu_v_out_max}, + { "psu_i_out" , &access_psu_i_out}, + { "psu_p_out" , &access_psu_p_out}, + { "psu_p_out_max" , &access_psu_p_out_max}, + { "psu_fan1_speed_rpm" , &access_psu_fan1_speed_rpm}, + { "psu_temp1_input" , &access_psu_temp1_input}, + { "psu_temp1_high_threshold" , &access_psu_temp1_high_threshold}, + { "psu_v_in" , &access_psu_v_in}, + { "psu_i_in" , &access_psu_i_in}, + { "psu_p_in" , &access_psu_p_in} +}; + +void *get_psu_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(psu_sysfs_attr_data_tbl)/sizeof(psu_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, psu_sysfs_attr_data_tbl[i].name) ==0) + { + return &psu_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_psu_access_data); + + +static int psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct psu_data *data; + int status =0; + int i,num, j=0; + PSU_PDATA *psu_platform_data; + PSU_DATA_ATTR *data_attr; + PSU_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_psu_ops.pre_probe) + { + status = (pddf_psu_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + /* Take control of the platform data */ + psu_platform_data = (PSU_PDATA *)(client->dev.platform_data); + num = psu_platform_data->len; + data->index = psu_platform_data->idx - 1; + data->num_psu_fans = psu_platform_data->num_psu_fans; + data->num_attr = num; + + + + /* Create and Add supported attr in the 'attributes' list */ + for (i=0; ipsu_attrs + i; + sysfs_data_entry = get_psu_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + continue; + } + + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[i] = &dy_ptr->dev_attr.attr; + strscpy(data->attr_info[i].name, data_attr->aname, ATTR_NAME_LEN); + data->attr_info[i].valid = 0; + mutex_init(&data->attr_info[i].update_lock); + + /*Create a duplicate entry*/ + get_psu_duplicate_sysfs(dy_ptr->index, new_str); + if (strcmp(new_str,"")) + { + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, new_str, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strscpy(new_str,"", ATTR_NAME_LEN); + } + } + data->psu_attribute_list[i+j] = NULL; + data->psu_attribute_group.attrs = data->psu_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->psu_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_psu_ops.post_probe) + { + status = (pddf_psu_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0;data->psu_attribute_list[i]!=NULL;i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + } + kfree(data); +exit: + return status; +} + +static void psu_remove(struct i2c_client *client) +{ + int i=0, ret = 0; + struct psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *platdata = (PSU_PDATA *)client->dev.platform_data; // use dev_get_platdata() + PSU_DATA_ATTR *platdata_sub = platdata->psu_attrs; + struct sensor_device_attribute *ptr = NULL; + + if (pddf_psu_ops.pre_remove) + { + ret = (pddf_psu_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); + for (i=0; data->psu_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + } + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_psu_ops.post_remove) + { + ret = (pddf_psu_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } +} + +enum psu_intf +{ + eeprom_intf, + smbus_intf +}; + +static const struct i2c_device_id psu_id[] = { + {"psu_eeprom", eeprom_intf}, + {"psu_pmbus", smbus_intf}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, psu_id); + +static struct i2c_driver psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "psu", + }, + .probe = psu_probe, + .remove = psu_remove, + .id_table = psu_id, + .address_list = normal_i2c, +}; + +int example_fun(void) +{ + pddf_dbg(PSU, KERN_ERR "CALLING FUN...\n"); + return 0; +} +EXPORT_SYMBOL(example_fun); + + +int psu_init(void) +{ + int status = 0; + + if (pddf_psu_ops.pre_init) + { + status = (pddf_psu_ops.pre_init)(); + if (status!=0) + return status; + } + + pddf_dbg(PSU, KERN_ERR "GENERIC_PSU_DRIVER.. init Invoked..\n"); + status = i2c_add_driver(&psu_driver); + if (status!=0) + return status; + + if (pddf_psu_ops.post_init) + { + status = (pddf_psu_ops.post_init)(); + if (status!=0) + return status; + } + + return status; +} +EXPORT_SYMBOL(psu_init); + +void psu_exit(void) +{ + pddf_dbg(PSU, "GENERIC_PSU_DRIVER.. exit\n"); + if (pddf_psu_ops.pre_exit) (pddf_psu_ops.pre_exit)(); + i2c_del_driver(&psu_driver); + if (pddf_psu_ops.post_exit) (pddf_psu_ops.post_exit)(); +} +EXPORT_SYMBOL(psu_exit); + +module_init(psu_init); +module_exit(psu_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.h b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.h new file mode 100644 index 000000000000..a94cf7441dbc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/modules/psu_driver/pddf_psu_driver.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * PSU driver data structures + */ +#ifndef __PDDF_PSU_DRIVER_H__ +#define __PDDF_PSU_DRIVER_H__ + +enum psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_MFR_ID, + PSU_SERIAL_NUM, + PSU_FAN_DIR, + PSU_V_OUT, + PSU_V_OUT_MIN, + PSU_V_OUT_MAX, + PSU_I_OUT, + PSU_P_OUT, /* This is in micro watts to comply with lm-sensors */ + PSU_P_OUT_MAX, + PSU_FAN1_SPEED, + PSU_TEMP1_INPUT, + PSU_TEMP1_HIGH_THRESHOLD, + PSU_V_IN, + PSU_I_IN, + PSU_P_IN, + PSU_ATTR_MAX +}; + + +/* Every client has psu_data which is divided into per attribute data */ +struct psu_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status; + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; +struct psu_data { + struct device *hwmon_dev; + u8 index; + int num_psu_fans; + int num_attr; + struct attribute *psu_attribute_list[MAX_PSU_ATTRS]; + struct attribute_group psu_attribute_group; + struct psu_attr_info attr_info[MAX_PSU_ATTRS]; +}; + + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/setup.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/setup.py similarity index 98% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/setup.py rename to platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/setup.py index 159e26656138..a1535165bb66 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/setup.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/setup.py @@ -1,4 +1,5 @@ import os +import sys from setuptools import setup os.listdir diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/__init__.py similarity index 63% rename from platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/__init__.py rename to platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/__init__.py index 0533d11584e1..21d9cd445e31 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/pddf/sonic_platform/__init__.py +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/__init__.py @@ -1,4 +1,4 @@ # All the derived classes for PDDF __all__ = ["platform", "chassis", "sfp", "psu", "thermal"] -from sonic_platform import * #[py/polluting-import] - +from . import platform +from . import chassis diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/chassis.py new file mode 100644 index 000000000000..74a4a0ff899c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/chassis.py @@ -0,0 +1,242 @@ +############################################################################# +# PDDF +# Module contains an implementation of SONiC Chassis API +# +############################################################################# + +try: + from sonic_platform_pddf_base.pddf_chassis import PddfChassis + import sys + import subprocess + import time + import os + import re + import shutil + from . import helper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_SFP = 56 +GETREG_PATH="/sys/devices/platform/sys_cpld/getreg" +SETREG_PATH="/sys/devices/platform/sys_cpld/setreg" +SET_SYS_STATUS_LED="echo {} {} > {}" +SET_SYS_STATUS_LED_IPMI="0x3A 0x39 0x02 0x00 {}" +GET_REBOOT_CAUSE="echo '0xA107' > {} && cat {}".format(GETREG_PATH, GETREG_PATH) + +ORG_HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +TMP_HW_REBOOT_CAUSE_FILE="/tmp/hw-reboot-cause.txt" + +BMC_EXIST = helper.APIHelper().is_bmc_present() + +class Chassis(PddfChassis): + """ + PDDF Platform-specific Chassis class + """ + sfp_status_dict={} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + PddfChassis.__init__(self, pddf_data, pddf_plugin_data) + + for port_idx in range(1, NUM_SFP+1): + present = self.get_sfp(port_idx).get_presence() + self.sfp_status_dict[port_idx] = '1' if present else '0' + + # Component firmware version initialization + from sonic_platform.component import Component + if BMC_EXIST: + NUM_COMPONENT = 10 + else: + NUM_COMPONENT = 7 + for i in range(0, NUM_COMPONENT): + component = Component(i) + self._component_list.append(component) + + def _getstatusoutput(self, cmd): + status = 0 + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = ret + else: + return data + + return status, data + + def initizalize_system_led(self): + return True + + def get_status_led(self): + return self.get_system_led("SYS_LED") + + def set_status_led(self, color): + if color == self.get_status_led(): + return False + + if BMC_EXIST: + sys_led_color_map = { + 'off': '00', + 'green': '01', + 'amber': '02', + 'amber_blink_1hz': '03', + 'amber_blink_4hz': '04', + 'green_blink_1hz': '05', + 'green_blink_4hz': '06', + 'alternate_blink_1hz': '07', + 'alternate_blink_4hz': '08' + } + color_val = sys_led_color_map.get(color.lower(), None) + if color_val is None: + print("SYS LED color %s not support!" % color) + return False + + status, _ = helper.APIHelper().ipmi_raw(SET_SYS_STATUS_LED_IPMI.format(color_val)) + return status + else: + color_val="0xd0" + if color == "green": + color_val="0xd0" + elif color == "amber": + color_val="0xe0" + + cmd=SET_SYS_STATUS_LED.format("0xA162", color_val, SETREG_PATH) + status, res = self._getstatusoutput(cmd) + + if status != 0: + return False + else: + return True + + def get_sfp(self, index): + """ + Retrieves sfp represented by (1-based) index + For Quanta the index in sfputil.py starts from 1, so override + Args: + index: An integer, the index (1-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 1. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + if (index == 0): + raise IndexError + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("override: SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + + return sfp + + + # Provide the functions/variables below for which implementation is to be overwritten + + 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. + """ + # Newer baseboard CPLD to get reboot cause from CPLD register + hw_reboot_cause = "" + status, hw_reboot_cause = self._getstatusoutput(GET_REBOOT_CAUSE) + if status != 0: + pass + + # This tmp copy is to retain the reboot-cause only for the current boot + if os.path.isfile(ORG_HW_REBOOT_CAUSE_FILE): + shutil.move(ORG_HW_REBOOT_CAUSE_FILE, TMP_HW_REBOOT_CAUSE_FILE) + + if hw_reboot_cause == "0x33" and os.path.isfile(TMP_HW_REBOOT_CAUSE_FILE): + with open(TMP_HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + if match is not None: + if match.group(1) == 'system': + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'System cold reboot' + return (reboot_cause, description) + + if hw_reboot_cause == "0x77": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power Cycle Reset' + elif hw_reboot_cause == "0x66": + reboot_cause = self.REBOOT_CAUSE_WATCHDOG + description = 'Hardware Watchdog Reset' + elif hw_reboot_cause == "0x44": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'CPU Warm Reset' + elif hw_reboot_cause == "0x33": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'Soft-Set Cold Reset' + elif hw_reboot_cause == "0x22": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'Soft-Set Warm Reset' + elif hw_reboot_cause == "0x11": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power On Reset' + else: + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Hardware reason' + + return (reboot_cause, description) + + def get_change_event(self, timeout=0): + sfp_dict = {} + + SFP_REMOVED = '0' + SFP_INSERTED = '1' + + SFP_PRESENT = True + SFP_ABSENT = False + + start_time = time.time() + time_period = timeout/float(1000) #Convert msecs to secs + + while time.time() < (start_time + time_period) or timeout == 0: + for port_idx in range(1, NUM_SFP+1): + if self.sfp_status_dict[port_idx] == SFP_REMOVED and \ + self.get_sfp(port_idx).get_presence() == SFP_PRESENT: + sfp_dict[port_idx] = SFP_INSERTED + self.sfp_status_dict[port_idx] = SFP_INSERTED + elif self.sfp_status_dict[port_idx] == SFP_INSERTED and \ + self.get_sfp(port_idx).get_presence() == SFP_ABSENT: + sfp_dict[port_idx] = SFP_REMOVED + self.sfp_status_dict[port_idx] = SFP_REMOVED + + if sfp_dict: + return True, {'sfp':sfp_dict} + + time.sleep(0.5) + + return True, {'sfp':{}} # Timeout + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + try: + if self._watchdog is None: + from sonic_platform.cpld_watchdog import Watchdog + # Create the watchdog Instance + self._watchdog = Watchdog() + + except Exception as e: + print("Fail to load watchdog due to {}".format(e)) + return self._watchdog + + def get_revision(self): + """ + Retrieves the hardware revision for the chassis + Returns: + A string containing the hardware revision for this chassis. + """ + return self._eeprom.revision_str().encode('utf-8').hex() diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/component.py new file mode 100644 index 000000000000..bfa9e49ab0f7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/component.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import subprocess +import re + +try: + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +COMPONENT_LIST = [ + ("BIOS", "Basic input/output System"), + ("ONIE", "Open Network Install Environment"), + ("BMC", "Baseboard Management Controller"), + ("FPGA", "FPGA for transceiver EEPROM access and other component I2C access"), + ("CPLD COMe", "COMe board CPLD"), + ("CPLD BASE", "CPLD for board functions, fan control and watchdog"), + ("CPLD SW1", "CPLD for port control SFP(1-24)"), + ("CPLD SW2", "CPLD for port control SFP(25-48), QSFP(49-56)"), + ("ASIC PCIe", "ASIC PCIe Firmware"), + ("SSD", "Solid State Drive - {}") +] +NAME_INDEX = 0 +DESCRIPTION_INDEX = 1 + +BIOS_VERSION_CMD = "dmidecode -s bios-version" +ONIE_VERSION_CMD = "cat /host/machine.conf" +FPGA_VERSION_PATH = "/sys/bus/platform/devices/fpga_sysfs/version" +COME_CPLD_VERSION_CMD = "cat /sys/devices/platform/sys_cpld/come_cpld_version" +SWCPLD1_VERSION_CMD = "i2cget -y -f 102 0x30 0x0" +SWCPLD2_VERSION_CMD = "i2cget -y -f 102 0x31 0x0" +GETREG_PATH="/sys/devices/platform/sys_cpld/getreg" +BASECPLD_VERSION_CMD="echo '0xA100' > {} && cat {}".format(GETREG_PATH, GETREG_PATH) +BMC_PRESENCE="echo '0xA108' > {} && cat {}".format(GETREG_PATH, GETREG_PATH) +SSD_VERSION_CMD = "smartctl -i /dev/sda" +ASIC_PCIE_VERSION_CMD = "bcmcmd 'pciephy fw version' | grep 'PCIe FW version' | cut -d ' ' -f 4" + +UNKNOWN_VER = "Unknown" + +class Component(): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + ComponentBase.__init__(self) + self.index = component_index + self.name = self.get_name() + + def __get_cpld_ver(self): + cpld_version_dict = dict() + cpld_ver_info = { + 'CPLD BASE': self.__get_basecpld_ver(), + 'CPLD SW1': self.__get_swcpld1_ver(), + 'CPLD SW2': self.__get_swcpld2_ver(), + 'CPLD COMe': self.__get_comecpld_ver() + } + for cpld_name, cpld_ver in cpld_ver_info.items(): + cpld_ver_str = "{}.{}".format(int(cpld_ver[2], 16), int( + cpld_ver[3], 16)) if cpld_ver else UNKNOWN_VER + cpld_version_dict[cpld_name] = cpld_ver_str + + return cpld_version_dict + + def __get_asic_pcie_ver(self): + status, raw_ver=self.run_command(ASIC_PCIE_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_bios_ver(self): + status, raw_ver=self.run_command(BIOS_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_comecpld_ver(self): + status, raw_ver=self.run_command(COME_CPLD_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_basecpld_ver(self): + status, raw_ver=self.run_command(BASECPLD_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_swcpld1_ver(self): + status, raw_ver=self.run_command(SWCPLD1_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_swcpld2_ver(self): + status, raw_ver=self.run_command(SWCPLD2_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_bmc_presence(self): + status, raw_ver=self.run_command(BMC_PRESENCE) + if status and raw_ver == "0x00": + return True + else: + return False + + def __get_bmc_ver(self): + cmd="ipmitool mc info | grep 'Firmware Revision'" + status, raw_ver=self.run_command(cmd) + if status: + bmc_ver=raw_ver.split(':')[-1].strip() + return {"BMC":bmc_ver} + else: + return {"BMC":"N/A"} + + def __get_fpga_version(self): + status, fpga_version = self.run_command("cat %s" % FPGA_VERSION_PATH) + if not status: + return UNKNOWN_VER + return fpga_version.replace("0x", "") + + def __get_onie_ver(self): + onie_ver = "N/A" + status, raw_onie_data = self.run_command(ONIE_VERSION_CMD) + if status: + ret = re.search(r"(?<=onie_version=).+[^\n]", raw_onie_data) + if ret != None: + onie_ver = ret.group(0) + return onie_ver + + def __get_ssd_ver(self): + ssd_ver = "N/A" + status, raw_ssd_data = self.run_command(SSD_VERSION_CMD) + if status: + ret = re.search(r"Firmware Version: +(.*)[^\\]", raw_ssd_data) + if ret != None: + ssd_ver = ret.group(1) + return ssd_ver + + def __get_ssd_desc(self, desc_format): + description = "N/A" + status, raw_ssd_data = self.run_command(SSD_VERSION_CMD) + if status: + ret = re.search(r"Device Model: +(.*)[^\\]", raw_ssd_data) + if ret != None: + try: + description = desc_format.format(ret.group(1)) + except (IndexError): + pass + return description + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][NAME_INDEX] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + # For SSD get the model name from device + if self.get_name() == "SSD": + return self.__get_ssd_desc(COMPONENT_LIST[self.index][1]) + + return COMPONENT_LIST[self.index][DESCRIPTION_INDEX] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version_info = { + "ONIE": self.__get_onie_ver(), + "SSD": self.__get_ssd_ver(), + "BIOS": self.__get_bios_ver(), + "FPGA": self.__get_fpga_version(), + "ASIC PCIe": self.__get_asic_pcie_ver(), + } + fw_version_info.update(self.__get_cpld_ver()) + if self.__get_bmc_presence(): + fw_version_info.update(self.__get_bmc_ver()) + return fw_version_info.get(self.name, UNKNOWN_VER) + + def run_command(self, cmd): + status = True + result = "" + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/cpld_watchdog.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/cpld_watchdog.py new file mode 100644 index 000000000000..b828dbf65887 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/cpld_watchdog.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python + +############################################################################# +# +# Watchdog contains an implementation of SONiC Platform Base Watchdog API +# +############################################################################# +try: + import ctypes + import fcntl + import os + import subprocess + import time + import array + import syslog + from .helper import APIHelper + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +LPC_CPLD_GETREG_PATH = "/sys/bus/platform/devices/sys_cpld/getreg" +LPC_CPLD_SETREG_PATH = "/sys/bus/platform/devices/sys_cpld/setreg" +LPC_WDT_SET_TIMER_L_REG = '0xa183' +LPC_WDT_SET_TIMER_M_REG = '0xa182' +LPC_WDT_SET_TIMER_H_REG = '0xa181' +LPC_WDT_TIMER_L_REG = '0xa186' +LPC_WDT_TIMER_M_REG = '0xa185' +LPC_WDT_TIMER_H_REG = '0xa184' +LPC_WDT_CTRL_REG = '0xa187' +LPC_WDT_ARM_REG = '0xa188' + +WDT_ENABLE = 0x1 +WDT_DISABLE = 0x0 +WDT_COMMON_ERROR = -1 +DEFAULT_TIMEOUT = 180 + +class CpldWatchdog(WatchdogBase): + + def __init__(self): + WatchdogBase.__init__(self) + # Set default value + self._api_helper = APIHelper() + self._ka_count = int(1) + self.armed = True if self._active() else False + self.timeout = self._gettimeout() if self.armed else DEFAULT_TIMEOUT + #self._disable() + + def _lpc_get(self, reg): + return self._api_helper.lpc_getreg(LPC_CPLD_GETREG_PATH, reg) + + def _lpc_set(self, reg, val): + if type(val) is int: + val = hex(val) + return self._api_helper.lpc_setreg(LPC_CPLD_SETREG_PATH, reg, val) + + def _active(self): + """ + WDT is active or not + """ + data = self._lpc_get(LPC_WDT_CTRL_REG) + return True if data == "0x01" else False + + def _enable(self): + """ + Turn on the watchdog timer + """ + status = self._lpc_set(LPC_WDT_CTRL_REG, WDT_ENABLE) + if not status: + pass + + def _disable(self): + """ + Turn off the watchdog timer + """ + status = self._lpc_set(LPC_WDT_CTRL_REG, WDT_DISABLE) + if not status: + pass + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + if bool(self._ka_count % 2): + status = self._lpc_set(LPC_WDT_ARM_REG, WDT_ENABLE) + else: + status = self._lpc_set(LPC_WDT_ARM_REG, WDT_DISABLE) + + if not status: + syslog.syslog(syslog.LOG_ERR, "Feed Watchdog failed") + + self._ka_count = self._ka_count + 1 + if (self._ka_count >= 11): + self._ka_count = 1 + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + ms = seconds * 1000 + ms_low_byte = ms & 0xff + ms_media_byte = (ms >> 8) & 0xff + ms_high_byte = (ms >> 16) & 0xff + self._lpc_set(LPC_WDT_SET_TIMER_L_REG, ms_low_byte) + self._lpc_set(LPC_WDT_SET_TIMER_M_REG, ms_media_byte) + self._lpc_set(LPC_WDT_SET_TIMER_H_REG, ms_high_byte) + return self._gettimeout() + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + data = [0, 0, 0] + data[0] = self._lpc_get(LPC_WDT_SET_TIMER_L_REG) + data[1] = self._lpc_get(LPC_WDT_SET_TIMER_M_REG) + data[2] = self._lpc_get(LPC_WDT_SET_TIMER_H_REG) + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + return seconds + + def _gettimeleft(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + data = [0, 0, 0] + data[0] = self._lpc_get(LPC_WDT_TIMER_L_REG) + data[1] = self._lpc_get(LPC_WDT_TIMER_M_REG) + data[2] = self._lpc_get(LPC_WDT_TIMER_H_REG) + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + + return seconds + + ################################################################# + + 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. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.armed: + self._keepalive() + if self.timeout != seconds: + self._disable() + time.sleep(1) + self.timeout = self._settimeout(seconds) + self._enable() + else: + self.timeout = self._settimeout(seconds) + self._keepalive() + self._enable() + self.armed = True + + ret = self.timeout + except IOError as e: + pass + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + 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. + """ + + timeleft = WDT_COMMON_ERROR + + if self.armed: + try: + timeleft = self._gettimeleft() + except IOError: + pass + + return timeleft + +class Watchdog(CpldWatchdog): + """PDDF Platform-Specific Watchdog Class""" + + def __init__(self): + CpldWatchdog.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/eeprom.py new file mode 100644 index 000000000000..7550fed99950 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/eeprom.py @@ -0,0 +1,78 @@ +try: + from sonic_platform_pddf_base.pddf_eeprom import PddfEeprom + import os +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +EEPROM_TMP_FILE = '/tmp/eeprom_dump.bin' + +class Eeprom(PddfEeprom): + + _TLV_DISPLAY_VENDOR_EXT = True + _TLV_INFO_MAX_LEN = 256 + pddf_obj = {} + plugin_data = {} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + + # system EEPROM always has device name EEPROM1 + self.eeprom_path = self.pddf_obj.get_path("EEPROM1", "eeprom") + if self.eeprom_path is None: + return + + super(PddfEeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + + try: + if os.path.exists(EEPROM_TMP_FILE): + with open(EEPROM_TMP_FILE, 'rb') as b_fd: + self.eeprom_data = bytearray(b_fd.read()) + else: + self.eeprom_data = self.read_eeprom() + with open(EEPROM_TMP_FILE, 'wb') as b_fd: + b_fd.write(self.eeprom_data) + os.chmod(EEPROM_TMP_FILE, 0o444) + except Exception as e: + self.eeprom_data = "N/A" + raise RuntimeError("PddfEeprom is not Programmed - Error: {}".format(str(e))) + 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) < self._TLV_INFO_MAX_LEN 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: + name = "Vendor Extension" + value = "" + if self._TLV_DISPLAY_VENDOR_EXT: + for c in tlv[2:2 + tlv[1]]: + value += "0x%02X " % c + 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 + + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan.py new file mode 100644 index 000000000000..1edef7f9f458 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan.py @@ -0,0 +1,192 @@ +import os + +try: + from sonic_platform_pddf_base.pddf_fan import PddfFan + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SET_FAN_STATUS_LED_CMD = "0x3A 0x39 0x02 {} {}" +BMC_EXIST = APIHelper().is_bmc_present() + +class Fan(PddfFan): + """PDDF Platform-Specific Fan class""" + + def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): + # idx is 0-based + PddfFan.__init__(self, tray_idx, fan_idx, pddf_data, pddf_plugin_data, is_psu_fan, psu_index) + self.helper = APIHelper() + + def get_presence(self): + """ + Retrieves the presence of fan + """ + if self.is_psu_fan: + from sonic_platform.platform import Platform + return Platform().get_chassis().get_psu(self.fans_psu_index-1).get_presence() + + return super().get_presence() + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + Or N/A if fan removed or abnormal + """ + if not self.get_status(): + return 'N/A' + + return super().get_direction() + + + 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) + """ + target_speed = 0 + if self.is_psu_fan: + # Target speed not usually supported for PSU fans + raise NotImplementedError + else: + fan_name = self.get_name() + f_r_fan = "Front" if fan_name.endswith("1") else "Rear" + speed_rpm = self.get_speed_rpm() + if(self.plugin_data['FAN']['FAN_MAX_RPM_SPEED'][f_r_fan].isnumeric()): + max_fan_rpm = int(self.plugin_data['FAN']['FAN_MAX_RPM_SPEED'][f_r_fan]) + else: + return target_speed + speed_percentage = round(int((speed_rpm * 100) / max_fan_rpm)) + target_speed = speed_percentage + + return target_speed + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + fan_name = self.get_name() + if self.is_psu_fan: + attr = "psu_fan{}_speed_rpm".format(self.fan_index) + device = "PSU{}".format(self.fans_psu_index) + output = self.pddf_obj.get_attr_name_output(device, attr) + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(float(output['status'])) + + max_speed = int(self.plugin_data['PSU']['PSU_FAN_MAX_SPEED']) + speed_percentage = round((speed*100)/max_speed) + if speed_percentage >= 100: + speed_percentage = 100 + return speed_percentage + else: + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_input" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) + + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(float(output['status'])) + + f_r_fan = "Front" if fan_name.endswith("1") else "Rear" + if(self.plugin_data['FAN']['FAN_MAX_RPM_SPEED'][f_r_fan].isnumeric()): + max_speed = int(self.plugin_data['FAN']['FAN_MAX_RPM_SPEED'][f_r_fan]) + else: + return 0; + speed_percentage = round((speed*100)/max_speed) + if speed_percentage >= 100: + speed_percentage = 100 + + return speed_percentage + + def get_status_led(self): + if not self.get_presence(): + return self.STATUS_LED_COLOR_OFF + if self.is_psu_fan: + # Usually no led for psu_fan hence raise a NotImplementedError + raise NotImplementedError + else: + fan_led_device = "FANTRAY{}".format(self.fantray_index) + "_LED" + if (not fan_led_device in self.pddf_obj.data.keys()): + # Implement a generic status_led color scheme + if self.get_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + result, color = self.pddf_obj.get_system_led_color(fan_led_device) + return (color) + + def is_under_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_min_th = target_speed * (1 - float(speed_tolerance) / 100) + if speed < speed_min_th: + return True + else: + return False + + def is_over_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_max_th = target_speed * (1 + float(speed_tolerance) / 100) + if speed > speed_max_th: + return True + else: + return False + + def set_status_led(self,color): + if self.is_psu_fan: + return super().set_status_led(color) + + if color == self.get_status_led(): + return False + + if BMC_EXIST: + fan_led_color_map = { + 'off': '00', + 'green': '01', + 'amber': '02', + 'red': '02' + } + + fan_index_val = hex(self.fantray_index + 3) + + color_val = fan_led_color_map.get(color.lower(), None) + + if fan_index_val is None: + return False + + if color_val is None: + return False + + status, _ = self.helper.ipmi_raw(SET_FAN_STATUS_LED_CMD.format(fan_index_val,color_val)) + + return status + else: + return self.set_system_led("SYS_LED", color) + diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..3b9bb607f632 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/fan_drawer.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + + +try: + from sonic_platform_pddf_base.pddf_fan_drawer import PddfFanDrawer +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(PddfFanDrawer): + """PDDF Platform-Specific Fan-Drawer class""" + + def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None): + # idx is 0-based + PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/helper.py new file mode 100644 index 000000000000..58451d4011bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/helper.py @@ -0,0 +1,143 @@ +import fcntl +import os +import struct +import subprocess +from mmap import * + +GETREG_PATH="/sys/devices/platform/sys_cpld/getreg" +BMC_PRESENCE="echo '0xA108' > {} && cat {}".format(GETREG_PATH, GETREG_PATH) + +class APIHelper(): + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except: + status = False + return status, result + + def get_cmd_output(self, cmd): + status = 0 + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = ret + + return status, data + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def read_one_line_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def lpc_getreg(self, getreg_path, reg): + """ + Get the cpld reg through lpc interface + + Args: + getreg_path: getreg sysfs path + reg: 16 bits reg addr in hex str format + + Returns: + A str, register value in hex str format + """ + file = open(getreg_path, 'w+') + # Acquire an exclusive lock on the file + fcntl.flock(file, fcntl.LOCK_EX) + + try: + file.write(reg) + file.flush() + + # Seek to the beginning of the file + file.seek(0) + + # Read the content of the file + result = file.readline().strip() + finally: + # Release the lock and close the file + fcntl.flock(file, fcntl.LOCK_UN) + file.close() + + return result + + def lpc_setreg(self, setreg_path, reg, val): + """ + Set the cpld reg through lpc interface + + Args: + setreg_path: setreg sysfs path + reg: 16 bits reg addr in hex str format + val: 8 bits register value in hex str format + + Returns: + A boolean, True if speed is set successfully, False if not + """ + status = True + file = open(setreg_path, 'w') + # Acquire an exclusive lock on the file + fcntl.flock(file, fcntl.LOCK_EX) + + try: + data = "{} {}".format(reg, val) + file.write(data) + file.flush() + except: + status = False + finally: + # Release the lock and close the file + fcntl.flock(file, fcntl.LOCK_UN) + file.close() + + return status + + @staticmethod + def ipmi_raw(cmd): + status = True + result = "" + cmd = "ipmitool raw {}".format(str(cmd)) + ret, raw_data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = raw_data + + return status, result + + def is_bmc_present(self): + """ + Get the BMC card present status + + Returns: + A boolean, True if present, False if absent + """ + status, presence = self.get_cmd_output(BMC_PRESENCE) + if status == 0 and presence == "0x00": + return True + else: + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/platform.py new file mode 100644 index 000000000000..8595e80692df --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/platform.py @@ -0,0 +1,23 @@ +############################################################################# +# PDDF +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + from sonic_platform_pddf_base.pddf_platform import PddfPlatform +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PddfPlatform): + """ + PDDF Platform-Specific Platform Class + """ + + def __init__(self): + PddfPlatform.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/psu.py new file mode 100644 index 000000000000..2bfee698b244 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/psu.py @@ -0,0 +1,33 @@ +try: + from sonic_platform_pddf_base.pddf_psu import PddfPsu +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class Psu(PddfPsu): + """PDDF Platform-Specific PSU class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten + def get_capacity(self): + return 550 + + def get_type(self): + return 'AC' + + def get_voltage_low_threshold(self): + return 4 + + def get_voltage_high_threshold(self): + return 13 + + def get_status_led(self): + if self.get_presence(): + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_AMBER + else: + return self.STATUS_LED_COLOR_OFF diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/sfp.py new file mode 100644 index 000000000000..418222cea7cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/sfp.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +try: + import ast + from sonic_platform_pddf_base.pddf_sfp import PddfSfp + from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CmisApi +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class Sfp(PddfSfp): + """ + PDDF Platform-Specific Sfp class + """ + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten + + def reset(self): + if self.port_index > 0 and self.port_index < 49: + return False + return super().reset() + + def get_presence(self): + presence = PddfSfp.get_presence(self) + if not presence and self._xcvr_api != None: + self._xcvr_api = None + + return presence + + def get_xcvr_api(self): + if self._xcvr_api is None and self.get_presence(): + self.refresh_xcvr_api() + + # Find and update the right optoe driver + api_to_driver_map = {\ + 'Sff8636Api': 'optoe1',\ + 'Sff8472Api': 'optoe2',\ + 'CmisApi': 'optoe3',\ + 'CCmisApi': 'optoe3',\ + 'Sff8436Api': 'sff8436'\ + } + create_dev = False + path_list = self.eeprom_path.split('/') + name_path = '/'.join(path_list[:-1]) + '/name' + del_dev_path = '/'.join(path_list[:-2]) + '/delete_device' + new_dev_path = '/'.join(path_list[:-2]) + '/new_device' + api_name = type(self._xcvr_api).__name__ + new_driver = api_to_driver_map.get(api_name, 'optoe1') + + try: + with open(name_path, 'r') as fd: + cur_driver = fd.readline().strip() + except FileNotFoundError: + create_dev = True + else: + if cur_driver != new_driver: + with open(del_dev_path, 'w') as fd: + fd.write("0x50") + create_dev = True + + if create_dev: + with open(new_dev_path, 'w') as fd: + fd.write("{} 0x50".format(new_driver)) + + if api_name == 'Sff8636Api' or \ + api_name == 'Sff8436Api': + self.write_eeprom(93,1,bytes([0x04])) + + return self._xcvr_api + + def get_platform_media_key(self, transceiver_dict, port_speed, lane_count): + api = self.get_xcvr_api() + api_name = type(api).__name__ + if api_name in ['CmisApi', 'CCmisApi']: + is_cmis = True + else: + is_cmis = False + + # Per lane speed + media_key = str(int(port_speed / lane_count)) + if is_cmis: + media_compliance_code = transceiver_dict['specification_compliance'] + if 'copper' in media_compliance_code: + media_len = transceiver_dict['cable_length'] + media_key += '-copper-' + str(media_len) + 'M' + else: + media_key += '-optical' + else: + media_compliance_dict = ast.literal_eval(transceiver_dict['specification_compliance']) + eth_compliance_str = '10/40G Ethernet Compliance Code' + ext_compliance_str = 'Extended Specification Compliance' + media_compliance_code = '' + if eth_compliance_str in media_compliance_dict: + media_compliance_code = media_compliance_dict[eth_compliance_str] + if ext_compliance_str in media_compliance_dict: + media_compliance_code = media_compliance_code + ' ' + media_compliance_dict[ext_compliance_str] + if 'CR' in media_compliance_code or "copper" in transceiver_dict['specification_compliance'].lower(): + media_len = transceiver_dict['cable_length'] + media_key += '-copper-' + str(media_len) + 'M' + else: + media_key += '-optical' + + return {\ + 'vendor_key': '',\ + 'media_key': media_key,\ + 'lane_speed_key': ''\ + } diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/thermal.py new file mode 100644 index 000000000000..0ead57d0bb30 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/thermal.py @@ -0,0 +1,13 @@ +try: + from sonic_platform_pddf_base.pddf_thermal import PddfThermal +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + + +class Thermal(PddfThermal): + """PDDF Platform-Specific Thermal class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): + PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index) + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/watchdog.py new file mode 100644 index 000000000000..1bfd5faaea75 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/pddf/sonic_platform/watchdog.py @@ -0,0 +1,15 @@ +try: + from sonic_platform_pddf_base.pddf_watchdog import PddfWatchdog +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + + +class Watchdog(PddfWatchdog): + """PDDF Platform-Specific Watchdog Class""" + + def __init__(self): + PddfWatchdog.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten + diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/ds2000_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/ds2000_platform_shutdown.sh new file mode 100644 index 000000000000..f0f6e3523c11 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/ds2000_platform_shutdown.sh @@ -0,0 +1,42 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +# Get BMC mode +GETREG_PATH="/sys/devices/platform/sys_cpld/getreg" +BMC_PRESENCE=`echo '0xA108' > $GETREG_PATH && cat $GETREG_PATH` +echo "BMC card ${BMC_PRESENCE}" + +if [ ${BMC_PRESENCE} == "0x00" ]; then + # Set all LEDs to BMC's control + ipmitool raw 0x3a 0x42 0x02 0x01 &> /dev/null + + # BMC cold power-cyle + ipmitool chassis power cycle &> /dev/null +else + # Set System LED to booting pattern + i2cset -f -y 100 0x0d 0x62 0x02 &> /dev/null + + # CPLD cold power-cyle + i2cset -f -y 100 0x0d 0x64 0x00 &> /dev/null +fi + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_post_device_create.sh b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_post_device_create.sh new file mode 100755 index 000000000000..fa09e6e686a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_post_device_create.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Set SYS_LED to Green, assuming everything came up fine. +#ipmitool raw 0x3A 0x0C 0x00 0x03 0x62 0xdc + +# Enable thermal shutdown by default +#i2cset -y -f 103 0x0d 0x75 0x1 + +# Load fpga extend driver after fpga device created +modprobe pddf_custom_fpga_extend + +SETREG_PATH="/sys/devices/platform/sys_cpld/setreg" +GETREG_PATH="/sys/devices/platform/sys_cpld/getreg" +BMC_PRESENCE=`echo '0xA108' > $GETREG_PATH && cat $GETREG_PATH` +#Set off Alarm LED +if [ ${BMC_PRESENCE} == "0x00" ]; then + # Set all LEDs to Manual control + ipmitool raw 0x3a 0x42 0x02 0x00 &> /dev/null + + # Set Alarm LED to OFF + ipmitool raw 0x3a 0x39 0x02 0x01 0x00 &> /dev/null +else + i2cset -f -y 100 0x0d 0x63 0x33 &> /dev/null +fi + +# enable FPGA control port status +echo '0xA130 0x01' > ${SETREG_PATH} diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_pre_driver_install.sh b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_pre_driver_install.sh new file mode 100755 index 000000000000..9a8cb8a46e39 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pddf_pre_driver_install.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Has customized those drivers,so rename them to lose effect +psu_driver=pddf_psu_driver_module.ko +fan_driver=pddf_fan_driver_module.ko +ker_name=$(uname -r) +driver_path=/usr/lib/modules/${ker_name}/extra/ +if [ -e ${driver_path}${psu_driver} ]; then + mv ${driver_path}${psu_driver} ${driver_path}${psu_driver}-bk +fi + +#if [ -e ${driver_path}${fan_driver} ]; then +# mv ${driver_path}${fan_driver} ${driver_path}${fan_driver}-bk +#fi +echo 'pddf psu,fan driver module has rename now' diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/platform_sensors.py new file mode 100644 index 000000000000..1a2c682234c5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/platform_sensors.py @@ -0,0 +1,178 @@ +#!/usr/bin/python +# +# Silverstone-v2 platform sensors. This script get the sensor data from BMC +# using ipmitool and display them in lm-sensor alike format. +# +# The following data is support: +# 1. Temperature sensors +# 2. PSUs +# 3. Fan Drawers + +import sys +import logging +import subprocess + +IPMI_SDR_CMD = ['/usr/bin/ipmitool', 'sdr', 'elist'] +MAX_NUM_FANS = 4 +MAX_NUM_PSUS = 2 + +SENSOR_NAME = 0 +SENSOR_VAL = 4 + +sensor_dict = {} + +def ipmi_sensor_dump(cmd): + ''' Execute ipmitool command return dump output + exit if any error occur. + ''' + global sensor_dict + sensor_dump = '' + + try: + sensor_dump = subprocess.check_output(IPMI_SDR_CMD, universal_newlines=True) + except subprocess.CalledProcessError as e: + logging.error('Error! Failed to execute: {}'.format(cmd)) + sys.exit(1) + + for line in sensor_dump.splitlines(): + sensor_info = line.split('|') + sensor_dict[sensor_info[SENSOR_NAME].strip()] = sensor_info[SENSOR_VAL].strip() + + return True + +def get_reading_by_name(sensor_name, sdr_elist_dump): + ''' + Search for the match sensor name, return sensor + reading value and unit, return object epmtry string + if search not match. + + The output of sensor dump: + TEMP_FB_U52 | 00h | ok | 7.1 | 31 degrees C + TEMP_FB_U17 | 01h | ok | 7.1 | 27 degrees C + TEMP_SW_U52 | 02h | ok | 7.1 | 30 degrees C + Fan2_Status | 07h | ok | 29.2 | Present + Fan2_Front | 0Eh | ok | 29.2 | 12000 RPM + Fan2_Rear | 46h | ok | 29.2 | 14700 RPM + PSU2_Status | 39h | ok | 10.2 | Presence detected + PSU2_Fan | 3Dh | ok | 10.2 | 16000 RPM + PSU2_VIn | 3Ah | ok | 10.2 | 234.30 Volts + PSU2_CIn | 3Bh | ok | 10.2 | 0.80 Amps + ''' + found = '' + + for line in sdr_elist_dump.splitlines(): + line = line.decode() + if sensor_name in line: + found = line.strip() + break + + if not found: + logging.error('Cannot find sensor name:' + sensor_name) + + else: + try: + found = found.split('|')[4] + except IndexError: + logging.error('Cannot get sensor data of:' + sensor_name) + + logging.basicConfig(level=logging.DEBUG) + return found + + +def read_temperature_sensors(): + sensor_list = [\ + ('Base_Temp_U5', 'Baseboard Left Temp'),\ + ('Base_Temp_U56', 'Baseboard Right Temp'),\ + ('Switch_Temp_U28', 'Switchboard Left Temp'),\ + ('Switch_Temp_U29', 'Switchboard Right Temp'),\ + ('CPU_Temp', 'CPU Internal Temp'),\ + ('Switch_Temp_U30', 'ASIC External Rear Temp'),\ + ('Switch_Temp_U31', 'ASIC External Front Temp'),\ + ('VDD_ANLG_Temp', 'VDD ANLG Temp'),\ + ('VDD_CORE_Temp', 'VDD CORE Temp')\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Temperature Sensors\n" + output += "Adapter: IPMI adapter\n" + for sensor in sensor_list: + output += sensor_format.format('{}:'.format(sensor[1]),\ + sensor_dict[sensor[0]],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_fan_sensors(num_fans): + + sensor_list = [\ + ('Fan{}_Status', 'Fan Drawer {} Status'),\ + ('Fan{}_Front', 'Fan {} front'),\ + ('Fan{}_Rear', 'Fan {} rear'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Fan Drawers\n" + output += "Adapter: IPMI adapter\n" + for fan_num in range(1, num_fans+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(fan_num) + display_sensor_name = sensor[1].format(fan_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_psu_sensors(num_psus): + + sensor_list = [\ + ('PSU{}_Status', 'PSU {} Status'),\ + ('PSU{}_Fan', 'PSU {} Fan 1'),\ + ('PSU{}_VIn', 'PSU {} Input Voltage'),\ + ('PSU{}_CIn', 'PSU {} Input Current'),\ + ('PSU{}_PIn', 'PSU {} Input Power'),\ + ('PSU{}_Temp1', 'PSU {} Temp1'),\ + ('PSU{}_Temp2', 'PSU {} Temp2'),\ + ('PSU{}_VOut', 'PSU {} Output Voltage'),\ + ('PSU{}_COut', 'PSU {} Output Current'),\ + ('PSU{}_POut', 'PSU {} Output Power'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "PSU\n" + output += "Adapter: IPMI adapter\n" + for psu_num in range(1, num_psus+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(psu_num) + display_sensor_name = sensor[1].format(psu_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def main(): + output_string = '' + + if ipmi_sensor_dump(IPMI_SDR_CMD): + output_string += read_temperature_sensors() + output_string += read_psu_sensors(MAX_NUM_PSUS) + output_string += read_fan_sensors(MAX_NUM_FANS) + + print(output_string) + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pre_pddf_init.sh b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pre_pddf_init.sh new file mode 100755 index 000000000000..e32b0c9cbfc1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/pre_pddf_init.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Probe Baseboard CPLD driver +modprobe lpc_basecpld +sleep 1 + +# Get BMC mode +PLATFORM=`sed -n 's/onie_platform=\(.*\)/\1/p' /host/machine.conf` +GETREG_PATH="/sys/devices/platform/sys_cpld/getreg" +BMC_PRESENCE=`echo '0xA108' > $GETREG_PATH && cat $GETREG_PATH` +echo "Platform ${PLATFORM} BMC card ${BMC_PRESENCE}" + +# Copy pddf-device.json according to bmc mode +PDDF_JSON="pddf-device.json" +PDDF_JSON_BMC="pddf-device-bmc.json" +PDDF_JSON_NONBMC="pddf-device-nonbmc.json" +PDDF_JSON_PATH="/usr/share/sonic/device/${PLATFORM}/pddf" + +COMPONENTS_JSON="platform_components.json" +COMPONENTS_JSON_BMC="platform_components-bmc.json" +COMPONENTS_JSON_NONBMC="platform_components-nonbmc.json" +COMPONENTS_JSON_PATH="/usr/share/sonic/device/${PLATFORM}/" + +if [ ${BMC_PRESENCE} == "0x00" ]; then + cp ${PDDF_JSON_PATH}/${PDDF_JSON_BMC} ${PDDF_JSON_PATH}/${PDDF_JSON} + cp ${COMPONENTS_JSON_PATH}/${COMPONENTS_JSON_BMC} ${COMPONENTS_JSON_PATH}/${COMPONENTS_JSON} +else + # BMC Card absent + cp ${PDDF_JSON_PATH}/${PDDF_JSON_NONBMC} ${PDDF_JSON_PATH}/${PDDF_JSON} + cp ${COMPONENTS_JSON_PATH}/${COMPONENTS_JSON_NONBMC} ${COMPONENTS_JSON_PATH}/${COMPONENTS_JSON} +fi diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/sensors new file mode 100644 index 000000000000..5d740a9eb7d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/scripts/sensors @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon python3 /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/ds2000-pddf-platform-monitor.service b/platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/ds2000-pddf-platform-monitor.service new file mode 100644 index 000000000000..5043d3d02755 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/ds2000-pddf-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=DS2000 Platform background monitor service +After=pmon.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/pddf_fan_control_sensor_refresh.py +Restart=always +RestartSec=30s +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/pddf-platform-init.service b/platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/pddf-platform-init.service new file mode 100644 index 000000000000..c62769508895 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/systemd/pddf-platform-init.service @@ -0,0 +1,15 @@ +[Unit] +Description=PDDF module and device initialization service +Before=pmon.service watchdog-control.service ztp.service +After=platform-init.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStartPre=-/usr/local/bin/pre_pddf_init.sh +ExecStart=/usr/local/bin/pddf_util.py install +ExecStop=/usr/local/bin/pddf_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/CPUPIDRegulation.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/CPUPIDRegulation.py new file mode 100755 index 000000000000..f38bb7c9fe80 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/CPUPIDRegulation.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/19 17:01 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Perform fan PWM PID control according to the CPU temperature provided by the Thermal team + +try: + import os + import sys + import getopt + import subprocess + import statistics + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Defaults +FUNCTION_NAME = 'FanControl' +DUTY_MAX = 100 +CPU_TEMP_MAX = 90 +TEMP_DIFF = 15 # abs(Tk - Tk-1) limit +CPU_TEMPERATURE = "cat /sys/class/thermal/thermal_zone1/temp" + +# PID Defaults Value +PWM_LIST = [35] # [PWMk-1] +T_LIST = [] # [Tk-2, Tk-1, Tk] +Kp = 3 +Ki = 0.5 +Kd = 0.2 +SET_POINT = 78 +PWM_MIN = 35 +PWM_MAX = 100 + + +class CPUPIDRegulation(object): + """ + Make a class we can use to capture stdout and sterr in the log + """ + # static temp var + _ori_temp = 0 + _new_perc = DUTY_MAX / 2 + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + init_fan_temperature = [0, 0] + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='a', + level=log_level, + format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + logging.debug('SET. logfile:%s / loglevel:%d' % (log_file, log_level)) + + def get_cpu_temperature(self): + """ + Get CPU temperature + """ + try: + temp = int(os.popen(CPU_TEMPERATURE).read().strip()) / 1000 + return temp + except Exception as E: + self.syslog.warning("Can't Get CPU temperature! Cause:%s" % str(E)) + logging.warning("Can't Get CPU temperature! Cause:%s" % str(E)) + return False + + def exception_data_handling(self): + """ + Get the temperature of CPU, and confirm whether the obtained value meets the conditions: + 1. The temperature range is 0~130; + 2. The temperature difference from the last time is within 15 + Otherwise, loop 5 times to get the temperature value again: + 1. if can't get the int value of temperature, return False; + 2. all temperatures are int, return the temperatures average value + """ + re_try = False + cpu_temp = self.get_cpu_temperature() + if cpu_temp >= CPU_TEMP_MAX: + logging.critical("The current temperature(%d) of CPU is higher than the high crirical 90 degrees" % cpu_temp) + + if cpu_temp is False: + re_try = True + elif cpu_temp not in range(CPU_TEMP_MAX+1): + re_try = True + elif T_LIST and abs(cpu_temp - T_LIST[-1]) > TEMP_DIFF: + re_try = True + + if re_try: + error_temp_list = list() + for _ in range(5): + cpu_temp = self.get_cpu_temperature() + if (type(cpu_temp) is int) and \ + (cpu_temp in range(CPU_TEMP_MAX+1)) and \ + (abs(cpu_temp - T_LIST[-1]) <= TEMP_DIFF): + return cpu_temp + else: + error_temp_list.append(cpu_temp) + if False in error_temp_list: + return False + return statistics.mean(error_temp_list) + return cpu_temp + + def pid_control(self): + """ + PID adjustment according to CPU Internal Temperature + :return: fans pwm + """ + cpu_temp = self.exception_data_handling() + if not cpu_temp: + return DUTY_MAX + if len(T_LIST) < 2: + T_LIST.append(float(cpu_temp)) + logging.info("Init CPU PID Control T_LIST:%s" % T_LIST) + return PWM_LIST[0] + else: + T_LIST.append(float(cpu_temp)) + pwm_k = PWM_LIST[0] + Kp * (T_LIST[2] - T_LIST[1]) + \ + Ki * (T_LIST[2] - SET_POINT) + \ + Kd * (T_LIST[2] - 2 * T_LIST[1] + T_LIST[0]) + if pwm_k < PWM_MIN: + #logging.info("CPU PID PWM calculation value:%d < %d, %d will be used"% (pwm_k, PWM_MIN, PWM_MIN)) + pwm_k = PWM_MIN + elif pwm_k > PWM_MAX: + logging.info("CPU PID PWM calculation value > %d, %d will be used" + % (PWM_MAX, PWM_MAX)) + pwm_k = PWM_MAX + PWM_LIST[0] = pwm_k + #logging.info("CPU PID: PWM=%d Temp list=%s" % (pwm_k, T_LIST)) + T_LIST.pop(0) + return pwm_k diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanControl.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanControl.py new file mode 100755 index 000000000000..c89daae72114 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanControl.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/19 17:44 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Fan control strategy main program + +try: + import re + import os + import sys + import getopt + import subprocess + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform + from . import CPUPIDRegulation + from . import FanLinearAdjustment + from . import SwitchInternalPIDRegulation +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +FUNCTION_NAME = "FanControl" +ERROR_COLOR = "amber" +NORMAL_COLOR = "green" +DUTY_MAX = 100 +FAN_NUMBER = 4 +PSU_NUMBER = 2 +SENSOR_NUMBER = 6 +Fan_Front_MAX = 29125 +Fan_Front_MIN = 1370 +Fan_Rear_MAX = 25375 +Fan_Rear_MIN = 1370 +FAN_STATUS_LIST = [True, True, True, True] + + +class FanControl(object): + """ + Make a class we can use to capture stdout and sterr in the log + """ + # static temp var + _ori_temp = 0 + _new_perc = DUTY_MAX / 2 + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + init_fan_temperature = [0, 0] + + def __init__(self, log_file, log_level): + self.FanLinearAdjustment = FanLinearAdjustment.FanLinearAdjustment(log_file, log_level, DUTY_MAX, FAN_NUMBER, + PSU_NUMBER, SENSOR_NUMBER) + self.SwitchInternalPIDRegulation = SwitchInternalPIDRegulation.SwitchInternalPIDRegulation(log_file, log_level) + self.CPUPIDRegulation = CPUPIDRegulation.CPUPIDRegulation(log_file, log_level) + # Needs a logger and a logger level + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='a', + level=log_level, + format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + logging.debug('SET. logfile:%s / loglevel:%d' % (log_file, log_level)) + + def get_psu_status(self, fan_duty_list): + """ + Get PSU Status.If one PSU not OK, all of the fans pwm will increase to 100 + :param fan_duty_list: A list.TO app the fans target pwm + """ + psu_status_list = [True, True] + for psu_index in range(PSU_NUMBER): + psu_presence = self.platform_chassis_obj.get_psu(psu_index).get_presence() + psu_status = self.platform_chassis_obj.get_psu(psu_index).get_status() + if not psu_presence: + psu_status_list[psu_index] = False + logging.critical( + "psu%s was error,presence:%s, status:%s" % (psu_index + 1, str(psu_presence), str(psu_status))) + + if False in psu_status_list: + fan_duty_list.append(DUTY_MAX) + + def get_fan_presence(self): + """ + Get all of fans status(fan drawer) + :return: A list indicating the status of all groups fans + """ + fan_presence_list = [True, True, True, True] # Default state: fans are OK + for fan_drawer_index in range(FAN_NUMBER): + fan_drawer = self.platform_chassis_obj.get_fan_drawer(fan_drawer_index) + fan0_presence = fan_drawer.get_fan(0).get_presence() + if not fan0_presence: + logging.warning("%s not presence"% (fan_drawer.get_fan(0).get_name())) + fan1_presence = fan_drawer.get_fan(1).get_presence() + if not fan1_presence: + logging.warning("%s not presence"% (fan_drawer.get_fan(1).get_name())) + if not fan0_presence and not fan1_presence: + fan_presence_list[fan_drawer_index] = False + logging.critical("Fan Drawer-%s not presence"% (str(fan_drawer_index + 1))) + return fan_presence_list + + def check_fans_presence(self, fan_duty_list): + """ + check all fans presence or not + """ + fans_presence_list = self.get_fan_presence() + fans_not_presence_num = fans_presence_list.count(False) + if fans_not_presence_num != 0: # all fans broken, power off + logging.critical("Some fan not presence, change others fan speed to max!") + fan_duty_list.append(DUTY_MAX) + + def set_fans_pwm_by_rpm(self, fan_duty_list): + """ + Set fans pwm by fans rpm. If all fans normal or 1 fan broken, + manage the fans follow thermal policy. + More than 1 fans broken, Will increase the fan speed to 100% + :param fan_duty_list: A list.TO app the fans target pwm + """ + fan_rpm_error_list = list() + for fan in self.platform_chassis_obj.get_all_fans(): + fan_name = fan.get_name() + fan_speed_rpm = fan.get_speed_rpm() + if fan_name.endswith("1") and (fan_speed_rpm not in range(Fan_Front_MIN, Fan_Front_MAX + 1)): + fan_rpm_error_list.append(fan_name) + if fan_name.endswith("2") and (fan_speed_rpm not in range(Fan_Rear_MIN, Fan_Rear_MAX + 1)): + fan_rpm_error_list.append(fan_name) + if not fan_rpm_error_list: + for fan_drawer_index in range(FAN_NUMBER): + if FAN_STATUS_LIST[fan_drawer_index] == False: + FAN_STATUS_LIST[fan_drawer_index] = True + self.platform_chassis_obj.get_fan_drawer(fan_drawer_index).set_status_led(NORMAL_COLOR) + return None + if len(fan_rpm_error_list) >= 2: + logging.critical("%s rpm less than the set minimum speed. " + "Will increase the fan speed to 100%%" % fan_rpm_error_list) + fan_duty_list.append(DUTY_MAX) + else: + logging.warning("%s rpm less than the set minimum speed. Fans pwm isn't changed" % fan_rpm_error_list) + + fan_modules_index_list = list(set(int(re.findall(r"Fantray(\d)_\d", x)[0]) for x in fan_rpm_error_list)) + for error_fan_drawer in fan_modules_index_list: + if FAN_STATUS_LIST[error_fan_drawer-1] == True: + FAN_STATUS_LIST[error_fan_drawer-1] = False + logging.warning("Fantray%d will be set to %s " % (error_fan_drawer, ERROR_COLOR)) + self.platform_chassis_obj.get_fan_drawer(error_fan_drawer-1).set_status_led(ERROR_COLOR) + + logging.warning("The STA front panel light will be set to %s " % ERROR_COLOR) + self.platform_chassis_obj.set_status_led(ERROR_COLOR) + + def get_linear_pid_pwm(self, fan_duty_list): + """ + Get the pwm value of liner regulation, cpu pid adjustment, switch internal pid adjustment + :param fan_duty_list: A list.TO app the fans target pwm + """ + linear_regulation = self.FanLinearAdjustment.linear_control() + cpu_pid_adjustment = self.CPUPIDRegulation.pid_control() + sw_pid_adjustment = self.SwitchInternalPIDRegulation.pid_control() + #logging.info("linear regulation PWM:%d, cpu pid PWM:%d, sw pid PWM:%d" % (linear_regulation, cpu_pid_adjustment, sw_pid_adjustment)) + fan_duty_list.append(linear_regulation) + fan_duty_list.append(cpu_pid_adjustment) + fan_duty_list.append(sw_pid_adjustment) + + def manage_fans(self): + """ + Set the fan speed according to the Fan Control Strategy + """ + fan_duty_speed_list = list() + + # Fan speed setting judgment-PSU + self.get_psu_status(fan_duty_speed_list) + + # Fan speed setting judgment-FAN presence + self.check_fans_presence(fan_duty_speed_list) + + # Fan speed setting judgment-FAN SPEED + self.set_fans_pwm_by_rpm(fan_duty_speed_list) + + # Fan speed setting judgment-linear and cpu pid and sw pid + self.get_linear_pid_pwm(fan_duty_speed_list) + + self._new_perc = max(fan_duty_speed_list) + if self._new_perc < 35: + self._new_perc = 35 + if self._new_perc > 100: + self._new_perc = 100 + fan_index = 0 + for fan in self.platform_chassis_obj.get_all_fans(): + fan_index += 1 + fan_rpm = fan.get_speed() + #logging.info("Get before setting fan speed: %s" % fan_rpm) + set_stat = fan.set_speed(self._new_perc) + if set_stat is False: + #logging.info('PASS. Set Fan%d duty_cycle (%d)' % (fan_index, self._new_perc)) + #else: + logging.error('FAIL. Set Fan%d duty_cycle (%d)' % (fan_index, self._new_perc)) + + +def handler(signum, frame): + logging.warning('Cause signal %d, will set all fan speed to max.' % signum) + platform_chassis = platform.Platform().get_chassis() + set_error = list() + fan_index = 1 + for fan in platform_chassis.get_all_fans(): + set_stat = fan.set_speed(DUTY_MAX) + fan_drawer = fan_index//2 + if not set_stat: + set_error.append(fan_drawer) + fan_index += 1 + if set_error: + logging.error('Fail. Set Fantray %s to (%d) failed' % (list(set(set_error)), DUTY_MAX)) + sys.exit(0) + + +def main(argv): + log_file = '/var/log/%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv, 'hdlt:', ['lfile=']) + except getopt.GetoptError: + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + for opt, arg in opts: + if opt == '-h': + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = FanControl(log_file, log_level) + # Loop forever, doing something useful hopefully: + time.sleep(30) + while True: + monitor.manage_fans() + time.sleep(4) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanLinearAdjustment.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanLinearAdjustment.py new file mode 100755 index 000000000000..1e3d7d761886 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/FanLinearAdjustment.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/16 17:00 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Fan PWM confirmation according to Thermal team's fan linear control strategy + +try: + import sys + import getopt + import subprocess + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Defaults +FUNCTION_NAME = "FanControl" + + +class FanLinearAdjustment(object): + """ + Make a class we can use to capture stdout and sterr in the log + """ + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + # u5 u56 u28 u29 + init_fan_temperature = [0, 0] + + def __init__(self, log_file, log_level, duty_max, fan_num, psu_num, sensor_num): + self.duty_max = duty_max + self.fan_num = fan_num + self.psu_num = psu_num + self.sensor_num = sensor_num + self.last_pwm = 0 + # Needs a logger and a logger level + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='a', + level=log_level, + format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.info: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + logging.info('SET. logfile:%s / loglevel:%d' % (log_file, log_level)) + + def get_all_temperature(self): + """ + Get u5 u56 u28 u29 temperature + return: [u5, u56, u28, u29 ] + """ + all_temperature_list = list() + for sensor_index in range(self.sensor_num): + temp = self.platform_chassis_obj.get_thermal(sensor_index).get_temperature() + if temp is None or str(temp).strip() == "": + return False + all_temperature_list.append(temp) + u5 = all_temperature_list[0] + u56 = all_temperature_list[1] + b2f = max(u5,u56) + if u5 <= -5: + logging.critical("The current temperature(%f) of u5 is lower than the low crirical -5 degrees." % u5) + elif u5 >= 58: + logging.critical("The current temperature(%f) of u5 is higher than the high critical 58 degrees." % u5) + elif u5 >= 55: + logging.critical("The current temperature(%f) of u5 is higher than the high warning 55 degrees." % u5) + if u56 <= -5: + logging.critical("The current temperature(%f) of u56 is lower than the low crirical -5 degrees." % u56) + elif u56 >= 58: + logging.critical("The current temperature(%f) of u56 is higher than the high critical 58 degrees." % u56) + elif u56 >= 55: + logging.critical("The current temperature(%f) of u56 is higher than the high warning 55 degrees." % u56) + u28 = all_temperature_list[4] + u29 = all_temperature_list[5] + f2b = max(u28, u29) + if u28 <= -5: + logging.critical("The current temperature(%f) of u28 is lower than the low crirical -5 degrees." % u28) + elif u28 >= 63: + logging.critical("The current temperature(%f) of u28 is higher than the high critical 63 degrees." % u28) + elif u28 >= 58: + logging.critical("The current temperature(%f) of u28 is higher than the high warning 58 degrees." % u28) + if u29 <= -5: + logging.critical("The current temperature(%f) of u29 is lower than the low crirical -5 degrees." % u29) + elif u29 >= 63: + logging.critical("The current temperature(%f) of u29 is higher than the high critical 63 degrees." % u29) + elif u29 >= 58: + logging.critical("The current temperature(%f) of u29 is higher than the high warning 58 degrees." % u29) + #logging.info("[u5:%s, u56:%s, u28:%s, u29:%s]" % (u5, u56, u28, u29)) + return [b2f, f2b] + + def get_fan_pwm_by_temperature(self, temp_list): + """ + According to the sensor temperature, the temperature rise and fall are judged, + and the fan speed with the highest speed is selected + :param temp_list: Sensor temperature list + :return: According to the sensor temperature, select the maximum expected fan value at each point(int) + """ + fan_direction = "NA" + for fan in self.platform_chassis_obj.get_all_fans(): + fan_status = fan.get_status() + if fan_status: + fan_direction = fan.get_direction() + #logging.info("fan direction: %s. INTAKE=B2F, EXHAUST=F2B" % str(fan_direction)) + break + all_temp = self.get_all_temperature() + if all_temp is False: + # According to Thermal suggestion, when the temperature can't be + # obtained, set the fan to full speed + logging.error("Can't get u5/u56/u28/u29 temperature, Will increase the fan speed to 100%%") + return self.duty_max + + # B2F=intake: U17 temperature, F2B-EXHAUST: U16 temperature + #logging.info("[B2F:%s, F2B:%s]" % (all_temp[0], all_temp[1])) + sensor_index = 0 if fan_direction == "INTAKE" else 1 + sensor_temp = float(all_temp[sensor_index]) + #logging.info("Use to adjustment sensor=%s, index=%s, last tem=%s" % (sensor_temp, sensor_index, temp_list[sensor_index] )) + temp_ascend = True + diff_temp = temp_list[sensor_index] - sensor_temp + if diff_temp > 0: + temp_ascend = False + + if sensor_index == 0: + if not temp_ascend: # B2F: U5,U56 temperature down + if sensor_temp <= 25: + sensor_temp_pwm = 35 + elif sensor_temp >= 45: + sensor_temp_pwm = self.duty_max + else: + sensor_temp_pwm = int((65 / 20) * (sensor_temp - 25) + 35) + else: # U5,U56 temperature up + if sensor_temp <= 28: + sensor_temp_pwm = 35 + elif sensor_temp >= 48: + sensor_temp_pwm = self.duty_max + else: + sensor_temp_pwm = int((65 / 20) * (sensor_temp - 28) + 35) + + return self.choose_pwm(temp_ascend, self.last_pwm, sensor_temp_pwm) + else: + if not temp_ascend: # F2B: U28,U29 temperature down + if sensor_temp <= 41: + sensor_temp_pwm = 35 + elif sensor_temp >= 51: + sensor_temp_pwm = 90 + else: + sensor_temp_pwm = int((55 / 10) * (sensor_temp - 41) + 35) + else: # U17 temperature up + if sensor_temp <= 44: + sensor_temp_pwm = 35 + elif sensor_temp >= 54: + sensor_temp_pwm = 90 + else: + sensor_temp_pwm = int((55 / 10) * (sensor_temp - 44) + 35) + return self.choose_pwm(temp_ascend, self.last_pwm, sensor_temp_pwm) + + @staticmethod + def choose_pwm(status, last_pwm, now_pwm): + """ + choose the pwm with Thermal rules + :param status: Temperature rises (True) or falls(False) + :param last_pwm:last pwm value + :param now_pwm:Calculated pwm from current temperature + :return:int.The pwm value + """ + if status: + return last_pwm if last_pwm >= now_pwm else now_pwm + else: + return now_pwm if last_pwm >= now_pwm else last_pwm + + def linear_control(self): + """ + According to linear adjustment return the fans pwm + :return: fans pwm + """ + new_perc = self.get_fan_pwm_by_temperature(self.init_fan_temperature) + self.init_fan_temperature = self.get_all_temperature() + self.last_pwm = new_perc + return new_perc diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/SwitchInternalPIDRegulation.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/SwitchInternalPIDRegulation.py new file mode 100755 index 000000000000..17992e830e86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/SwitchInternalPIDRegulation.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/19 16:26 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Perform fan PWM PID control according to the Switch Internal temperature provided by the Thermal team + +try: + import os + import sys + import getopt + import subprocess + import statistics + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Defaults +FUNCTION_NAME = 'FanControl' +DUTY_MAX = 100 +SW_TEMP_MAX = 125 +SW_MAJOR_ALARM = 105 +SW_SHUTDOWN = 120 +SW_CRITICAL = 110 +TEMP_DIFF = 15 # abs(Tk - Tk-1) limit +SWITCH_INTERNAL_PEAK_TEMP = "bcmcmd 'show temp' | grep maximum | cut -d ' ' -f 5" + +# PID Defaults Value +PWM_LIST = [35] # [PWMk-1] +T_LIST = [] # [Tk-2, Tk-1, Tk] +Kp = 2.5 +Ki = 0.5 +Kd = 0.3 +SET_POINT = 86 +PWM_MIN = 35 +PWM_MAX = 100 + + +class SwitchInternalPIDRegulation(object): + """ + Make a class we can use to capture stdout and sterr in the log + """ + _new_perc = DUTY_MAX / 2 + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + + def __init__(self, log_file, log_level): + # Needs a logger and a logger level + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='a', + level=log_level, + format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + logging.debug('SET. logfile:%s / loglevel:%d' % (log_file, log_level)) + + def get_switch_internal_temperature(self): + """ + Get Switch internal temperature + """ + try: + value = subprocess.check_output(SWITCH_INTERNAL_PEAK_TEMP, shell=True,universal_newlines=True, stderr=subprocess.STDOUT)[:-1] + return int(float(value)) + except Exception as E: + self.syslog.warning("Can't Get switch internal temperature! Cause:%s" % str(E)) + logging.warning("Can't Get switch internal temperature! Cause:%s" % str(E)) + return False + + def exception_data_handling(self): + """ + Get the temperature of Switch Internal, and confirm whether the obtained value meets the conditions: + 1. The temperature range is 0~150; + 2. The temperature difference from the last time is within 15 + Otherwise, loop 5 times to get the temperature value again: + 1. if can't get the int value of temperature, return False; + 2. all temperatures are int, return the temperatures average value + """ + re_try = False + sw_temp = self.get_switch_internal_temperature() + if sw_temp is False: + re_try = True + elif sw_temp not in range(SW_TEMP_MAX+1): + re_try = True + elif T_LIST and abs(sw_temp - T_LIST[-1]) > TEMP_DIFF: + re_try = True + + if re_try: + error_temp_list = list() + while len(error_temp_list) < 5: + sw_temp = self.get_switch_internal_temperature() + if (type(sw_temp) is int) and \ + (sw_temp in range(SW_TEMP_MAX+1)) and \ + (abs(sw_temp - T_LIST[-1]) <= TEMP_DIFF): + return sw_temp + else: + error_temp_list.append(sw_temp) + if False in error_temp_list: + return False + return statistics.mean(error_temp_list) + return sw_temp + + def pid_control(self): + """ + PID adjustment according to Switch Internal Temperature + :return: fans pwm + """ + sw_temp = self.exception_data_handling() + if not sw_temp: + return 50 + + if sw_temp >= SW_SHUTDOWN: + logging.critical("The Switch Internal temperature exceeds %sC, DUT will reboot after 30 seconds" % SW_SHUTDOWN) + time.sleep(30) + os.popen("reboot") + elif sw_temp >= SW_CRITICAL: + logging.critical("High temperature critical warning: switch internal temperature %sC, High critical %sC" + % (sw_temp, SW_CRITICAL)) + elif sw_temp >= SW_MAJOR_ALARM: + logging.critical("High temperature warning: switch internal temperature %sC, High warning %sC" + % (sw_temp, SW_MAJOR_ALARM)) + + if len(T_LIST) < 2: + T_LIST.append(float(sw_temp)) + self.syslog.debug("Init Switch Internal PID Control T_LIST:%s" % T_LIST) + logging.info("Init Switch Internal PID Control T_LIST:%s" % T_LIST) + return PWM_LIST[0] + else: + T_LIST.append(float(sw_temp)) + pwm_k = PWM_LIST[0] + Kp * (T_LIST[2] - T_LIST[1]) + \ + Ki * (T_LIST[2] - SET_POINT) + \ + Kd * (T_LIST[2] - 2 * T_LIST[1] + T_LIST[0]) + if pwm_k < PWM_MIN: + #logging.info("Switch Internal PID PWM calculation value < %d, %d will be used"% (PWM_MIN, PWM_MIN)) + pwm_k = PWM_MIN + elif pwm_k > PWM_MAX: + logging.critical("Switch Internal PID PWM calculation value > %d, %d will be used" + % (PWM_MAX, PWM_MAX)) + pwm_k = PWM_MAX + PWM_LIST[0] = pwm_k + #logging.info("Switch Internal PID: PWM=%d Temp list=%s" % (pwm_k, T_LIST)) + T_LIST.pop(0) + return pwm_k diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/__init__.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/__init__.py new file mode 100755 index 000000000000..fd2df8085779 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/FanControl/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*-# + +# @Time : 2023/6/20 16:01 +# @Mail : yajiang@celestica.com +# @Author : jiang tao diff --git a/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/pddf_fan_control_sensor_refresh.py b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/pddf_fan_control_sensor_refresh.py new file mode 100755 index 000000000000..f47aadb53c1f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds2000/utils/pddf_fan_control_sensor_refresh.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*-# + +# @Time : 2023/7/31 13:15 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + +import sys +import os +import json +sys.path.append(r"/usr/local/bin") +from FanControl import FanControl + + +pddf_device_path = '/usr/share/sonic/platform/pddf/pddf-device.json' +with open(pddf_device_path) as f: + json_data = json.load(f) +bmc_present = json_data["PLATFORM"]["bmc_present"] +if bmc_present == "False": + FanControl.main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/Makefile new file mode 100644 index 000000000000..183bf0a20059 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/Makefile @@ -0,0 +1,8 @@ +LED_TARGET:= pddf_custom_led_module +$(LED_TARGET)-objs := ./led_driver/pddf_custom_led_module.o + +PSU_TARGET:= pddf_custom_psu_driver_module +$(PSU_TARGET)-objs := ./psu_driver/pddf_psu_api.o ./psu_driver/pddf_psu_driver.o + +obj-m := mc24lc64t.o baseboard_cpld.o pddf_custom_fpga_algo.o pddf_custom_fpga_extend.o +obj-m += $(LED_TARGET).o $(PSU_TARGET).o diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/baseboard_cpld.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/baseboard_cpld.c new file mode 100644 index 000000000000..54d4c1514815 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/baseboard_cpld.c @@ -0,0 +1,414 @@ +/* + * baseboard_cpld.c - driver for DS3000 Base Board CPLD + * This driver implement sysfs for CPLD register access using LPC bus. + * Copyright (C) 2019 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "baseboard" +/** + * CPLD register address for read and write. + */ +#define VERSION_ADDR 0xA100 +#define SCRATCH_ADDR 0xA101 +#define SYS_LED_ADDR 0xA162 +#define CARD_PRES_ADDR 0xA108 +#define COME_CPLD_VER_ADDR 0xA1E0 + +#define CPLD_REGISTER_SIZE 0x77 + +struct baseboard_cpld_data { + struct mutex cpld_lock; + uint16_t read_addr; +}; + +struct baseboard_cpld_data *cpld_data; + +/** + * Read the value from scratch register as hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf,"0x%2.2x\n", data); +} + +/** + * Set scratch register with specific hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long data; + char *last; + + mutex_lock(&cpld_data->cpld_lock); + data = (uint16_t)strtoul(buf,&last,16); + if(data == 0 && buf == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + outb(data, SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(scratch); + + +/* CPLD version attributes */ +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = -EIO; + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n",inb(VERSION_ADDR)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RO(version); + + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint16_t addr; + char *last; + + addr = (uint16_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + cpld_data->read_addr = addr; + return count; +} + +static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = -EIO; + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RW(getreg); + +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint16_t addr; + uint8_t value; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + + strscpy(clone, buf, count); + + mutex_lock(&cpld_data->cpld_lock); + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + addr = (uint16_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + value = (uint8_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + outb(value,addr); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_WO(setreg); + +/** + * Show system led status - on/off/1hz/4hz + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0x3; + return sprintf(buf, "%s\n", + data == 0x03 ? "off" : data == 0x02 ? "4hz" : data ==0x01 ? "1hz": "on"); +} + +/** + * Set the status of system led - on/off/1hz/4hz + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status,data; + if(sysfs_streq(buf, "off")){ + led_status = 0x03; + }else if(sysfs_streq(buf, "4hz")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "1hz")){ + led_status = 0x01; + }else if(sysfs_streq(buf, "on")){ + led_status = 0x00; + }else{ + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + data = data & ~(0x3); + data = data | led_status; + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(sys_led); + +/** + * Show system led color - both/green/yellow/none + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t sys_led_color_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = (data >> 4) & 0x3; + return sprintf(buf, "%s\n", + data == 0x03 ? "off" : data == 0x02 ? "yellow" : data ==0x01 ? "green": "both"); +} + +/** + * Set the color of system led - both/green/yellow/none + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_color_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status,data; + if(sysfs_streq(buf, "off")){ + led_status = 0x03; + }else if(sysfs_streq(buf, "yellow")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "green")){ + led_status = 0x01; + }else if(sysfs_streq(buf, "both")){ + led_status = 0x00; + }else{ + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + data = data & ~( 0x3 << 4); + data = data | (led_status << 4); + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(sys_led_color); + +/** + * Show BMC card presence + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return string absent or present of BMC card. + */ +static ssize_t bmc_presence_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(CARD_PRES_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0x1; + return sprintf(buf, "%s\n", + data == 0x01 ? "absent" : "present"); +} +static DEVICE_ATTR_RO(bmc_presence); + +/* COME CPLD version attributes */ +static ssize_t come_cpld_version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = -EIO; + // COME CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n",inb(COME_CPLD_VER_ADDR)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RO(come_cpld_version); + +static struct attribute *baseboard_cpld_attrs[] = { + &dev_attr_version.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_sys_led.attr, + &dev_attr_sys_led_color.attr, + &dev_attr_bmc_presence.attr, + &dev_attr_come_cpld_version.attr, + NULL, +}; + +static struct attribute_group baseboard_cpld_attrs_grp = { + .attrs = baseboard_cpld_attrs, +}; + +static struct resource baseboard_cpld_resources[] = { + { + .start = 0xA100, + .end = 0xA1FF, + .flags = IORESOURCE_IO, + }, +}; + +static void baseboard_cpld_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device baseboard_cpld_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(baseboard_cpld_resources), + .resource = baseboard_cpld_resources, + .dev = { + .release = baseboard_cpld_dev_release, + } +}; + +static int baseboard_cpld_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret =0; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct baseboard_cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + cpld_data->read_addr = VERSION_ADDR; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (unlikely(!res)) { + printk(KERN_ERR "Specified Resource Not Available...\n"); + return -1; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &baseboard_cpld_attrs_grp); + if (ret) { + printk(KERN_ERR "Cannot create sysfs for baseboard CPLD\n"); + } + return 0; +} + +static int baseboard_cpld_drv_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &baseboard_cpld_attrs_grp); + return 0; +} + +static struct platform_driver baseboard_cpld_drv = { + .probe = baseboard_cpld_drv_probe, + .remove = __exit_p(baseboard_cpld_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int baseboard_cpld_init(void) +{ + // Register platform device and platform driver + platform_device_register(&baseboard_cpld_dev); + platform_driver_register(&baseboard_cpld_drv); + return 0; +} + +void baseboard_cpld_exit(void) +{ + // Unregister platform device and platform driver + platform_driver_unregister(&baseboard_cpld_drv); + platform_device_unregister(&baseboard_cpld_dev); +} + +module_init(baseboard_cpld_init); +module_exit(baseboard_cpld_exit); + +MODULE_AUTHOR("Pradchaya Phucharoen "); +MODULE_DESCRIPTION("Celestica DS3000 Baseboard CPLD Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_defs.h b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_defs.h new file mode 100644 index 000000000000..e786e567d433 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_defs.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * Platform LED related defines and structures + */ + + +/***************************************** + * kobj list + *****************************************/ + +struct kobject *platform_kobj=NULL; +struct kobject *led_kobj=NULL; + +struct kobject *state_attr_kobj=NULL; +struct kobject *cur_state_kobj=NULL; + +/***************************************** + * Static Data provided from user + * space JSON data file + *****************************************/ +#define NAME_SIZE 32 +#define VALUE_SIZE 5 +typedef enum { + STATUS_LED_COLOR_OFF=0, + STATUS_LED_COLOR_GREEN=1, + STATUS_LED_COLOR_YELLOW=2, + STATUS_LED_COLOR_RED=3, + STATUS_LED_COLOR_BLUE=4, + STATUS_LED_COLOR_GREEN_BLINK=5, + STATUS_LED_COLOR_YELLOW_BLINK=6, + STATUS_LED_COLOR_RED_BLINK=7, + STATUS_LED_COLOR_BLUE_BLINK=8, + STATUS_LED_COLOR_AMBER, + STATUS_LED_COLOR_AMBER_BLINK, + MAX_LED_STATUS +}LED_STATUS; + +char* LED_STATUS_STR[] = { + "off", + "green", + "yellow", + "red", + "blue", + "green_blink", + "yellow_blink", + "red_blink", + "blue_blink", + "amber", + "amber_blink" +}; + + +typedef struct +{ + char bits[NAME_SIZE]; + int pos; + int mask_bits; +}MASK_BITS; + +typedef struct +{ + int swpld_addr; + int swpld_addr_offset; + MASK_BITS bits; + u8 reg_values[VALUE_SIZE]; + char value[NAME_SIZE]; + char attr_devtype[NAME_SIZE]; + char attr_devname[NAME_SIZE]; +} LED_DATA; + +typedef struct +{ + int state; + char color[NAME_SIZE]; +/* S3IP System LED RW sysfs */ + int sys_led; + int bmc_led; + int fan_led; + int psu_led; + int loc_led; +/* S3IP Power LED RO sysfs */ + int psu1_led; + int psu2_led; +/* S3IP Fantray LED RO sysfs */ + int fantray1_led; + int fantray2_led; + int fantray3_led; + int fantray4_led; + int fantray5_led; + int fantray6_led; + int fantray7_led; +} CUR_STATE_DATA; + +typedef struct +{ + CUR_STATE_DATA cur_state; + char device_name[NAME_SIZE]; + int index; + LED_DATA data[MAX_LED_STATUS]; + int swpld_addr; + int swpld_addr_offset; + char attr_devtype[NAME_SIZE]; + char attr_devname[NAME_SIZE]; +} LED_OPS_DATA; + +typedef enum{ + LED_SYS, + LED_PSU, + LED_FAN, + LED_FANTRAY, + LED_DIAG, + LED_LOC, + LED_BMC, + LED_TYPE_MAX +} LED_TYPE; +char* LED_TYPE_STR[LED_TYPE_MAX] = +{ + "LED_SYS", + "LED_PSU", + "LED_FAN", + "LED_FANTRAY", + "LED_DIAG", + "LED_LOC", + "LED_BMC" +}; + +/***************************************** + * Data exported from kernel for + * user space plugin to get/set + *****************************************/ +#define PDDF_LED_DATA_ATTR( _prefix, _name, _mode, _show, _store, _type, _len, _addr) \ + struct pddf_data_attribute pddf_dev_##_prefix##_attr_##_name = { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .type = _type , \ + .len = _len , \ + .addr = _addr } diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_module.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_module.c new file mode 100644 index 000000000000..8f0da48b4d98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/led_driver/pddf_custom_led_module.c @@ -0,0 +1,873 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * A pddf kernel module to manage various LEDs of a switch + */ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include +#include +#include "pddf_custom_led_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include +#include +#include + +#define DEBUG 0 +#define MAX_PSU_NUM 2 +#define MAX_FANTRAY_NUM 7 +LED_OPS_DATA sys_led_ops_data[1]={0}; +LED_OPS_DATA psu_led_ops_data[MAX_PSU_NUM]={0}; +LED_OPS_DATA diag_led_ops_data[1]= {0}; +LED_OPS_DATA fan_led_ops_data[1]= {0}; +LED_OPS_DATA loc_led_ops_data[1]= {0}; +LED_OPS_DATA bmc_led_ops_data[1]= {0}; +LED_OPS_DATA fantray_led_ops_data[MAX_FANTRAY_NUM]={0}; +LED_OPS_DATA temp_data={0}; +LED_OPS_DATA* dev_list[LED_TYPE_MAX] = { + sys_led_ops_data, + psu_led_ops_data, + fan_led_ops_data, + fantray_led_ops_data, + diag_led_ops_data, + loc_led_ops_data, + bmc_led_ops_data, + NULL +}; +int num_psus = 0; +int num_fantrays = 0; + +extern int board_i2c_cpld_read_new(unsigned short cpld_addr, char *name, u8 reg); +extern int board_i2c_cpld_write_new(unsigned short cpld_addr, char *name, u8 reg, u8 value); +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int board_i2c_fpga_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_fpga_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern ssize_t show_pddf_s3ip_data(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t store_pddf_s3ip_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +static LED_STATUS find_state_index(const char* state_str) { + int index; + char *ptr = (char *)state_str; + while (*ptr && *ptr!= '\n' && *ptr !='\0') ptr++; + *ptr='\0'; + for ( index = 0; index < MAX_LED_STATUS; index++) { + if (strcmp(state_str, LED_STATUS_STR[index]) == 0 ) { + return index; + } + } + return MAX_LED_STATUS; +} + +static LED_TYPE get_dev_type(char* name) +{ + LED_TYPE ret = LED_TYPE_MAX; + if(strcasecmp(name, "SYS_LED") == 0) { + ret = LED_SYS; + } else if(strcasecmp(name, "FAN_LED") == 0) { + ret = LED_FAN; + } else if(strstr(name, "PSU_LED")) { + ret = LED_PSU; + } else if(strcasecmp(name, "DIAG_LED") == 0) { + ret = LED_DIAG; + } else if(strcasecmp(name, "LOC_LED") == 0) { + ret = LED_LOC; + } else if(strstr(name, "FANTRAY_LED")) { + ret = LED_FANTRAY; + } +#if DEBUG > 1 + pddf_dbg(LED, KERN_INFO "LED get_dev_type: %s; %d\n", name, ret); +#endif + return (ret); +} +static int dev_index_check(LED_TYPE type, int index) +{ +#if DEBUG + pddf_dbg(LED, "dev_index_check: type:%s[%d] index:%d num_psus:%d num_fantrays:%d\n", + LED_TYPE_STR[type], type, index, num_psus, num_fantrays); +#endif + switch(type) + { + case LED_PSU: + if(index >= MAX_PSU_NUM) return (-1); + break; + case LED_FANTRAY: + if(index >= MAX_FANTRAY_NUM) return (-1); + break; + default: + if(index >= 1) return (-1); + break; + } + return (0); +} + +static LED_OPS_DATA* find_led_ops_data(struct device_attribute *da) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr = (LED_OPS_DATA*)_ptr->addr; + LED_TYPE led_type; + if(!ptr || strlen(ptr->device_name) == 0 ) return (NULL); + + if((led_type=get_dev_type(ptr->device_name)) == LED_TYPE_MAX) { + printk(KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__); + return (NULL); + } + if(dev_index_check(led_type, ptr->index) == -1) { + printk(KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%s;%d\n", __func__, ptr->index, ptr->device_name, led_type); + return (NULL); + } +#if DEBUG > 1 + pddf_dbg(LED, "find_led_ops_data: name:%s; index=%d tempAddr:%p actualAddr:%p\n", + ptr->device_name, ptr->index, ptr, dev_list[led_type]+ptr->index); +#endif + return (dev_list[led_type]+ptr->index); +} + +static void print_led_data(LED_OPS_DATA *ptr, LED_STATUS state) +{ + int i = 0; + if(!ptr) return ; + pddf_dbg(LED, KERN_INFO "Print %s index:%d num_psus:%d num_fantrays:%d ADDR=%p\n", + ptr->device_name, ptr->index, num_psus, num_fantrays, ptr); + pddf_dbg(LED, KERN_INFO "\tindex: %d\n", ptr->index); + pddf_dbg(LED, KERN_INFO "\tdevtype/devname: %s:%s\n", ptr->attr_devtype, ptr->attr_devname); + pddf_dbg(LED, KERN_INFO "\tcur_state: %d; %s \n", ptr->cur_state.state, ptr->cur_state.color); + for (i = 0; i< MAX_LED_STATUS; i++) { + if(ptr->data[i].swpld_addr && (i == state || state == -1)) { + pddf_dbg(LED, KERN_INFO "\t\t[%s]: addr/offset:0x%x;0x%x color:%s; value:[%s][0x%x][0x%x] mask_bits: 0x%x;" + "pos:%d attr_devtype:%s attr_devname:%s\n",LED_STATUS_STR[i], ptr->data[i].swpld_addr, + ptr->data[i].swpld_addr_offset, LED_STATUS_STR[i], ptr->data[i].value, + ptr->data[i].reg_values[0], ptr->data[i].reg_values[1], ptr->data[i].bits.mask_bits, + ptr->data[i].bits.pos, ptr->data[i].attr_devtype, ptr->data[i].attr_devname); + } + } +} + +ssize_t get_status_led(struct device_attribute *da) +{ + int ret=0; + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + uint32_t color_val=0, sys_val=0; + int state=0; + int cpld_type=0; + int j; + + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: device: %s %d not configured\n", __func__, + temp_data_ptr->device_name, temp_data_ptr->index); + return (-1); + } + + if (strcmp(ops_ptr->attr_devtype, "cpld") == 0) { + cpld_type = 1; + sys_val = board_i2c_cpld_read_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset); + } else if (strcmp(ops_ptr->attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return (-1); + } + + if (sys_val < 0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x read failed\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return sys_val; + } + + strscpy(temp_data.cur_state.color, "None", NAME_SIZE); + for (state=0; statedata[state].bits.mask_bits); + for (j = 0; j < VALUE_SIZE && ops_ptr->data[state].reg_values[j] != 0xff; j++) { + if ((color_val ^ (ops_ptr->data[state].reg_values[j] << ops_ptr->data[state].bits.pos)) == 0) { + strscpy(temp_data.cur_state.color, LED_STATUS_STR[state], NAME_SIZE); + break; + } + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "Get : %s:%d addr/offset:0x%x; 0x%x devtype:%s;%s value=0x%x [%s]\n", + ops_ptr->device_name, ops_ptr->index, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, + ops_ptr->attr_devtype, cpld_type? "cpld": "fpgai2c", sys_val, temp_data.cur_state.color); +#endif + return(ret); +} + +ssize_t set_status_led(struct device_attribute *da) +{ + int ret=0; + uint32_t sys_val=0, new_val=0, read_val=0; + LED_STATUS cur_state = MAX_LED_STATUS; + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + char* _buf=temp_data_ptr->cur_state.color; + int cpld_type = 0; + + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: device: %s %d not configured\n", + __func__, ops_ptr->device_name, ops_ptr->index); + return (-1); + } + + pddf_dbg(LED, KERN_ERR "%s: Set [%s;%d] color[%s]\n", __func__, + temp_data_ptr->device_name, temp_data_ptr->index, + temp_data_ptr->cur_state.color); + cur_state = find_state_index(_buf); + + if (cur_state == MAX_LED_STATUS) { + pddf_dbg(LED, KERN_ERR "ERROR %s: not supported: %s\n", _buf, __func__); + return (-1); + } + + if (ops_ptr->data[cur_state].swpld_addr != 0x0) { + if (strcmp(ops_ptr->data[cur_state].attr_devtype, "cpld") == 0) { + cpld_type = 1; + sys_val = board_i2c_cpld_read_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset); + } else if (strcmp(ops_ptr->data[cur_state].attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype); + return (-1); + } + + if (sys_val < 0){ + return sys_val; + } + + + new_val = (sys_val & ops_ptr->data[cur_state].bits.mask_bits) | + (ops_ptr->data[cur_state].reg_values[0] << ops_ptr->data[cur_state].bits.pos); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s state %d; %s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, cur_state, _buf); + return (-1); + } + + if (strcmp(ops_ptr->data[cur_state].attr_devtype, "cpld") == 0) { + ret = board_i2c_cpld_write_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset, new_val); + read_val = board_i2c_cpld_read_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset); + } else if (strcmp(ops_ptr->data[cur_state].attr_devtype, "fpgai2c") == 0) { + ret = board_i2c_fpga_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, (uint8_t)new_val); + read_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype); + return (-1); + } + +#if DEBUG + pddf_dbg(LED, KERN_ERR "Set color:%s; 0x%x:0x%x sys_val:0x%x new_val:0x%x devtype:%s w_ret:0x%x read:0x%x devtype:%s\n", + LED_STATUS_STR[cur_state], ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, sys_val, new_val, + cpld_type? "cpld":"fpgai2c", ret, read_val, ops_ptr->data[cur_state].attr_devtype); +#endif + + return(ret); +} + + +ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, + char *buf) +{ + int ret = 0; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + switch (ptr->type) + { + case PDDF_CHAR: + ret = sprintf(buf, "%s\n", ptr->addr); + break; + case PDDF_INT_DEC: + ret = sprintf(buf, "%d\n", *(int*)(ptr->addr)); + break; + case PDDF_INT_HEX: + ret = sprintf(buf, "0x%x\n", *(int*)(ptr->addr)); + break; + case PDDF_USHORT: + ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr)); + break; + case PDDF_UINT32: + ret = sprintf(buf, "0x%x\n", *(uint32_t *)(ptr->addr)); + break; + default: + break; + } +#if DEBUG > 1 + pddf_dbg(LED, "[ READ ] DATA ATTR PTR [%s] TYPE:%d, Value:[%s]\n", + ptr->dev_attr.attr.name, ptr->type, buf); +#endif + return ret; +} + +ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0, num = 0; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + switch (ptr->type) + { + case PDDF_CHAR: + memcpy(ptr->addr, buf, strlen(buf)-1); // to discard newline char form buf + ptr->addr[strlen(buf)-1] = '\0'; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_CHAR VALUE:%s\n", + ptr->dev_attr.attr.name, ptr->addr); +#endif + break; + case PDDF_INT_DEC: + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_DEC VALUE:%d\n", + ptr->dev_attr.attr.name, *(int *)(ptr->addr)); +#endif + break; + case PDDF_INT_HEX: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_HEX VALUE:0x%x\n", + ptr->dev_attr.attr.name, *(int *)(ptr->addr)); +#endif + break; + case PDDF_USHORT: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(unsigned short *)(ptr->addr) = (unsigned short)num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_USHORT VALUE:%x\n", + ptr->dev_attr.attr.name, *(unsigned short *)(ptr->addr)); +#endif + break; + case PDDF_UINT32: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(uint32_t *)(ptr->addr) = (uint32_t)num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_UINT32 VALUE:%d\n", + ptr->dev_attr.attr.name, *(uint32_t *)(ptr->addr)); +#endif + break; + default: + break; + } + return count; +} + +ssize_t show_pddf_s3ip_data(struct device *dev, struct device_attribute *da, + char *buf) +{ + int ret = 0; + pddf_dbg(LED, KERN_ERR " %s", __FUNCTION__); + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + if (_ptr == NULL) { + pddf_dbg(LED, KERN_ERR "%s return", __FUNCTION__); + return -1; + } + LED_OPS_DATA* ops_ptr=(LED_OPS_DATA*)_ptr->addr; + uint32_t color_val=0, sys_val=0; + int state=0, j; + int cpld_type=0; + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: device: %s %d not configured\n", __func__, + ops_ptr->device_name, ops_ptr->index); + return (-1); + } + if ( strcmp(ops_ptr->attr_devtype, "cpld") == 0) { + cpld_type=1; + sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else if ( strcmp(ops_ptr->attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return (-1); + } + + if (sys_val < 0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x read failed\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return sys_val; + } + for (state=0; statedata[state].bits.mask_bits); + for (j = 0; j < VALUE_SIZE && ops_ptr->data[state].reg_values[j] != 0xff; j++) { + if ((color_val ^ (ops_ptr->data[state].reg_values[j] << ops_ptr->data[state].bits.pos))==0) { + ret = sprintf(buf, "%d\n", state); + break; + } + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "Get : %s:%d addr/offset:0x%x; 0x%x devtype:%s;%s value=0x%x [%d]\n", + ops_ptr->device_name, ops_ptr->index, ops_ptr->swpld_addr, + ops_ptr->swpld_addr_offset, ops_ptr->attr_devtype, cpld_type? "cpld": "fpgai2c", sys_val, state); +#endif + return ret; +} + +ssize_t store_pddf_s3ip_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0; + int cur_state = 0; + uint32_t sys_val=0, new_val=0, read_val=0; + int cpld_type=0; + + pddf_dbg(LED, KERN_ERR "%s: %s;%d", __FUNCTION__, buf, cur_state); + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + ret = kstrtoint(buf,10,&cur_state); + if (_ptr == NULL || cur_state >= MAX_LED_STATUS || ret !=0) { + pddf_dbg(LED, KERN_ERR "%s return", __FUNCTION__); + return -1; + } + LED_OPS_DATA* ops_ptr=(LED_OPS_DATA*)_ptr->addr; + + if ( strcmp(ops_ptr->attr_devtype, "cpld") == 0) { + cpld_type=1; + sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else if ( strcmp(ops_ptr->attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return (-1); + } + + new_val = (sys_val & ops_ptr->data[cur_state].bits.mask_bits) | + (ops_ptr->data[cur_state].reg_values[0] << ops_ptr->data[cur_state].bits.pos); + + if ( strcmp(ops_ptr->data[cur_state].attr_devtype, "cpld") == 0) { + ret = board_i2c_cpld_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, new_val); + read_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else if ( strcmp(ops_ptr->data[cur_state].attr_devtype, "fpgai2c") == 0) { + ret = board_i2c_fpga_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, (uint8_t)new_val); + read_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype); + return (-1); + } + +#if DEBUG + pddf_dbg(LED, KERN_INFO "Set color:%s; 0x%x:0x%x sys_val:0x%x new_val:0x%x devtype:%s w_ret:0x%x read:0x%x devtype:%s\n", + LED_STATUS_STR[cur_state], ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, + sys_val, new_val, cpld_type? "cpld":"fpgai2c", ret, read_val, ops_ptr->data[cur_state].attr_devtype); +#endif + return count; +} + + +static int load_led_ops_data(struct device_attribute *da, LED_STATUS state) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr = (LED_OPS_DATA*)_ptr->addr; + LED_TYPE led_type; + LED_OPS_DATA* ops_ptr = NULL; + int i = 0; + char *token = NULL, *value_ptr = NULL; + + if(!ptr || strlen(ptr->device_name)==0 ) { + pddf_dbg(LED, KERN_INFO "SYSTEM_LED: load_led_ops_data return -1 device_name:%s\n", ptr? ptr->device_name:"NULL"); + return(-1); + } + + if(ptr->device_name) + { + pddf_dbg(LED, KERN_INFO "[%s]: load_led_ops_data: index=%d addr=0x%x;0x%x devtype:%s devname=%s valu=%s\n", + ptr->device_name, ptr->index, ptr->swpld_addr, ptr->swpld_addr_offset, ptr->attr_devtype, ptr->attr_devname, ptr->data[0].value); + } + if((led_type=get_dev_type(ptr->device_name))==LED_TYPE_MAX) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__); + return(-1); + } + if(dev_index_check(led_type, ptr->index)==-1) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%d\n", __func__, ptr->index, led_type); + return(-1); + } + ops_ptr = dev_list[led_type]+ptr->index; + + memcpy(ops_ptr->device_name, ptr->device_name, sizeof(ops_ptr->device_name)); + ops_ptr->index = ptr->index; + memcpy(&ops_ptr->data[state], &ptr->data[0], sizeof(LED_DATA)); + ops_ptr->data[state].swpld_addr = ptr->swpld_addr; + ops_ptr->data[state].swpld_addr_offset = ptr->swpld_addr_offset; + ops_ptr->swpld_addr = ptr->swpld_addr; + ops_ptr->swpld_addr_offset = ptr->swpld_addr_offset; + memcpy(ops_ptr->data[state].attr_devtype, ptr->attr_devtype, sizeof(ops_ptr->data[state].attr_devtype)); + memcpy(ops_ptr->data[state].attr_devname, ptr->attr_devname, sizeof(ops_ptr->data[state].attr_devname)); + memcpy(ops_ptr->attr_devtype, ptr->attr_devtype, sizeof(ops_ptr->attr_devtype)); + memcpy(ops_ptr->attr_devname, ptr->attr_devname, sizeof(ops_ptr->attr_devname)); +#ifdef __STDC_LIB_EXT1__ + memset_s(ops_ptr->data[state].reg_values, sizeof(ops_ptr->data[state].reg_values), 0xff, sizeof(ops_ptr->data[state].reg_values)); +#else + memset(ops_ptr->data[state].reg_values, 0xff, sizeof(ops_ptr->data[state].reg_values)); +#endif + value_ptr = kzalloc(sizeof(ops_ptr->data[state].value), GFP_KERNEL); + if (value_ptr) { + memcpy(value_ptr, ops_ptr->data[state].value, sizeof(ops_ptr->data[state].value)); + while((token = strsep((char**)&value_ptr,";")) != NULL && i < VALUE_SIZE) { + if (kstrtou8(token, 16, &ops_ptr->data[state].reg_values[i])) { + pddf_dbg(LED, KERN_ERR "load_led_ops_data: [%s] conversion error\n", token); + } + i++; + } + kfree(value_ptr); + } + + print_led_data(dev_list[led_type]+ptr->index, state); + + memset(ptr, 0, sizeof(LED_OPS_DATA)); + return (0); +} + +static int show_led_ops_data(struct device_attribute *da) +{ + LED_OPS_DATA* ops_ptr = find_led_ops_data(da); + print_led_data(ops_ptr, -1); + return(0); +} + +static int verify_led_ops_data(struct device_attribute *da) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + + if(ops_ptr) + memcpy(ptr, ops_ptr, sizeof(LED_OPS_DATA)); + else + { + pddf_dbg(LED, "SYSTEM_LED: verify_led_ops_data: Failed to find ops_ptr name:%s; index=%d\n", ptr->device_name, ptr->index); + } + return (0); +} + + +ssize_t dev_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ +#if DEBUG + pddf_dbg(LED, KERN_INFO "dev_operation [%s]\n", buf); +#endif + if(strncmp(buf, "show", strlen("show")) == 0) { + show_led_ops_data(da); + } + else if(strncmp(buf, "verify", strlen("verify")) == 0) { + verify_led_ops_data(da); + } + else if(strncmp(buf, "get_status", strlen("get_status")) == 0) { + get_status_led(da); + } + else if(strncmp(buf, "set_status", strlen("set_status")) == 0) { + set_status_led(da); + } + else { + LED_STATUS index = find_state_index(buf); + if (index < MAX_LED_STATUS) { + load_led_ops_data(da, index); + } else { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s\n", __FUNCTION__, buf); + } + } + return (count); +} + +ssize_t store_config_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret, num; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + if(strncmp(ptr->dev_attr.attr.name, "num_psus", strlen("num_psus")) == 0) { + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n", + ptr->dev_attr.attr.name, num, num_psus); +#endif + return(count); + } + if (strncmp(ptr->dev_attr.attr.name, "num_fantrays", strlen("num_fantrays")) ==0) { + ret = kstrtoint(buf, 10, &num); + if (ret == 0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n", + ptr->dev_attr.attr.name, num, num_fantrays); +#endif + return (count); + } + return (count); +} + +ssize_t store_bits_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int len = 0, num1 = 0, num2 = 0, i=0, rc1=0, rc2=0; + char mask=0xFF; + char *pptr=NULL; + char bits[NAME_SIZE]; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + MASK_BITS* bits_ptr=(MASK_BITS*)(ptr->addr); + memcpy(bits_ptr->bits, buf, strlen(buf)-1); // to discard newline char form buf + bits_ptr->bits[strlen(buf)-1] = '\0'; + if((pptr=strstr(buf,":")) != NULL) { + len = pptr-buf; + sprintf(bits, buf); + bits[len] = '\0'; + rc1 = kstrtoint(bits, 16, &num1); + if (rc1 == 0) + { + sprintf(bits, ++pptr); + rc2 = kstrtoint(bits, 16, &num2); + if (rc2 == 0) + { + for (i=num2; i<=num1; i++) { + mask &= ~(1 << i); + } + bits_ptr->mask_bits = mask; + bits_ptr->pos = num2; + } + } + } else { + rc1 = kstrtoint(buf, 16, &num1); + if (rc1 == 0) + { + bits_ptr->mask_bits = mask & ~(1 << num1); + bits_ptr->pos = num1; + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR Bits [%s] VALUE:%s mask:0x%x; pos:0x%x\n", + ptr->dev_attr.attr.name, bits_ptr->bits, bits_ptr->mask_bits, bits_ptr->pos); +#endif + return (count); +} + +/************************************************************************** + * platform/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(platform, num_psus, S_IWUSR|S_IRUGO, show_pddf_data, + store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_psus); +PDDF_LED_DATA_ATTR(platform, num_fantrays, S_IWUSR|S_IRUGO, show_pddf_data, + store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_fantrays); + +struct attribute* attrs_platform[]={ + &pddf_dev_platform_attr_num_psus.dev_attr.attr, + &pddf_dev_platform_attr_num_fantrays.dev_attr.attr, + NULL, +}; +struct attribute_group attr_group_platform={ + .attrs = attrs_platform, +}; + +/************************************************************************** + * led/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(dev, device_name, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.device_name); +PDDF_LED_DATA_ATTR(dev, attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.attr_devtype); +PDDF_LED_DATA_ATTR(dev, attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.attr_devname); +PDDF_LED_DATA_ATTR(dev, index, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&temp_data.index); +PDDF_LED_DATA_ATTR(dev, swpld_addr, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr); +PDDF_LED_DATA_ATTR(dev, swpld_addr_offset, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr_offset); +PDDF_LED_DATA_ATTR(dev, dev_ops , S_IWUSR, NULL, + dev_operation, PDDF_CHAR, NAME_SIZE, (void*)&temp_data); + +struct attribute* attrs_dev[] = { + &pddf_dev_dev_attr_device_name.dev_attr.attr, + &pddf_dev_dev_attr_attr_devtype.dev_attr.attr, + &pddf_dev_dev_attr_attr_devname.dev_attr.attr, + &pddf_dev_dev_attr_index.dev_attr.attr, + &pddf_dev_dev_attr_swpld_addr.dev_attr.attr, + &pddf_dev_dev_attr_swpld_addr_offset.dev_attr.attr, + &pddf_dev_dev_attr_dev_ops.dev_attr.attr, + NULL, +}; + +struct attribute_group attr_group_dev = { + .attrs = attrs_dev, +}; + +/************************************************************************** + * state_attr/ attributes + **************************************************************************/ +#define LED_DEV_STATE_ATTR_GROUP(name, func) \ + PDDF_LED_DATA_ATTR(name, bits, S_IWUSR|S_IRUGO, show_pddf_data, \ + store_bits_data, PDDF_CHAR, NAME_SIZE, func.bits.bits); \ + PDDF_LED_DATA_ATTR(name, value, S_IWUSR|S_IRUGO, show_pddf_data, \ + store_pddf_data, PDDF_CHAR, NAME_SIZE, func.value); \ + struct attribute* attrs_##name[]={ \ + &pddf_dev_##name##_attr_bits.dev_attr.attr, \ + &pddf_dev_##name##_attr_value.dev_attr.attr, \ + NULL, \ + }; \ + struct attribute_group attr_group_##name={ \ + .attrs = attrs_##name, \ + }; \ + + +LED_DEV_STATE_ATTR_GROUP(state_attr, (void*)&temp_data.data[0]) + +/************************************************************************** + * cur_state/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(cur_state, color, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.cur_state.color); +PDDF_LED_DATA_ATTR(cur_state, sys_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void*)&sys_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, loc_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, NAME_SIZE, (void*)&loc_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, bmc_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void*)&bmc_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, fan_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, psu_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), NULL); +PDDF_LED_DATA_ATTR(cur_state, psu1_led, S_IRUGO, show_pddf_s3ip_data, + NULL, PDDF_INT_DEC, sizeof(int), (void *)&psu_led_ops_data[0]); +PDDF_LED_DATA_ATTR(cur_state, psu2_led, S_IRUGO, show_pddf_s3ip_data, + NULL, PDDF_INT_DEC, sizeof(int), (void *)&psu_led_ops_data[1]); +PDDF_LED_DATA_ATTR(cur_state, fantray1_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[0]); +PDDF_LED_DATA_ATTR(cur_state, fantray2_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[1]); +PDDF_LED_DATA_ATTR(cur_state, fantray3_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[2]); +PDDF_LED_DATA_ATTR(cur_state, fantray4_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[3]); +PDDF_LED_DATA_ATTR(cur_state, fantray5_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[4]); +PDDF_LED_DATA_ATTR(cur_state, fantray6_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[5]); +PDDF_LED_DATA_ATTR(cur_state, fantray7_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[6]); + + +struct attribute* attrs_cur_state[] = { + &pddf_dev_cur_state_attr_color.dev_attr.attr, + &pddf_dev_cur_state_attr_sys_led.dev_attr.attr, + &pddf_dev_cur_state_attr_loc_led.dev_attr.attr, + &pddf_dev_cur_state_attr_bmc_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fan_led.dev_attr.attr, + &pddf_dev_cur_state_attr_psu_led.dev_attr.attr, + &pddf_dev_cur_state_attr_psu1_led.dev_attr.attr, + &pddf_dev_cur_state_attr_psu2_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray1_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray2_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray3_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray4_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray5_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray6_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray7_led.dev_attr.attr, + NULL, +}; + +struct attribute_group attr_group_cur_state={ + .attrs = attrs_cur_state, +}; + +/*************************************************************************/ +#define KOBJ_FREE(obj) \ + if(obj) kobject_put(obj); \ + +void free_kobjs(void) +{ + KOBJ_FREE(cur_state_kobj) + KOBJ_FREE(state_attr_kobj) + KOBJ_FREE(led_kobj) + KOBJ_FREE(platform_kobj) +} + +int KBOJ_CREATE(char* name, struct kobject* parent, struct kobject** child) +{ + if (parent) { + *child = kobject_create_and_add(name, parent); + } else { + printk(KERN_ERR "PDDF_LED ERROR to create %s kobj; null parent\n", name); + free_kobjs(); + return (-ENOMEM); + } + return (0); +} + +int LED_DEV_ATTR_CREATE(struct kobject *kobj, const struct attribute_group *attr, const char* name) +{ + int status = sysfs_create_group(kobj, attr); + if(status) { + pddf_dbg(LED, KERN_ERR "Driver ERROR: sysfs_create %s failed rc=%d\n", name, status); + } + return (status); +} + + +static int __init led_init(void) { + struct kobject *device_kobj; + pddf_dbg(LED, KERN_INFO "PDDF GENERIC LED MODULE init..\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + KBOJ_CREATE("platform", device_kobj, &platform_kobj); + KBOJ_CREATE("led", device_kobj, &led_kobj); + KBOJ_CREATE("state_attr", led_kobj, &state_attr_kobj); + KBOJ_CREATE("cur_state", led_kobj, &cur_state_kobj); + + LED_DEV_ATTR_CREATE(platform_kobj, &attr_group_platform, "attr_group_platform"); + LED_DEV_ATTR_CREATE(led_kobj, &attr_group_dev, "attr_group_dev"); + LED_DEV_ATTR_CREATE(state_attr_kobj, &attr_group_state_attr, "attr_group_state_attr"); + LED_DEV_ATTR_CREATE(cur_state_kobj, &attr_group_cur_state, "attr_group_cur_state"); + return (0); +} + + +static void __exit led_exit(void) { + pddf_dbg(LED, "PDDF GENERIC LED MODULE exit..\n"); + free_kobjs(); +} + +module_init(led_init); +module_exit(led_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/mc24lc64t.c new file mode 100644 index 000000000000..638d59d653ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/mc24lc64t.c @@ -0,0 +1,172 @@ +/* + * mc24lc64t.c - driver for Microchip 24LC64T + * + * Copyright (C) 2017 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes. + +struct mc24lc64t_data { + struct mutex update_lock; +}; + +static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, read_time, i = 0; + int status; + + mutex_lock(&drvdata->update_lock); + + if (i2c_smbus_write_byte_data(client, off>>8, off)) + { + status = -EIO; + goto exit; + } + + msleep(1); + +begin: + + if (i < count) + { + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + do { + read_time = jiffies; + + status = i2c_smbus_read_byte(client); + if (status >= 0) + { + buf[i++] = status; + goto begin; + } + } while (time_before(read_time, timeout)); + + status = -ETIMEDOUT; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + + return status; +} + + +static ssize_t mc24lc64t_write (struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count){ + + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, write_time, i = 0; + int status; + u16 value; + + mutex_lock(&drvdata->update_lock); + +begin: + if (i < count){ + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + value = (buf[i] << 8 | ( off &0xff)); + do { + write_time = jiffies; + status = i2c_smbus_write_word_data(client, off>>8, value); + if (status >= 0) + { + // increase offset + off++; + // increase buffer index + i++; + goto begin; + } + } while (time_before(write_time, timeout)); + status = -ETIMEDOUT; + goto exit; + } + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + return status; +} + + +static struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUGO, + }, + .size = EEPROM_SIZE, + .read = mc24lc64t_read, + .write = mc24lc64t_write, +}; + +static int mc24lc64t_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct mc24lc64t_data *drvdata; + int err; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA + | I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + + if (!(drvdata = devm_kzalloc(&client->dev, + sizeof(struct mc24lc64t_data), GFP_KERNEL))) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + return err; +} + +static void mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); +} + +static const struct i2c_device_id mc24lc64t_id[] = { + { "24lc64t", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mc24lc64t_id); + +static struct i2c_driver mc24lc64t_driver = { + .driver = { + .name = "mc24lc64t", + .owner = THIS_MODULE, + }, + .probe = mc24lc64t_probe, + .remove = mc24lc64t_remove, + .id_table = mc24lc64t_id, +}; + +module_i2c_driver(mc24lc64t_driver); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Microchip 24LC64T Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_algo.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_algo.c new file mode 100644 index 000000000000..45fdcb4c9665 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_algo.c @@ -0,0 +1,626 @@ +/* + * pddf_custom_fpga_algo.c - driver algorithm for FPGAPCIE AXI IIC. + * + * Copyright (C) 2023 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../pddf/i2c/modules/include/pddf_i2c_algo.h" + +#define DEBUG_KERN 0 + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#define XIIC_MSB_OFFSET 0 +#define XIIC_REG_OFFSET (0x100 + XIIC_MSB_OFFSET) + +/* + * Register offsets in bytes from RegisterBase. Three is added to the + * base offset to access LSB (IBM style) of the word + */ +#define XIIC_CR_REG_OFFSET (0x00 + XIIC_REG_OFFSET) /* Control Register */ +#define XIIC_SR_REG_OFFSET (0x04 + XIIC_REG_OFFSET) /* Status Register */ +#define XIIC_DTR_REG_OFFSET (0x08 + XIIC_REG_OFFSET) /* Data Tx Register */ +#define XIIC_DRR_REG_OFFSET (0x0C + XIIC_REG_OFFSET) /* Data Rx Register */ +#define XIIC_ADR_REG_OFFSET (0x10 + XIIC_REG_OFFSET) /* Address Register */ +#define XIIC_TFO_REG_OFFSET (0x14 + XIIC_REG_OFFSET) /* Tx FIFO Occupancy */ +#define XIIC_RFO_REG_OFFSET (0x18 + XIIC_REG_OFFSET) /* Rx FIFO Occupancy */ +#define XIIC_TBA_REG_OFFSET (0x1C + XIIC_REG_OFFSET) /* 10 Bit Address reg */ +#define XIIC_RFD_REG_OFFSET (0x20 + XIIC_REG_OFFSET) /* Rx FIFO Depth reg */ +#define XIIC_GPO_REG_OFFSET (0x24 + XIIC_REG_OFFSET) /* Output Register */ + +/* Control Register masks */ +#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */ +#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */ +#define XIIC_CR_MSMS_MASK 0x04 /* Master starts Txing=1 */ +#define XIIC_CR_DIR_IS_TX_MASK 0x08 /* Dir of tx. Txing=1 */ +#define XIIC_CR_NO_ACK_MASK 0x10 /* Tx Ack. NO ack = 1 */ +#define XIIC_CR_REPEATED_START_MASK 0x20 /* Repeated start = 1 */ +#define XIIC_CR_GENERAL_CALL_MASK 0x40 /* Gen Call enabled = 1 */ + +/* Status Register masks */ +#define XIIC_SR_GEN_CALL_MASK 0x01 /* 1=a mstr issued a GC */ +#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x02 /* 1=when addr as slave */ +#define XIIC_SR_BUS_BUSY_MASK 0x04 /* 1 = bus is busy */ +#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x08 /* 1=Dir: mstr <-- slave */ +#define XIIC_SR_TX_FIFO_FULL_MASK 0x10 /* 1 = Tx FIFO full */ +#define XIIC_SR_RX_FIFO_FULL_MASK 0x20 /* 1 = Rx FIFO full */ +#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x40 /* 1 = Rx FIFO empty */ +#define XIIC_SR_TX_FIFO_EMPTY_MASK 0x80 /* 1 = Tx FIFO empty */ + +/* Interrupt Status Register masks Interrupt occurs when... */ +#define XIIC_INTR_ARB_LOST_MASK 0x01 /* 1 = arbitration lost */ +#define XIIC_INTR_TX_ERROR_MASK 0x02 /* 1=Tx error/msg complete */ +#define XIIC_INTR_TX_EMPTY_MASK 0x04 /* 1 = Tx FIFO/reg empty */ +#define XIIC_INTR_RX_FULL_MASK 0x08 /* 1=Rx FIFO/reg=OCY level */ +#define XIIC_INTR_BNB_MASK 0x10 /* 1 = Bus not busy */ +#define XIIC_INTR_AAS_MASK 0x20 /* 1 = when addr as slave */ +#define XIIC_INTR_NAAS_MASK 0x40 /* 1 = not addr as slave */ +#define XIIC_INTR_TX_HALF_MASK 0x80 /* 1 = TX FIFO half empty */ + +/* The following constants specify the depth of the FIFOs */ +#define IIC_RX_FIFO_DEPTH 16 /* Rx fifo capacity */ +#define IIC_TX_FIFO_DEPTH 16 /* Tx fifo capacity */ + +/* + * Tx Fifo upper bit masks. + */ +#define XIIC_TX_DYN_START_MASK 0x0100 /* 1 = Set dynamic start */ +#define XIIC_TX_DYN_STOP_MASK 0x0200 /* 1 = Set dynamic stop */ + +/* + * The following constants define the register offsets for the Interrupt + * registers. There are some holes in the memory map for reserved addresses + * to allow other registers to be added and still match the memory map of the + * interrupt controller registers + */ +#define XIIC_IISR_OFFSET 0x20 /* Interrupt Status Register */ +#define XIIC_RESETR_OFFSET 0x40 /* Reset Register */ + +#define XIIC_RESET_MASK 0xAUL + +#define XIIC_PM_TIMEOUT 1000 /* ms */ +/* timeout waiting for the controller to respond */ +#define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000)) + +struct fpgalogic_i2c { + void __iomem *base; + u32 reg_shift; + u32 reg_io_width; + wait_queue_head_t wait; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + int ip_clock_khz; + int bus_clock_khz; + void (*reg_set)(struct fpgalogic_i2c *i2c, int reg, u8 value); + u8 (*reg_get)(struct fpgalogic_i2c *i2c, int reg); + u32 timeout; + struct mutex lock; +}; + +static struct fpgalogic_i2c fpgalogic_i2c[I2C_PCI_MAX_BUS]; +extern void __iomem * fpga_ctl_addr; +extern int (*ptr_fpgapci_read)(uint32_t); +extern int (*ptr_fpgapci_write)(uint32_t, uint32_t); +extern int (*pddf_i2c_pci_add_numbered_bus)(struct i2c_adapter *, int); +static int xiic_reinit(struct fpgalogic_i2c *i2c); + + +void i2c_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * i2c_release_mutex - release mutex + */ +void i2c_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static inline void xiic_setreg32(struct fpgalogic_i2c *i2c, int reg, int value) +{ + (void)iowrite32(value, i2c->base + reg); +} + +static inline int xiic_getreg32(struct fpgalogic_i2c *i2c, int reg) +{ + u32 ret; + + ret = ioread32(i2c->base + reg); + + return ret; +} + +static inline void xiic_irq_clr(struct fpgalogic_i2c *i2c, u32 mask) +{ + u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + + xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); +} + +static int xiic_clear_rx_fifo(struct fpgalogic_i2c *i2c) +{ + u8 sr; + unsigned long timeout; + + timeout = jiffies + XIIC_I2C_TIMEOUT; + for (sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); + !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); + sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET)) { + xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + if (time_after(jiffies, timeout)) { + printk("Failed to clear rx fifo\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +/** + * Wait until something change in a given register + * @i2c: AXI IIC device instance + * @reg: register to query + * @mask: bitmask to apply on register value + * @val: expected result + * @timeout: timeout in jiffies + * + * Timeout is necessary to avoid to stay here forever when the chip + * does not answer correctly. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int poll_wait(struct fpgalogic_i2c *i2c, + int reg, u8 mask, u8 val, + const unsigned long timeout) +{ + unsigned long j; + u8 status = 0; + + j = jiffies + timeout; + while (1) { + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, reg); + mutex_unlock(&i2c->lock); + if ((status & mask) == val) + break; + if (time_after(jiffies, j)) + return -ETIMEDOUT; + cpu_relax(); + cond_resched(); + } + return 0; +} + +/** + * Wait until is possible to process some data + * @i2c: AXI IIC device instance + * + * Used when the device is in polling mode (interrupts disabled). + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int xiic_poll_wait(struct fpgalogic_i2c *i2c) +{ + u8 mask = 0, status = 0; + int err = 0; + int val = 0; + int tmp = 0; + mutex_lock(&i2c->lock); + if (i2c->state == STATE_DONE) { + /* transfer is over */ + mask = XIIC_SR_BUS_BUSY_MASK; + } else if (i2c->state == STATE_WRITE || i2c->state == STATE_START){ + /* on going transfer */ + if (0 == i2c->msg->len){ + mask = XIIC_INTR_TX_ERROR_MASK; + } else { + mask = XIIC_SR_TX_FIFO_FULL_MASK; + } + } + else if (i2c->state == STATE_READ){ + /* on going receive */ + mask = XIIC_SR_TX_FIFO_EMPTY_MASK | XIIC_SR_RX_FIFO_EMPTY_MASK; + } + mutex_unlock(&i2c->lock); + // printk("Wait for: 0x%x\n", mask); + + /* + * once we are here we expect to get the expected result immediately + * so if after 50ms we timeout then something is broken. + */ + + if (1 == i2c->nmsgs && 0 == i2c->msg->len && i2c->state == STATE_START && !(i2c->msg->flags & I2C_M_RD)) { /* for i2cdetect I2C_SMBUS_QUICK mode*/ + err = poll_wait(i2c, XIIC_IISR_OFFSET, mask, mask, msecs_to_jiffies(50)); + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); + mutex_unlock(&i2c->lock); + if (0 != err) { /* AXI IIC as an transceiver , if ever an XIIC_INTR_TX_ERROR_MASK interrupt happens, means no such i2c device */ + err = 0; + } else { + err = -ETIMEDOUT; + } + } else { + if (mask & XIIC_SR_TX_FIFO_EMPTY_MASK){ + err = poll_wait(i2c, XIIC_SR_REG_OFFSET, mask, XIIC_SR_TX_FIFO_EMPTY_MASK, msecs_to_jiffies(50)); + mask &= ~XIIC_SR_TX_FIFO_EMPTY_MASK; + } + if (0 == err){ + err = poll_wait(i2c, XIIC_SR_REG_OFFSET, mask, 0, msecs_to_jiffies(50)); + } + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + + if ((status & XIIC_INTR_ARB_LOST_MASK) || + ((status & XIIC_INTR_TX_ERROR_MASK) && + !(status & XIIC_INTR_RX_FULL_MASK) && + !(i2c->msg->flags & I2C_M_RD))) { /* AXI IIC as an transceiver , if ever an XIIC_INTR_TX_ERROR_MASK interrupt happens, return */ + err = -ETIMEDOUT; + + if (status & XIIC_INTR_ARB_LOST_MASK) { + val = xiic_getreg32(i2c, XIIC_CR_REG_OFFSET); + tmp = XIIC_CR_MSMS_MASK; + val &=(~tmp); + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, val); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, XIIC_INTR_ARB_LOST_MASK); + printk("%s: TRANSFER STATUS ERROR, ISR: bit 0x%x happens\n", + __func__, XIIC_INTR_ARB_LOST_MASK); + } + if (status & XIIC_INTR_TX_ERROR_MASK) { + int sta = 0; + int cr = 0; + sta = xiic_getreg32(i2c,XIIC_SR_REG_OFFSET); + cr = xiic_getreg32(i2c,XIIC_CR_REG_OFFSET); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, XIIC_INTR_TX_ERROR_MASK); + printk("%s: TRANSFER STATUS ERROR, ISR: bit 0x%x happens; SR: bit 0x%x; CR: bit 0x%x\n", + __func__, status, sta, cr); + } + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + (void)xiic_reinit(i2c); + mutex_unlock(&i2c->lock); + return err; + } + mutex_unlock(&i2c->lock); + } + + if (err) + printk("%s: STATUS timeout, bit 0x%x did not clear in 50ms\n", + __func__, status); + return err; +} + +static void xiic_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + //unsigned long flags; + u16 val; + + /* + * If we spin here because we are in timeout, so we are going + * to be in STATE_ERROR. + */ + mutex_lock(&i2c->lock); + // printk("STATE: %d\n", i2c->state); + + if (i2c->state == STATE_START) { + i2c->state =(msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + /* if it's the time sequence is 'start bit + address + read bit + stop bit' */ + if (i2c->state == STATE_READ){ + /* it's the last message so we include dynamic stop bit with length */ + val = msg->len | XIIC_TX_DYN_STOP_MASK; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, val); + goto out; + } + } + if (i2c->state == STATE_READ){ + /* suit for I2C_FUNC_SMBUS_BLOCK_DATA */ + if (msg->flags & I2C_M_RECV_LEN) { + msg->len = xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + msg->flags &= ~I2C_M_RECV_LEN; + msg->buf[i2c->pos++] = msg->len; + } + else { + msg->buf[i2c->pos++] = xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + } + } else if (i2c->state == STATE_WRITE){ + /* if it reaches the last byte data to be sent */ + if ((i2c->pos == msg->len - 1) && (i2c->nmsgs == 1)){ + val = msg->buf[i2c->pos++] | XIIC_TX_DYN_STOP_MASK; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, val); + i2c->state = STATE_DONE; + goto out; + /* if it is not the last byte data to be sent */ + } else if (i2c->pos < msg->len) { + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, msg->buf[i2c->pos++]); + goto out; + } + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->pos = 0; + if (i2c->nmsgs) { + i2c->msg++; + msg = i2c->msg; + if (!(msg->flags & I2C_M_NOSTART)) /* send start? */{ + i2c->state = STATE_START; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK); + goto out; + } + } else { /* end? */ + i2c->state = STATE_DONE; + goto out; + } + } + +out: + mutex_unlock(&i2c->lock); + return ; +} + +static int fpga_axi_iic_poll(struct fpgalogic_i2c *i2c, + struct i2c_msg *msgs, int num) +{ + int ret = 0; + // u8 ctrl; + + mutex_lock(&i2c->lock); + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + /* Set receive Fifo depth to maximum (zero based). */ + xiic_setreg32(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + + /* Reset Tx Fifo. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + + /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); + + /* set i2c clock as 100Hz. */ + //xiic_setreg32(i2c, 0x13c, 0x7C); + + /* make sure RX fifo is empty */ + ret = xiic_clear_rx_fifo(i2c); + if (ret){ + mutex_unlock(&i2c->lock); + return ret; + } + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + // printk("STATE: %d\n", i2c->state); + + if (msgs->len == 0 && num == 1){ /* suit for i2cdetect time sequence */ + u8 status = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + xiic_irq_clr(i2c, status); + /* send out the 1st byte data and stop bit */ + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msgs) | XIIC_TX_DYN_START_MASK | XIIC_TX_DYN_STOP_MASK); + } else { + /* send out the 1st byte data */ + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msgs) | XIIC_TX_DYN_START_MASK); + } + mutex_unlock(&i2c->lock); + while (1) { + int err; + + err = xiic_poll_wait(i2c); + if (err) { + i2c->state = STATE_ERROR; + break; + }else if (i2c->state == STATE_DONE){ + break; + } + xiic_process(i2c); + } + + return (i2c->state == STATE_DONE) ? num : -EIO; +} + +static int fpga_axi_iic_access(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int err = -EIO; + u8 retry = 0, max_retry = 0; + + if(((1 == msgs->len && (msgs->flags & I2C_M_RD)) + || (0 == msgs->len && !(msgs->flags & I2C_M_RD)) ) && num == 1 ) /* I2C_SMBUS_QUICK or I2C_SMBUS_BYTE */ + max_retry = 1; + else + max_retry = 5; // retry 5 times if receive a NACK or other errors + + while((-EIO == err) && (retry < max_retry)) + { + err = fpga_axi_iic_poll(i2c, msgs, num); + retry++; + } + + return err; +} + +/** + * A callback function show available smbus functions. + */ +static u32 fpga_axi_iic_func(struct i2c_adapter *adap) +{ + /* a typical full-I2C adapter would use the following */ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm axi_iic_algorithm = { + .master_xfer = fpga_axi_iic_access, + .functionality = fpga_axi_iic_func, +}; + +static int xiic_reinit(struct fpgalogic_i2c *i2c) +{ + int ret; + int val = 0; + + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + + /* Set receive Fifo depth to maximum (zero based). */ + xiic_setreg32(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + + /* Reset Tx Fifo. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + + /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ + val |= XIIC_CR_ENABLE_DEVICE_MASK; + //val |= XIIC_CR_TX_FIFO_RESET_MASK; + //val |= XIIC_CR_MSMS_MASK; + val |= XIIC_CR_DIR_IS_TX_MASK; + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, val); + + /* make sure RX fifo is empty */ + ret = xiic_clear_rx_fifo(i2c); + if (ret) + return ret; + + return 0; +} + +static int fpgai2c_init(struct fpgalogic_i2c *i2c) +{ + // int prescale; + // int diff; + // u8 ctrl; + int ret; + + + //i2c->reg_set = xiic_setreg32; + //i2c->reg_get = xiic_getreg32; + + ret = xiic_reinit(i2c); + if (ret < 0) { + printk("Cannot xiic_reinit\n"); + return ret; + } + + /* Initialize interrupt handlers if not already done */ + init_waitqueue_head(&i2c->wait); + return 0; +}; + +static int adap_data_init(struct i2c_adapter *adap, int i2c_ch_index) +{ + struct fpgapci_devdata *pci_privdata = 0; + pci_privdata = (struct fpgapci_devdata*) dev_get_drvdata(adap->dev.parent); + + if (pci_privdata == 0) { + printk("[%s]: ERROR pci_privdata is 0\n", __FUNCTION__); + return -1; + } +#ifdef DEBUG_KERN + pddf_dbg(FPGA, KERN_INFO "[%s] index: [%d] fpga_data__base_addr:0x%0x8lx" + " fpgapci_bar_len:0x%08lx fpga_i2c_ch_base_addr:0x%08lx ch_size=0x%x supported_i2c_ch=%d", + __FUNCTION__, i2c_ch_index, pci_privdata->fpga_data_base_addr, + pci_privdata->bar_length, pci_privdata->fpga_i2c_ch_base_addr, + pci_privdata->fpga_i2c_ch_size, pci_privdata->max_fpga_i2c_ch); +#endif + if (i2c_ch_index >= pci_privdata->max_fpga_i2c_ch + || pci_privdata->max_fpga_i2c_ch > I2C_PCI_MAX_BUS){ + printk("[%s]: ERROR i2c_ch_index=%d max_ch_index=%d out of range: %d\n", + __FUNCTION__, i2c_ch_index, pci_privdata->max_fpga_i2c_ch, I2C_PCI_MAX_BUS); + return -1; + } + +#ifdef __STDC_LIB_EXT1__ + memset_s(&fpgalogic_i2c[i2c_ch_index], sizeof(fpgalogic_i2c[0]), 0, sizeof(fpgalogic_i2c[0])); +#else + memset(&fpgalogic_i2c[i2c_ch_index], 0, sizeof(fpgalogic_i2c[0])); +#endif + fpgalogic_i2c[i2c_ch_index].base = pci_privdata->fpga_i2c_ch_base_addr + + i2c_ch_index* pci_privdata->fpga_i2c_ch_size; + mutex_init(&fpgalogic_i2c[i2c_ch_index].lock); + fpgai2c_init(&fpgalogic_i2c[i2c_ch_index]); + + adap->algo_data = &fpgalogic_i2c[i2c_ch_index]; + i2c_set_adapdata(adap, &fpgalogic_i2c[i2c_ch_index]); + return 0; +} + +static int pddf_i2c_pci_add_numbered_bus_default (struct i2c_adapter *adap, int i2c_ch_index) +{ + int ret = 0; + + adap_data_init(adap, i2c_ch_index); + adap->algo = &axi_iic_algorithm; + ret = i2c_add_numbered_adapter(adap); + return ret; +} + +/* + * FPGAPCI APIs + */ +static int board_i2c_fpgapci_read(uint32_t offset) +{ + int data; + data=ioread32(fpga_ctl_addr+offset); + return data; +} + + +static int board_i2c_fpgapci_write(uint32_t offset, uint32_t value) +{ + iowrite32(value, fpga_ctl_addr+offset); + return (0); +} + + +static int __init pddf_custom_fpga_algo_init(void) +{ + pddf_dbg(FPGA, KERN_INFO "[%s]\n", __FUNCTION__); + pddf_i2c_pci_add_numbered_bus = &pddf_i2c_pci_add_numbered_bus_default; + ptr_fpgapci_read = board_i2c_fpgapci_read; + ptr_fpgapci_write = board_i2c_fpgapci_write; + return 0; +} +static void __exit pddf_custom_fpga_algo_exit(void) +{ + pddf_dbg(FPGA, KERN_INFO "[%s]\n", __FUNCTION__); + pddf_i2c_pci_add_numbered_bus = NULL; + ptr_fpgapci_read = NULL; + ptr_fpgapci_write = NULL; + return; +} + +module_init(pddf_custom_fpga_algo_init); +module_exit(pddf_custom_fpga_algo_exit); + +MODULE_DESCRIPTION("Module driver algorithm for 7021 FPGAPCIe AXI IIC"); +MODULE_VERSION("1.0.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_extend.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_extend.c new file mode 100644 index 000000000000..4ea09f09404f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/pddf_custom_fpga_extend.c @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * fpga-cls.c - front panel port control. + * + * Copyright (C) 2019 Celestica Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../../../../pddf/i2c/modules/include/pddf_i2c_algo.h" + +#define FPGA_VERSION_ADDR 0x0000 +#define FPGA_SCRATCH_ADDR 0x0004 +#define FPGA_BCM_TEMP_ADDR 0x001c +#define FPGA_BCM_TEMP_LOW_ADDR 0x0078 +#define FPGA_BCM_TEMP_HIGH_ADDR 0x0080 +#define FPGA_REG_SPACE_SIZE 0x2000 + + +/* + * fpga_priv - port fpga private data + * @dev: device for reference + * @base: virtual base address + * @num_ports: number of front panel ports + * @fp_devs: list of front panel port devices + */ +struct fpga_priv { + void __iomem *base; + struct mutex fpga_lock; // For FPGA internal lock + void __iomem * fpga_read_addr; +}; + +extern void __iomem * fpga_ctl_addr; + +/** + * Show the value of the register set by 'set_fpga_reg_address' + * If the address is not set by 'set_fpga_reg_address' first, + * The version register is selected by default. + * @param buf register value in hextring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + // read data from the address + uint32_t data; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + data = ioread32(fpga->fpga_read_addr); + return sprintf(buf, "0x%8.8x\n", data); +} +/** + * Store the register address + * @param buf address wanted to be read value of + * @return number of bytes stored, or an error code + */ +static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t addr; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + addr = (uint32_t)strtoul(buf, &last, 16); + if (addr == 0 && buf == last) { + return -EINVAL; + } + fpga->fpga_read_addr = fpga->base + addr; + return count; +} +/** + * Show value of fpga scratch register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + + return sprintf(buf, "0x%8.8x\n", ioread32(fpga->base + FPGA_SCRATCH_ADDR) & 0xffffffff); +} +/** + * Store value of fpga scratch register + * @param buf scratch register value passing from user space + * @return number of bytes stored, or an error code + */ +static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t data; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + data = (uint32_t)strtoul(buf, &last, 16); + if (data == 0 && buf == last) { + return -EINVAL; + } + iowrite32(data, fpga->base + FPGA_SCRATCH_ADDR); + return count; +} + +/** + * Show value of fpga version register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_version(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + + return sprintf(buf, "0x%8.8x\n", ioread32(fpga->base + FPGA_VERSION_ADDR) & 0xffffffff); +} + + +/** + * Store a value in a specific register address + * @param buf the value and address in format '0xhhhh 0xhhhhhhhh' + * @return number of bytes sent by user space, or an error code + */ +static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // register are 4 bytes + uint32_t addr; + uint32_t value; + uint32_t mode = 8; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + strscpy(clone, buf, count); + mutex_lock(&fpga->fpga_lock); + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + addr = (uint32_t)strtoul(tok, &last, 16); + if (addr == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + value = (uint32_t)strtoul(tok, &last, 16); + if (value == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mode = 32; + } else { + mode = (uint32_t)strtoul(tok, &last, 10); + if (mode == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + } + if (mode == 32) { + iowrite32(value, fpga->base + addr); + } else if (mode == 8) { + iowrite8(value, fpga->base + addr); + } else { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + mutex_unlock(&fpga->fpga_lock); + return count; +} + +/** + * Read all FPGA register in binary mode. + * @param buf Raw transceivers port startus and control register values + * @return number of bytes read, or an error code + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i = 0; + ssize_t status; + u8 read_reg; + struct device *dev = kobj_to_dev(kobj); + struct fpga_priv *fpga = dev_get_drvdata(dev); + + if ( off + count > FPGA_REG_SPACE_SIZE ) { + return -EINVAL; + } + mutex_lock(&fpga->fpga_lock); + while (i < count) { + read_reg = ioread8(fpga->base + off + i); + buf[i++] = read_reg; + } + status = count; + mutex_unlock(&fpga->fpga_lock); + return status; +} + +/** + * Show value of fpga bcm switch internal temp sensor register calculated by FPGA + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_bcm_temp_fpga(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + uint32_t reg_val = ioread32(fpga->base + FPGA_BCM_TEMP_ADDR) & 0x3ffff; + + return sprintf(buf, "0x%08x\n", reg_val); +} + +/** + * Show value of fpga bcm switch internal temp sensor register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_bcm_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + u8 low_byte = ioread32(fpga->base + FPGA_BCM_TEMP_LOW_ADDR) & 0xff; + u8 high_byte = ioread32(fpga->base + FPGA_BCM_TEMP_HIGH_ADDR) & 0xff; + + return sprintf(buf, "0x%02x%02x\n", high_byte, low_byte); +} + +/* FPGA attributes */ +static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address); +static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value); +static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch); +static DEVICE_ATTR( version, 0400, get_fpga_version, NULL); +static DEVICE_ATTR( bcm_temp_fpga, 0400, get_fpga_bcm_temp_fpga, NULL); +static DEVICE_ATTR( bcm_temp, 0400, get_fpga_bcm_temp, NULL); +static BIN_ATTR_RO( dump, FPGA_REG_SPACE_SIZE); + +static struct bin_attribute *fpga_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute *fpga_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_scratch.attr, + &dev_attr_version.attr, + &dev_attr_bcm_temp_fpga.attr, + &dev_attr_bcm_temp.attr, + &dev_attr_setreg.attr, + NULL, +}; + +static struct attribute_group fpga_attr_grp = { + .attrs = fpga_attrs, + .bin_attrs = fpga_bin_attrs, +}; + + +static int cls_fpga_probe(struct platform_device *pdev) +{ + struct fpga_priv *fpga; + int ret = -ENOMEM; + + if (!fpga_ctl_addr){ + printk(KERN_WARNING, "fpga_ctl_addr is null"); + return ret; + } + + fpga = devm_kzalloc(&pdev->dev, sizeof(struct fpga_priv), GFP_KERNEL); + if (!fpga){ + ret = -ENOMEM; + goto err_exit; + } + + mutex_init(&fpga->fpga_lock); + dev_set_drvdata(&pdev->dev, fpga); + fpga->base = fpga_ctl_addr; + + printk("FPGA version: 0x%x\n", ioread32(fpga->base + FPGA_VERSION_ADDR)); + + ret = sysfs_create_group(&pdev->dev.kobj, &fpga_attr_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create FPGA system sysfs attributes\n"); + goto err_remove_fpga; + } + + return 0; + +err_remove_fpga: + sysfs_remove_group(&pdev->dev.kobj, &fpga_attr_grp); +mem_unmap: + iounmap(fpga->base); +err_exit: + return ret; +} + +static int cls_fpga_remove(struct platform_device *pdev) +{ + struct fpga_priv *fpga = dev_get_drvdata(&pdev->dev); + + sysfs_remove_group(&pdev->dev.kobj, &fpga_attr_grp); + iounmap(fpga->base); + return 0; +} + +static void fpga_dev_release( struct device * dev) +{ + return; +} +static struct resource cls_fpga_resources[] = { + { + .start = NULL, + .end = NULL, + .flags = IORESOURCE_IO, + }, +}; + +static struct platform_device cls_fpga_dev = { + .name = "fpga_sysfs", + .id = -1, + .num_resources = ARRAY_SIZE(cls_fpga_resources), + .resource = cls_fpga_resources, + .dev = { + .release = fpga_dev_release, + } +}; + +static struct platform_driver cls_fpga_driver = { + .probe = cls_fpga_probe, + .remove = cls_fpga_remove, + .driver = { + .name = "fpga_sysfs", + }, +}; + +static int __init drv_init(void) +{ + int rc = 0; + + rc = platform_device_register(&cls_fpga_dev); + rc += platform_driver_register(&cls_fpga_driver); + printk("fpga drv_init:%d\n", rc); + return rc; +} + +static void __exit drv_exit(void) +{ + platform_driver_unregister(&cls_fpga_driver); + platform_device_unregister(&cls_fpga_dev); + printk("fpga drv_exit.\n"); +} + +module_init(drv_init); +module_exit(drv_exit); + +MODULE_AUTHOR("Nicholas Wu"); +MODULE_DESCRIPTION("Celestica fpga access/control driver"); +MODULE_VERSION("2.0.0"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:cls-fpga"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.c new file mode 100644 index 000000000000..338417125569 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.c @@ -0,0 +1,478 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description of various APIs related to PSU component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_psu_defs.h" +#include "pddf_psu_driver.h" + + +#define PSU_REG_VOUT_MODE 0x20 +#define PSU_REG_READ_VOUT 0x8b + +/*#define PSU_DEBUG*/ +#ifdef PSU_DEBUG +#define psu_dbg(...) printk(__VA_ARGS__) +#else +#define psu_dbg(...) +#endif + + +void get_psu_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + case PSU_V_OUT: + strscpy(str, "in3_input", ATTR_NAME_LEN); + break; + case PSU_I_OUT: + strscpy(str, "curr2_input", ATTR_NAME_LEN); + break; + case PSU_P_OUT: + strscpy(str, "power2_input", ATTR_NAME_LEN); + break; + case PSU_FAN1_SPEED: + strscpy(str, "fan1_input", ATTR_NAME_LEN); + break; + case PSU_TEMP1_INPUT: + strscpy(str, "temp1_input", ATTR_NAME_LEN); + break; + default: + break; + } + + return; +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static u8 psu_get_vout_mode(struct i2c_client *client) +{ + u8 status = 0, retry = 10; + uint8_t offset = PSU_REG_VOUT_MODE; + + while (retry) + { + status = i2c_smbus_read_byte_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + printk(KERN_ERR "%s: Get PSU Vout mode failed\n", __func__); + return 0; + } + else + { + /*printk(KERN_ERR "%s: vout_mode reg value 0x%x\n", __func__, status);*/ + return status; + } +} + +static u16 psu_get_v_out(struct i2c_client *client) +{ + u16 status = 0, retry = 10; + uint8_t offset = PSU_REG_READ_VOUT; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + printk(KERN_ERR "%s: Get PSU Vout failed\n", __func__); + return 0; + } + else + { + /*printk(KERN_ERR "%s: vout reg value 0x%x\n", __func__, status);*/ + return status; + } +} + +int psu_update_hw(struct device *dev, struct psu_attr_info *info, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + + +int psu_update_attr(struct device *dev, struct psu_attr_info *data, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data=NULL; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) + { + dev_dbg(&client->dev, "Starting update for %s\n", data->name); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: pre_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: post_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return 0; +} + +ssize_t psu_show_default(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); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i, status=0; + u16 value = 0; + u8 vout_mode = 0; + int exponent, mantissa; + int multiplier = 1000; + char new_str[ATTR_NAME_LEN] = ""; + PSU_SYSFS_ATTR_DATA *ptr = NULL; + + for (i=0;inum_attr;i++) + { + ptr = (PSU_SYSFS_ATTR_DATA *)pdata->psu_attrs[i].access_data; + get_psu_duplicate_sysfs(ptr->index , new_str); + if ( strcmp(attr->dev_attr.attr.name, pdata->psu_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0 ) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + strscpy(new_str, "", ATTR_NAME_LEN); + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) + { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + psu_update_attr(dev, sysfs_attr_info, usr_data); + + switch(attr->index) + { + case PSU_PRESENT: + case PSU_POWER_GOOD: + status = sysfs_attr_info->val.intval; + return sprintf(buf, "%d\n", status); + break; + case PSU_MODEL_NAME: + case PSU_MFR_ID: + case PSU_SERIAL_NUM: + case PSU_FAN_DIR: + return sprintf(buf, "%s\n", sysfs_attr_info->val.strval); + break; + case PSU_V_OUT: + value = psu_get_v_out(client); + vout_mode = psu_get_vout_mode(client); + if ((vout_mode >> 5) == 0) + exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f); + else + exponent = 0; + + mantissa = value; + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + + case PSU_V_OUT_MIN: + case PSU_V_OUT_MAX: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + vout_mode = psu_get_vout_mode(client); + if ((vout_mode >> 5) == 0) + exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f); + else + exponent = 0; + mantissa = two_complement_to_int(value & 0xffff, 16, 0xffff); + + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + case PSU_I_OUT: + case PSU_V_IN: + case PSU_I_IN: + case PSU_P_OUT_MAX: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + case PSU_P_IN: + case PSU_P_OUT: + multiplier = 1000000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + case PSU_FAN1_SPEED: + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent)); + else + return sprintf(buf, "%d\n", (mantissa) / (1 << -exponent)); + + break; + case PSU_TEMP1_INPUT: + case PSU_TEMP1_HIGH_THRESHOLD: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + default: + printk(KERN_ERR "%s: Unable to find attribute index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t psu_store_default(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 psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->psu_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + /*No write attributes for now in PSU*/ + default: + goto exit; + } + + psu_update_hw(dev, sysfs_attr_info, usr_data); + +exit: + return count; +} + +extern int board_i2c_cpld_read_new(unsigned short cpld_addr, char *name, u8 reg); +int sonic_i2c_get_psu_byte_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0; + int val = 0; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + + + if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0) + { + val = board_i2c_cpld_read_new(adata->devaddr, adata->devname, adata->offset); + if (val < 0){ + return val; + } + padata->val.intval = ((val & adata->mask) == adata->cmpval); + psu_dbg(KERN_ERR "%s: byte_value = 0x%x\n", __FUNCTION__, padata->val.intval); + } + + return status; +} + +int sonic_i2c_get_psu_block_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char buf[32]=""; //temporary placeholder for block data + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, buf); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + buf[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read block of data from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + buf[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strscpy(padata->val.strval, buf+1, data_len-1); + else + strscpy(padata->val.strval, buf, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, buf block: %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_word_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read a word from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: word value : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.h b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.h new file mode 100644 index 000000000000..24e4ea02e7ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_api.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * PSU driver related api declarations + */ + +#ifndef __PDDF_PSU_API_H__ +#define __PDDF_PSU_API_H__ + +extern void get_psu_duplicate_sysfs(int idx, char *str); +extern ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +extern int sonic_i2c_get_psu_byte_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_block_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_word_default(void *client, PSU_DATA_ATTR *adata, void *data); + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_defs.h b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_defs.h new file mode 100644 index 000000000000..60e81a9f5878 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_defs.h @@ -0,0 +1,90 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description: + * Platform PSU defines/structures header file + */ + +#ifndef __PDDF_PSU_DEFS_H__ +#define __PDDF_PSU_DEFS_H__ + + +#define MAX_NUM_PSU 5 +#define MAX_PSU_ATTRS 32 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct PSU_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum psu_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute + char devname[DEV_TYPE_LEN]; // Name of the device from where this sysfs attr is read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + void *access_data; + +}PSU_DATA_ATTR; + +typedef struct PSU_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, PSU_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, PSU_DATA_ATTR *adata, void *data); + void *data; +} PSU_SYSFS_ATTR_DATA; + +typedef struct PSU_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + PSU_SYSFS_ATTR_DATA *a_ptr; +} PSU_SYSFS_ATTR_DATA_ENTRY; + + +/* PSU CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */ +typedef struct PSU_DATA +{ + int idx; // psu index + int num_psu_fans; + PSU_DATA_ATTR psu_attr; + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR psu_attrs[MAX_PSU_ATTRS]; +}PSU_DATA; + +typedef struct PSU_PDATA +{ + int idx; // psu index + int num_psu_fans; // num of fans supported by the PSU + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR *psu_attrs; +}PSU_PDATA; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.c new file mode 100644 index 000000000000..fa5d31a0866a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.c @@ -0,0 +1,398 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * A pddf kernel module driver for PSU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_driver.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_api.h" + + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +struct pddf_ops_t pddf_psu_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = NULL, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_psu_ops); + + +PSU_SYSFS_ATTR_DATA access_psu_present = {PSU_PRESENT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_byte_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_present); + +PSU_SYSFS_ATTR_DATA access_psu_model_name = {PSU_MODEL_NAME, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_model_name); + +PSU_SYSFS_ATTR_DATA access_psu_power_good = {PSU_POWER_GOOD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_byte_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_power_good); + +PSU_SYSFS_ATTR_DATA access_psu_mfr_id = {PSU_MFR_ID, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_mfr_id); + +PSU_SYSFS_ATTR_DATA access_psu_serial_num = {PSU_SERIAL_NUM, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_serial_num); + +PSU_SYSFS_ATTR_DATA access_psu_fan_dir = {PSU_FAN_DIR, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan_dir); + +PSU_SYSFS_ATTR_DATA access_psu_v_out = {PSU_V_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out); + +PSU_SYSFS_ATTR_DATA access_psu_v_out_min = {PSU_V_OUT_MIN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out_min); + +PSU_SYSFS_ATTR_DATA access_psu_v_out_max = {PSU_V_OUT_MAX, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out_max); + +PSU_SYSFS_ATTR_DATA access_psu_i_out = {PSU_I_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out = {PSU_P_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out_max = {PSU_P_OUT_MAX, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out_max); + +PSU_SYSFS_ATTR_DATA access_psu_fan1_speed_rpm = {PSU_FAN1_SPEED, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan1_speed_rpm); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_input = {PSU_TEMP1_INPUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_input); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_high_threshold = {PSU_TEMP1_HIGH_THRESHOLD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_high_threshold); + +PSU_SYSFS_ATTR_DATA access_psu_v_in = {PSU_V_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_in); + +PSU_SYSFS_ATTR_DATA access_psu_i_in = {PSU_I_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_in); + +PSU_SYSFS_ATTR_DATA access_psu_p_in = {PSU_P_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_in); + +PSU_SYSFS_ATTR_DATA_ENTRY psu_sysfs_attr_data_tbl[]= +{ + { "psu_present", &access_psu_present}, + { "psu_model_name", &access_psu_model_name}, + { "psu_power_good" , &access_psu_power_good}, + { "psu_mfr_id" , &access_psu_mfr_id}, + { "psu_serial_num" , &access_psu_serial_num}, + { "psu_fan_dir" , &access_psu_fan_dir}, + { "psu_v_out" , &access_psu_v_out}, + { "psu_v_out_min" , &access_psu_v_out_min}, + { "psu_v_out_max" , &access_psu_v_out_max}, + { "psu_i_out" , &access_psu_i_out}, + { "psu_p_out" , &access_psu_p_out}, + { "psu_p_out_max" , &access_psu_p_out_max}, + { "psu_fan1_speed_rpm" , &access_psu_fan1_speed_rpm}, + { "psu_temp1_input" , &access_psu_temp1_input}, + { "psu_temp1_high_threshold" , &access_psu_temp1_high_threshold}, + { "psu_v_in" , &access_psu_v_in}, + { "psu_i_in" , &access_psu_i_in}, + { "psu_p_in" , &access_psu_p_in} +}; + +void *get_psu_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(psu_sysfs_attr_data_tbl)/sizeof(psu_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, psu_sysfs_attr_data_tbl[i].name) ==0) + { + return &psu_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_psu_access_data); + + +static int psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct psu_data *data; + int status =0; + int i,num, j=0; + PSU_PDATA *psu_platform_data; + PSU_DATA_ATTR *data_attr; + PSU_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_psu_ops.pre_probe) + { + status = (pddf_psu_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + /* Take control of the platform data */ + psu_platform_data = (PSU_PDATA *)(client->dev.platform_data); + num = psu_platform_data->len; + data->index = psu_platform_data->idx - 1; + data->num_psu_fans = psu_platform_data->num_psu_fans; + data->num_attr = num; + + + + /* Create and Add supported attr in the 'attributes' list */ + for (i=0; ipsu_attrs + i; + sysfs_data_entry = get_psu_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + continue; + } + + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[i] = &dy_ptr->dev_attr.attr; + strscpy(data->attr_info[i].name, data_attr->aname, ATTR_NAME_LEN); + data->attr_info[i].valid = 0; + mutex_init(&data->attr_info[i].update_lock); + + /*Create a duplicate entry*/ + get_psu_duplicate_sysfs(dy_ptr->index, new_str); + if (strcmp(new_str,"")) + { + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, new_str, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strscpy(new_str,"", ATTR_NAME_LEN); + } + } + data->psu_attribute_list[i+j] = NULL; + data->psu_attribute_group.attrs = data->psu_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->psu_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_psu_ops.post_probe) + { + status = (pddf_psu_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0;data->psu_attribute_list[i]!=NULL;i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + } + kfree(data); +exit: + return status; +} + +static void psu_remove(struct i2c_client *client) +{ + int i=0, ret = 0; + struct psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *platdata = (PSU_PDATA *)client->dev.platform_data; // use dev_get_platdata() + PSU_DATA_ATTR *platdata_sub = platdata->psu_attrs; + struct sensor_device_attribute *ptr = NULL; + + if (pddf_psu_ops.pre_remove) + { + ret = (pddf_psu_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); + for (i=0; data->psu_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + } + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_psu_ops.post_remove) + { + ret = (pddf_psu_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } +} + +enum psu_intf +{ + eeprom_intf, + smbus_intf +}; + +static const struct i2c_device_id psu_id[] = { + {"psu_eeprom", eeprom_intf}, + {"psu_pmbus", smbus_intf}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, psu_id); + +static struct i2c_driver psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "psu", + }, + .probe = psu_probe, + .remove = psu_remove, + .id_table = psu_id, + .address_list = normal_i2c, +}; + +int example_fun(void) +{ + pddf_dbg(PSU, KERN_ERR "CALLING FUN...\n"); + return 0; +} +EXPORT_SYMBOL(example_fun); + + +int psu_init(void) +{ + int status = 0; + + if (pddf_psu_ops.pre_init) + { + status = (pddf_psu_ops.pre_init)(); + if (status!=0) + return status; + } + + pddf_dbg(PSU, KERN_ERR "GENERIC_PSU_DRIVER.. init Invoked..\n"); + status = i2c_add_driver(&psu_driver); + if (status!=0) + return status; + + if (pddf_psu_ops.post_init) + { + status = (pddf_psu_ops.post_init)(); + if (status!=0) + return status; + } + + return status; +} +EXPORT_SYMBOL(psu_init); + +void psu_exit(void) +{ + pddf_dbg(PSU, "GENERIC_PSU_DRIVER.. exit\n"); + if (pddf_psu_ops.pre_exit) (pddf_psu_ops.pre_exit)(); + i2c_del_driver(&psu_driver); + if (pddf_psu_ops.post_exit) (pddf_psu_ops.post_exit)(); +} +EXPORT_SYMBOL(psu_exit); + +module_init(psu_init); +module_exit(psu_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.h b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.h new file mode 100644 index 000000000000..a94cf7441dbc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/psu_driver/pddf_psu_driver.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * PSU driver data structures + */ +#ifndef __PDDF_PSU_DRIVER_H__ +#define __PDDF_PSU_DRIVER_H__ + +enum psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_MFR_ID, + PSU_SERIAL_NUM, + PSU_FAN_DIR, + PSU_V_OUT, + PSU_V_OUT_MIN, + PSU_V_OUT_MAX, + PSU_I_OUT, + PSU_P_OUT, /* This is in micro watts to comply with lm-sensors */ + PSU_P_OUT_MAX, + PSU_FAN1_SPEED, + PSU_TEMP1_INPUT, + PSU_TEMP1_HIGH_THRESHOLD, + PSU_V_IN, + PSU_I_IN, + PSU_P_IN, + PSU_ATTR_MAX +}; + + +/* Every client has psu_data which is divided into per attribute data */ +struct psu_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status; + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; +struct psu_data { + struct device *hwmon_dev; + u8 index; + int num_psu_fans; + int num_attr; + struct attribute *psu_attribute_list[MAX_PSU_ATTRS]; + struct attribute_group psu_attribute_group; + struct psu_attr_info attr_info[MAX_PSU_ATTRS]; +}; + + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/switchboard_fpga.c similarity index 67% rename from platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c rename to platform/broadcom/sonic-platform-modules-cel/ds3000/modules/switchboard_fpga.c index e41b64badefc..305253403625 100644 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/modules/switchboard_fpga.c @@ -1,9 +1,9 @@ /* - * switchboard.c - driver for Silverstone Switch board FPGA/CPLD. + * switchboard_fpga.c - driver for ds3000 Switch board FPGA/CPLD. * * Author: Pradchaya Phucharoen * - * Copyright (C) 2018 Celestica Corp. + * Copyright (C) 2019 Celestica Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,18 +14,18 @@ * \--sys * \--devices * \--platform - * \--silverstone + * \--switchboard * |--FPGA * |--CPLD1 * |--CPLD2 * \--SFF * |--QSFP[1..32] - * \--SFP[1..2] + * \--SFP1 * */ #ifndef TEST_MODE -#define MOD_VERSION "1.2.0" +#define MOD_VERSION "2.2.0" #else #define MOD_VERSION "TEST" #endif @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -55,9 +53,9 @@ static int majorNumber; -#define CLASS_NAME "silverstone_fpga" +#define CLASS_NAME "ds3000_fpga" #define DRIVER_NAME "switchboard" -#define FPGA_PCI_NAME "Silverstone_fpga_pci" +#define FPGA_PCI_NAME "ds3000_fpga_pci" #define DEVICE_NAME "fwupgrade" @@ -72,7 +70,6 @@ static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr, static int fpgafw_init(void); static void fpgafw_exit(void); - /* ======================================== FPGA PCIe BAR 0 Registers @@ -88,11 +85,7 @@ I2C_CH7 0x00000700 - 0x00000710. I2C_CH8 0x00000800 - 0x00000810. I2C_CH9 0x00000900 - 0x00000910. I2C_CH10 0x00000A00 - 0x00000A10. -I2C_CH11 0x00000B00 - 0x00000B10. -I2C_CH12 0x00000C00 - 0x00000C10. -I2C_CH13 0x00000D00 - 0x00000D10. SPI Master 0x00001200 - 0x00001300. -DPLL SPI Master 0x00001320 - 0x0000132F. PORT XCVR 0x00004000 - 0x00004FFF. */ @@ -115,6 +108,7 @@ PORT XCVR 0x00004000 - 0x00004FFF. #define FPGA_MISC_CTRL 0x0050 #define FPGA_MISC_STATUS 0x0054 #define FPGA_AVS_VID_STATUS 0x0068 +#define FPGA_FEATURE_CARD_GPIO 0x0070 #define FPGA_PORT_XCVR_READY 0x000c /* I2C_MASTER BASE ADDR */ @@ -133,11 +127,7 @@ PORT XCVR 0x00004000 - 0x00004FFF. #define I2C_MASTER_CH_8 8 #define I2C_MASTER_CH_9 9 #define I2C_MASTER_CH_10 10 -#define I2C_MASTER_CH_11 11 -#define I2C_MASTER_CH_12 12 -#define I2C_MASTER_CH_13 13 - -#define I2C_MASTER_CH_TOTAL I2C_MASTER_CH_5 +#define I2C_MASTER_CH_TOTAL I2C_MASTER_CH_10 /* SPI_MASTER */ #define SPI_MASTER_WR_EN 0x1200 /* one bit */ @@ -193,7 +183,6 @@ PORT XCVR 0x00004000 - 0x00004FFF. */ #define INTR_INT_N 5 #define INTR_PRESENT 4 -#define INTR_TXFAULT 2 #define INTR_RXLOS 1 #define INTR_MODABS 0 @@ -208,7 +197,6 @@ PORT XCVR 0x00004000 - 0x00004FFF. */ #define MASK_INT_N 5 #define MASK_PRESENT 4 -#define MASK_TXFAULT 2 #define MASK_RXLOS 1 #define MASK_MODABS 0 @@ -249,17 +237,19 @@ enum { * */ + #define VIRTUAL_I2C_QSFP_PORT 32 -#define VIRTUAL_I2C_SFP_PORT 2 +#define VIRTUAL_I2C_SFP_PORT 1 #define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT + VIRTUAL_I2C_SFP_PORT -#define VIRTUAL_I2C_BUS_OFFSET 10 +#define VIRTUAL_I2C_BUS_OFFSET 2 #define CPLD1_SLAVE_ADDR 0x30 #define CPLD2_SLAVE_ADDR 0x31 -static struct class* fpgafwclass = NULL; // < The device-driver class struct pointer -static struct device* fpgafwdev = NULL; // < The device-driver device struct pointer +static struct class* fpgafwclass = NULL; ///< The device-driver class struct pointer +static struct device* fpgafwdev = NULL; ///< The device-driver device struct pointer +static struct platform_device *ds3000_dev; #define PCI_VENDOR_ID_TEST 0x1af4 @@ -308,38 +298,31 @@ struct i2c_dev_data { /* PREDEFINED I2C SWITCH DEVICE TOPOLOGY */ static struct i2c_switch fpga_i2c_bus_dev[] = { - /* BUS3 QSFP Exported as virtual bus */ - {I2C_MASTER_CH_3, 0x71, 2, QSFP, "QSFP1"}, {I2C_MASTER_CH_3, 0x71, 3, QSFP, "QSFP2"}, - {I2C_MASTER_CH_3, 0x71, 0, QSFP, "QSFP3"}, {I2C_MASTER_CH_3, 0x71, 1, QSFP, "QSFP4"}, - {I2C_MASTER_CH_3, 0x71, 6, QSFP, "QSFP5"}, {I2C_MASTER_CH_3, 0x71, 5, QSFP, "QSFP6"}, - {I2C_MASTER_CH_3, 0x73, 7, QSFP, "QSFP7"}, {I2C_MASTER_CH_3, 0x71, 4, QSFP, "QSFP8"}, - - {I2C_MASTER_CH_3, 0x73, 4, QSFP, "QSFP9"}, {I2C_MASTER_CH_3, 0x73, 3, QSFP, "QSFP10"}, - {I2C_MASTER_CH_3, 0x73, 6, QSFP, "QSFP11"}, {I2C_MASTER_CH_3, 0x73, 2, QSFP, "QSFP12"}, - {I2C_MASTER_CH_3, 0x73, 1, QSFP, "QSFP13"}, {I2C_MASTER_CH_3, 0x73, 5, QSFP, "QSFP14"}, - {I2C_MASTER_CH_3, 0x71, 7, QSFP, "QSFP15"}, {I2C_MASTER_CH_3, 0x73, 0, QSFP, "QSFP16"}, - - {I2C_MASTER_CH_3, 0x72, 1, QSFP, "QSFP17"}, {I2C_MASTER_CH_3, 0x72, 7, QSFP, "QSFP18"}, - {I2C_MASTER_CH_3, 0x72, 4, QSFP, "QSFP19"}, {I2C_MASTER_CH_3, 0x72, 0, QSFP, "QSFP20"}, - {I2C_MASTER_CH_3, 0x72, 5, QSFP, "QSFP21"}, {I2C_MASTER_CH_3, 0x72, 2, QSFP, "QSFP22"}, - {I2C_MASTER_CH_3, 0x70, 5, QSFP, "QSFP23"}, {I2C_MASTER_CH_3, 0x72, 6, QSFP, "QSFP24"}, - - {I2C_MASTER_CH_3, 0x72, 3, QSFP, "QSFP25"}, {I2C_MASTER_CH_3, 0x70, 6, QSFP, "QSFP26"}, - {I2C_MASTER_CH_3, 0x70, 0, QSFP, "QSFP27"}, {I2C_MASTER_CH_3, 0x70, 7, QSFP, "QSFP28"}, - {I2C_MASTER_CH_3, 0x70, 2, QSFP, "QSFP29"}, {I2C_MASTER_CH_3, 0x70, 4, QSFP, "QSFP30"}, - {I2C_MASTER_CH_3, 0x70, 3, QSFP, "QSFP31"}, {I2C_MASTER_CH_3, 0x70, 1, QSFP, "QSFP32"}, + /* BUS2 QSFP Exported as virtual bus */ + {I2C_MASTER_CH_2, 0x72, 0, QSFP, "QSFP1"}, {I2C_MASTER_CH_2, 0x72, 1, QSFP, "QSFP2"}, + {I2C_MASTER_CH_2, 0x72, 2, QSFP, "QSFP3"}, {I2C_MASTER_CH_2, 0x72, 3, QSFP, "QSFP4"}, + {I2C_MASTER_CH_2, 0x72, 4, QSFP, "QSFP5"}, {I2C_MASTER_CH_2, 0x72, 5, QSFP, "QSFP6"}, + {I2C_MASTER_CH_2, 0x72, 6, QSFP, "QSFP7"}, {I2C_MASTER_CH_2, 0x72, 7, QSFP, "QSFP8"}, + {I2C_MASTER_CH_2, 0x73, 0, QSFP, "QSFP9"}, {I2C_MASTER_CH_2, 0x73, 1, QSFP, "QSFP10"}, + {I2C_MASTER_CH_2, 0x73, 2, QSFP, "QSFP11"}, {I2C_MASTER_CH_2, 0x73, 3, QSFP, "QSFP12"}, + {I2C_MASTER_CH_2, 0x73, 4, QSFP, "QSFP13"}, {I2C_MASTER_CH_2, 0x73, 5, QSFP, "QSFP14"}, + {I2C_MASTER_CH_2, 0x73, 6, QSFP, "QSFP15"}, {I2C_MASTER_CH_2, 0x73, 7, QSFP, "QSFP16"}, + {I2C_MASTER_CH_2, 0x74, 0, QSFP, "QSFP17"}, {I2C_MASTER_CH_2, 0x74, 1, QSFP, "QSFP18"}, + {I2C_MASTER_CH_2, 0x74, 2, QSFP, "QSFP19"}, {I2C_MASTER_CH_2, 0x74, 3, QSFP, "QSFP20"}, + {I2C_MASTER_CH_2, 0x74, 4, QSFP, "QSFP21"}, {I2C_MASTER_CH_2, 0x74, 5, QSFP, "QSFP22"}, + {I2C_MASTER_CH_2, 0x74, 6, QSFP, "QSFP23"}, {I2C_MASTER_CH_2, 0x74, 7, QSFP, "QSFP24"}, + {I2C_MASTER_CH_2, 0x75, 0, QSFP, "QSFP25"}, {I2C_MASTER_CH_2, 0x75, 1, QSFP, "QSFP26"}, + {I2C_MASTER_CH_2, 0x75, 2, QSFP, "QSFP27"}, {I2C_MASTER_CH_2, 0x75, 3, QSFP, "QSFP28"}, + {I2C_MASTER_CH_2, 0x75, 4, QSFP, "QSFP29"}, {I2C_MASTER_CH_2, 0x75, 5, QSFP, "QSFP30"}, + {I2C_MASTER_CH_2, 0x75, 6, QSFP, "QSFP31"}, {I2C_MASTER_CH_2, 0x75, 7, QSFP, "QSFP32"}, /* BUS1 SFP+ Exported as virtual bus */ - {I2C_MASTER_CH_1, 0xFF, 0, SFP, "SFP1"}, - /* BUS2 SFP+ Exported as virtual bus */ - {I2C_MASTER_CH_2, 0xFF, 0, SFP, "SFP2"}, - /* BUS4 CPLD Access via I2C */ - {I2C_MASTER_CH_4, 0xFF, 0, NONE, "CPLD_S"}, - /* BUS5 CPLD_B */ - {I2C_MASTER_CH_5, 0xFF, 0, NONE, "CPLD_B"}, + {I2C_MASTER_CH_1, 0x72, 0, SFP, "SFP1"}, + /* BUS3 Switchboard CPLD */ + {I2C_MASTER_CH_3, 0xFF, 0, NONE, "I2C_3"}, }; #define VIRTUAL_I2C_PORT_LENGTH ARRAY_SIZE(fpga_i2c_bus_dev) -#define SW_I2C_CPLD_INDEX SFF_PORT_TOTAL +#define VIRTUAL_I2C_CPLD_INDEX SFF_PORT_TOTAL struct fpga_device { /* data mmio region */ @@ -354,7 +337,7 @@ static struct fpga_device fpga_dev = { .data_mmio_len = 0, }; -struct silverstone_fpga_data { +struct ds3000_fpga_data { struct device *sff_devices[SFF_PORT_TOTAL]; struct i2c_client *sff_i2c_clients[SFF_PORT_TOTAL]; struct i2c_adapter *i2c_adapter[VIRTUAL_I2C_PORT_LENGTH]; @@ -369,7 +352,7 @@ struct sff_device_data { enum PORT_TYPE port_type; }; -struct silverstone_fpga_data *fpga_data; +struct ds3000_fpga_data *fpga_data; /* * Kernel object for other module drivers. @@ -385,18 +368,6 @@ static struct kobject *cpld2 = NULL; */ static struct device *sff_dev = NULL; - -static ssize_t version_show(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - u32 version; - - mutex_lock(&fpga_data->fpga_lock); - version = ioread32(fpga_dev.data_base_addr + FPGA_VERSION); - mutex_unlock(&fpga_data->fpga_lock); - return sprintf(buf, "%d.%d\n", version >> 16, version & 0xFFFF); -} - /** * Show the value of the register set by 'set_fpga_reg_address' * If the address is not set by 'set_fpga_reg_address' first, @@ -404,75 +375,86 @@ static ssize_t version_show(struct device *dev, struct device_attribute *devattr * @param buf register value in hextring * @return number of bytes read, or an error code */ -static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr, - char *buf) +static ssize_t get_fpga_reg_value(struct device *dev, + struct device_attribute *attr, char *buf) { // read data from the address uint32_t data; data = ioread32(fpga_data->fpga_read_addr); return sprintf(buf, "0x%8.8x\n", data); } + /** * Store the register address * @param buf address wanted to be read value of * @return number of bytes stored, or an error code */ -static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr, +static ssize_t set_fpga_reg_address(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + ssize_t status; uint32_t addr; - char *last; - addr = (uint32_t)strtoul(buf, &last, 16); - if (addr == 0 && buf == last) { - return -EINVAL; + status = kstrtou32(buf, 0, &addr); + if (status == 0) { + fpga_data->fpga_read_addr = fpga_dev.data_base_addr + addr; + status = count; } - fpga_data->fpga_read_addr = fpga_dev.data_base_addr + addr; - return count; + return status; } + /** * Show value of fpga scratch register * @param buf register value in hexstring * @return number of bytes read, or an error code */ -static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr, - char *buf) +static ssize_t get_fpga_scratch(struct device *dev, + struct device_attribute *attr, char *buf) { - return sprintf(buf, "0x%8.8x\n", ioread32(fpga_dev.data_base_addr + FPGA_SCRATCH) & 0xffffffff); + uint32_t data; + data = ioread32(fpga_dev.data_base_addr + FPGA_SCRATCH); + data &= 0xffffffff; + return sprintf(buf, "0x%8.8x\n", data); } + /** * Store value of fpga scratch register * @param buf scratch register value passing from user space * @return number of bytes stored, or an error code */ -static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr, +static ssize_t set_fpga_scratch(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + ssize_t status; uint32_t data; - char *last; - data = (uint32_t)strtoul(buf, &last, 16); - if (data == 0 && buf == last) { - return -EINVAL; + + status = kstrtou32(buf, 0, &data); + if (status == 0) { + iowrite32(data, fpga_dev.data_base_addr + FPGA_SCRATCH); + status = count; } - iowrite32(data, fpga_dev.data_base_addr + FPGA_SCRATCH); - return count; + return status; } + /** * Store a value in a specific register address * @param buf the value and address in format '0xhhhh 0xhhhhhhhh' * @return number of bytes sent by user space, or an error code */ -static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr, +static ssize_t set_fpga_reg_value(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { - // register are 4 bytes + //register is 4 bytes uint32_t addr; uint32_t value; uint32_t mode = 8; char *tok; char clone[count]; char *pclone = clone; - char *last; + ssize_t status; strcpy(clone, buf); @@ -482,8 +464,8 @@ static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *d mutex_unlock(&fpga_data->fpga_lock); return -EINVAL; } - addr = (uint32_t)strtoul(tok, &last, 16); - if (addr == 0 && tok == last) { + status = kstrtou32(tok, 0, &addr); + if (status != 0) { mutex_unlock(&fpga_data->fpga_lock); return -EINVAL; } @@ -492,8 +474,8 @@ static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *d mutex_unlock(&fpga_data->fpga_lock); return -EINVAL; } - value = (uint32_t)strtoul(tok, &last, 16); - if (value == 0 && tok == last) { + status = kstrtou32(tok, 0, &value); + if (status != 0) { mutex_unlock(&fpga_data->fpga_lock); return -EINVAL; } @@ -501,8 +483,8 @@ static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *d if (tok == NULL) { mode = 32; } else { - mode = (uint32_t)strtoul(tok, &last, 10); - if (mode == 0 && tok == last) { + status = kstrtou32(tok, 0, &mode); + if (status != 0) { mutex_unlock(&fpga_data->fpga_lock); return -EINVAL; } @@ -521,8 +503,6 @@ static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *d /** * Show FPGA port XCVR ready status - * @param buf 1 if the functin is ready, 0 if not. - * @return number of bytes read, or an error code */ static ssize_t ready_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -540,14 +520,12 @@ static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address); static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch); static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value); static DEVICE_ATTR_RO(ready); -static DEVICE_ATTR_RO(version); static struct attribute *fpga_attrs[] = { &dev_attr_getreg.attr, &dev_attr_scratch.attr, &dev_attr_setreg.attr, &dev_attr_ready.attr, - &dev_attr_version.attr, NULL, }; @@ -555,78 +533,90 @@ static struct attribute_group fpga_attr_grp = { .attrs = fpga_attrs, }; -static ssize_t cpld1_version_show(struct device *dev, - struct device_attribute *attr, char *buf) +/* SW CPLDs attributes */ +static ssize_t cpld1_getreg_show(struct device *dev, + struct device_attribute *attr, char *buf) { - u8 version; + // CPLD register is one byte + uint8_t data; int err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], - CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x00, - I2C_SMBUS_BYTE_DATA, - (union i2c_smbus_data *)&version); + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, + I2C_SMBUS_READ, fpga_data->cpld1_read_addr, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + if (err < 0) return err; - return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F); -} -struct device_attribute dev_attr_cpld1_version = __ATTR(version, 0444, cpld1_version_show , NULL); -/* SW CPLDs attributes */ -static ssize_t cpld1_getreg_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - // CPLD register is one byte - uint8_t data; - fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld1_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); return sprintf(buf, "0x%2.2x\n", data); } -static ssize_t cpld1_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) + +static ssize_t cpld1_getreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { + ssize_t status; uint8_t addr; - char *last; - addr = (uint8_t)strtoul(buf, &last, 16); - if (addr == 0 && buf == last) { - return -EINVAL; + + status = kstrtou8(buf, 0, &addr); + if (status == 0) { + fpga_data->cpld1_read_addr = addr; + status = count; } - fpga_data->cpld1_read_addr = addr; - return size; + return status; } -struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store); -static ssize_t cpld1_scratch_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t cpld1_scratch_show(struct device *dev, + struct device_attribute *attr, char *buf) { // CPLD register is one byte - __u8 data; + uint8_t data; int err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); if (err < 0) return err; + return sprintf(buf, "0x%2.2x\n", data); } -static ssize_t cpld1_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) + +static ssize_t cpld1_scratch_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { // CPLD register is one byte - __u8 data; - char *last; + uint8_t data; + ssize_t status; int err; - data = (uint8_t)strtoul(buf, &last, 16); - if (data == 0 && buf == last) { - return -EINVAL; + + status = kstrtou8(buf, 0, &data); + if (status != 0) { + return status; } - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); if (err < 0) return err; - return size; + + return count; } -struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch, 0600, cpld1_scratch_show, cpld1_scratch_store); -static ssize_t cpld1_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t cpld1_setreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { uint8_t addr, value; char *tok; - char clone[size]; + char clone[count]; char *pclone = clone; + ssize_t status; int err; - char *last; strcpy(clone, buf); @@ -634,29 +624,33 @@ static ssize_t cpld1_setreg_store(struct device *dev, struct device_attribute *a if (tok == NULL) { return -EINVAL; } - addr = (uint8_t)strtoul(tok, &last, 16); - if (addr == 0 && tok == last) { + status = kstrtou8(tok, 0, &addr); + if (status != 0) { return -EINVAL; } tok = strsep((char**)&pclone, " "); if (tok == NULL) { return -EINVAL; } - value = (uint8_t)strtoul(tok, &last, 16); - if (value == 0 && tok == last) { + status = kstrtou8(tok, 0, &value); + if (status != 0) { return -EINVAL; } - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value); if (err < 0) return err; - return size; + return count; } + +struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store); +struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch, 0600, cpld1_scratch_show, cpld1_scratch_store); struct device_attribute dev_attr_cpld1_setreg = __ATTR(setreg, 0200, NULL, cpld1_setreg_store); static struct attribute *cpld1_attrs[] = { - &dev_attr_cpld1_version.attr, &dev_attr_cpld1_getreg.attr, &dev_attr_cpld1_scratch.attr, &dev_attr_cpld1_setreg.attr, @@ -667,80 +661,86 @@ static struct attribute_group cpld1_attr_grp = { .attrs = cpld1_attrs, }; -static ssize_t cpld2_version_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t cpld2_getreg_show(struct device *dev, + struct device_attribute *attr, char *buf) { - u8 version; + // CPLD register is one byte + uint8_t data; int err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], - CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x00, - I2C_SMBUS_BYTE_DATA, - (union i2c_smbus_data *)&version); + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); if (err < 0) return err; - return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F); -} -struct device_attribute dev_attr_cpld2_version = __ATTR(version, 0444, cpld2_version_show , NULL); -static ssize_t cpld2_getreg_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - // CPLD register is one byte - uint8_t data; - fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); return sprintf(buf, "0x%2.2x\n", data); } -static ssize_t cpld2_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t cpld2_getreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { // CPLD register is one byte - uint32_t addr; - char *last; - addr = (uint8_t)strtoul(buf, &last, 16); - if (addr == 0 && buf == last) { - return -EINVAL; + uint8_t addr; + ssize_t status; + + status = kstrtou8(buf, 0, &addr); + if (status == 0) { + fpga_data->cpld2_read_addr = addr; + status = count; } - fpga_data->cpld2_read_addr = addr; - return size; + return status; } -struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store); -static ssize_t cpld2_scratch_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t cpld2_scratch_show(struct device *dev, + struct device_attribute *attr, char *buf) { // CPLD register is one byte - __u8 data; + uint8_t data; int err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); if (err < 0) return err; + return sprintf(buf, "0x%2.2x\n", data); } -static ssize_t cpld2_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t cpld2_scratch_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { // CPLD register is one byte - __u8 data; - char *last; + uint8_t data; int err; + ssize_t status; - data = (uint8_t)strtoul(buf, &last, 16); - if (data == 0 && buf == last) { + status = kstrtou8(buf, 0, &data); + if (status != 0) { return -EINVAL; } - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); if (err < 0) return err; - return size; + + return count; } -struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch, 0600, cpld2_scratch_show, cpld2_scratch_store); -static ssize_t cpld2_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t cpld2_setreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { uint8_t addr, value; char *tok; - char clone[size]; + char clone[count]; char *pclone = clone; + ssize_t status; int err; - char *last; strcpy(clone, buf); @@ -748,29 +748,33 @@ static ssize_t cpld2_setreg_store(struct device *dev, struct device_attribute *a if (tok == NULL) { return -EINVAL; } - addr = (uint8_t)strtoul(tok, &last, 16); - if (addr == 0 && tok == last) { + status = kstrtou8(tok, 0, &addr); + if (status != 0) { return -EINVAL; } tok = strsep((char**)&pclone, " "); if (tok == NULL) { return -EINVAL; } - value = (uint8_t)strtoul(tok, &last, 16); - if (value == 0 && tok == last) { + status = kstrtou8(tok, 0, &value); + if (status != 0) { return -EINVAL; } - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value); if (err < 0) return err; - return size; + return count; } + +struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store); +struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch, 0600, cpld2_scratch_show, cpld2_scratch_store); struct device_attribute dev_attr_cpld2_setreg = __ATTR(setreg, 0200, NULL, cpld2_setreg_store); static struct attribute *cpld2_attrs[] = { - &dev_attr_cpld2_version.attr, &dev_attr_cpld2_getreg.attr, &dev_attr_cpld2_scratch.attr, &dev_attr_cpld2_setreg.attr, @@ -782,7 +786,8 @@ static struct attribute_group cpld2_attr_grp = { }; /* QSFP/SFP+ attributes */ -static ssize_t qsfp_modirq_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t qsfp_modirq_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -796,7 +801,8 @@ static ssize_t qsfp_modirq_show(struct device *dev, struct device_attribute *att } DEVICE_ATTR_RO(qsfp_modirq); -static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t qsfp_modprs_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -810,7 +816,8 @@ static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *att } DEVICE_ATTR_RO(qsfp_modprs); -static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t sfp_txfault_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -824,7 +831,8 @@ static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *att } DEVICE_ATTR_RO(sfp_txfault); -static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t sfp_rxlos_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -838,7 +846,8 @@ static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, } DEVICE_ATTR_RO(sfp_rxlos); -static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t sfp_modabs_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -852,7 +861,8 @@ static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr } DEVICE_ATTR_RO(sfp_modabs); -static ssize_t qsfp_lpmode_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t qsfp_lpmode_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -864,33 +874,36 @@ static ssize_t qsfp_lpmode_show(struct device *dev, struct device_attribute *att mutex_unlock(&fpga_data->fpga_lock); return sprintf(buf, "%d\n", (data >> CTRL_LPMOD) & 1U); } -static ssize_t qsfp_lpmode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t qsfp_lpmode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { ssize_t status; - long value; + uint32_t value; u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); unsigned int portid = dev_data->portid; unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; mutex_lock(&fpga_data->fpga_lock); - status = kstrtol(buf, 0, &value); + status = kstrtou32(buf, 0, &value); if (status == 0) { - // if value is 0, disable the lpmode + // check if value is 0 clear data = ioread32(fpga_dev.data_base_addr + REGISTER); if (!value) data = data & ~( (u32)0x1 << CTRL_LPMOD); else data = data | ((u32)0x1 << CTRL_LPMOD); iowrite32(data, fpga_dev.data_base_addr + REGISTER); - status = size; + status = count; } mutex_unlock(&fpga_data->fpga_lock); return status; } DEVICE_ATTR_RW(qsfp_lpmode); -static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t qsfp_reset_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -903,33 +916,136 @@ static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr return sprintf(buf, "%d\n", (data >> CTRL_RST) & 1U); } -static ssize_t qsfp_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t qsfp_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { ssize_t status; - long value; + uint32_t value; u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); unsigned int portid = dev_data->portid; unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; mutex_lock(&fpga_data->fpga_lock); - status = kstrtol(buf, 0, &value); + status = kstrtou32(buf, 0, &value); if (status == 0) { - // if value is 0, reset signal is low + // check if value is 0 clear data = ioread32(fpga_dev.data_base_addr + REGISTER); if (!value) data = data & ~( (u32)0x1 << CTRL_RST); else data = data | ((u32)0x1 << CTRL_RST); iowrite32(data, fpga_dev.data_base_addr + REGISTER); - status = size; + status = count; } mutex_unlock(&fpga_data->fpga_lock); return status; } DEVICE_ATTR_RW(qsfp_reset); -static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t qsfp_isr_flags_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + data = (u8) ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + /* + * Unify the return pattern to 2-bit + * [1] : module interrupt + * [0] : presence + */ + data = data & valid_bits; + data = data >> 4; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t qsfp_isr_flags_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value << 4; + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_isr_flags); + +static ssize_t qsfp_isr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + /* + * Unify the return pattern to 2-bit + * [1] : module interrupt + * [0] : presence + */ + data = data & valid_bits; + data = data >> 4; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t qsfp_isr_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value << 4; + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_isr_mask); + +static ssize_t sfp_txdisable_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 data; struct sff_device_data *dev_data = dev_get_drvdata(dev); @@ -941,7 +1057,9 @@ static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *a mutex_unlock(&fpga_data->fpga_lock); return sprintf(buf, "%d\n", (data >> CTRL_TXDIS) & 1U); } -static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t sfp_txdisable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { ssize_t status; long value; @@ -960,22 +1078,112 @@ static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute * else data = data | ((u32)0x1 << CTRL_TXDIS); iowrite32(data, fpga_dev.data_base_addr + REGISTER); - status = size; + status = count; } mutex_unlock(&fpga_data->fpga_lock); return status; } DEVICE_ATTR_RW(sfp_txdisable); +static ssize_t sfp_isr_flags_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_RXLOS) | BIT(INTR_MODABS); + + mutex_lock(&fpga_data->fpga_lock); + data = (u8) ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + data = data & valid_bits; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t sfp_isr_flags_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(sfp_isr_flags); + +static ssize_t sfp_isr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_RXLOS) | BIT(INTR_MODABS); + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + data = data & valid_bits; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t sfp_isr_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_RXLOS) | BIT(INTR_MODABS); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(sfp_isr_mask); + static struct attribute *sff_attrs[] = { &dev_attr_qsfp_modirq.attr, &dev_attr_qsfp_modprs.attr, &dev_attr_qsfp_lpmode.attr, &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_isr_flags.attr, + &dev_attr_qsfp_isr_mask.attr, &dev_attr_sfp_txfault.attr, &dev_attr_sfp_rxlos.attr, &dev_attr_sfp_modabs.attr, &dev_attr_sfp_txdisable.attr, + &dev_attr_sfp_isr_flags.attr, + &dev_attr_sfp_isr_mask.attr, NULL, }; @@ -989,22 +1197,30 @@ static const struct attribute_group *sff_attr_grps[] = { }; -static ssize_t port_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t port_led_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) { // value can be "nomal", "test" __u8 led_mode_1, led_mode_2; int err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); if (err < 0) return err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_2); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_2); if (err < 0) return err; + return sprintf(buf, "%s %s\n", led_mode_1 ? "test" : "normal", led_mode_2 ? "test" : "normal"); } -static ssize_t port_led_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t port_led_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int status; __u8 led_mode_1; @@ -1015,62 +1231,65 @@ static ssize_t port_led_mode_store(struct device *dev, struct device_attribute * } else { return -EINVAL; } - status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, - I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); - status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, - I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); - return size; + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x09, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x09, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); + return count; } DEVICE_ATTR_RW(port_led_mode); // Only work when port_led_mode set to 1 -static ssize_t port_led_color_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t port_led_color_show(struct device *dev, + struct device_attribute *attr, char *buf) { - // value can be R/G/B/C/M/Y/W/OFF + // value can be "off", "green", "amber", "both" __u8 led_color1, led_color2; int err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color1); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x0A, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color1); if (err < 0) return err; - err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color2); + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x0A, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color2); if (err < 0) return err; return sprintf(buf, "%s %s\n", - led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "red" : led_color1 == 0x04 ? - "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : led_color1 == 0x01 ? "magenta" : "white", - led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "red" : led_color1 == 0x04 ? - "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : led_color1 == 0x01 ? "magenta" : "white"); + led_color1 == 0x03 ? "off" : led_color1 == 0x02 ? "green" : led_color1 == 0x01 ? "amber" : "both", + led_color2 == 0x03 ? "off" : led_color2 == 0x02 ? "green" : led_color2 == 0x01 ? "amber" : "both"); } -static ssize_t port_led_color_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +static ssize_t port_led_color_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int status; __u8 led_color; if (sysfs_streq(buf, "off")) { - led_color = 0x07; - } else if (sysfs_streq(buf, "green")) { - led_color = 0x06; - } else if (sysfs_streq(buf, "red")) { - led_color = 0x05; - } else if (sysfs_streq(buf, "yellow")) { - led_color = 0x04; - } else if (sysfs_streq(buf, "blue")) { led_color = 0x03; - } else if (sysfs_streq(buf, "cyan")) { + } else if (sysfs_streq(buf, "green")) { led_color = 0x02; - } else if (sysfs_streq(buf, "magenta")) { + } else if (sysfs_streq(buf, "amber")) { led_color = 0x01; - } else if (sysfs_streq(buf, "white")) { + } else if (sysfs_streq(buf, "both")) { led_color = 0x00; } else { status = -EINVAL; return status; } - status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, - I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color); - status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, - I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color); - return size; + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, + I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, + (union i2c_smbus_data*)&led_color); + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, + I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, + (union i2c_smbus_data*)&led_color); + return count; } DEVICE_ATTR_RW(port_led_color); @@ -1084,7 +1303,7 @@ static struct attribute_group sff_led_test_grp = { .attrs = sff_led_test, }; -static struct device * silverstone_sff_init(int portid) { +static struct device * ds3000_sff_init(int portid) { struct sff_device_data *new_data; struct device *new_device; @@ -1096,7 +1315,9 @@ static struct device * silverstone_sff_init(int portid) { /* The QSFP port ID start from 1 */ new_data->portid = portid + 1; new_data->port_type = fpga_i2c_bus_dev[portid].port_type; - new_device = device_create_with_groups(fpgafwclass, sff_dev, MKDEV(0, 0), new_data, sff_attr_grps, "%s", fpga_i2c_bus_dev[portid].calling_name); + new_device = device_create_with_groups(fpgafwclass, sff_dev, + MKDEV(0, 0), new_data, sff_attr_grps, "%s", + fpga_i2c_bus_dev[portid].calling_name); if (IS_ERR(new_device)) { printk(KERN_ALERT "Cannot create sff device @port%d", portid); kfree(new_data); @@ -1195,37 +1416,34 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, struct i2c_dev_data *dev_data; void __iomem *pci_bar; unsigned int portid, master_bus; + unsigned int REG_FDR0; unsigned int REG_CR0; unsigned int REG_SR0; unsigned int REG_DR0; unsigned int REG_ID0; + REG_FDR0 = 0; + REG_CR0 = 0; + REG_SR0 = 0; + REG_DR0 = 0; + REG_ID0 = 0; + /* Write the command register */ dev_data = i2c_get_adapdata(adapter); portid = dev_data->portid; pci_bar = fpga_dev.data_base_addr; - master_bus = dev_data->pca9548.master_bus; - REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100; - REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100; - REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100; - REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100; - REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100; - - if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) { - error = -EINVAL; - goto Done; - } #ifdef DEBUG_KERN - printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X " + printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-15s|CMD %2.2X " , portid, addr, flags, rw, rw == 1 ? "READ " : "WRITE" , size, size == 0 ? "QUICK" : size == 1 ? "BYTE" : size == 2 ? "BYTE_DATA" : size == 3 ? "WORD_DATA" : size == 4 ? "PROC_CALL" : - size == 5 ? "BLOCK_DATA" : "ERROR" + size == 5 ? "BLOCK_DATA" : + size == 8 ? "I2C_BLOCK_DATA" : "ERROR" , cmd); #endif /* Map the size to what the chip understands */ @@ -1235,6 +1453,7 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: break; default: printk(KERN_INFO "Unsupported transaction %d\n", size); @@ -1242,12 +1461,27 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, goto Done; } + master_bus = dev_data->pca9548.master_bus; + + if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) { + error = -ENXIO; + goto Done; + } + + REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100; + iowrite8(portid, pci_bar + REG_ID0); ////[S][ADDR/R] - //Clear status register + // Clear status register iowrite8(0, pci_bar + REG_SR0); - iowrite8(1 << I2C_CR_BIT_MIEN | 1 << I2C_CR_BIT_MTX | 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0); + iowrite8(1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MTX | + 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0); SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN); if (rw == I2C_SMBUS_READ && @@ -1274,9 +1508,10 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, if (size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_WORD_DATA || size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA || (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)) { - //sent command code to data register + // sent command code to data register iowrite8(cmd, pci_bar + REG_DR0); info( "MS Send CMD 0x%2.2X", cmd); @@ -1294,14 +1529,15 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, case I2C_SMBUS_WORD_DATA: cnt = 2; break; case I2C_SMBUS_BLOCK_DATA: - // in block data mode keep number of byte in block[0] + case I2C_SMBUS_I2C_BLOCK_DATA: + /* In block data modes keep number of byte in block[0] */ cnt = data->block[0]; break; default: cnt = 0; break; } - // [CNT] used only bloack data write + // [CNT] used only block data write if (size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE) { iowrite8(cnt, pci_bar + REG_DR0); @@ -1320,11 +1556,12 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_WORD_DATA || - size == I2C_SMBUS_BLOCK_DATA + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA )) { - int bid = 0; + bid = 0; info( "MS prepare to sent [%d bytes]", cnt); - if (size == I2C_SMBUS_BLOCK_DATA ) { + if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_I2C_BLOCK_DATA) { bid = 1; // block[0] is cnt; cnt += 1; // offset from block[0] } @@ -1338,13 +1575,15 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, goto Done; } } + } - //REPEATE START + // REPEATE START if ( rw == I2C_SMBUS_READ && ( size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_WORD_DATA || - size == I2C_SMBUS_BLOCK_DATA + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA )) { info( "MS Repeated Start"); @@ -1370,7 +1609,8 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_WORD_DATA || - size == I2C_SMBUS_BLOCK_DATA + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA )) { switch (size) { @@ -1380,12 +1620,15 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, case I2C_SMBUS_WORD_DATA: cnt = 2; break; case I2C_SMBUS_BLOCK_DATA: - //will be changed after recived first data + // will be changed after recived first data cnt = 3; break; + case I2C_SMBUS_I2C_BLOCK_DATA: + cnt = data->block[0]; break; default: cnt = 0; break; } + bid = 0; info( "MS Receive"); //set to Receive mode @@ -1395,7 +1638,7 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, for (bid = -1; bid < cnt; bid++) { - // Wait {A} + // Wait for byte transfer error = i2c_wait_ack(adapter, 12, 0); if (error < 0) { goto Done; @@ -1415,8 +1658,12 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, info ( "SET STOP in read loop"); SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA); } - data->block[bid] = ioread8(pci_bar + REG_DR0); - + if (size == I2C_SMBUS_I2C_BLOCK_DATA) { + // block[0] is read length + data->block[bid + 1] = ioread8(pci_bar + REG_DR0); + } else { + data->block[bid] = ioread8(pci_bar + REG_DR0); + } info( "DATA IN [%d] %2.2X", bid, data->block[bid]); if (size == I2C_SMBUS_BLOCK_DATA && bid == 0) { @@ -1426,9 +1673,8 @@ static int smbus_access(struct i2c_adapter *adapter, u16 addr, } } - //[P] + // [P] SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA); - i2c_wait_ack(adapter, 12, 0); info( "MS STOP"); Done: @@ -1481,28 +1727,38 @@ static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr, if ( prev_switch != switch_addr && prev_switch != 0 ) { // reset prev_port PCA9548 chip retry = 3; - while(retry--){ - error = smbus_access(adapter, (u16)(prev_switch), flags, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL); - if(error >= 0){ + while (retry--) { + error = smbus_access(adapter, (u16)(prev_switch), flags, + I2C_SMBUS_WRITE, 0x00, + I2C_SMBUS_BYTE, NULL); + if (error >= 0) { break; - }else{ - dev_dbg(&adapter->dev,"Failed to deselect ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error); + } else { + dev_dbg(&adapter->dev, + "Failed to deselect ch %d of 0x%x, CODE %d\n", + prev_ch, prev_switch, error); } } - if(retry == 0) + if (retry < 0) { goto release_unlock; + } // set PCA9548 to current channel retry = 3; - while(retry--){ - error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL); - if(error >= 0){ + while (retry--) { + error = smbus_access(adapter, switch_addr, flags, + I2C_SMBUS_WRITE, 1 << channel, + I2C_SMBUS_BYTE, NULL); + if (error >= 0) { break; - }else{ - dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", channel, switch_addr, error); + } else { + dev_dbg(&adapter->dev, + "Failed to deselect ch %d of 0x%x, CODE %d\n", + prev_ch, prev_switch, error); } } - if(retry == 0) + if (retry < 0) { goto release_unlock; + } // update lasted port fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel; @@ -1511,16 +1767,21 @@ static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr, if ( prev_ch != channel || prev_switch == 0 ) { // set new PCA9548 at switch_addr to current retry = 3; - while(retry--){ - error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL); - if(error >= 0){ + while (retry--) { + error = smbus_access(adapter, switch_addr, flags, + I2C_SMBUS_WRITE, 1 << channel, + I2C_SMBUS_BYTE, NULL); + if (error >= 0) { break; - }else{ - dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", channel, switch_addr, error); + } else { + dev_dbg(&adapter->dev, + "Failed to deselect ch %d of 0x%x, CODE %d\n", + prev_ch, prev_switch, error); } } - if(retry == 0) + if (retry < 0) { goto release_unlock; + } // update lasted port fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel; } @@ -1529,22 +1790,24 @@ static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr, // Do SMBus communication error = smbus_access(adapter, addr, flags, rw, cmd, size, data); - if(error < 0){ - dev_dbg( &adapter->dev,"smbus_xfer failed (%d) @ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X " - , error, addr, flags, rw, rw == 1 ? "READ " : "WRITE" - , size, size == 0 ? "QUICK" : - size == 1 ? "BYTE" : - size == 2 ? "BYTE_DATA" : - size == 3 ? "WORD_DATA" : - size == 4 ? "PROC_CALL" : - size == 5 ? "BLOCK_DATA" : - size == 8 ? "I2C_BLOCK_DATA" : "ERROR" - , cmd); + if (error < 0) { + dev_dbg( &adapter->dev, + "smbus_xfer failed (%d) @ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X " + , error, addr, flags, rw, rw == 1 ? "READ " : "WRITE" + , size, size == 0 ? "QUICK" : + size == 1 ? "BYTE" : + size == 2 ? "BYTE_DATA" : + size == 3 ? "WORD_DATA" : + size == 4 ? "PROC_CALL" : + size == 5 ? "BLOCK_DATA" : + size == 8 ? "I2C_BLOCK_DATA" : "ERROR" + , cmd); } release_unlock: mutex_unlock(&fpga_i2c_master_locks[master_bus - 1]); - dev_dbg(&adapter->dev,"switch ch %d of 0x%x -> ch %d of 0x%x\n", prev_ch, prev_switch, channel, switch_addr); + dev_dbg(&adapter->dev, "switch ch %d of 0x%x -> ch %d of 0x%x\n", + prev_ch, prev_switch, channel, switch_addr); return error; } @@ -1559,10 +1822,11 @@ static u32 fpga_i2c_func(struct i2c_adapter *a) I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; + I2C_FUNC_SMBUS_BLOCK_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK; } -static const struct i2c_algorithm silverstone_i2c_algorithm = { +static const struct i2c_algorithm ds3000_i2c_algorithm = { .smbus_xfer = fpga_i2c_access, .functionality = fpga_i2c_func, }; @@ -1577,23 +1841,24 @@ static const struct i2c_algorithm silverstone_i2c_algorithm = { * When bus_number_offset is -1, created adapter with dynamic bus number. * Otherwise create adapter at i2c bus = bus_number_offset + portid. */ -static struct i2c_adapter * silverstone_i2c_init(struct platform_device *pdev, int portid, int bus_number_offset) +static struct i2c_adapter * ds3000_i2c_init(struct platform_device *pdev, + int portid, int bus_number_offset) { int error; - struct i2c_adapter *new_adapter; struct i2c_dev_data *new_data; void __iomem *i2c_freq_base_reg; new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL); if (!new_adapter) { - printk(KERN_ALERT "Cannot alloc i2c adapter for %s", fpga_i2c_bus_dev[portid].calling_name); + printk(KERN_ALERT "Cannot alloc i2c adapter for %s", + fpga_i2c_bus_dev[portid].calling_name); return NULL; } new_adapter->owner = THIS_MODULE; new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - new_adapter->algo = &silverstone_i2c_algorithm; + new_adapter->algo = &ds3000_i2c_algorithm; /* If the bus offset is -1, use dynamic bus number */ if (bus_number_offset == -1) { new_adapter->nr = -1; @@ -1603,7 +1868,8 @@ static struct i2c_adapter * silverstone_i2c_init(struct platform_device *pdev, i new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); if (!new_data) { - printk(KERN_ALERT "Cannot alloc i2c data for %s", fpga_i2c_bus_dev[portid].calling_name); + printk(KERN_ALERT "Cannot alloc i2c data for %s", + fpga_i2c_bus_dev[portid].calling_name); kfree_sensitive(new_adapter); return NULL; } @@ -1631,32 +1897,16 @@ static struct i2c_adapter * silverstone_i2c_init(struct platform_device *pdev, i return new_adapter; }; -static void silverstone_dev_release( struct device * dev) -{ - return; -} - -static struct platform_device silverstone_dev = { - .name = DRIVER_NAME, - .id = -1, - .num_resources = 0, - .resource = NULL, - .dev = { - .release = silverstone_dev_release, - } -}; - /** * Board info for QSFP/SFP+ eeprom. - * Note: Using OOM optoe as I2C eeprom driver. - * https://www.opencompute.org/wiki/Networking/SpecsAndDesigns#Open_Optical_Monitoring + * Note: Using sff8436 as I2C eeprom driver. */ static struct i2c_board_info sff8436_eeprom_info[] = { - { I2C_BOARD_INFO("optoe1", 0x50) }, //For QSFP w/ sff8436 - { I2C_BOARD_INFO("optoe2", 0x50) }, //For SFP+ w/ sff8472 + { I2C_BOARD_INFO("optoe1", 0x50) }, + { I2C_BOARD_INFO("optoe2", 0x50) }, }; -static int silverstone_drv_probe(struct platform_device *pdev) +static int ds3000_drv_probe(struct platform_device *pdev) { int ret = 0; int portid_count; @@ -1667,7 +1917,7 @@ static int silverstone_drv_probe(struct platform_device *pdev) /* The device class need to be instantiated before this function called */ BUG_ON(fpgafwclass == NULL); - fpga_data = devm_kzalloc(&pdev->dev, sizeof(struct silverstone_fpga_data), + fpga_data = devm_kzalloc(&pdev->dev, sizeof(struct ds3000_fpga_data), GFP_KERNEL); if (!fpga_data) @@ -1679,6 +1929,7 @@ static int silverstone_drv_probe(struct platform_device *pdev) fpga_data->cpld2_read_addr = 0x00; mutex_init(&fpga_data->fpga_lock); + for (ret = I2C_MASTER_CH_1 ; ret <= I2C_MASTER_CH_TOTAL; ret++) { mutex_init(&fpga_i2c_master_locks[ret - 1]); } @@ -1777,14 +2028,15 @@ static int silverstone_drv_probe(struct platform_device *pdev) } for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) { - fpga_data->i2c_adapter[portid_count] = silverstone_i2c_init(pdev, portid_count, VIRTUAL_I2C_BUS_OFFSET); + fpga_data->i2c_adapter[portid_count] = ds3000_i2c_init(pdev, portid_count, VIRTUAL_I2C_BUS_OFFSET); } + /* Init SFF devices */ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) { struct i2c_adapter *i2c_adap = fpga_data->i2c_adapter[portid_count]; if (i2c_adap) { - fpga_data->sff_devices[portid_count] = silverstone_sff_init(portid_count); + fpga_data->sff_devices[portid_count] = ds3000_sff_init(portid_count); sff_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]); BUG_ON(sff_data == NULL); if ( sff_data->port_type == QSFP ) { @@ -1797,19 +2049,21 @@ static int silverstone_drv_probe(struct platform_device *pdev) &fpga_data->sff_i2c_clients[portid_count]->dev.kobj, "i2c"); } + } + printk(KERN_INFO "Virtual I2C buses created\n"); + #ifdef TEST_MODE return 0; #endif - fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, + fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld1_version); - fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, + fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld2_version); - printk(KERN_INFO "Switch CPLD1 VERSION: %2.2x\n", cpld1_version); - printk(KERN_INFO "Switch CPLD2 VERSION: %2.2x\n", cpld2_version); - + printk(KERN_INFO "CPLD1 VERSON: %2.2x\n", cpld1_version); + printk(KERN_INFO "CPLD2 VERSON: %2.2x\n", cpld2_version); /* Init I2C buses that has PCA9548 switch device. */ for (portid_count = 0; portid_count < VIRTUAL_I2C_PORT_LENGTH; portid_count++) { @@ -1826,7 +2080,8 @@ static int silverstone_drv_probe(struct platform_device *pdev) if (prev_i2c_switch != ( (master_bus << 8) | switch_addr) ) { // Found the bus with PCA9548, trying to clear all switch in it. - smbus_access(fpga_data->i2c_adapter[portid_count], switch_addr, 0x00, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL); + smbus_access(fpga_data->i2c_adapter[portid_count], switch_addr, 0x00, + I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL); prev_i2c_switch = ( master_bus << 8 ) | switch_addr; } } @@ -1834,7 +2089,7 @@ static int silverstone_drv_probe(struct platform_device *pdev) return 0; } -static int silverstone_drv_remove(struct platform_device *pdev) +static int ds3000_drv_remove(struct platform_device *pdev) { int portid_count; struct sff_device_data *rem_data; @@ -1872,20 +2127,20 @@ static int silverstone_drv_remove(struct platform_device *pdev) return 0; } +static struct platform_driver ds3000_drv = { + .probe = ds3000_drv_probe, + .remove = __exit_p(ds3000_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + #ifdef TEST_MODE #define FPGA_PCI_BAR_NUM 2 #else #define FPGA_PCI_BAR_NUM 0 #endif -static struct platform_driver silverstone_drv = { - .probe = silverstone_drv_probe, - .remove = __exit_p(silverstone_drv_remove), - .driver = { - .name = DRIVER_NAME, - }, -}; - static const struct pci_device_id fpga_id_table[] = { { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) }, { PCI_VDEVICE(TEST, TEST_PCIE_DEVICE_ID) }, @@ -1934,11 +2189,15 @@ static int fpga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_INFO ""); fpga_version = ioread32(fpga_dev.data_base_addr); printk(KERN_INFO "FPGA VERSION : %8.8x\n", fpga_version); - fpgafw_init(); - platform_device_register(&silverstone_dev); - platform_driver_register(&silverstone_drv); + if ((err = fpgafw_init()) < 0) { + goto pci_unmap; + } + ds3000_dev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + platform_driver_register(&ds3000_drv); return 0; +pci_unmap: + pci_iounmap(pdev, fpga_dev.data_base_addr); pci_release: pci_release_regions(pdev); pci_disable: @@ -1948,8 +2207,8 @@ static int fpga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void fpga_pci_remove(struct pci_dev *pdev) { - platform_driver_unregister(&silverstone_drv); - platform_device_unregister(&silverstone_dev); + platform_driver_unregister(&ds3000_drv); + platform_device_unregister(ds3000_dev); fpgafw_exit(); pci_iounmap(pdev, fpga_dev.data_base_addr); pci_release_regions(pdev); @@ -1974,7 +2233,8 @@ struct fpga_reg_data { uint32_t value; }; -static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { +static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { int ret = 0; struct fpga_reg_data data; mutex_lock(&fpga_data->fpga_lock); @@ -2065,25 +2325,24 @@ static int fpgafw_init(void) { // Register the device driver fpgafwdev = device_create(fpgafwclass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME); - if (IS_ERR(fpgafwdev)) { // Clean up if there is an error + if (IS_ERR(fpgafwdev)) { // Clean up if there is an error class_destroy(fpgafwclass); // Repeated code but the alternative is goto statements unregister_chrdev(majorNumber, DEVICE_NAME); printk(KERN_ALERT "Failed to create the FW upgrade device node\n"); return PTR_ERR(fpgafwdev); } - printk(KERN_INFO "FPGA fw upgrade device node created correctly\n"); + printk(KERN_INFO "FPGA fw upgrade device node created correctly\n"); // Made it! device was initialized return 0; } static void fpgafw_exit(void) { device_destroy(fpgafwclass, MKDEV(majorNumber, 0)); // remove the device - class_unregister(fpgafwclass); // unregister the device class class_destroy(fpgafwclass); // remove the device class unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number printk(KERN_INFO "Goodbye!\n"); } -int silverstone_init(void) +int ds3000_init(void) { int rc; rc = pci_register_driver(&pci_dev_ops); @@ -2092,15 +2351,15 @@ int silverstone_init(void) return 0; } -void silverstone_exit(void) +void ds3000_exit(void) { pci_unregister_driver(&pci_dev_ops); } -module_init(silverstone_init); -module_exit(silverstone_exit); +module_init(ds3000_init); +module_exit(ds3000_exit); -MODULE_AUTHOR("Celestica Inc."); -MODULE_DESCRIPTION("Celestica Silverstone platform driver"); +MODULE_AUTHOR("Pradchaya P. "); +MODULE_DESCRIPTION("Celestica ds3000 switchboard driver"); MODULE_VERSION(MOD_VERSION); MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/setup.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/setup.py new file mode 100644 index 000000000000..02fcfff6aea1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/setup.py @@ -0,0 +1,28 @@ +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Celestica Platforms based on PDDF', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + packages=['sonic_platform'], + 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.9', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/__init__.py new file mode 100644 index 000000000000..21d9cd445e31 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/__init__.py @@ -0,0 +1,4 @@ +# All the derived classes for PDDF +__all__ = ["platform", "chassis", "sfp", "psu", "thermal"] +from . import platform +from . import chassis diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/chassis.py new file mode 100644 index 000000000000..00fe4a2457a2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/chassis.py @@ -0,0 +1,295 @@ +############################################################################# +# PDDF +# Module contains an implementation of SONiC Chassis API +# +############################################################################# + +try: + import os + import re + import shutil + import subprocess + from . import component + from .event import XcvrEvent + from .helper import APIHelper + from .thermal import ThermalMon, THERMAL_MONITOR_SENSORS + from sonic_py_common import logger + from sonic_platform_pddf_base.pddf_chassis import PddfChassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +RESET_SOURCE_OS_REG = '0xa106' +LPC_SYSLED_REG = '0xa162' +LPC_GETREG_PATH = "/sys/bus/platform/devices/baseboard/getreg" +LPC_SETREG_PATH = "/sys/bus/platform/devices/baseboard/setreg" +LED_CTRL_MODE_GET_CMD = "ipmitool raw 0x3a 0x42 0x01" + +ORG_HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +TMP_HW_REBOOT_CAUSE_FILE="/tmp/hw-reboot-cause.txt" + +SYSLOG_IDENTIFIER = "Chassis" +helper_logger = logger.Logger(SYSLOG_IDENTIFIER) + +class Chassis(PddfChassis): + """ + PDDF Platform-specific Chassis class + """ + SYSLED_COLOR_VAL_MAP = { + 'off': '0xff', + 'green': '0xdc', + 'amber': '0xec', + 'amber_blink': '0xee', + 'amber_blink_4hz': '0xee', + 'amber_blink_1hz': '0xed', + 'green_blink': '0xde', + 'green_blink_4hz': '0xde', + 'green_blink_1hz': '0xdd' + } + + SYSLED_VAL_COLOR_MAP = { + '0xff': 'off', + '0xdc': 'green', + '0xec': 'amber', + '0xee': 'amber_blink_4hz', + '0xed': 'amber_blink_1hz', + '0xde': 'green_blink_4hz', + '0xdd': 'green_blink_1hz' + } + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + PddfChassis.__init__(self, pddf_data, pddf_plugin_data) + self._api_helper = APIHelper() + + for index in range(self.platform_inventory['num_components']): + component_obj = component.Component(index) + self._component_list.append(component_obj) + + if not self._api_helper.is_bmc_present(): + thermal_count = len(self._thermal_list) + for idx, name in enumerate(THERMAL_MONITOR_SENSORS): + thermal = ThermalMon(thermal_count + idx, name) + self._thermal_list.append(thermal) + + def initizalize_system_led(self): + """ + This function is not defined in chassis base class, + system-health command would invoke chassis.initizalize_system_led(), + add this stub function just to let the command sucessfully execute + """ + pass + + def get_status_led(self): + """ + Gets the state of the system LED + Args: + None + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + led_status = self._api_helper.lpc_getreg(LPC_GETREG_PATH, LPC_SYSLED_REG) + color = self.SYSLED_VAL_COLOR_MAP.get(led_status, 'unknown') + return color + + 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 + """ + if self._api_helper.is_bmc_present(): + led_mode_cmd = LED_CTRL_MODE_GET_CMD + if os.getuid() != 0: + cmd = "sudo " + cmd + led_mode_cmd = "sudo " + led_mode_cmd + status, mode = self._api_helper.get_cmd_output(led_mode_cmd) + # led take automatic control mode, led not settable + if status != 0 or mode.strip() == "01": + helper_logger.log_info("SYS LED takes automatic ctrl mode!") + return False + + # Set SYS_LED through baseboard cpld + color_val = self.SYSLED_COLOR_VAL_MAP.get(color, None) + if color_val == None: + helper_logger.log_error("SYS LED color {} not support!".format(color)) + return False + + status = self._api_helper.lpc_setreg(LPC_SETREG_PATH, LPC_SYSLED_REG, color_val) + + return status + + def get_sfp(self, index): + """ + Retrieves sfp represented by (1-based) index + For Quanta the index in sfputil.py starts from 1, so override + Args: + index: An integer, the index (1-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 1. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + if (index == 0): + raise IndexError + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("override: SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + + return sfp + # Provide the functions/variables below for which implementation is to be overwritten + + 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. + """ + hw_reboot_cause = self._api_helper.lpc_getreg(LPC_GETREG_PATH, RESET_SOURCE_OS_REG) + + if hw_reboot_cause == "0x33" and os.path.isfile(TMP_HW_REBOOT_CAUSE_FILE): + with open(TMP_HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + description = 'CPU cold reset' + if match is not None: + if match.group(1) == 'system': + return (self.REBOOT_CAUSE_NON_HARDWARE, 'System cold reboot') + elif hw_reboot_cause == "0x99": + reboot_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC + description = 'ASIC Overload Reboot' + elif hw_reboot_cause == "0x88": + reboot_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU + description = 'CPU Overload Reboot' + elif hw_reboot_cause == "0x66": + reboot_cause = self.REBOOT_CAUSE_WATCHDOG + description = 'Hardware Watchdog Reset' + elif hw_reboot_cause == "0x55": + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'CPU Cold Reset' + elif hw_reboot_cause == "0x44": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'CPU Warm Reset' + elif hw_reboot_cause == "0x33": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'Soft-Set Cold Reset' + elif hw_reboot_cause == "0x22": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'Soft-Set Warm Reset' + elif hw_reboot_cause == "0x11": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power Off Reset' + elif hw_reboot_cause == "0x00": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power Cycle Reset' + else: + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Hardware reason' + + return (reboot_cause, description) + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + try: + if self._watchdog is None: + from sonic_platform.cpld_watchdog import Watchdog + # Create the watchdog Instance from cpld watchdog + self._watchdog = Watchdog() + + except Exception as e: + helper_logger.log_error("Fail to load watchdog due to {}".format(e)) + return self._watchdog + + ############################################################## + ###################### Event methods ######################### + ############################################################## + 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. + """ + # SFP event + if self.get_num_sfps() == 0: + for index in range(self.platform_inventory['num_ports']): + sfp = Sfp(index, self.pddf_obj, self.plugin_data) + self._sfp_list.append(sfp) + + succeed, sfp_event = XcvrEvent(self._sfp_list).get_xcvr_event(timeout) + if succeed: + return True, {'sfp': sfp_event} + + return False, {'sfp': {}} + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_revision(self): + """ + Retrieves the hardware revision for the chassis + Returns: + A string containing the hardware revision for this chassis. + """ + return self._eeprom.revision_str() + + def get_system_airflow(self): + """ + Retrieve system airflow + Returns: + string: INTAKE or EXHAUST + """ + airflow = self.get_serial()[5:8] + if airflow == "B2F": + return "INTAKE" + elif airflow == "F2B": + return "EXHAUST" + return "Unknown" + + def get_thermal_manager(self): + """ + Retrieves thermal manager class on this chasssis + + Returns: + A class derived from ThermalManagerBase representing the + specified thermal manager + """ + if not self._api_helper.is_bmc_present(): + from .thermal_manager import ThermalManager + return ThermalManager + return None diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/component.py new file mode 100644 index 000000000000..d6abdeb8c968 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/component.py @@ -0,0 +1,321 @@ +try: + import re + import subprocess + from .helper import APIHelper + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BMC_EXIST =APIHelper().is_bmc_present() +FPGA_VERSION_PATH = "/sys/bus/platform/devices/fpga_sysfs/version" +Bios_Version_Cmd = "dmidecode -t bios | grep Version" + +BIOS_VERSION_CMD = "dmidecode -s bios-version" +ONIE_VERSION_CMD = "cat /host/machine.conf" +SWCPLD1_VERSION_CMD = "i2cget -y -f 102 0x30 0x0 | tr a-z A-Z | cut -d 'X' -f 2" +SWCPLD2_VERSION_CMD = "i2cget -y -f 102 0x31 0x0 | tr a-z A-Z | cut -d 'X' -f 2" +BASECPLD_VERSION_CMD = "cat /sys/devices/platform/baseboard/version | tr a-z A-Z | cut -d 'X' -f 2" +COME_CPLD_VERSION_CMD = "cat /sys/devices/platform/baseboard/come_cpld_version | tr a-z A-Z | cut -d 'X' -f 2" +SSD_VERSION_CMD = "smartctl -i /dev/sda" +ASIC_PCIE_VERSION_CMD = "bcmcmd 'pciephy fw version' | grep 'PCIe FW version' | cut -d ' ' -f 4" + + +COMPONENT_NAME_LIST = ["BIOS", "ONIE", "BMC", "FPGA", "CPLD COMe", "CPLD BASE", + "CPLD SW1", "CPLD SW2", "ASIC PCIe", "SSD"] +COMPONENT_DES_LIST = ["Basic input/output System", + "Open Network Install Environment", + "Baseboard Management Controller", + "FPGA for transceiver EEPROM access and other component I2C access", + "COMe board CPLD", + "CPLD for board functions, fan control and watchdog", + "CPLD for port control QSFP(1-16)", + "CPLD for port control QSFP(17-32), SFP(33)", + "ASIC PCIe Firmware", + "Solid State Drive - {}"] + +UNKNOWN_VER = "Unknown" + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + ComponentBase.__init__(self) + self.index = component_index + self.helper = APIHelper() + self.name = self.get_name() + + def get_firmware_version(self): + """ + Retrieves the available firmware version of the component + + Note: the firmware version will be read from image + + Args: + image_path: A string, path to firmware image + + Returns: + A string containing the available firmware version of the component + """ + fw_version_info = { + "ONIE": self.__get_onie_ver(), + "SSD": self.__get_ssd_ver(), + "BIOS": self.__get_bios_ver(), + "FPGA": self.__get_fpga_version(), + "ASIC PCIe": self.__get_asic_pcie_ver(), + } + fw_version_info.update(self.__get_cpld_ver()) + if self.__get_bmc_presence(): + fw_version_info.update(self.__get_bmc_ver()) + return fw_version_info.get(self.name, UNKNOWN_VER) + + def get_firmware_update_notification(self, image_path): + """ + Retrieves a notification on what should be done in order to complete + the component firmware update + + Args: + image_path: A string, path to firmware image + + Returns: + A string containing the component firmware update notification if required. + By default 'None' value will be used, which indicates that no actions are required + """ + type = self.get_type() + if type == 'bios': + return "BIOS will be updated, please wait for completion and reboot the device to take effect!" + elif type == 'cpld' or type == 'fpga': + return "{} will be updated, please wait for completion and power reboot device to take effect!".format(type.upper()) + elif type == 'bmc': + return "BMC image will be updated, please wait for completion!" + return None + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + This API performs firmware installation only: this may/may not be the same as firmware update. + In case platform component requires some extra steps (apart from calling Low Level Utility) + to load the installed firmware (e.g, reboot, power cycle, etc.) - this must be done manually by user + + Note: in case immediate actions are required to complete the component firmware update + (e.g., reboot, power cycle, etc.) - will be done automatically by API and no return value provided + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + #if self.component_data == None: + self.component_data = self._get_component_data() + pre_cmd = self.component_data['pre-update'] + update_cmd = self.component_data['update'] + post_cmd = self.component_data['post-update'] + if pre_cmd != None: + status, _ = self._api_helper.get_cmd_output(pre_cmd) + if status != 0: + return False + if update_cmd != None: + update_cmd = update_cmd.format(image_path) + status, _ = self._api_helper.get_cmd_output(update_cmd) + if status != 0: + return False + if post_cmd != None: + status, _ = self._api_helper.get_cmd_output(post_cmd) + if status != 0: + return False + + return True + + def update_firmware(self, image_path): + """ + Updates firmware of the component + + This API performs firmware update: it assumes firmware installation and loading in a single call. + In case platform component requires some extra steps (apart from calling Low Level Utility) + to load the installed firmware (e.g, reboot, power cycle, etc.) - this will be done automatically by API + + Args: + image_path: A string, path to firmware image + + Returns: + Boolean False if image_path doesn't exist instead of throwing an exception error + Nothing when the update is successful + + Raises: + RuntimeError: update failed + """ + status = self.install_firmware(image_path) + if not status: + return status + + type = self.get_type() + if type == 'fpga' or type == 'cpld': + # TODO:: power cycle FPGA or CPLD + pass + + return True + + def auto_update_firmware(self, image_path, boot_type): + """ + Updates firmware of the component + + This API performs firmware update automatically based on boot_type: it assumes firmware installation + and/or creating a loading task during the reboot, if needed, in a single call. + In case platform component requires some extra steps (apart from calling Low Level Utility) + to load the installed firmware (e.g, reboot, power cycle, etc.) - this will be done automatically during the reboot. + The loading task will be created by API. + + Args: + image_path: A string, path to firmware image + boot_type: A string, reboot type following the upgrade + - none/fast/warm/cold + + Returns: + Output: A return code + return_code: An integer number, status of component firmware auto-update + - return code of a positive number indicates successful auto-update + - status_installed = 1 + - status_updated = 2 + - status_scheduled = 3 + - return_code of a negative number indicates failed auto-update + - status_err_boot_type = -1 + - status_err_image = -2 + - status_err_unknown = -3 + + Raises: + RuntimeError: auto-update failure cause + """ + raise NotImplementedError + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_NAME_LIST[self.index] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + # For SSD get the model name from device + if self.get_name() == "SSD": + return "Solid State Drive - {}".format(self.__get_ssd_model()) + + return COMPONENT_DES_LIST[self.index] + + def __get_cpld_ver(self): + cpld_version_dict = dict() + cpld_ver_info = { + 'CPLD BASE': self.__get_basecpld_ver(), + 'CPLD SW1': self.__get_swcpld1_ver(), + 'CPLD SW2': self.__get_swcpld2_ver(), + 'CPLD COMe': self.__get_comecpld_ver(), + } + + for cpld_name, cpld_ver in cpld_ver_info.items(): + ver1 = int(cpld_ver.strip()) / 10 + ver2 = int(cpld_ver.strip()) % 10 + version = "%d.%d" % (ver1,ver2) + cpld_version_dict[cpld_name] = version + return cpld_version_dict + + def __get_asic_pcie_ver(self): + status, raw_ver=self.helper.run_command(ASIC_PCIE_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_bios_ver(self): + status, raw_ver=self.helper.run_command(BIOS_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_basecpld_ver(self): + status, raw_ver=self.helper.run_command(BASECPLD_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_comecpld_ver(self): + status, raw_ver=self.helper.run_command(COME_CPLD_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_swcpld1_ver(self): + status, raw_ver=self.helper.run_command(SWCPLD1_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_swcpld2_ver(self): + status, raw_ver=self.helper.run_command(SWCPLD2_VERSION_CMD) + if status: + return raw_ver + else: + return UNKNOWN_VER + + def __get_bmc_presence(self): + if BMC_EXIST: + return True + else: + return False + + def __get_bmc_ver(self): + cmd="ipmitool mc info | grep 'Firmware Revision'" + status, raw_ver=self.helper.run_command(cmd) + if status: + bmc_ver=raw_ver.split(':')[-1].strip() + return {"BMC":bmc_ver} + else: + return {"BMC":"N/A"} + + def __get_fpga_version(self): + status, fpga_version = self.helper.run_command("cat %s" % FPGA_VERSION_PATH) + if not status: + return UNKNOWN_VER + return fpga_version.replace("0x", "") + + def __get_onie_ver(self): + onie_ver = "N/A" + status, raw_onie_data = self.helper.run_command(ONIE_VERSION_CMD) + if status: + ret = re.search(r"(?<=onie_version=).+[^\n]", raw_onie_data) + if ret != None: + onie_ver = ret.group(0) + return onie_ver + + def __get_ssd_ver(self): + ssd_ver = "N/A" + status, raw_ssd_data = self.helper.run_command(SSD_VERSION_CMD) + if status: + ret = re.search(r"Firmware Version: +(.*)[^\\]", raw_ssd_data) + if ret != None: + ssd_ver = ret.group(1) + return ssd_ver + + def __get_ssd_model(self): + model = "N/A" + + status, raw_ssd_data = self.helper.run_command(SSD_VERSION_CMD) + if status: + ret = re.search(r"Device Model: +(.*)[^\\]", raw_ssd_data) + if ret != None: + try: + model = ret.group(1) + except (IndexError): + pass + return model diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/cpld_watchdog.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/cpld_watchdog.py new file mode 100644 index 000000000000..7889ce15f83f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/cpld_watchdog.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python + +############################################################################# +# +# Watchdog contains an implementation of SONiC Platform Base Watchdog API +# +############################################################################# +try: + import ctypes + import fcntl + import os + import subprocess + import time + import array + import syslog + from .helper import APIHelper + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +LPC_CPLD_GETREG_PATH = "/sys/bus/platform/devices/baseboard/getreg" +LPC_CPLD_SETREG_PATH = "/sys/bus/platform/devices/baseboard/setreg" +LPC_WDT_SET_TIMER_L_REG = '0xa183' +LPC_WDT_SET_TIMER_M_REG = '0xa182' +LPC_WDT_SET_TIMER_H_REG = '0xa181' +LPC_WDT_TIMER_L_REG = '0xa186' +LPC_WDT_TIMER_M_REG = '0xa185' +LPC_WDT_TIMER_H_REG = '0xa184' +LPC_WDT_CTRL_REG = '0xa187' +LPC_WDT_ARM_REG = '0xa188' + +WDT_ENABLE = 0x1 +WDT_DISABLE = 0x0 +WDT_COMMON_ERROR = -1 +DEFAULT_TIMEOUT = 180 + +class CpldWatchdog(WatchdogBase): + + def __init__(self): + WatchdogBase.__init__(self) + # Set default value + self._api_helper = APIHelper() + self._ka_count = int(1) + self.armed = True if self._active() else False + self.timeout = self._gettimeout() if self.armed else DEFAULT_TIMEOUT + #self._disable() + + def _lpc_get(self, reg): + return self._api_helper.lpc_getreg(LPC_CPLD_GETREG_PATH, reg) + + def _lpc_set(self, reg, val): + if type(val) is int: + val = hex(val) + return self._api_helper.lpc_setreg(LPC_CPLD_SETREG_PATH, reg, val) + + def _active(self): + """ + WDT is active or not + """ + data = self._lpc_get(LPC_WDT_CTRL_REG) + return True if data == "0x01" else False + + def _enable(self): + """ + Turn on the watchdog timer + """ + status = self._lpc_set(LPC_WDT_CTRL_REG, WDT_ENABLE) + if not status: + pass + + def _disable(self): + """ + Turn off the watchdog timer + """ + status = self._lpc_set(LPC_WDT_CTRL_REG, WDT_DISABLE) + if not status: + pass + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + if bool(self._ka_count % 2): + status = self._lpc_set(LPC_WDT_ARM_REG, WDT_ENABLE) + else: + status = self._lpc_set(LPC_WDT_ARM_REG, WDT_DISABLE) + + if not status: + syslog.syslog(syslog.LOG_ERR, "Feed Watchdog failed") + + self._ka_count = self._ka_count + 1 + if (self._ka_count >= 11): + self._ka_count = 1 + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + ms = seconds * 1000 + ms_low_byte = ms & 0xff + ms_media_byte = (ms >> 8) & 0xff + ms_high_byte = (ms >> 16) & 0xff + self._lpc_set(LPC_WDT_SET_TIMER_L_REG, ms_low_byte) + self._lpc_set(LPC_WDT_SET_TIMER_M_REG, ms_media_byte) + self._lpc_set(LPC_WDT_SET_TIMER_H_REG, ms_high_byte) + return self._gettimeout() + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + data = [0, 0, 0] + data[0] = self._lpc_get(LPC_WDT_SET_TIMER_L_REG) + data[1] = self._lpc_get(LPC_WDT_SET_TIMER_M_REG) + data[2] = self._lpc_get(LPC_WDT_SET_TIMER_H_REG) + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + return seconds + + def _gettimeleft(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + data = [0, 0, 0] + data[0] = self._lpc_get(LPC_WDT_TIMER_L_REG) + data[1] = self._lpc_get(LPC_WDT_TIMER_M_REG) + data[2] = self._lpc_get(LPC_WDT_TIMER_H_REG) + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + + return seconds + + ################################################################# + + 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. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.armed: + self._keepalive() + if self.timeout != seconds: + self._disable() + time.sleep(1) + self.timeout = self._settimeout(seconds) + self._enable() + else: + self.timeout = self._settimeout(seconds) + self._keepalive() + self._enable() + self.armed = True + ret = self.timeout + except IOError as e: + pass + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + 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. + """ + + timeleft = WDT_COMMON_ERROR + + if self.armed: + try: + timeleft = self._gettimeleft() + except IOError: + pass + + return timeleft + +class Watchdog(CpldWatchdog): + """PDDF Platform-Specific Watchdog Class""" + + def __init__(self): + CpldWatchdog.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/eeprom.py new file mode 100644 index 000000000000..cb3c825516e7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/eeprom.py @@ -0,0 +1,84 @@ +try: + import os + from sonic_platform_pddf_base.pddf_eeprom import PddfEeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +EEPROM_TMP_FILE = '/tmp/eeprom_dump.bin' + +class Eeprom(PddfEeprom): + + _TLV_DISPLAY_VENDOR_EXT = True + _TLV_INFO_MAX_LEN = 256 + pddf_obj = {} + plugin_data = {} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + + # system EEPROM always has device name EEPROM1 + self.eeprom_path = self.pddf_obj.get_path("EEPROM1", "eeprom") + if self.eeprom_path is None: + return + + super(PddfEeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + if os.path.exists(EEPROM_TMP_FILE): + with open(EEPROM_TMP_FILE, 'rb') as b_fd: + self.eeprom_data = bytearray(b_fd.read()) + else: + self.eeprom_data = self.read_eeprom() + with open(EEPROM_TMP_FILE, 'wb') as b_fd: + b_fd.write(self.eeprom_data) + os.chmod(EEPROM_TMP_FILE, 0o444) + except Exception as e: + self.eeprom_data = "N/A" + raise RuntimeError("PddfEeprom is not Programmed - Error: {}".format(str(e))) + 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) < self._TLV_INFO_MAX_LEN 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: + name = "Vendor Extension" + value = "" + if self._TLV_DISPLAY_VENDOR_EXT: + for c in tlv[2:2 + tlv[1]]: + value += "0x%02X " % c + 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 + + + # Provide the functions/variables below for which implementation is to be overwritten + def revision_str(self): + (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + "N/A" + if type(results[2]) is bytearray: + return str(int.from_bytes(results[2], byteorder='little')) + + return results[2].decode('ascii') diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/event.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/event.py new file mode 100644 index 000000000000..86a1390cd6b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/event.py @@ -0,0 +1,52 @@ +try: + import time + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(repr(e) + " - required module not found") + +class XcvrEvent: + ''' Listen to insert/remove QSFP/SFP+ events ''' + + def __init__(self, sfp_list): + self._sfp_list = sfp_list + self._logger = Logger() + + xcvr_change_event_data = {'valid': 0, 'last': 0, 'present': 0} + + def get_xcvr_event(self, timeout): + port_dict = {} + + # Using polling mode + now = time.time() + + if timeout < 1000: + timeout = 1000 + timeout = timeout / float(1000) # Convert to secs + + if now < (self.xcvr_change_event_data['last'] + timeout) \ + and self.xcvr_change_event_data['valid']: + return True, port_dict + + bitmap = 0 + for sfp in self._sfp_list: + modpres = sfp.get_presence() + index = sfp.port_index - 1 + if modpres: + bitmap = bitmap | (1 << index) + + changed_ports = self.xcvr_change_event_data['present'] ^ bitmap + if changed_ports: + for sfp in self._sfp_list: + index = sfp.port_index - 1 + if changed_ports & (1 << index): + if (bitmap & (1 << index)) == 0: + port_dict[str(index + 1)] = '0' + else: + port_dict[str(index + 1)] = '1' + + # Update the cache dict + self.xcvr_change_event_data['present'] = bitmap + self.xcvr_change_event_data['last'] = now + self.xcvr_change_event_data['valid'] = 1 + + return True, port_dict diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan.py new file mode 100644 index 000000000000..e50a7d70e2e6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan.py @@ -0,0 +1,246 @@ +import os + +try: + from .helper import APIHelper + from sonic_platform_pddf_base.pddf_fan import PddfFan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SET_FAN_STATUS_LED_CMD = "0x3A 0x39 0x02 {} {}" +BMC_EXIST = APIHelper().is_bmc_present() + +class Fan(PddfFan): + """PDDF Platform-Specific Fan class""" + + BMC_FAN_FSC_STATUS_CMD = "ipmitool raw 0x3a 0x26 0x00" + LPC_CPLD_SETREG_PATH = "/sys/bus/platform/devices/baseboard/setreg" + FAN_PWM_CTRL_REG_MAP = { + 1: '0xa1b2', + 2: '0xa1b8', + 3: '0xa1c4', + 4: '0xa1ca' + } + + def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): + # idx is 0-based + PddfFan.__init__(self, tray_idx, fan_idx, pddf_data, pddf_plugin_data, is_psu_fan, psu_index) + self._api_helper = APIHelper() + + def get_presence(self): + """ + Retrieves the presence of fan + """ + if self.is_psu_fan: + return super().get_presence() + return super().get_presence() + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + Or N/A if fan removed or abnormal + """ + if not self.get_status(): + return "N/A" + + if self.is_psu_fan: + from sonic_platform.psu import Psu + psu = Psu(self.fans_psu_index - 1, self.pddf_obj, self.plugin_data) + model = psu.get_model() + if model in ["FSP550-20FM", "G1251-0550WNA"]: + return "EXHAUST" + elif model in ["FSP550-29FM", "G1251-0550WRA"]: + return "INTAKE" + return "Unknown" + + return super().get_direction() + + + 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) + """ + target_speed = 0 + if self.is_psu_fan: + # PSU fan not controllable, return current speed + return self.get_speed() + else: + speed_rpm = self.get_speed_rpm() + if self.fan_index == 1: + if(self.plugin_data['FAN']['FRONT_FAN_MAX_RPM_SPEED'].isnumeric()): + max_fan_rpm = int(self.plugin_data['FAN']['FRONT_FAN_MAX_RPM_SPEED']) + else: + return target_speed + else: + if(self.plugin_data['FAN']['REAR_FAN_MAX_RPM_SPEED'].isnumeric()): + max_fan_rpm = int(self.plugin_data['FAN']['REAR_FAN_MAX_RPM_SPEED']) + else: + return target_speed + speed_percentage = round(int((speed_rpm * 100) / max_fan_rpm)) + target_speed = speed_percentage + + return target_speed + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan: + attr = "psu_fan{}_speed_rpm".format(self.fan_index) + device = "PSU{}".format(self.fans_psu_index) + output = self.pddf_obj.get_attr_name_output(device, attr) + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(float(output['status'])) + + max_speed = int(self.plugin_data['PSU']['PSU_FAN_MAX_SPEED']) + speed_percentage = round((speed*100)/max_speed) + return speed_percentage if speed_percentage <= 100 else 100 + else: + # Get fan rpm instead of fan pwm + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_input" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) + + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(float(output['status'])) + + if self.fan_index == 1: + max_speed = int(self.plugin_data['FAN']['FRONT_FAN_MAX_RPM_SPEED']) + else: + max_speed = int(self.plugin_data['FAN']['REAR_FAN_MAX_RPM_SPEED']) + speed_percentage = round((speed*100)/max_speed) + + return speed_percentage if speed_percentage <= 100 else 100 + + def set_speed(self, speed): + """ + Sets the fan speed + + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + + Returns: + A boolean, True if speed is set successfully, False if not + """ + if self.is_psu_fan: + print("Setting PSU fan speed is not allowed") + return False + + if speed < 0 or speed > 100: + print("Error: Invalid speed %d. Please provide a valid speed percentage" % speed) + return False + + if 'duty_cycle_to_pwm' not in self.plugin_data['FAN']: + print("Setting fan speed is not allowed !") + return False + + if(self.plugin_data['FAN']['duty_cycle_to_pwm'].isnumeric()) + duty_cycle_to_pwm = int(self.plugin_data['FAN']['duty_cycle_to_pwm']) + else: + return False + pwm = int(round(duty_cycle_to_pwm(speed))) + + if self._api_helper.is_bmc_present(): + status, data = self._api_helper.get_cmd_output(self.BMC_FAN_FSC_STATUS_CMD) + if status != 0: + print("Error: failed to get BMC FSC status") + return False + if data == '01': + # Enable BMC FSC mode + return False + + # FAN 1 & 2 in same fantray share the same register, skip Fan2 setting + if self.fan_index == 2: + return True + # Set FAN PWM through baseboard CPLD + reg = self.FAN_PWM_CTRL_REG_MAP.get(self.fantray_index) + status = self._api_helper.lpc_setreg(self.LPC_CPLD_SETREG_PATH, reg, hex(pwm)) + + return status + + 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 + """ + return 15 if "PSU" in self.get_name() else 25 + + def is_under_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_min_th = target_speed * (1 - float(speed_tolerance) / 100) + if speed < speed_min_th: + return True + else: + return False + + def is_over_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_max_th = target_speed * (1 + float(speed_tolerance) / 100) + if speed > speed_max_th: + return True + else: + return False + + def set_status_led(self,color): + if self.is_psu_fan: + return super().set_status_led(color) + + if color == self.get_status_led(): + return False + + if BMC_EXIST: + fan_led_color_map = { + 'off': '00', + 'green': '01', + 'amber': '02', + 'red': '02' + } + + fan_index_val = hex(self.fantray_index + 3) + + color_val = fan_led_color_map.get(color.lower(), None) + + if fan_index_val is None: + return False + + if color_val is None: + return False + + status, _ = self._api_helper.ipmi_raw(SET_FAN_STATUS_LED_CMD.format(fan_index_val,color_val)) + + return status + else: + return self.set_system_led("SYS_LED", color) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..3b582835accd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/fan_drawer.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + + +try: + from sonic_platform_pddf_base.pddf_fan_drawer import PddfFanDrawer +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(PddfFanDrawer): + """PDDF Platform-Specific Fan-Drawer class""" + + def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None): + # idx is 0-based + PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten + def get_presence(self): + status = False + # Usually if a tray is removed, all the fans inside it are absent + if self._fan_list and len(self._fan_list) == 2: + status = self._fan_list[0].get_presence() or self._fan_list[1].get_presence() + else: + status = self._fan_list[0].get_presence() + return status + + def get_name(self): + return "Fantray {0}".format(self.fantray_index) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/helper.py new file mode 100644 index 000000000000..7ec1f23e950c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/helper.py @@ -0,0 +1,139 @@ +import fcntl +import os +import struct +import subprocess +from mmap import * + +BMC_PRES_SYS_PATH = '/sys/bus/platform/devices/baseboard/bmc_presence' + +class APIHelper(): + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except: + status = False + return status, result + + def get_cmd_output(self, cmd): + status = 0 + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = ret + + return status, data + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def read_one_line_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def lpc_getreg(self, getreg_path, reg): + """ + Get the cpld reg through lpc interface + + Args: + getreg_path: getreg sysfs path + reg: 16 bits reg addr in hex str format + + Returns: + A str, register value in hex str format + """ + file = open(getreg_path, 'w+') + # Acquire an exclusive lock on the file + fcntl.flock(file, fcntl.LOCK_EX) + + try: + file.write(reg) + file.flush() + + # Seek to the beginning of the file + file.seek(0) + + # Read the content of the file + result = file.readline().strip() + finally: + # Release the lock and close the file + fcntl.flock(file, fcntl.LOCK_UN) + file.close() + + return result + + def lpc_setreg(self, setreg_path, reg, val): + """ + Set the cpld reg through lpc interface + + Args: + setreg_path: setreg sysfs path + reg: 16 bits reg addr in hex str format + val: 8 bits register value in hex str format + + Returns: + A boolean, True if speed is set successfully, False if not + """ + status = True + file = open(setreg_path, 'w') + # Acquire an exclusive lock on the file + fcntl.flock(file, fcntl.LOCK_EX) + + try: + data = "{} {}".format(reg, val) + file.write(data) + file.flush() + except: + status = False + finally: + # Release the lock and close the file + fcntl.flock(file, fcntl.LOCK_UN) + file.close() + + return status + + def is_bmc_present(self): + """ + Get the BMC card present status + + Returns: + A boolean, True if present, False if absent + """ + presence = self.read_txt_file(BMC_PRES_SYS_PATH) + if presence == None: + print("Failed to get BMC card presence status") + return True if presence == "present" else False + + def run_command(self,cmd): + status = True + result = "" + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/pcie.py new file mode 100644 index 000000000000..6c01e694fdb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/pcie.py @@ -0,0 +1,10 @@ +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Pcie(PcieUtil): + """Celestica Platform-specific PCIe class""" + + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/platform.py new file mode 100644 index 000000000000..8595e80692df --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/platform.py @@ -0,0 +1,23 @@ +############################################################################# +# PDDF +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + from sonic_platform_pddf_base.pddf_platform import PddfPlatform +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PddfPlatform): + """ + PDDF Platform-Specific Platform Class + """ + + def __init__(self): + PddfPlatform.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/psu.py new file mode 100644 index 000000000000..27ea301e307a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/psu.py @@ -0,0 +1,49 @@ +try: + from sonic_platform_pddf_base.pddf_psu import PddfPsu + from .helper import APIHelper +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +LPC_GETREG_PATH = "/sys/bus/platform/devices/baseboard/getreg" +LPC_PSU_STATUS_REG = '0xa160' +LPC_PSU_POWER_STATUS_OFFSET = 0 +LPC_PSU_PRES_STATUS_OFFSET = 2 + +class Psu(PddfPsu): + """PDDF Platform-Specific PSU class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) + self._api_helper = APIHelper() + + # Provide the functions/variables below for which implementation is to be overwritten + def get_capacity(self): + return 550 + + def get_type(self): + return 'AC' + + def get_revision(self): + """ + Retrieves the revision of the device + Returns: + string: revision of device + """ + if not self.get_presence(): + return 'N/A' + + if self._api_helper.is_bmc_present(): + cmd = "ipmitool fru list {} | grep 'Product Version'".format(5 - self.psu_index) + status, output = self._api_helper.get_cmd_output(cmd) + if status == 0: + rev = output.split()[-1] + return rev + else: + # Get the revision information from FRU + cmd = "i2cget -y -f {} {} 0x2d w".format(42 + self.psu_index - 1, hex(0x52 + self.psu_index - 1)) + status, output = self._api_helper.get_cmd_output(cmd) + if status == 0: + rev = bytes.fromhex(output.strip('0x')).decode('utf-8') + # swap to change the endian difference + return rev[::-1] + return 'N/A' diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/sfp.py new file mode 100644 index 000000000000..5f88fb99704b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/sfp.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python + +try: + import ast + import syslog + import time + from multiprocessing import Lock + from sonic_platform_pddf_base.pddf_sfp import PddfSfp + from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CmisApi +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class Sfp(PddfSfp): + """ + PDDF Platform-Specific Sfp class + """ + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + self.eeprom_lock = Lock() + + # Provide the functions/variables below for which implementation is to be overwritten + # Add reties to work around FPGAPCI 0050/eeprom: offset 0x0: sometimes read failed + 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 + """ + buf = None + eeprom_raw = [] + sysfs_sfp_i2c_client_eeprom_path = self.eeprom_path + + if not self.get_presence(): + return None + + sysfsfile_eeprom = None + attempts = 0 + max_retries = 5 + success = False + while attempts < max_retries and not success: + try: + if attempts > 0: + time.sleep(0.2) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "rb", 0) + sysfsfile_eeprom.seek(offset) + buf = sysfsfile_eeprom.read(num_bytes) + success = True + except Exception as ex: + attempts += 1 + # Eliminate the redundant errors by showing errors only for lower page and page 0 + if attempts == max_retries: + if offset < 256: + syslog.syslog(syslog.LOG_INFO, "port {0}: {1}: offset {2}: read reach retry limit, refer to last eeprom cache".format(self.port_index, sysfs_sfp_i2c_client_eeprom_path, hex(offset))) + return None + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + + if buf is None: + return None + + for x in buf: + eeprom_raw.append(x) + + while len(eeprom_raw) < num_bytes: + eeprom_raw.append(0) + return bytes(eeprom_raw) + + # Read out any bytes from any offset + 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 + """ + self.eeprom_lock.acquire() + bytes = self.__read_eeprom(offset, num_bytes) + self.eeprom_lock.release() + return bytes + + def get_presence(self): + presence = PddfSfp.get_presence(self) + if not presence and self._xcvr_api != None: + self._xcvr_api = None + + return presence + + def get_xcvr_api(self): + if self._xcvr_api is None and self.get_presence(): + self.refresh_xcvr_api() + + # Find and update the right optoe driver + api_to_driver_map = {\ + 'Sff8636Api': 'optoe1',\ + 'Sff8472Api': 'optoe2',\ + 'CmisApi': 'optoe3',\ + 'CCmisApi': 'optoe3',\ + 'Sff8436Api': 'sff8436'\ + } + create_dev = False + path_list = self.eeprom_path.split('/') + name_path = '/'.join(path_list[:-1]) + '/name' + del_dev_path = '/'.join(path_list[:-2]) + '/delete_device' + new_dev_path = '/'.join(path_list[:-2]) + '/new_device' + api_name = type(self._xcvr_api).__name__ + new_driver = api_to_driver_map.get(api_name, 'optoe1') + + try: + with open(name_path, 'r') as fd: + cur_driver = fd.readline().strip() + except FileNotFoundError: + create_dev = True + else: + if cur_driver != new_driver: + with open(del_dev_path, 'w') as fd: + fd.write("0x50") + create_dev = True + + if create_dev: + with open(new_dev_path, 'w') as fd: + fd.write("{} 0x50".format(new_driver)) + + if api_name == 'Sff8636Api' or \ + api_name == 'Sff8436Api': + self.write_eeprom(93,1,bytes([0x04])) + + return self._xcvr_api + + def get_platform_media_key(self, transceiver_dict, port_speed, lane_count): + api = self.get_xcvr_api() + api_name = type(api).__name__ + if api_name in ['CmisApi', 'CCmisApi']: + is_cmis = True + else: + is_cmis = False + + # Per lane speed + media_key = str(int(port_speed / lane_count)) + if is_cmis: + media_compliance_code = transceiver_dict['specification_compliance'] + if 'copper' in media_compliance_code: + media_len = transceiver_dict['cable_length'] + media_key += '-copper-' + str(media_len) + 'M' + else: + media_key += '-optical' + else: + media_compliance_dict = ast.literal_eval(transceiver_dict['specification_compliance']) + eth_compliance_str = '10/40G Ethernet Compliance Code' + ext_compliance_str = 'Extended Specification Compliance' + media_compliance_code = '' + if eth_compliance_str in media_compliance_dict: + media_compliance_code = media_compliance_dict[eth_compliance_str] + if ext_compliance_str in media_compliance_dict: + media_compliance_code = media_compliance_code + ' ' + media_compliance_dict[ext_compliance_str] + if 'CR' in media_compliance_code or "copper" in transceiver_dict['specification_compliance'].lower(): + media_len = transceiver_dict['cable_length'] + media_key += '-copper-' + str(media_len) + 'M' + else: + media_key += '-optical' + + return {\ + 'vendor_key': '',\ + 'media_key': media_key,\ + 'lane_speed_key': ''\ + } diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal.py new file mode 100644 index 000000000000..ac73015d1ea3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal.py @@ -0,0 +1,56 @@ +try: + from sonic_platform_pddf_base.pddf_thermal import PddfThermal + from sonic_platform_base.thermal_base import ThermalBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +SENSORS_LOW_THRESHOLD_MAP = {"Base_Temp_U5": -5, "Base_Temp_U56": -5, + "Switch_Temp_U28": -5, "Switch_Temp_U29": -5} + +class Thermal(PddfThermal): + """PDDF Platform-Specific Thermal class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): + PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index) + + # Provide the functions/variables below for which implementation is to be overwritten + + def get_high_threshold(self): + if self.is_psu_thermal: + device = "PSU{}".format(self.thermals_psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_temp1_high_threshold") + if not output: + return None + + temp1 = output['status'] + # temperature returned is in milli celcius + return float(temp1)/1000 + else: + return super().get_high_threshold() + + def get_low_threshold(self): + low_threshold = SENSORS_LOW_THRESHOLD_MAP.get(self.get_name(), None) + if low_threshold != None: + return low_threshold + return super().get_low_threshold() + + +BCM_TEMP_GET_CMD = "cat /sys/devices/platform/fpga_sysfs/bcm_temp" +THERMAL_MONITOR_SENSORS = ["CPU_Temp", "BCM_SW_Temp", "VDD_CORE_Temp", "VDD_ANLG_Temp"] +THERMAL_THRESHOLDS = { "CPU_Temp": { "high_threshold": 89, "low_threshold": 'N/A', "high_crit_threshold": 93, + "temp_cmd": "r=$(cat /sys/class/thermal/thermal_zone1/temp) && printf '%.1f' $(($r / 1000))" }, + "BCM_SW_Temp": { "high_threshold": 110, "low_threshold": 'N/A', "high_crit_threshold": 120, + "temp_cmd": "r=$(cat /sys/devices/platform/fpga_sysfs/bcm_temp) && printf '%.1f' $(((434100 - ((12500000 / $r - 1) * 535) + 5000) / 1000))"}, + "VDD_CORE_Temp": { "high_threshold": 120, "low_threshold": 'N/A', "high_crit_threshold": 'N/A', + "temp_cmd": "r=$(cat /sys/class/hwmon/hwmon45/temp1_input) && printf '%.1f' $(($r / 1000))" }, + "VDD_ANLG_Temp": { "high_threshold": 120, "low_threshold": 'N/A', "high_crit_threshold": 'N/A', + "temp_cmd": "r=$(cat /sys/class/hwmon/hwmon44/temp1_input) && printf '%.1f' $(($r / 1000))" }} + +class ThermalMon(ThermalBase): + def __init__(self, index, name): + self.thermal_index = index + 1 + self.thermal_name = name + self._helper = APIHelper() + diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_actions.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_actions.py new file mode 100644 index 000000000000..8be043d94310 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_actions.py @@ -0,0 +1,341 @@ +from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object +from .helper import APIHelper + +from sonic_py_common import logger + +sonic_logger = logger.Logger('thermal_actions') + + +class SetFanSpeedAction(ThermalPolicyActionBase): + """ + Base thermal action class to set speed for fans + """ + # JSON field definition + JSON_FIELD_SPEED = 'speed' + + def __init__(self): + """ + Constructor of SetFanSpeedAction + """ + self.default_speed = 50 + self.hightemp_speed = 100 + self.speed = self.default_speed + + def load_from_json(self, json_obj): + """ + Construct SetFanSpeedAction via JSON. JSON example: + { + "type": "fan.all.set_speed" + "speed": "100" + } + :param json_obj: A JSON object representing a SetFanSpeedAction action. + :return: + """ + if SetFanSpeedAction.JSON_FIELD_SPEED in json_obj: + speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + if speed < 0 or speed > 100: + raise ValueError('SetFanSpeedAction invalid speed value {} in JSON policy file, valid value should be [0, 100]'. + format(speed)) + self.speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + else: + raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. + format(SetFanSpeedAction.JSON_FIELD_SPEED)) + + @classmethod + def set_all_fan_speed(cls, thermal_info_dict, speed): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME] + for fan in fan_info_obj.get_all_fans(): + fan.set_speed(int(speed)) + + +@thermal_json_object('fan.all.set_speed') +class SetAllFanSpeedAction(SetFanSpeedAction): + """ + Action to set speed for all fans + """ + def execute(self, thermal_info_dict): + """ + Set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + SetAllFanSpeedAction.set_all_fan_speed(thermal_info_dict, self.speed) + + +class LinearFanController(): + """ + Common Linear FAN Controller for B2F and F2B + """ + def __init__(self, low_temp, high_temp, hyst_temp, low_pwm, high_pwm): + self._low_temp = low_temp + self._high_temp = high_temp + self._hyst_temp = hyst_temp + self._low_pwm = low_pwm + self._high_pwm = high_pwm + self._linear_slope = (high_pwm - low_pwm) / (high_temp - low_temp) + self._last_pwm = None + + def calc_fan_speed(self, thermal_data): + temp = thermal_data.curr_temp + descend = thermal_data.temp_descend + + low_temp = self._low_temp - self._hyst_temp if descend else self._low_temp + high_temp = self._high_temp - self._hyst_temp if descend else self._high_temp + if temp <= low_temp: + sonic_logger.log_debug("[LinearController] temp: {} equal or lower than low temp: {}, set to lowest pwm: {}".format(temp, low_temp, self._low_pwm)) + self._last_pwm = self._low_pwm + return self._low_pwm + elif temp >= high_temp: + sonic_logger.log_debug("[LinearController] temp: {} equal or higher than high temp: {}, set to highest pwm: {}".format(temp, high_temp, self._high_pwm)) + self._last_pwm = self._high_pwm + return self._high_pwm + else: + pwm = float(self._linear_slope * (temp - low_temp) + self._low_pwm) + if descend: + if self._last_pwm != None and pwm > self._last_pwm: + pwm = self._last_pwm + else: + if self._last_pwm != None and pwm < self._last_pwm: + pwm = self._last_pwm + self._last_pwm = pwm + sonic_logger.log_debug("[LinearController] temp: {}, slope: {}, low_temp: {}, low_pwm: {}, set to pwm: {}".format(temp, self._linear_slope, low_temp, self._low_pwm, pwm)) + return pwm + +class PIDFanController(): + """ + Common FAN PID controller for CPU and BCM Temp + """ + MAX_SPEED = 255 + MIN_SPEED = 89 + def __init__(self, setpoint, p_val, i_val, d_val): + self._setpoint = setpoint + self._p = p_val + self._i = i_val + self._d = d_val + self._curr_speed = self.MIN_SPEED + + def calc_fan_speed(self, thermal_data): + hist2_temp = thermal_data.hist2_temp + hist1_temp = thermal_data.hist1_temp + temp = thermal_data.curr_temp + + if hist2_temp == None or hist1_temp == None: + return round(self._curr_speed / 2.55) + speed = self._curr_speed + self._p * (temp - hist1_temp) \ + + self._i * (temp - self._setpoint) + self._d * (temp - 2 * hist1_temp + hist2_temp) + if speed > self.MAX_SPEED: + speed = self.MAX_SPEED + elif speed < self.MIN_SPEED: + speed = self.MIN_SPEED + self._curr_speed = speed + speed_percent = float(speed / 2.55) + sonic_logger.log_debug("[PIDController] setpoint: {} p: {} i: {} d: {}, temp: {} hist_temp1: {} hist_temp2: {}, pwm: {}, percent: {}".format(self._setpoint, self._p, self._i, self._d, temp, hist1_temp, hist2_temp, speed, speed_percent)) + return speed_percent + + +@thermal_json_object('thermal.temp_check_and_fsc_algo_control') +class ThermalAlgorithmAction(SetFanSpeedAction): + """ + Action to check thermal sensor temperature change status and set speed for all fans + """ + THERMAL_LOG_LEVEL = "thermal_log_level" + CPU_PID_PARAMS = "cpu_pid_params" + BCM_PID_PARAMS = "bcm_pid_params" + F2B_LINEAR_PARAMS = "f2b_linear_params" + B2F_LINEAR_PARAMS = "b2f_linear_params" + + def __init__(self): + SetFanSpeedAction.__init__(self) + self.sys_airflow = None + self.cpu_pid_params = None + self.bcm_pid_params = None + self.f2b_linear_params = None + self.b2f_linear_params = None + self.cpu_fan_controller = None + self.bcm_fan_controller = None + self.linear_fan_controller = None + + def load_from_json(self, json_obj): + """ + Construct ThermalAlgorithmAction via JSON. JSON example: + { + "type": "thermal.temp_check_and_fsc_algo_control", + "cpu_pid_params": [82, 3, 0.5, 0.2], + "bcm_pid_params": [88, 4, 0.3, 0.4], + "f2b_linear_params": [34, 54, 3, 35, 100], + "b2f_linear_params": [28, 48, 3, 35, 100] + } + :param json_obj: A JSON object representing a ThermalAlgorithmAction action. + :return: + """ + if self.THERMAL_LOG_LEVEL in json_obj: + thermal_log_level = json_obj[self.THERMAL_LOG_LEVEL] + if not isinstance(thermal_log_level, int) or thermal_log_level not in range(0,8): + raise ValueError('ThermalAlgorithmAction invalid thermal log level, a interger in range 0-7 is required') + sonic_logger.set_min_log_priority(thermal_log_level) + if self.CPU_PID_PARAMS in json_obj: + cpu_pid_params = json_obj[self.CPU_PID_PARAMS] + if not isinstance(cpu_pid_params, list) or len(cpu_pid_params) != 4: + raise ValueError('ThermalAlgorithmAction invalid SetPoint PID {} in JSON policy file, valid value should be [point, p, i, d]'. + format(cpu_pid_params)) + self.cpu_pid_params = cpu_pid_params + else: + raise ValueError('ThermalAlgorithmAction missing mandatory field [setpoint, p, i, d] in JSON policy file') + + if self.BCM_PID_PARAMS in json_obj: + bcm_pid_params = json_obj[self.BCM_PID_PARAMS] + if not isinstance(bcm_pid_params, list) or len(bcm_pid_params) != 4: + raise ValueError('ThermalAlgorithmAction invalid SetPoint PID {} in JSON policy file, valid value should be [point, p, i, d]'. + format(bcm_pid_params)) + self.bcm_pid_params = bcm_pid_params + else: + raise ValueError('ThermalAlgorithmAction missing mandatory field [setpoint, p, i, d] in JSON policy file') + + if self.F2B_LINEAR_PARAMS in json_obj: + f2b_linear_params = json_obj[self.F2B_LINEAR_PARAMS] + if not isinstance(f2b_linear_params, list) or len(f2b_linear_params) != 5: + raise ValueError('ThermalAlgorithmAction invalid SetPoint PID {} in JSON policy file, valid value should be [point, p, i, d]'. + format(f2b_linear_params)) + self.f2b_linear_params = f2b_linear_params + else: + raise ValueError('ThermalAlgorithmAction missing mandatory field [low_temp, high_temp, hyst_temp, low_pwm, high_pwm] in JSON policy file') + + if self.B2F_LINEAR_PARAMS in json_obj: + b2f_linear_params = json_obj[self.B2F_LINEAR_PARAMS] + if not isinstance(b2f_linear_params, list) or len(b2f_linear_params) != 5: + raise ValueError('ThermalAlgorithmAction invalid SetPoint PID {} in JSON policy file, valid value should be [point, p, i, d]'. + format(b2f_linear_params)) + self.b2f_linear_params = b2f_linear_params + else: + raise ValueError('ThermalAlgorithmAction missing mandatory field [low_temp, high_temp, hyst_temp, low_pwm, high_pwm] in JSON policy file') + + sonic_logger.log_info("[ThermalAlgorithmAction] cpu_pid: {}, bcm_pid: {}, f2b_linear: {}, b2f_linear: {}".format(self.cpu_pid_params, self.bcm_pid_params, self.f2b_linear_params, self.b2f_linear_params)) + + def execute(self, thermal_info_dict): + """ + Check check thermal sensor temperature change status and set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + if self.sys_airflow == None: + from .thermal_infos import ChassisInfo + if ChassisInfo.INFO_NAME in thermal_info_dict: + chassis_info_obj = thermal_info_dict[ChassisInfo.INFO_NAME] + chassis = chassis_info_obj.get_chassis() + self.sys_airflow = chassis.get_system_airflow() + + if self.cpu_fan_controller == None: + self.cpu_fan_controller = PIDFanController(self.cpu_pid_params[0], self.cpu_pid_params[1], + self.cpu_pid_params[2], self.cpu_pid_params[3]) + if self.bcm_fan_controller == None: + self.bcm_fan_controller = PIDFanController(self.bcm_pid_params[0], self.bcm_pid_params[1], + self.bcm_pid_params[2], self.bcm_pid_params[3]) + if self.linear_fan_controller == None: + if self.sys_airflow == 'INTAKE': + linear_params = self.b2f_linear_params + else: + linear_params = self.f2b_linear_params + self.linear_fan_controller = LinearFanController(linear_params[0], linear_params[1], linear_params[2], \ + linear_params[3], linear_params[4]) + + from .thermal_infos import ThermalInfo + if ThermalInfo.INFO_NAME in thermal_info_dict and \ + isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo): + + thermal_info_obj = thermal_info_dict[ThermalInfo.INFO_NAME] + thermals_data = thermal_info_obj.get_thermals_data() + cpu_thermal_data = thermals_data["CPU_Temp"] + cpu_fan_pwm = self.cpu_fan_controller.calc_fan_speed(cpu_thermal_data) + bcm_thermal_data = thermals_data["BCM_SW_Temp"] + bcm_fan_pwm = self.bcm_fan_controller.calc_fan_speed(bcm_thermal_data) + if self.sys_airflow == 'INTAKE': + thermal_data = thermals_data["Base_Temp_U5"] + linear_fan_pwm1 = self.linear_fan_controller.calc_fan_speed(thermal_data) + thermal_data = thermals_data["Base_Temp_U56"] + linear_fan_pwm2 = self.linear_fan_controller.calc_fan_speed(thermal_data) + else: + thermal_data = thermals_data["Switch_Temp_U28"] + linear_fan_pwm1 = self.linear_fan_controller.calc_fan_speed(thermal_data) + thermal_data = thermals_data["Switch_Temp_U29"] + linear_fan_pwm2 = self.linear_fan_controller.calc_fan_speed(thermal_data) + target_fan_pwm = max(cpu_fan_pwm, bcm_fan_pwm, linear_fan_pwm1, linear_fan_pwm2) + sonic_logger.log_info("[ThermalAlgorithmAction] cpu_pid_pwm: {}, bcm_pid_pwm: {}, linear_fan_pwm: {}, linear_fan_pwm2: {}, target_pwm: {}".format(cpu_fan_pwm, bcm_fan_pwm, linear_fan_pwm1, linear_fan_pwm2, target_fan_pwm)) + SetAllFanSpeedAction.set_all_fan_speed(thermal_info_dict, round(target_fan_pwm)) + + +@thermal_json_object('switch.shutdown') +class SwitchPolicyAction(ThermalPolicyActionBase): + """ + Base class for thermal action. Once all thermal conditions in a thermal policy are matched, + all predefined thermal action will be executed. + """ + def execute(self, thermal_info_dict): + """ + Take action when thermal condition matches. For example, adjust speed of fan or shut + down the switch. + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + sonic_logger.log_warning("Alarm for temperature critical is detected, shutdown Device") + # Wait for 30s then shutdown + import time + time.sleep(30) + # Power off COMe through CPLD + CPLD_POWRE_OFF_CMD = "echo 0xa120 0xfc > /sys/bus/platform/devices/baseboard/setreg" + api_helper = APIHelper() + api_helper.get_cmd_output(CPLD_POWER_OFF_CMD) + + +@thermal_json_object('thermal_control.control') +class ControlThermalAlgoAction(ThermalPolicyActionBase): + """ + Action to control the thermal control algorithm + """ + # JSON field definition + JSON_FIELD_STATUS = 'status' + + def __init__(self): + self.status = True + + def load_from_json(self, json_obj): + """ + Construct ControlThermalAlgoAction via JSON. JSON example: + { + "type": "thermal_control.control" + "status": "true" + } + :param json_obj: A JSON object representing a ControlThermalAlgoAction action. + :return: + """ + if ControlThermalAlgoAction.JSON_FIELD_STATUS in json_obj: + status_str = json_obj[ControlThermalAlgoAction.JSON_FIELD_STATUS].lower() + if status_str == 'true': + self.status = True + elif status_str == 'false': + self.status = False + else: + raise ValueError('Invalid {} field value, please specify true of false'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + else: + raise ValueError('ControlThermalAlgoAction ' + 'missing mandatory field {} in JSON policy file'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + + def execute(self, thermal_info_dict): + """ + Disable thermal control algorithm + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import ChassisInfo + if ChassisInfo.INFO_NAME in thermal_info_dict: + chassis_info_obj = thermal_info_dict[ChassisInfo.INFO_NAME] + chassis = chassis_info_obj.get_chassis() + thermal_manager = chassis.get_thermal_manager() + if self.status: + thermal_manager.start_thermal_control_algorithm() + else: + thermal_manager.stop_thermal_control_algorithm() diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_conditions.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_conditions.py new file mode 100644 index 000000000000..c8bb51ef966c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_conditions.py @@ -0,0 +1,121 @@ +from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +class FanCondition(ThermalPolicyConditionBase): + def get_fan_info(self, thermal_info_dict): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + return thermal_info_dict[FanInfo.INFO_NAME] + else: + return None + +@thermal_json_object('fantray.any.absence') +class AnyFantrayAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fantrays()) > 0 if fan_info_obj else False + +@thermal_json_object('fantray.all.absence') +class AllFantrayAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_presence_fantrays()) == 0 if fan_info_obj else False + +@thermal_json_object('fantray.all.presence') +class AllFantrayPresenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fantrays()) == 0 if fan_info_obj else True + +@thermal_json_object('fan.rotor.more_than_one.failed') +class FanRotorMoreThanOneFailedCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) > 1 if fan_info_obj else False + +@thermal_json_object('fan.rotor.less_than_two.failed') +class FanRotorLessThanTwoFailedCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) < 2 if fan_info_obj else True + +class PsuCondition(ThermalPolicyConditionBase): + def get_psu_info(self, thermal_info_dict): + from .thermal_infos import PsuInfo + if PsuInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[PsuInfo.INFO_NAME], PsuInfo): + return thermal_info_dict[PsuInfo.INFO_NAME] + else: + return None + +@thermal_json_object('psu.any.absence') +class AnyPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) > 0 if psu_info_obj else False + +@thermal_json_object('psu.all.absence') +class AllPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_presence_psus()) == 0 if psu_info_obj else False + +@thermal_json_object('psu.all.presence') +class AllPsuPresenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) == 0 if psu_info_obj else True + + +class ThermalCondition(ThermalPolicyConditionBase): + def get_thermal_info(self, thermal_info_dict): + from .thermal_infos import ThermalInfo + if ThermalInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo): + return thermal_info_dict[ThermalInfo.INFO_NAME] + else: + return None + +@thermal_json_object('thermal.over.high_critical_threshold') +class ThermalOverHighCriticalCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return thermal_info_obj.is_any_over_high_critical_threshold() + else: + return False + +@thermal_json_object('thermal.any.over.high_threshold') +class AnyThermalOverHighThresholdCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return thermal_info_obj.is_any_warm_up_and_over_high_threshold() + else: + return False + +@thermal_json_object('thermal.any.below.low_threshold') +class AnyThermalBelowLowThresholdCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return thermal_info_obj.is_any_cool_down_and_below_low_threshold() + else: + return False + +@thermal_json_object('thermal.all.below.high_threshold') +class AnyThermalOverHighThresholdCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return not thermal_info_obj.is_any_warm_up_and_over_high_threshold() + else: + return True + +@thermal_json_object('thermal.all.over.low_threshold') +class AnyThermalBelowLowThresholdCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return not thermal_info_obj.is_any_cool_down_and_below_low_threshold() + else: + return True diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_infos.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_infos.py new file mode 100644 index 000000000000..4925637f8cb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_infos.py @@ -0,0 +1,362 @@ +from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object +from sonic_py_common import logger + +sonic_logger = logger.Logger('thermal_infos') + +@thermal_json_object('fan_info') +class FanInfo(ThermalPolicyInfoBase): + """ + Fan information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'fan_info' + FAN_LOW_WARNING_SPEED = 1370 + FAN_FRONT_HIGH_WARNING_SPEED = 29125 + FAN_REAR_HIGH_WARNING_SPEED = 25375 + + def __init__(self): + self._all_fans = set() + self._absence_fans = set() + self._presence_fans = set() + self._absence_fantrays = set() + self._presence_fantrays = set() + self._low_warning_fans = set() + self._high_warning_fans = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence fans. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + try: + for fantray in chassis.get_all_fan_drawers(): + if fantray.get_presence() and fantray not in self._presence_fantrays: + self._presence_fantrays.add(fantray) + self._status_changed = True + if fantray in self._absence_fantrays: + self._absence_fantrays.remove(fantray) + elif not fantray.get_presence() and fantray not in self._absence_fantrays: + self._absence_fantrays.add(fantray) + self._status_changed = True + if fantray in self._presence_fantrays: + self._presence_fantrays.remove(fantray) + + for fan in fantray.get_all_fans(): + if fan.get_presence() and fantray not in self._presence_fans: + self._presence_fans.add(fan) + self._status_changed = True + if fan in self._absence_fans: + self._absence_fans.remove(fan) + elif not fan.get_presence() and fan not in self._absence_fans: + self._absence_fans.add(fan) + self._status_changed = True + if fan in self._presence_fans: + self._presence_fans.remove(fan) + + fan_name = fan.get_name() + fan_rpm = fan.get_speed_rpm() + if fan not in self._all_fans: + self._all_fans.add(fan) + # FAN Low speed warning + if fan_rpm < self.FAN_LOW_WARNING_SPEED and fan not in self._low_warning_fans: + self._low_warning_fans.add(fan) + sonic_logger.log_warning("FAN {} speed {}, low speed warning".format(fan_name, fan_rpm)) + elif fan_rpm > self.FAN_LOW_WARNING_SPEED and fan in self._low_warning_fans: + sonic_logger.log_notice("FAN {}, restore from low speed warning".format(fan_name)) + self._low_warning_fans.remove(fan) + # FAN high speed warning + if fan.fan_index == 1: + if fan_rpm > self.FAN_FRONT_HIGH_WARNING_SPEED and fan not in self._high_warning_fans: + self._high_warning_fans.add(fan) + sonic_logger.log_warning("FAN {} speed {}, high speed warning".format(fan_name, fan_rpm)) + elif fan_rpm > self.FAN_FRONT_HIGH_WARNING_SPEED and fan in self._high_warning_fans: + self._high_warning_fans.remove(fan) + sonic_logger.log_notice("FAN {}, restore from high speed warning".format(fan_name)) + else: + if fan_rpm > self.FAN_REAR_HIGH_WARNING_SPEED and fan not in self._high_warning_fans: + self._high_warning_fans.add(fan) + sonic_logger.log_warning("FAN {} speed {}, high speed warning".format(fan_name, fan_rpm)) + elif fan_rpm > self.FAN_REAR_HIGH_WARNING_SPEED and fan in self._high_warning_fans: + self._high_warning_fans.remove(fan) + sonic_logger.log_notice("FAN {}, restore from high speed warning".format(fan_name)) + except Exception as e: + sonic_logger.log_warning("Catch exception: {}, File: {}, Line: {}".format(type(e).__name__, __file__, e.__traceback__.tb_lineno)) + + def get_all_fans(self): + """ + Retrieves all fans + :return: A set of fans + """ + return self._all_fans + + def get_absence_fantrays(self): + """ + Retrieves absence fans + :return: A set of absence fantrays + """ + return self._absence_fantrays + + def get_presence_fantrays(self): + """ + Retrieves presence fans + :return: A set of presence fantrays + """ + return self._presence_fantrays + + def get_absence_fans(self): + """ + Retrieves absence fans + :return: A set of absence fans + """ + return self._absence_fans + + def get_presence_fans(self): + """ + Retrieves presence fans + :return: A set of presence fans + """ + return self._presence_fans + + def get_low_warning_fans(self): + """ + Retrieves low rpm warning fans + :return: A set of low rpm warning fans + """ + return self._low_warning_fans + + def get_high_warning_fans(self): + """ + Retrieves high rpm warning fans + :return: A set of high rpm warning fans + """ + return self._high_warning_fans + + def is_status_changed(self): + """ + Retrieves if the status of fan information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('psu_info') +class PsuInfo(ThermalPolicyInfoBase): + """ + PSU information needed by thermal policy + """ + INFO_NAME = 'psu_info' + PSU_TEMP_HIGH_WARNING_THRESHOLD = 65 + + def __init__(self): + self._absence_psus = set() + self._presence_psus = set() + self._high_warning_psus = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence PSUs. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + try: + for psu in chassis.get_all_psus(): + if psu.get_presence() and psu not in self._presence_psus: + self._presence_psus.add(psu) + self._status_changed = True + if psu in self._absence_psus: + self._absence_psus.remove(psu) + elif (not psu.get_presence()) and psu not in self._absence_psus: + self._absence_psus.add(psu) + self._status_changed = True + if psu in self._presence_psus: + self._presence_psus.remove(psu) + # PSU Temp high warning + psu_name = psu.get_name() + psu_temp = psu.get_temperature() + if psu_temp != None and psu_temp != 'N/A': + if psu_temp > self.PSU_TEMP_HIGH_WARNING_THRESHOLD and psu not in self._high_warning_psus: + self._high_warning_psus.add(psu) + sonic_logger.log_warning("PSU {} temp {}, high temperature warning".format(psu_name, psu_temp)) + elif psu_temp < self.PSU_TEMP_HIGH_WARNING_THRESHOLD and psu in self._high_warning_psus: + self._high_warning_psus.remove(psu) + sonic_logger.log_notice("PSU {} restore from high temperature warning".format(psu_name)) + except Exception as e: + sonic_logger.log_warning("Catch exception: {}, File: {}, Line: {}".format(type(e).__name__, __file__, e.__traceback__.tb_lineno)) + + def get_absence_psus(self): + """ + Retrieves presence PSUs + :return: A set of absence PSUs + """ + return self._absence_psus + + def get_presence_psus(self): + """ + Retrieves presence PSUs + :return: A set of presence fans + """ + return self._presence_psus + + def get_high_warning_psus(self): + """ + Retrieves high temperature warning PSUs + :return: A set of high temp fans + """ + return self._high_warning_psus + + def is_status_changed(self): + """ + Retrieves if the status of PSU information changed + :return: True if status changed else False + """ + return self._status_changed + + +class ThermalData(): + def __init__(self, name): + self.name = name + self.hist2_temp = None + self.hist1_temp = None + self.curr_temp = None + self.temp_descend = False + + def update_temp(self, temp): + self.hist2_temp = self.hist1_temp + self.hist1_temp = self.curr_temp + self.curr_temp = temp + return self + + def update_temp_trend(self): + if self.hist1_temp == None: + self.temp_descend = False + elif self.curr_temp < self.hist1_temp: + self.temp_descend = True + else: + self.temp_descend = False + return self + +@thermal_json_object('thermal_info') +class ThermalInfo(ThermalPolicyInfoBase): + """ + Thermal information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'thermal_info' + THERMAL_SHUTDOWN_TEMP_MAP = {"CPU_Temp": 93, "BCM_SW_Temp": 120} + + def __init__(self): + self.init = False + self._high_warning_thermals = set() + self._low_warning_thermals = set() + self._high_shutdown_thermals = set() + self._thermals_data = {} + + def collect(self, chassis): + """ + Collect thermal sensor temperature change status + :param chassis: The chassis object + :return: + """ + try: + for thermal in chassis.get_all_thermals(): + name = thermal.get_name() + temp = thermal.get_temperature() + if temp == None or temp == 'N/A': + continue + high_threshold = thermal.get_high_threshold() + low_threshold = thermal.get_low_threshold() + thermal_shutdown = self.THERMAL_SHUTDOWN_TEMP_MAP.get(name, None) + + # Collect thermal data + thermal_data = self._thermals_data.get(name, None) + if thermal_data == None: + thermal_data = ThermalData(name) + self._thermals_data[name] = thermal_data + thermal_data.update_temp(temp).update_temp_trend() + + # Handle high threshold condition + if high_threshold != None and high_threshold != 'N/A': + if temp > high_threshold and thermal not in self._high_warning_thermals: + self._high_warning_thermals.add(thermal) + sonic_logger.log_warning("Thermal {} temp {}, high threshold warning".format(name, temp)) + if thermal_shutdown != None and temp > thermal_shutdown: + self._high_shutdown_thermals.add(thermal) + sonic_logger.log_warning("Thermal {} temp {}, high temp shutdown warning".format(name, temp)) + elif temp < (high_threshold - 3) and thermal in self._high_warning_thermals: + self._high_warning_thermals.remove(thermal) + sonic_logger.log_notice("Thermal {}, restore from high threshold warning".format(name)) + if thermal in self._high_shutdown_thermals: + self._high_shutdown_thermals.remove(thermal) + + # Handle low threshold condition + if low_threshold != None and low_threshold != 'N/A': + if temp < low_threshold and thermal not in self._low_warning_thermals: + self._low_warning_thermals.add(thermal) + sonic_logger.log_warning("Thermal {} temp {}, low threshold warning".format(name, temp)) + elif temp > (low_threshold + 3) and thermal in self._low_warning_thermals: + self._low_warning_thermals.remove(thermal) + sonic_logger.log_notice("Thermal {}, restore from low threshold warning".format(name)) + except Exception as e: + sonic_logger.log_warning("Catch exception: {}, File: {}, Line: {}".format(type(e).__name__, __file__, e.__traceback__.tb_lineno)) + + def is_any_warm_up_and_over_high_threshold(self): + """ + Retrieves if the temperature is warm up and over high threshold + :return: True if the temperature is warm up and over high threshold else False + """ + return len(self._high_warning_thermals) > 0 + + def is_any_cool_down_and_below_low_threshold(self): + """ + Retrieves if the temperature is cold down and below low threshold + :return: True if the temperature is cold down and below low threshold else False + """ + return len(self._low_warning_thermals) > 0 + + def is_any_over_high_critical_threshold(self): + """ + Retrieves if the temperature is over high critical threshold + :return: True if the temperature is over high critical threshold else False + """ + return len(self._high_shutdown_thermals) > 0 + + def get_thermals_data(self): + """ + Retrieves all the thermal data + :return: thermal data dict using thermal name as key + """ + return self._thermals_data + + +@thermal_json_object('chassis_info') +class ChassisInfo(ThermalPolicyInfoBase): + """ + Chassis information needed by thermal policy + """ + INFO_NAME = 'chassis_info' + + def __init__(self): + self._chassis = None + + def collect(self, chassis): + """ + Collect platform chassis. + :param chassis: The chassis object + :return: + """ + self._chassis = chassis + + def get_chassis(self): + """ + Retrieves platform chassis object + :return: A platform chassis object. + """ + return self._chassis diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_manager.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_manager.py new file mode 100644 index 000000000000..fb9557270f05 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/thermal_manager.py @@ -0,0 +1,21 @@ +from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase +from .thermal_infos import * +from .thermal_conditions import * +from .thermal_actions import * + +class ThermalManager(ThermalManagerBase): + @classmethod + def initialize(cls): + """ + Initialize thermal manager, including register thermal condition types and thermal action types + and any other vendor specific initialization. + """ + return True + + @classmethod + def deinitialize(cls): + """ + Destroy thermal manager, including any vendor specific cleanup. + :return: + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/watchdog.py new file mode 100644 index 000000000000..90b5ee352c08 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform/watchdog.py @@ -0,0 +1,14 @@ +try: + from sonic_platform_pddf_base.pddf_watchdog import PddfWatchdog +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + + +class Watchdog(PddfWatchdog): + """PDDF Platform-Specific Watchdog Class""" + + def __init__(self): + PddfWatchdog.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform_setup.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform_setup.py new file mode 100644 index 000000000000..a1535165bb66 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/pddf/sonic_platform_setup.py @@ -0,0 +1,28 @@ +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Celestica Platforms based on PDDF', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + packages=['sonic_platform'], + 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-cel/ds3000/scripts/ds3000_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/ds3000_platform_shutdown.sh new file mode 100755 index 000000000000..89c53b2ccb7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/ds3000_platform_shutdown.sh @@ -0,0 +1,39 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +bmc_present=`cat /sys/bus/platform/devices/baseboard/bmc_presence` + +if [[ "$bmc_present" == "present" ]]; then + # Set all LEDs to BMC's control + ipmitool raw 0x3a 0x42 0x02 0x01 &> /dev/null + + # BMC cold power-cyle + ipmitool chassis power cycle &> /dev/null +else + # Set System LED to booting pattern + i2cset -f -y 100 0x0d 0x62 0x02 &> /dev/null + + # CPLD cold power-cyle + i2cset -f -y 100 0x0d 0x64 0x00 &> /dev/null +fi + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_post_device_create.sh b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_post_device_create.sh new file mode 100755 index 000000000000..95e4def3f903 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_post_device_create.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +declare -r CPLD_SETREG="/sys/bus/platform/devices/baseboard/setreg" +declare -r CPLD_GETREG="/sys/bus/platform/devices/baseboard/getreg" + +# Load fpga extend driver after fpga device created +modprobe pddf_custom_fpga_extend + +# attach ucd90120 devices, bus 107, devices 0x34 and 0x35 +echo "ucd90120 0x34" > /sys/bus/i2c/devices/i2c-107/new_device +echo "ucd90120 0x35" > /sys/bus/i2c/devices/i2c-107/new_device + +# attach mp2975 devices, bus 108, devices 0x70 and 0x7a +echo "mp2975 0x70" > /sys/bus/i2c/devices/i2c-108/new_device +echo "mp2975 0x7a" > /sys/bus/i2c/devices/i2c-108/new_device + +# Set SYS_LED to Green, assuming everything came up fine. +echo "0xa162 0xdc" > ${CPLD_SETREG} + +# Disable CPLD thermal shutdown by default +echo "0xa175 0x0" > ${CPLD_SETREG} + +BMC_PRESENCE_SYS_PATH="/sys/bus/platform/devices/baseboard/bmc_presence" +BMC_PRESENCE=`cat ${BMC_PRESENCE_SYS_PATH}` + +#Set off Alarm LED +if [ ${BMC_PRESENCE} == "present" ]; then + # Set all LEDs to Manual control + ipmitool raw 0x3a 0x42 0x02 0x00 &> /dev/null + # Set Alarm LED to OFF + ipmitool raw 0x3a 0x39 0x02 0x01 0x00 &> /dev/null + + #Set CPLD Fan LED register to BMC control + ipmitool raw 0x3a 0x64 0x00 0x02 0x65 0x10 &> /dev/null +else + i2cset -f -y 100 0x0d 0x63 0x33 &> /dev/null +fi diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_pre_driver_install.sh b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_pre_driver_install.sh new file mode 100755 index 000000000000..29bc603d447c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pddf_pre_driver_install.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Has customized those drivers,so rename them to lose effect +psu_driver=pddf_psu_driver_module.ko +ker_name=$(uname -r) +driver_path=/usr/lib/modules/${ker_name}/extra/ +if [ -e ${driver_path}${psu_driver} ]; then + mv ${driver_path}${psu_driver} ${driver_path}${psu_driver}-bk +fi + +echo 'pddf psu driver module has rename now' diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/platform_sensors.py new file mode 100644 index 000000000000..8cab9ee29554 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/platform_sensors.py @@ -0,0 +1,179 @@ +#!/usr/bin/python +# +# Silverstone-v2 platform sensors. This script get the sensor data from BMC +# using ipmitool and display them in lm-sensor alike format. +# +# The following data is support: +# 1. Temperature sensors +# 2. PSUs +# 3. Fan Drawers + +import sys +import logging +import subprocess + +IPMI_SDR_CMD = ['/usr/bin/ipmitool', 'sdr', 'elist'] +MAX_NUM_FANS = 4 +MAX_NUM_PSUS = 2 + +SENSOR_NAME = 0 +SENSOR_VAL = 4 + +sensor_dict = {} + +def ipmi_sensor_dump(cmd): + ''' Execute ipmitool command return dump output + exit if any error occur. + ''' + global sensor_dict + sensor_dump = '' + + try: + sensor_dump = subprocess.check_output(IPMI_SDR_CMD, universal_newlines=True) + except subprocess.CalledProcessError as e: + logging.error('Error! Failed to execute: {}'.format(cmd)) + sys.exit(1) + + for line in sensor_dump.splitlines(): + sensor_info = line.split('|') + sensor_dict[sensor_info[SENSOR_NAME].strip()] = sensor_info[SENSOR_VAL].strip() + + return True + +def get_reading_by_name(sensor_name, sdr_elist_dump): + ''' + Search for the match sensor name, return sensor + reading value and unit, return object epmtry string + if search not match. + + The output of sensor dump: + TEMP_FB_U52 | 00h | ok | 7.1 | 31 degrees C + TEMP_FB_U17 | 01h | ok | 7.1 | 27 degrees C + TEMP_SW_U52 | 02h | ok | 7.1 | 30 degrees C + Fan2_Status | 07h | ok | 29.2 | Present + Fan2_Front | 0Eh | ok | 29.2 | 12000 RPM + Fan2_Rear | 46h | ok | 29.2 | 14700 RPM + PSU2_Status | 39h | ok | 10.2 | Presence detected + PSU2_Fan | 3Dh | ok | 10.2 | 16000 RPM + PSU2_VIn | 3Ah | ok | 10.2 | 234.30 Volts + PSU2_CIn | 3Bh | ok | 10.2 | 0.80 Amps + ''' + found = '' + + for line in sdr_elist_dump.splitlines(): + line = line.decode() + if sensor_name in line: + found = line.strip() + break + + if not found: + logging.error('Cannot find sensor name:' + sensor_name) + + else: + try: + found = found.split('|')[4] + except IndexError: + logging.error('Cannot get sensor data of:' + sensor_name) + + logging.basicConfig(level=logging.DEBUG) + return found + + +def read_temperature_sensors(): + sensor_list = [\ + ('Base_Temp_U5', 'Baseboard Left Temp'),\ + ('Base_Temp_U56', 'Baseboard Right Temp'),\ + ('Switch_Temp_U28', 'Switchboard Left Temp'),\ + ('Switch_Temp_U29', 'Switchboard Right Temp'),\ + ('CPU_Temp', 'CPU Internal Temp'),\ + ('Switch_Temp_U17', 'ASIC External Front Temp'),\ + ('Switch_Temp_U18', 'ASIC External Rear Temp'),\ + ('TEMP_SW_Internal', 'ASIC Internal Temp'),\ + ('VDD_ANLG_Temp', 'MP2975 VDD ANLG Temp'),\ + ('VDD_CORE_Temp', 'MP2975 VDD CORE Temp')\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Temperature Sensors\n" + output += "Adapter: IPMI adapter\n" + for sensor in sensor_list: + output += sensor_format.format('{}:'.format(sensor[1]),\ + sensor_dict[sensor[0]],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_fan_sensors(num_fans): + + sensor_list = [\ + ('Fan{}_Status', 'Fan Drawer {} Status'),\ + ('Fan{}_Front', 'Fan {} front'),\ + ('Fan{}_Rear', 'Fan {} rear'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Fan Drawers\n" + output += "Adapter: IPMI adapter\n" + for fan_num in range(1, num_fans+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(fan_num) + display_sensor_name = sensor[1].format(fan_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_psu_sensors(num_psus): + + sensor_list = [\ + ('PSU{}_Status', 'PSU {} Status'),\ + ('PSU{}_Fan', 'PSU {} Fan 1'),\ + ('PSU{}_VIn', 'PSU {} Input Voltage'),\ + ('PSU{}_CIn', 'PSU {} Input Current'),\ + ('PSU{}_PIn', 'PSU {} Input Power'),\ + ('PSU{}_Temp1', 'PSU {} Temp1'),\ + ('PSU{}_Temp2', 'PSU {} Temp2'),\ + ('PSU{}_VOut', 'PSU {} Output Voltage'),\ + ('PSU{}_COut', 'PSU {} Output Current'),\ + ('PSU{}_POut', 'PSU {} Output Power'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "PSU\n" + output += "Adapter: IPMI adapter\n" + for psu_num in range(1, num_psus+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(psu_num) + display_sensor_name = sensor[1].format(psu_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def main(): + output_string = '' + + if ipmi_sensor_dump(IPMI_SDR_CMD): + output_string += read_temperature_sensors() + output_string += read_psu_sensors(MAX_NUM_PSUS) + output_string += read_fan_sensors(MAX_NUM_FANS) + + print(output_string) + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pre_pddf_init.sh b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pre_pddf_init.sh new file mode 100755 index 000000000000..2556858cdab9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/pre_pddf_init.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Probe Baseboard CPLD driver +modprobe baseboard_cpld +sleep 1 + +# Get BMC mode +PLATFORM=`sed -n 's/onie_platform=\(.*\)/\1/p' /host/machine.conf` +BMC_PRESENCE_SYS_PATH="/sys/bus/platform/devices/baseboard/bmc_presence" +BMC_PRESENCE=`cat ${BMC_PRESENCE_SYS_PATH}` +echo "Platform ${PLATFORM} BMC card ${BMC_PRESENCE}" + +# Copy pddf-device.json according to bmc mode +PDDF_JSON="pddf-device.json" +PDDF_JSON_BMC="pddf-device-bmc.json" +PDDF_JSON_NONBMC="pddf-device-nonbmc.json" +PDDF_JSON_PATH="/usr/share/sonic/device/${PLATFORM}/pddf" +PLATFORM_COMPONENTS_FILE="/usr/share/sonic/device/${PLATFORM}/platform_components.json" +if [ ${BMC_PRESENCE} == "present" ]; then + cp ${PDDF_JSON_PATH}/${PDDF_JSON_BMC} ${PDDF_JSON_PATH}/${PDDF_JSON} + # Add BMC component if BMC exists + if ! grep -q "BMC" ${PLATFORM_COMPONENTS_FILE}; then + sed -i '6i \ "BMC": {},' ${PLATFORM_COMPONENTS_FILE} + fi +else + # BMC Card absent + cp ${PDDF_JSON_PATH}/${PDDF_JSON_NONBMC} ${PDDF_JSON_PATH}/${PDDF_JSON} + # Remove BMC component for NonBMC + sed -i '/"BMC"/d' ${PLATFORM_COMPONENTS_FILE} +fi diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/sensors new file mode 100644 index 000000000000..5d740a9eb7d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/scripts/sensors @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon python3 /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/systemd/pddf-platform-init.service b/platform/broadcom/sonic-platform-modules-cel/ds3000/systemd/pddf-platform-init.service new file mode 100644 index 000000000000..f4098b34b60e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/systemd/pddf-platform-init.service @@ -0,0 +1,16 @@ +[Unit] +Description=PDDF module and device initialization service +Before=pmon.service watchdog-control.service +Before=opennsl-modules.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStartPre=-/usr/local/bin/pre_pddf_init.sh +ExecStart=/usr/local/bin/pddf_util.py install +ExecStop=/usr/local/bin/pddf_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +WantedBy=opennsl-modules.service diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/afulnx_64 b/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/afulnx_64 new file mode 100755 index 0000000000000000000000000000000000000000..0ba1549c2891bac2e3c6aa385c5c2182c5319826 GIT binary patch literal 1134256 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

N-hG0B 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�&@`Zc)D`wR2w+3`ZMQIZA@(_X}5H<@$( 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 blLj{% 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 literal 0 HcmV?d00001 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/fpga_prog b/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/fpga_prog new file mode 100755 index 0000000000000000000000000000000000000000..3227da590a0a516dadac3e4b7b0f5ce6a4f1fb66 GIT binary patch literal 17536 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 b)x>wONXX@~?nPznSKMZ4oM%Nvi|zjxa%%%M literal 0 HcmV?d00001 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/ispvm b/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/ispvm new file mode 100755 index 0000000000000000000000000000000000000000..f8e216556ebe1f37526e30257aa4c6e278f8ba6b GIT binary patch literal 101752 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 bq+j^*hhILW>umj>pchAQwfH*ts@DGlP$Tz1 literal 0 HcmV?d00001 diff --git a/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/pddf_switch_svc.py b/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/pddf_switch_svc.py new file mode 100644 index 000000000000..319178d62a41 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/ds3000/utils/pddf_switch_svc.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# Script to stop and start the respective platforms default services. +# This will be used while switching the pddf->non-pddf mode and vice versa +import os +import sys +import commands + +def check_pddf_support(): + return True + +def stop_platform_svc(): + status, output = commands.getstatusoutput("systemctl stop xxxx-platform-init.service") + if status: + print "Stop xxxx-platform-init.service failed %d"%status + return False + status, output = commands.getstatusoutput("systemctl disable xxxx-platform-init.service") + if status: + print "Disable xxxx-platform-init.service failed %d"%status + return False + + status, output = commands.getstatusoutput("/usr/local/bin/xxxx_util.py clean") + if status: + print "xxxx_util.py clean command failed %d"%status + return False + + # HACK , stop the pddf-platform-init service if it is active + status, output = commands.getstatusoutput("systemctl stop pddf-platform-init.service") + if status: + print "Stop pddf-platform-init.service along with other platform serives failed %d"%status + return False + + return True + +def start_platform_svc(): + status, output = commands.getstatusoutput("/usr/local/bin/xxxx_util.py install") + if status: + print "xxxx_util.py install command failed %d"%status + return False + + status, output = commands.getstatusoutput("systemctl enable xxxx-platform-init.service") + if status: + print "Enable xxxx-platform-init.service failed %d"%status + return False + status, output = commands.getstatusoutput("systemctl start xxxx-platform-init.service") + if status: + print "Start xxxx-platform-init.service failed %d"%status + return False + + return True + +def start_platform_pddf(): + # Enable PDDF 2.0 object class for xxxx + status, output = commands.getstatusoutput("mkdir /usr/share/sonic/platform/sonic_platform") + if status: + print "Unable to create 2.0 object class folder /usr/share/sonic/platform/sonic_platform" + return False + + status, output = commands.getstatusoutput("systemctl start pddf-platform-init.service") + if status: + print "Start pddf-platform-init.service failed %d"%status + return False + + return True + +def stop_platform_pddf(): + # Disable PDDF 2.0 object class for xxxx + status, output = commands.getstatusoutput("rm -r /usr/share/sonic/platform/sonic_platform") + if status: + print "Unable to delete 2.0 object class folder /usr/share/sonic/platform/sonic_platform" + return False + + status, output = commands.getstatusoutput("systemctl stop pddf-platform-init.service") + if status: + print "Stop pddf-platform-init.service failed %d"%status + return False + + return True + +def main(): + pass + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/pid_config_questone2.ini b/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/pid_config_questone2.ini new file mode 100644 index 000000000000..7227dd6273c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/pid_config_questone2.ini @@ -0,0 +1,19 @@ +#[PID thermal control setting] +[PID enable] +PID_enable=0 + +[SWITCH_TEMP] +setpoint = 95 +P = 3 +I = 0.5 +D = 0.5 +min_output = 76 + +[CPU_TEMP] +setpoint = -15 +P = 3 +I = 0.5 +D = 0.5 +min_output = 76 + + diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modprobe.conf b/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modprobe.conf new file mode 100644 index 000000000000..57a28ea72eac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modprobe.conf @@ -0,0 +1 @@ +options switchboard_fpga allow_unsafe_i2c_access=1 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modules.conf b/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modules.conf new file mode 100644 index 000000000000..574c48f7a66f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/cfg/questone2-modules.conf @@ -0,0 +1,16 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x +8021q + diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/Makefile new file mode 100644 index 000000000000..c32df8e5e6e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/Makefile @@ -0,0 +1 @@ +obj-m := mc24lc64t.o questone2_switchboard.o questone2_baseboard_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/mc24lc64t.c new file mode 100644 index 000000000000..4603b3d41065 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/mc24lc64t.c @@ -0,0 +1,171 @@ +/* + * mc24lc64t.c - driver for Microchip 24LC64T + * + * Copyright (C) 2017 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes. + +struct mc24lc64t_data { + struct mutex update_lock; +}; + +static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, read_time, i = 0; + int status; + + mutex_lock(&drvdata->update_lock); + + if (i2c_smbus_write_byte_data(client, off>>8, off)) + { + status = -EIO; + goto exit; + } + + msleep(1); + +begin: + + if (i < count) + { + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + do { + read_time = jiffies; + + status = i2c_smbus_read_byte(client); + if (status >= 0) + { + buf[i++] = status; + goto begin; + } + } while (time_before(read_time, timeout)); + + status = -ETIMEDOUT; + goto exit; + } + + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + + return status; +} + +static ssize_t mc24lc64t_write (struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count){ + + struct i2c_client *client = kobj_to_i2c_client(kobj); + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + unsigned long timeout, write_time, i = 0; + int status; + u16 value; + + mutex_lock(&drvdata->update_lock); + +begin: + if (i < count){ + timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/ + value = (buf[i] << 8)| off; + do { + write_time = jiffies; + status = i2c_smbus_write_word_data(client, off>>8, value); + if (status >= 0) + { + // increase offset + off++; + // increase buffer index + i++; + goto begin; + } + } while (time_before(write_time, timeout)); + status = -ETIMEDOUT; + goto exit; + } + status = count; + +exit: + mutex_unlock(&drvdata->update_lock); + return status; +} + +static struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUGO, + }, + .size = EEPROM_SIZE, + .read = mc24lc64t_read, + .write = mc24lc64t_write, +}; + +static int mc24lc64t_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct mc24lc64t_data *drvdata; + int err; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA + | I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + + if (!(drvdata = devm_kzalloc(&client->dev, + sizeof(struct mc24lc64t_data), GFP_KERNEL))) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + + return err; +} + +static void mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); +} + +static const struct i2c_device_id mc24lc64t_id[] = { + { "24lc64t", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mc24lc64t_id); + +static struct i2c_driver mc24lc64t_driver = { + .driver = { + .name = "mc24lc64t", + .owner = THIS_MODULE, + }, + .probe = mc24lc64t_probe, + .remove = mc24lc64t_remove, + .id_table = mc24lc64t_id, +}; + +module_i2c_driver(mc24lc64t_driver); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Microchip 24LC64T Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_baseboard_cpld.c b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_baseboard_cpld.c new file mode 100644 index 000000000000..20c353ee5d00 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_baseboard_cpld.c @@ -0,0 +1,408 @@ +/* + * seastone2_baseboard_cpld.c - driver for Seastone2 Base Board CPLD + * This driver implement sysfs for CPLD register access using LPC bus. + * Copyright (C) 2017 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "sys_cpld" +/** + * CPLD register address for read and write. + */ +#define VERSION_ADDR 0xA100 +#define SCRATCH_ADDR 0xA101 +#define SYS_LED_ADDR 0xA162 +#define THERMAL_ADDR 0xA176 +#define CPLD_REGISTER_SIZE 0x77 + +struct baseboard_cpld_data { + struct mutex cpld_lock; + uint16_t read_addr; +}; + +struct baseboard_cpld_data *cpld_data; + +/** + * Read the value from scratch register as hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf,"0x%2.2x\n", data); +} + +/** + * Set scratch register with specific hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long data; + char *last; + + mutex_lock(&cpld_data->cpld_lock); + data = (uint16_t)strtoul(buf,&last,16); + if(data == 0 && buf == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + outb(data, SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(scratch); + + +/* CPLD version attributes */ +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + int len = sprintf(buf, "0x%2.2x\n",inb(VERSION_ADDR)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RO(version); + + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint16_t addr; + char *last; + + addr = (uint16_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + cpld_data->read_addr = addr; + return count; +} + +static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + int len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RW(getreg); + +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint16_t addr; + uint8_t value; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + + strscpy(clone, buf, count); + + mutex_lock(&cpld_data->cpld_lock); + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + addr = (uint16_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + value = (uint8_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + outb(value,addr); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_WO(setreg); + +/** + * Read all CPLD register in binary mode. + * @return number of byte read. + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i=0; + ssize_t status; + + mutex_lock(&cpld_data->cpld_lock); +begin: + if(i < count){ + buf[i++] = inb(VERSION_ADDR + off); + off++; + msleep(1); + goto begin; + } + status = count; +exit: + mutex_unlock(&cpld_data->cpld_lock); + return status; +} +static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE); + +/** + * Show system led status - on/off/1k/4k + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0x3; + return sprintf(buf, "%s\n", + data == 0x03 ? "off" : data == 0x02 ? "4k" : data ==0x01 ? "1k": "on"); +} + +/** + * Set the status of system led - on/off/1k/4k + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status,data; + if(sysfs_streq(buf, "off")){ + led_status = 0x03; + }else if(sysfs_streq(buf, "4k")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "1k")){ + led_status = 0x01; + }else if(sysfs_streq(buf, "on")){ + led_status = 0x00; + }else{ + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + data = data & ~(0x3); + data = data | led_status; + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(sys_led); + +/** + * Show system led color - both/green/yellow/none + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t sys_led_color_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = (data >> 4) & 0x3; + return sprintf(buf, "%s\n", + data == 0x03 ? "off" : data == 0x02 ? "yellow" : data ==0x01 ? "green": "both"); +} + +/** + * Set the color of system led - both/green/yellow/none + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_color_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status,data; + if(sysfs_streq(buf, "off")){ + led_status = 0x03; + }else if(sysfs_streq(buf, "yellow")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "green")){ + led_status = 0x01; + }else if(sysfs_streq(buf, "both")){ + led_status = 0x00; + }else{ + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + data = data & ~( 0x3 << 4); + data = data | (led_status << 4); + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(sys_led_color); + +static struct attribute *baseboard_cpld_attrs[] = { + &dev_attr_version.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_sys_led.attr, + &dev_attr_sys_led_color.attr, + NULL, +}; + +static struct bin_attribute *baseboard_cpld_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute_group baseboard_cpld_attrs_grp = { + .attrs = baseboard_cpld_attrs, + .bin_attrs = baseboard_cpld_bin_attrs, +}; + +static struct resource baseboard_cpld_resources[] = { + { + .start = 0xA100, + .end = 0xA1FF, + .flags = IORESOURCE_IO, + }, +}; + +static void baseboard_cpld_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device baseboard_cpld_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(baseboard_cpld_resources), + .resource = baseboard_cpld_resources, + .dev = { + .release = baseboard_cpld_dev_release, + } +}; + +static int baseboard_cpld_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret =0; + int portid_count; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct baseboard_cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + cpld_data->read_addr = VERSION_ADDR; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (unlikely(!res)) { + printk(KERN_ERR "Specified Resource Not Available...\n"); + return -1; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &baseboard_cpld_attrs_grp); + if (ret) { + printk(KERN_ERR "Cannot create sysfs for baseboard CPLD\n"); + } + return 0; +} + +static int baseboard_cpld_drv_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &baseboard_cpld_attrs_grp); + return 0; +} + +static struct platform_driver baseboard_cpld_drv = { + .probe = baseboard_cpld_drv_probe, + .remove = __exit_p(baseboard_cpld_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int baseboard_cpld_init(void) +{ + // Register platform device and platform driver + platform_device_register(&baseboard_cpld_dev); + platform_driver_register(&baseboard_cpld_drv); + return 0; +} + +void baseboard_cpld_exit(void) +{ + // Unregister platform device and platform driver + platform_driver_unregister(&baseboard_cpld_drv); + platform_device_unregister(&baseboard_cpld_dev); +} + +module_init(baseboard_cpld_init); +module_exit(baseboard_cpld_exit); + +MODULE_AUTHOR("Pradchaya Phucharoen "); +MODULE_DESCRIPTION("Celestica Seastone2/Questone2 Baseboard CPLD Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_switchboard.c b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_switchboard.c new file mode 100644 index 000000000000..945d5f26c875 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/modules/questone2_switchboard.c @@ -0,0 +1,2211 @@ +/* + * seastone_switchboard.c - driver for seastone2/questone2 Switch board FPGA/CPLD. + * + * Author: Pradchaya Phucharoen + * + * Copyright (C) 2017 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * / + * \--sys + * \--devices + * \--platform + * \--seastone2 + * |--FPGA + * |--CPLD1 + * |--CPLD2 + * \--SFF + * |--QSFP[1..32] + * \--SFP[1..2] + * + */ + +#ifndef TEST_MODE +#define MOD_VERSION "2.0.0" +#else +#define MOD_VERSION "TEST" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static int majorNumber; +#ifdef SEASTONE2 +#define CLASS_NAME "seastone2_fpga" +#define DRIVER_NAME "seastone2" +#define FPGA_PCI_NAME "Seastone2_fpga_pci" +#else +#define CLASS_NAME "questone2_fpga" +#define DRIVER_NAME "questone2" +#define FPGA_PCI_NAME "questone2_fpga_pci" +#endif +#define DEVICE_NAME "fwupgrade" + + +static int smbus_access(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char rw, u8 cmd, + int size, union i2c_smbus_data *data); + +static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char rw, u8 cmd, + int size, union i2c_smbus_data *data); + +static int fpgafw_init(void); +static void fpgafw_exit(void); + + +/* +======================================== +FPGA PCIe BAR 0 Registers +======================================== +Misc Control 0x00000000 – 0x000000FF. +I2C_CH1 0x00000100 - 0x00000110 +I2C_CH2 0x00000200 - 0x00000210. +I2C_CH3 0x00000300 - 0x00000310. +I2C_CH4 0x00000400 - 0x00000410. +I2C_CH5 0x00000500 - 0x00000510. +I2C_CH6 0x00000600 - 0x00000610. +I2C_CH7 0x00000700 - 0x00000710. +I2C_CH8 0x00000800 - 0x00000810. +I2C_CH9 0x00000900 - 0x00000910. +I2C_CH10 0x00000A00 - 0x00000A10. +SPI Master 0x00001200 - 0x00001300. +PORT XCVR 0x00004000 - 0x00004FFF. +*/ + +/* MISC */ +#define FPGA_VERSION 0x0000 +#define FPGA_VERSION_MJ_MSK 0xff00 +#define FPGA_VERSION_MN_MSK 0x00ff +#define FPGA_SCRATCH 0x0004 +#define FPGA_BROAD_TYPE 0x0008 +#define FPGA_BROAD_REV_MSK 0x0038 +#define FPGA_BROAD_ID_MSK 0x0007 +#define FPGA_PLL_STATUS 0x0014 +#define BMC_I2C_SCRATCH 0x0020 +#define FPGA_SLAVE_CPLD_REST 0x0030 +#define FPGA_PERIPH_RESET_CTRL 0x0034 +#define FPGA_INT_STATUS 0x0040 +#define FPGA_INT_SRC_STATUS 0x0044 +#define FPGA_INT_FLAG 0x0048 +#define FPGA_INT_MASK 0x004c +#define FPGA_MISC_CTRL 0x0050 +#define FPGA_MISC_STATUS 0x0054 +#define FPGA_AVS_VID_STATUS 0x0068 +#define FPGA_FEATURE_CARD_GPIO 0x0070 +#define FPGA_PORT_XCVR_READY 0x000c + +/* I2C_MASTER BASE ADDR */ +#define I2C_MASTER_FREQ_1 0x0100 +#define I2C_MASTER_CTRL_1 0x0104 +#define I2C_MASTER_STATUS_1 0x0108 +#define I2C_MASTER_DATA_1 0x010c +#define I2C_MASTER_PORT_ID_1 0x0110 +#define I2C_MASTER_CH_1 1 +#define I2C_MASTER_CH_2 2 +#define I2C_MASTER_CH_3 3 +#define I2C_MASTER_CH_4 4 +#define I2C_MASTER_CH_5 5 +#define I2C_MASTER_CH_6 6 +#define I2C_MASTER_CH_7 7 +#define I2C_MASTER_CH_8 8 +#define I2C_MASTER_CH_9 9 +#define I2C_MASTER_CH_10 10 +#define I2C_MASTER_CH_TOTAL I2C_MASTER_CH_10 + +/* SPI_MASTER */ +#define SPI_MASTER_WR_EN 0x1200 /* one bit */ +#define SPI_MASTER_WR_DATA 0x1204 /* 32 bits */ +#define SPI_MASTER_CHK_ID 0x1208 /* one bit */ +#define SPI_MASTER_VERIFY 0x120c /* one bit */ +#define SPI_MASTER_STATUS 0x1210 /* 15 bits */ +#define SPI_MASTER_MODULE_RST 0x1214 /* one bit */ + +/* FPGA FRONT PANEL PORT MGMT */ +#define SFF_PORT_CTRL_BASE 0x4000 +#define SFF_PORT_STATUS_BASE 0x4004 +#define SFF_PORT_INT_STATUS_BASE 0x4008 +#define SFF_PORT_INT_MASK_BASE 0x400c + +#define PORT_XCVR_REGISTER_SIZE 0x1000 + +/* PORT CTRL REGISTER +[31:7] RSVD +[6] LPMOD 6 +[5] RSVD +[4] RST 4 +[3:1] RSVD +[0] TXDIS 0 +*/ +#define CTRL_LPMOD 6 +#define CTRL_RST 4 +#define CTRL_TXDIS 0 + +/* PORT STATUS REGISTER +[31:6] RSVD +[5] IRQ 5 +[4] PRESENT 4 +[3] RSVD +[2] TXFAULT 2 +[1] RXLOS 1 +[0] MODABS 0 +*/ +#define STAT_IRQ 5 +#define STAT_PRESENT 4 +#define STAT_TXFAULT 2 +#define STAT_RXLOS 1 +#define STAT_MODABS 0 + +/* PORT INTRPT REGISTER +[31:6] RSVD +[5] INT_N 5 +[4] PRESENT 4 +[3] RSVD +[2] RSVD +[1] RXLOS 1 +[0] MODABS 0 +*/ +#define INTR_INT_N 5 +#define INTR_PRESENT 4 +#define INTR_TXFAULT 2 +#define INTR_RXLOS 1 +#define INTR_MODABS 0 + +/* PORT INT MASK REGISTER +[31:6] RSVD +[5] INT_N 5 +[4] PRESENT 4 +[3] RSVD +[2] RSVD +[1] RXLOS_INT 1 +[0] MODABS 0 +*/ +#define MASK_INT_N 5 +#define MASK_PRESENT 4 +#define MASK_TXFAULT 2 +#define MASK_RXLOS 1 +#define MASK_MODABS 0 + +enum { + I2C_SR_BIT_RXAK = 0, + I2C_SR_BIT_MIF, + I2C_SR_BIT_SRW, + I2C_SR_BIT_BCSTM, + I2C_SR_BIT_MAL, + I2C_SR_BIT_MBB, + I2C_SR_BIT_MAAS, + I2C_SR_BIT_MCF +}; + +enum { + I2C_CR_BIT_BCST = 0, + I2C_CR_BIT_RSTA = 2, + I2C_CR_BIT_TXAK, + I2C_CR_BIT_MTX, + I2C_CR_BIT_MSTA, + I2C_CR_BIT_MIEN, + I2C_CR_BIT_MEN, +}; + +/** + * + * The function is i2c algorithm implement to allow master access to + * correct endpoint devices trough the PCA9548 switch devices. + * + * FPGA I2C Master [mutex resource] + * | + * | + * --------------------------- + * | PCA9548(s) | + * ---1--2--3--4--5--6--7--8-- + * | | | | | | | | + * EEPROM ... EEPROM + * + */ + + +#ifdef SEASTONE2 +#define VIRTUAL_I2C_QSFP_PORT 32 +#define VIRTUAL_I2C_SFP_PORT 1 +#define VIRTUAL_I2C_CPLD_PORT 1 +#define VIRTUAL_I2C_POWER_CHIP_PORT 1 +#define VIRTUAL_I2C_CPLD_B_PORT 1 +#define VIRTUAL_I2C_PSU 1 +#define VIRTUAL_I2C_FAN_TRAY 4 +#define VIRTUAL_I2C_POWER_MON 1 +#define VIRTUAL_I2C_LM75 1 + +#define VIRTUAL_I2C_PORT_LENGTH \ + VIRTUAL_I2C_SFP_PORT+VIRTUAL_I2C_QSFP_PORT+VIRTUAL_I2C_POWER_CHIP_PORT+VIRTUAL_I2C_CPLD_PORT+VIRTUAL_I2C_CPLD_B_PORT+VIRTUAL_I2C_PSU+VIRTUAL_I2C_FAN_TRAY+VIRTUAL_I2C_POWER_MON+VIRTUAL_I2C_LM75 + +#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT+VIRTUAL_I2C_SFP_PORT +#else +#define VIRTUAL_I2C_SFP_PORT 48 +#define VIRTUAL_I2C_QSFP_PORT 8 +#define VIRTUAL_I2C_CPLD_PORT 1 +#define VIRTUAL_I2C_POWER_CHIP_PORT 1 +#define VIRTUAL_I2C_CPLD_B_PORT 1 +#define VIRTUAL_I2C_PSU 1 +#define VIRTUAL_I2C_FAN_TRAY 4 +#define VIRTUAL_I2C_POWER_MON 1 +#define VIRTUAL_I2C_LM75 1 + +#define VIRTUAL_I2C_PORT_LENGTH \ + VIRTUAL_I2C_SFP_PORT+VIRTUAL_I2C_QSFP_PORT+VIRTUAL_I2C_POWER_CHIP_PORT+VIRTUAL_I2C_CPLD_PORT+VIRTUAL_I2C_CPLD_B_PORT+VIRTUAL_I2C_PSU+VIRTUAL_I2C_FAN_TRAY+VIRTUAL_I2C_POWER_MON+VIRTUAL_I2C_LM75 + +#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT+VIRTUAL_I2C_SFP_PORT +#endif + +#define VIRTUAL_I2C_CPLD_INDEX SFF_PORT_TOTAL + +#define VIRTUAL_I2C_BUS_OFFSET 2 +#define CPLD1_SLAVE_ADDR 0x30 +#define CPLD2_SLAVE_ADDR 0x31 + +static struct class* fpgafwclass = NULL; ///< The device-driver class struct pointer +static struct device* fpgafwdev = NULL; ///< The device-driver device struct pointer + +#define PCI_VENDOR_ID_TEST 0x1af4 + +#ifndef PCI_VENDOR_ID_XILINX +#define PCI_VENDOR_ID_XILINX 0x10EE +#endif + +#define FPGA_PCIE_DEVICE_ID 0x7021 +#define TEST_PCIE_DEVICE_ID 0x1110 + + +#ifdef DEBUG_KERN +#define info(fmt,args...) printk(KERN_INFO "line %3d : "fmt,__LINE__,##args) +#define check(REG) printk(KERN_INFO "line %3d : %-8s = %2.2X",__LINE__,#REG,ioread8(REG)); +#else +#define info(fmt,args...) +#define check(REG) +#endif + +#define GET_REG_BIT(REG,BIT) ((ioread8(REG) >> BIT) & 0x01) +#define SET_REG_BIT_H(REG,BIT) iowrite8(ioread8(REG) | (0x01 << BIT),REG) +#define SET_REG_BIT_L(REG,BIT) iowrite8(ioread8(REG) & ~(0x01 << BIT),REG) + +static struct mutex fpga_i2c_master_locks[I2C_MASTER_CH_TOTAL]; +/* Store lasted switch address and channel */ +static uint16_t fpga_i2c_lasted_access_port[I2C_MASTER_CH_TOTAL]; + +enum PORT_TYPE { + NONE, + QSFP, + SFP +}; + +struct i2c_switch{ + unsigned char master_bus; // I2C bus number + unsigned char switch_addr; // PCA9548 device address, 0xFF if directly connect to a bus. + unsigned char channel; // PCA9548 channel number. If the switch_addr is 0xFF, this value is ignored. + enum PORT_TYPE port_type; // QSFP/SFP tranceiver port type. + char calling_name[20]; // Calling name. +}; + +struct i2c_dev_data { + int portid; + struct i2c_switch pca9548; +}; + +#ifdef SEASTONE2 +/* PREDEFINED I2C SWITCH DEVICE TOPOLOGY */ +static struct i2c_switch fpga_i2c_bus_dev[] = { + /* BUS2 QSFP Exported as virtual bus */ + {I2C_MASTER_CH_2,0x72,0,QSFP,"QSFP1"}, {I2C_MASTER_CH_2,0x72,1,QSFP,"QSFP2"}, {I2C_MASTER_CH_2,0x72,2,QSFP,"QSFP3"}, {I2C_MASTER_CH_2,0x72,3,QSFP,"QSFP4"}, + {I2C_MASTER_CH_2,0x72,4,QSFP,"QSFP5"}, {I2C_MASTER_CH_2,0x72,5,QSFP,"QSFP6"}, {I2C_MASTER_CH_2,0x72,6,QSFP,"QSFP7"}, {I2C_MASTER_CH_2,0x72,7,QSFP,"QSFP8"}, + {I2C_MASTER_CH_2,0x73,0,QSFP,"QSFP9"}, {I2C_MASTER_CH_2,0x73,1,QSFP,"QSFP10"},{I2C_MASTER_CH_2,0x73,2,QSFP,"QSFP11"},{I2C_MASTER_CH_2,0x73,3,QSFP,"QSFP12"}, + {I2C_MASTER_CH_2,0x73,4,QSFP,"QSFP13"},{I2C_MASTER_CH_2,0x73,5,QSFP,"QSFP14"},{I2C_MASTER_CH_2,0x73,6,QSFP,"QSFP15"},{I2C_MASTER_CH_2,0x73,7,QSFP,"QSFP16"}, + {I2C_MASTER_CH_2,0x74,0,QSFP,"QSFP17"},{I2C_MASTER_CH_2,0x74,1,QSFP,"QSFP18"},{I2C_MASTER_CH_2,0x74,2,QSFP,"QSFP19"},{I2C_MASTER_CH_2,0x74,3,QSFP,"QSFP20"}, + {I2C_MASTER_CH_2,0x74,4,QSFP,"QSFP21"},{I2C_MASTER_CH_2,0x74,5,QSFP,"QSFP22"},{I2C_MASTER_CH_2,0x74,6,QSFP,"QSFP23"},{I2C_MASTER_CH_2,0x74,7,QSFP,"QSFP24"}, + {I2C_MASTER_CH_2,0x75,0,QSFP,"QSFP25"},{I2C_MASTER_CH_2,0x75,1,QSFP,"QSFP26"},{I2C_MASTER_CH_2,0x75,2,QSFP,"QSFP27"},{I2C_MASTER_CH_2,0x75,3,QSFP,"QSFP28"}, + {I2C_MASTER_CH_2,0x75,4,QSFP,"QSFP29"},{I2C_MASTER_CH_2,0x75,5,QSFP,"QSFP30"},{I2C_MASTER_CH_2,0x75,6,QSFP,"QSFP31"},{I2C_MASTER_CH_2,0x75,7,QSFP,"QSFP32"}, + /* BUS1 SFP+ Exported as virtual bus */ + {I2C_MASTER_CH_1,0x72,0,SFP,"SFP1"},{I2C_MASTER_CH_1,0x72,1,SFP,"SFP2"}, + /* BUS3 CPLD Access via SYSFS */ + {I2C_MASTER_CH_3,0xFF,0,NONE,"CPLD"}, + /* BUS5 POWER CHIP Exported as virtual bus */ + {I2C_MASTER_CH_5,0xFF,0,NONE,"POWER"}, + /* BUS4 CPLD_B */ + {I2C_MASTER_CH_4,0xFF,0,NONE,"CPLD_B"}, + /* BUS6 PSU */ + {I2C_MASTER_CH_6,0xFF,0,NONE,"PSU"}, + /* BUS7 FAN */ + /* Channel 2 is no hardware connected */ + {I2C_MASTER_CH_7,0x77,0,NONE,"FAN5"},{I2C_MASTER_CH_7,0x77,1,NONE,"FAN4"},{I2C_MASTER_CH_7,0x77,3,NONE,"FAN2"},{I2C_MASTER_CH_7,0x77,4,NONE,"FAN1"}, + /* BUS8 POWER MONITOR */ + {I2C_MASTER_CH_8,0xFF,0,NONE,"UCD90120"}, + /* BUS9 LM75 */ + {I2C_MASTER_CH_9,0xFF,0,NONE,"LM75"}, +}; +#else +/* PREDEFINED I2C SWITCH DEVICE TOPOLOGY */ +static struct i2c_switch fpga_i2c_bus_dev[] = { + /* BUS1 SFP Exported as virtual bus */ + {I2C_MASTER_CH_10,0x72,0,SFP,"SFP1"}, {I2C_MASTER_CH_10,0x72,1,SFP,"SFP2"}, {I2C_MASTER_CH_10,0x72,2,SFP,"SFP3"}, {I2C_MASTER_CH_10,0x72,3,SFP,"SFP4"}, + {I2C_MASTER_CH_10,0x72,4,SFP,"SFP5"}, {I2C_MASTER_CH_10,0x72,5,SFP,"SFP6"}, {I2C_MASTER_CH_10,0x72,6,SFP,"SFP7"}, {I2C_MASTER_CH_10,0x72,7,SFP,"SFP8"}, + {I2C_MASTER_CH_10,0x73,0,SFP,"SFP9"}, {I2C_MASTER_CH_10,0x73,1,SFP,"SFP10"},{I2C_MASTER_CH_10,0x73,2,SFP,"SFP11"},{I2C_MASTER_CH_10,0x73,3,SFP,"SFP12"}, + {I2C_MASTER_CH_10,0x73,4,SFP,"SFP13"},{I2C_MASTER_CH_10,0x73,5,SFP,"SFP14"},{I2C_MASTER_CH_10,0x73,6,SFP,"SFP15"},{I2C_MASTER_CH_10,0x73,7,SFP,"SFP16"}, + {I2C_MASTER_CH_10,0x74,0,SFP,"SFP17"},{I2C_MASTER_CH_10,0x74,1,SFP,"SFP18"},{I2C_MASTER_CH_10,0x74,2,SFP,"SFP19"},{I2C_MASTER_CH_10,0x74,3,SFP,"SFP20"}, + {I2C_MASTER_CH_10,0x74,4,SFP,"SFP21"},{I2C_MASTER_CH_10,0x74,5,SFP,"SFP22"},{I2C_MASTER_CH_10,0x74,6,SFP,"SFP23"},{I2C_MASTER_CH_10,0x74,7,SFP,"SFP24"}, + {I2C_MASTER_CH_10,0x75,0,SFP,"SFP25"},{I2C_MASTER_CH_10,0x75,1,SFP,"SFP26"},{I2C_MASTER_CH_10,0x75,2,SFP,"SFP27"},{I2C_MASTER_CH_10,0x75,3,SFP,"SFP28"}, + {I2C_MASTER_CH_10,0x75,4,SFP,"SFP29"},{I2C_MASTER_CH_10,0x75,5,SFP,"SFP30"},{I2C_MASTER_CH_10,0x75,6,SFP,"SFP31"},{I2C_MASTER_CH_10,0x75,7,SFP,"SFP32"}, + {I2C_MASTER_CH_10,0x76,0,SFP,"SFP33"},{I2C_MASTER_CH_10,0x76,1,SFP,"SFP34"},{I2C_MASTER_CH_10,0x76,2,SFP,"SFP35"},{I2C_MASTER_CH_10,0x76,3,SFP,"SFP36"}, + {I2C_MASTER_CH_10,0x76,4,SFP,"SFP37"},{I2C_MASTER_CH_10,0x76,5,SFP,"SFP38"},{I2C_MASTER_CH_10,0x76,6,SFP,"SFP39"},{I2C_MASTER_CH_10,0x76,7,SFP,"SFP40"}, + {I2C_MASTER_CH_10,0x77,0,SFP,"SFP41"},{I2C_MASTER_CH_10,0x77,1,SFP,"SFP42"},{I2C_MASTER_CH_10,0x77,2,SFP,"SFP43"},{I2C_MASTER_CH_10,0x77,3,SFP,"SFP44"}, + {I2C_MASTER_CH_10,0x77,4,SFP,"SFP45"},{I2C_MASTER_CH_10,0x77,5,SFP,"SFP46"},{I2C_MASTER_CH_10,0x77,6,SFP,"SFP47"},{I2C_MASTER_CH_10,0x77,7,SFP,"SFP48"}, + /* BUS2 QSFP28 Exported as virtual bus */ + {I2C_MASTER_CH_2,0x74,4,QSFP,"QSFP1"},{I2C_MASTER_CH_2,0x74,5,QSFP,"QSFP2"},{I2C_MASTER_CH_2,0x74,6,QSFP,"QSFP3"},{I2C_MASTER_CH_2,0x74,7,QSFP,"QSFP4"}, + {I2C_MASTER_CH_2,0x74,0,QSFP,"QSFP5"},{I2C_MASTER_CH_2,0x74,1,QSFP,"QSFP6"},{I2C_MASTER_CH_2,0x74,2,QSFP,"QSFP7"},{I2C_MASTER_CH_2,0x74,3,QSFP,"QSFP8"}, + /* BUS3 CPLD Access via SYSFS */ + {I2C_MASTER_CH_3,0xFF,0,NONE,"CPLD"}, + /* BUS5 POWER CHIP Exported as virtual bus */ + {I2C_MASTER_CH_5,0xFF,0,NONE,"POWER"}, + /* BUS4 CPLD_B */ + {I2C_MASTER_CH_4,0xFF,0,NONE,"CPLD_B"}, + /* BUS6 PSU */ + {I2C_MASTER_CH_6,0xFF,0,NONE,"PSU"}, + /* BUS7 FAN */ + /* Channel 2 is no hardware connected */ + {I2C_MASTER_CH_7,0x77,0,NONE,"FAN5"},{I2C_MASTER_CH_7,0x77,1,NONE,"FAN4"},{I2C_MASTER_CH_7,0x77,3,NONE,"FAN2"},{I2C_MASTER_CH_7,0x77,4,NONE,"FAN1"}, + /* BUS8 UCD90120 */ + {I2C_MASTER_CH_8,0xFF,0,NONE,"UCD90120"}, + /* BUS9 TEMP SENSOR LM75 */ + {I2C_MASTER_CH_9,0xFF,0,NONE,"LM75"} +}; +#endif +struct fpga_device{ + /* data mmio region */ + void __iomem *data_base_addr; + resource_size_t data_mmio_start; + resource_size_t data_mmio_len; +}; + +static struct fpga_device fpga_dev = { + .data_base_addr = NULL, + .data_mmio_start = NULL, + .data_mmio_len = NULL, +}; + +struct seastone2_fpga_data { + struct device *sff_devices[SFF_PORT_TOTAL]; + struct i2c_client *sff_i2c_clients[SFF_PORT_TOTAL]; + struct i2c_adapter *i2c_adapter[VIRTUAL_I2C_PORT_LENGTH]; + struct mutex fpga_lock; // For FPGA internal lock + unsigned long fpga_read_addr; + uint8_t cpld1_read_addr; + uint8_t cpld2_read_addr; +}; + +struct sff_device_data { + int portid; + enum PORT_TYPE port_type; +}; + +struct seastone2_fpga_data *fpga_data; + +/* + * Kernel object for other module drivers. + * Other module can use these kobject as a parent. + */ + +static struct kobject *fpga = NULL; +static struct kobject *cpld1 = NULL; +static struct kobject *cpld2 = NULL; + +/** + * Device node in sysfs tree. + */ +static struct device *sff_dev = NULL; + +/** + * [get_fpga_reg_value description] + * @param dev [description] + * @param devattr [description] + * @param buf [description] + * @return [description] + */ +static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + // read data from the address + uint32_t data; + data = ioread32(fpga_data->fpga_read_addr); + return sprintf(buf,"0x%8.8x\n",data); +} +/** + * [set_fpga_reg_address description] + * @param dev [description] + * @param devattr [description] + * @param buf [description] + * @param count [description] + * @return [description] + */ +static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t addr; + char *last; + + addr = (uint32_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + fpga_data->fpga_read_addr = fpga_dev.data_base_addr+addr; + return count; +} +/** + * [get_fpga_scratch description] + * @param dev [description] + * @param devattr [description] + * @param buf [description] + * @return [description] + */ +static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf,"0x%8.8x\n", ioread32(fpga_dev.data_base_addr+FPGA_SCRATCH) & 0xffffffff); +} +/** + * [set_fpga_scratch description] + * @param dev [description] + * @param devattr [description] + * @param buf [description] + * @param count [description] + * @return [description] + */ +static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t data; + char *last; + data = (uint32_t)strtoul(buf,&last,16); + if(data == 0 && buf == last){ + return -EINVAL; + } + iowrite32(data, fpga_dev.data_base_addr+FPGA_SCRATCH); + return count; +} +/** + * [set_fpga_reg_value description] + * @param dev [description] + * @param devattr [description] + * @param buf [description] + * @return [description] + */ +static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + //register is 4 bytes + uint32_t addr; + uint32_t value; + uint32_t mode = 8; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + + strscpy(clone, buf, count); + + mutex_lock(&fpga_data->fpga_lock); + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + addr = (uint32_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + value = (uint32_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mode = 32; + }else{ + mode = (uint32_t)strtoul(tok,&last,10); + if(mode == 0 && tok == last){ + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + } + if(mode == 32){ + iowrite32(value, fpga_dev.data_base_addr+addr); + }else if(mode == 8){ + iowrite8(value, fpga_dev.data_base_addr+addr); + }else{ + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + mutex_unlock(&fpga_data->fpga_lock); + return count; +} + +/** + * Read all FPGA XCVR register in binary mode. + * @param filp [description] + * @param kobj [description] + * @param attr [description] + * @param buf [description] + * @param off [description] + * @param count [description] + * @return [description] + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i=0; + ssize_t status; + u8 read_reg; + + if( off + count > PORT_XCVR_REGISTER_SIZE ){ + return -EINVAL; + } + mutex_lock(&fpga_data->fpga_lock); + while(i < count){ + read_reg = ioread8(fpga_dev.data_base_addr + SFF_PORT_CTRL_BASE + off + i); + buf[i++] = read_reg; + } + status = count; + mutex_unlock(&fpga_data->fpga_lock); + return status; +} + +/** + * Show FPGA port XCVR ready status + * @param dev [description] + * @param attr [description] + * @param buf [description] + * @return [description] + */ +static ssize_t ready_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int REGISTER = FPGA_PORT_XCVR_READY; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> 0) & 1U); +} + +/* FPGA attributes */ +static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address); +static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch); +static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value); +static DEVICE_ATTR_RO(ready); +static BIN_ATTR_RO( dump, PORT_XCVR_REGISTER_SIZE); + +static struct bin_attribute *fpga_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute *fpga_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_scratch.attr, + &dev_attr_setreg.attr, + &dev_attr_ready.attr, + NULL, +}; + +static struct attribute_group fpga_attr_grp = { + .attrs = fpga_attrs, + .bin_attrs = fpga_bin_attrs, +}; + +/* SW CPLDs attributes */ +static ssize_t cpld1_getreg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + uint8_t data; + int err; + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, + I2C_SMBUS_READ, fpga_data->cpld1_read_addr, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + + if (err < 0) + return err; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t cpld1_getreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + uint8_t addr; + + status = kstrtou8(buf, 0, &addr); + if (status == 0) { + fpga_data->cpld1_read_addr = addr; + status = count; + } + return status; +} +struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store); + +static ssize_t cpld1_dump_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + uint8_t data; + fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00,I2C_SMBUS_READ,fpga_data->cpld1_read_addr,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&data); + return sprintf(buf,"0x%2.2x\n",data); +} +static ssize_t cpld1_dump_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + uint8_t addr; + char *last; + addr = (uint8_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + fpga_data->cpld1_read_addr = addr; + return size; +} +struct device_attribute dev_attr_cpld1_dump = __ATTR(dump,0600,cpld1_dump_show,cpld1_dump_store); + +static ssize_t cpld1_scratch_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + __u8 data; + int err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00,I2C_SMBUS_READ,0x01,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&data); + if(err < 0) + return err; + return sprintf(buf, "0x%2.2x\n",data); +} +static ssize_t cpld1_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + // CPLD register is one byte + __u8 data; + char *last; + int err; + data = (uint8_t)strtoul(buf,&last,16); + if(data == 0 && buf == last){ + return -EINVAL; + } + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00,I2C_SMBUS_WRITE,0x01,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&data); + if(err < 0) + return err; + return size; +} +struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch,0600,cpld1_scratch_show,cpld1_scratch_store); + +static ssize_t cpld1_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + + uint8_t addr,value; + char *tok; + char clone[size]; + char *pclone = clone; + int err; + char *last; + + strscpy(clone, buf, size); + + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + return sprintf(buf,"ERROR line %d",__LINE__); + } + addr = (uint8_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + return sprintf(buf,"ERROR line %d",__LINE__); + } + value = (uint8_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + return -EINVAL; + } + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00,I2C_SMBUS_WRITE,addr,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&value); + if(err < 0) + return sprintf(buf,"ERROR line %d",__LINE__); + + return size; +} +struct device_attribute dev_attr_cpld1_setreg = __ATTR(setreg,0200,NULL,cpld1_setreg_store); + +static struct attribute *cpld1_attrs[] = { + &dev_attr_cpld1_getreg.attr, + &dev_attr_cpld1_dump.attr, + &dev_attr_cpld1_scratch.attr, + &dev_attr_cpld1_setreg.attr, + NULL, +}; + +static struct attribute_group cpld1_attr_grp = { + .attrs = cpld1_attrs, +}; + +static ssize_t cpld2_getreg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + uint8_t data; + int err; + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data); + if (err < 0) + return err; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t cpld2_getreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint8_t addr; + ssize_t status; + + status = kstrtou8(buf, 0, &addr); + if (status == 0) { + fpga_data->cpld2_read_addr = addr; + status = count; + } + return status; +} +struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store); + +static ssize_t cpld2_dump_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + uint8_t data; + fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00,I2C_SMBUS_READ,fpga_data->cpld2_read_addr,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&data); + return sprintf(buf,"0x%2.2x\n",data); +} +static ssize_t cpld2_dump_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + // CPLD register is one byte + uint32_t addr; + char *last; + addr = (uint8_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + fpga_data->cpld2_read_addr = addr; + return size; +} +struct device_attribute dev_attr_cpld2_dump = __ATTR(dump,0600,cpld2_dump_show,cpld2_dump_store); + +static ssize_t cpld2_scratch_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + __u8 data; + int err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00,I2C_SMBUS_READ,0x01,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&data); + if(err < 0) + return err; + return sprintf(buf, "0x%2.2x\n",data); +} +static ssize_t cpld2_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + // CPLD register is one byte + __u8 data; + char *last; + int err; + + data = (uint8_t)strtoul(buf,&last,16); + if(data == 0 && buf == last){ + return -EINVAL; + } + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00,I2C_SMBUS_WRITE,0x01,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&data); + if(err < 0) + return err; + return size; +} +struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch,0600,cpld2_scratch_show,cpld2_scratch_store); + +static ssize_t cpld2_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + uint8_t addr,value; + char *tok; + char clone[size]; + char *pclone = clone; + int err; + char *last; + + strscpy(clone, buf, size); + + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + return -EINVAL; + } + addr = (uint8_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + return -EINVAL; + } + value = (uint8_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + return -EINVAL; + } + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00,I2C_SMBUS_WRITE,addr,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&value); + if(err < 0) + return err; + + return size; +} +struct device_attribute dev_attr_cpld2_setreg = __ATTR(setreg,0200,NULL,cpld2_setreg_store); + +static struct attribute *cpld2_attrs[] = { + &dev_attr_cpld2_getreg.attr, + &dev_attr_cpld2_dump.attr, + &dev_attr_cpld2_scratch.attr, + &dev_attr_cpld2_setreg.attr, + NULL, +}; + +static struct attribute_group cpld2_attr_grp = { + .attrs = cpld2_attrs, +}; + +/* QSFP/SFP+ attributes */ +static ssize_t qsfp_modirq_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_IRQ) & 1U); +} +DEVICE_ATTR_RO(qsfp_modirq); + +static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_PRESENT) & 1U); +} +DEVICE_ATTR_RO(qsfp_modprs); + +static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_TXFAULT) & 1U); +} +DEVICE_ATTR_RO(sfp_txfault); + +static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_RXLOS) & 1U); +} +DEVICE_ATTR_RO(sfp_rxlos); + +static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_MODABS) & 1U); +} +DEVICE_ATTR_RO(sfp_modabs); + +static ssize_t qsfp_lpmode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_LPMOD) & 1U); +} +static ssize_t qsfp_lpmode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + long value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr+REGISTER); + if(!value) + data = data & ~( (u32)0x1 << CTRL_LPMOD); + else + data = data | ((u32)0x1 << CTRL_LPMOD); + iowrite32(data,fpga_dev.data_base_addr+REGISTER); + status = size; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_lpmode); + +static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_RST) & 1U); +} + +static ssize_t qsfp_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + long value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr+REGISTER); + if(!value) + data = data & ~( (u32)0x1 << CTRL_RST); + else + data = data | ((u32)0x1 << CTRL_RST); + iowrite32(data,fpga_dev.data_base_addr+REGISTER); + status = size; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_reset); + +static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr+REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_TXDIS) & 1U); +} +static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + long value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid-1)*0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr+REGISTER); + if(!value) + data = data & ~( (u32)0x1 << CTRL_TXDIS); + else + data = data | ((u32)0x1 << CTRL_TXDIS); + iowrite32(data,fpga_dev.data_base_addr+REGISTER); + status = size; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(sfp_txdisable); + +static struct attribute *sff_attrs[] = { + &dev_attr_qsfp_modirq.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_sfp_txfault.attr, + &dev_attr_sfp_rxlos.attr, + &dev_attr_sfp_modabs.attr, + &dev_attr_sfp_txdisable.attr, + NULL, +}; + +static struct attribute_group sff_attr_grp = { + .attrs = sff_attrs, +}; + +static const struct attribute_group *sff_attr_grps[] = { + &sff_attr_grp, + NULL +}; + + +static ssize_t port_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // value can be "nomal", "test" + __u8 led_mode_1,led_mode_2; + int err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00,I2C_SMBUS_READ,0x09,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_mode_1); + if(err < 0) + return err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00,I2C_SMBUS_READ,0x09,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_mode_2); + if(err < 0) + return err; + return sprintf(buf, "%s %s\n", + led_mode_1 ? "test" : "normal", + led_mode_2 ? "test" : "normal"); +} +static ssize_t port_led_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int status; + __u8 led_mode_1; + if(sysfs_streq(buf, "test")){ + led_mode_1 = 0x01; + }else if(sysfs_streq(buf, "normal")){ + led_mode_1 = 0x00; + }else{ + return -EINVAL; + } + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00, + I2C_SMBUS_WRITE,0x09,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_mode_1); + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00, + I2C_SMBUS_WRITE,0x09,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_mode_1); + return size; +} +DEVICE_ATTR_RW(port_led_mode); + +// Only work when port_led_mode set to 1 +static ssize_t port_led_color_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + // value can be "off", "green", "amber", "both" + __u8 led_color1,led_color2; + int err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00,I2C_SMBUS_READ,0x09,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_color1); + if(err < 0) + return err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00,I2C_SMBUS_READ,0x09,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_color2); + if(err < 0) + return err; + return sprintf(buf, "%s %s\n", + led_color1 == 0x03 ? "off" : led_color1 == 0x02 ? "green" : led_color1 ==0x01 ? "amber": "both", + led_color2 == 0x03 ? "off" : led_color2 == 0x02 ? "green" : led_color2 ==0x01 ? "amber": "both"); +} + +static ssize_t port_led_color_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int status; + __u8 led_color; + if(sysfs_streq(buf, "off")){ + led_color = 0x03; + }else if(sysfs_streq(buf, "green")){ + led_color = 0x02; + }else if(sysfs_streq(buf, "amber")){ + led_color = 0x01; + }else if(sysfs_streq(buf, "both")){ + led_color = 0x00; + }else{ + status = -EINVAL; + return status; + } + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00, + I2C_SMBUS_WRITE,0x0A,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_color); + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00, + I2C_SMBUS_WRITE,0x0A,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&led_color); + return size; +} +DEVICE_ATTR_RW(port_led_color); + +static struct attribute *sff_led_test[] = { + &dev_attr_port_led_mode.attr, + &dev_attr_port_led_color.attr, + NULL, +}; + +static struct attribute_group sff_led_test_grp = { + .attrs = sff_led_test, +}; + +static struct device * seastone2_sff_init(int portid){ + struct sff_device_data *new_data; + struct device *new_device; + + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); + if (!new_data) { + printk(KERN_ALERT "Cannot alloc sff device data @port%d", portid); + return NULL; + } + /* The QSFP port ID start from 1 */ + new_data->portid = portid+1; + new_data->port_type = fpga_i2c_bus_dev[portid].port_type; + new_device = device_create_with_groups(fpgafwclass, sff_dev, MKDEV(0,0), new_data, sff_attr_grps, "%s",fpga_i2c_bus_dev[portid].calling_name); + if (IS_ERR(new_device)) { + printk(KERN_ALERT "Cannot create sff device @port%d", portid); + kfree(new_data); + return NULL; + } + return new_device; +} + +static int i2c_wait_ack(struct i2c_adapter *a,unsigned long timeout,int writing){ + int error = 0; + int Status; + + struct i2c_dev_data *new_data = i2c_get_adapdata(a); + void __iomem *pci_bar = fpga_dev.data_base_addr; + + unsigned int REG_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + unsigned int master_bus = new_data->pca9548.master_bus; + + if(master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL){ + error = -ENXIO; + return error; + } + + REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus-1)*0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus-1)*0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus-1)*0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus-1)*0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus-1)*0x0100; + + check(pci_bar+REG_SR0); + check(pci_bar+REG_CR0); + + timeout = jiffies + msecs_to_jiffies(timeout); + while(1){ + Status = ioread8(pci_bar+REG_SR0); + if(jiffies > timeout){ + info("Status %2.2X",Status); + info("Error Timeout"); + error = -ETIMEDOUT; + break; + } + + + if(Status & (1 << I2C_SR_BIT_MIF)){ + break; + } + + if(writing == 0 && (Status & (1<portid; + void __iomem *pci_bar = fpga_dev.data_base_addr; + +#ifdef DEBUG_KERN + printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-15s|CMD %2.2X " + ,portid,addr,flags,rw,rw == 1 ? "READ ":"WRITE" + ,size, size == 0 ? "QUICK" : + size == 1 ? "BYTE" : + size == 2 ? "BYTE_DATA" : + size == 3 ? "WORD_DATA" : + size == 4 ? "PROC_CALL" : + size == 5 ? "BLOCK_DATA" : + size == 8 ? "I2C_BLOCK_DATA" : "ERROR" + ,cmd); +#endif + /* Map the size to what the chip understands */ + switch (size) { + case I2C_SMBUS_QUICK: + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + case I2C_SMBUS_WORD_DATA: + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: + break; + default: + printk(KERN_INFO "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; + } + + unsigned int REG_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + unsigned int master_bus = dev_data->pca9548.master_bus; + + if(master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL){ + error = -ENXIO; + goto Done; + } + + REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus-1)*0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus-1)*0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus-1)*0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus-1)*0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus-1)*0x0100; + + iowrite8(portid,pci_bar+REG_ID0); + + int cnt=0; + + ////[S][ADDR/R] + // Clear status register + iowrite8(0,pci_bar+REG_SR0); + iowrite8(1 << I2C_CR_BIT_MIEN | 1 << I2C_CR_BIT_MTX | 1 << I2C_CR_BIT_MSTA ,pci_bar+REG_CR0); + SET_REG_BIT_H(pci_bar+REG_CR0,I2C_CR_BIT_MEN); + + if(rw == I2C_SMBUS_READ && + (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)){ + // sent device address with Read mode + iowrite8(addr << 1 | 0x01,pci_bar+REG_DR0); + }else{ + // sent device address with Write mode + iowrite8(addr << 1 | 0x00,pci_bar+REG_DR0); + } + + + + info( "MS Start"); + + //// Wait {A} + error = i2c_wait_ack(adapter,12,1); + if(error<0){ + info( "get error %d",error); + goto Done; + } + + //// [CMD]{A} + if(size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA || + (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)){ + + // sent command code to data register + iowrite8(cmd,pci_bar+REG_DR0); + info( "MS Send CMD 0x%2.2X",cmd); + + // Wait {A} + error = i2c_wait_ack(adapter,12,1); + if(error<0){ + info( "get error %d",error); + goto Done; + } + } + + switch(size){ + case I2C_SMBUS_BYTE_DATA: + cnt = 1; break; + case I2C_SMBUS_WORD_DATA: + cnt = 2; break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: + /* In block data modes keep number of byte in block[0] */ + cnt = data->block[0]; + break; + default: + cnt = 0; break; + } + + // [CNT] used only block data write + if(size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE){ + + iowrite8(cnt,pci_bar+REG_DR0); + info( "MS Send CNT 0x%2.2X",cnt); + + // Wait {A} + error = i2c_wait_ack(adapter,12,1); + if(error<0){ + info( "get error %d",error); + goto Done; + } + } + + // [DATA]{A} + if( rw == I2C_SMBUS_WRITE && ( + size == I2C_SMBUS_BYTE || + size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA + )){ + int bid=0; + info( "MS prepare to sent [%d bytes]",cnt); + if(size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_I2C_BLOCK_DATA){ + bid=1; // block[0] is cnt; + cnt+=1; // offset from block[0] + } + for(;bidblock[bid],pci_bar+REG_DR0); + info( " Data > %2.2X",data->block[bid]); + // Wait {A} + error = i2c_wait_ack(adapter,12,1); + if(error<0){ + goto Done; + } + } + + } + + // REPEATE START + if( rw == I2C_SMBUS_READ && ( + size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA + )){ + info( "MS Repeated Start"); + + SET_REG_BIT_L(pci_bar+REG_CR0,I2C_CR_BIT_MEN); + iowrite8(1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MTX | + 1 << I2C_CR_BIT_MSTA | + 1 << I2C_CR_BIT_RSTA ,pci_bar+REG_CR0); + SET_REG_BIT_H(pci_bar+REG_CR0,I2C_CR_BIT_MEN); + + // sent Address with Read mode + iowrite8( addr<<1 | 0x1 ,pci_bar+REG_DR0); + + // Wait {A} + error = i2c_wait_ack(adapter,12,1); + if(error<0){ + goto Done; + } + + } + + if( rw == I2C_SMBUS_READ && ( + size == I2C_SMBUS_BYTE || + size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA || + size == I2C_SMBUS_I2C_BLOCK_DATA + )){ + + switch(size){ + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + cnt = 1; break; + case I2C_SMBUS_WORD_DATA: + cnt = 2; break; + case I2C_SMBUS_BLOCK_DATA: + // will be changed after recived first data + cnt = 3; break; + case I2C_SMBUS_I2C_BLOCK_DATA: + cnt = data->block[0]; break; + default: + cnt = 0; break; + } + + int bid = 0; + info( "MS Receive"); + + //set to Receive mode + iowrite8(1 << I2C_CR_BIT_MEN | + 1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MSTA , pci_bar+REG_CR0); + + for(bid=-1;bidblock[bid+1] = ioread8(pci_bar+REG_DR0); + }else { + data->block[bid] = ioread8(pci_bar+REG_DR0); + } + info( "DATA IN [%d] %2.2X",bid,data->block[bid]); + + if(size == I2C_SMBUS_BLOCK_DATA && bid == 0){ + cnt = data->block[0] + 1; + } + } + } + } + +Stop: + // [P] + SET_REG_BIT_L(pci_bar+REG_CR0,I2C_CR_BIT_MSTA); + info( "MS STOP"); + +Done: + iowrite8(1<pca9548.master_bus; + unsigned char switch_addr = dev_data->pca9548.switch_addr; + unsigned char channel = dev_data->pca9548.channel; + + // Acquire the master resource. + mutex_lock(&fpga_i2c_master_locks[master_bus-1]); + uint16_t prev_port = fpga_i2c_lasted_access_port[master_bus-1]; + + if(switch_addr != 0xFF){ + // Check lasted access switch address on a master + if((unsigned char)(prev_port >> 8) == switch_addr){ + // check if channel is the same + if((unsigned char)(prev_port & 0x00FF) != channel){ + // set new PCA9548 at switch_addr to current + error= smbus_access(adapter,switch_addr,flags,I2C_SMBUS_WRITE,1 << channel,I2C_SMBUS_BYTE,NULL); + // update lasted port + fpga_i2c_lasted_access_port[master_bus-1] = switch_addr << 8 | channel; + } + }else{ + // reset prev_port PCA9548 chip + error= smbus_access(adapter,(u16)(prev_port >> 8),flags,I2C_SMBUS_WRITE,0x00,I2C_SMBUS_BYTE,NULL); + // set PCA9548 to current channel + error= smbus_access(adapter,switch_addr,flags,I2C_SMBUS_WRITE,1 << channel,I2C_SMBUS_BYTE,NULL); + // update lasted port + fpga_i2c_lasted_access_port[master_bus-1] = switch_addr << 8 | channel; + } + } + + // Do SMBus communication + error = smbus_access(adapter,addr,flags,rw,cmd,size,data); + // reset the channel + mutex_unlock(&fpga_i2c_master_locks[master_bus-1]); + return error; +} + + + +/** + * A callback function show available smbus functions. + */ +static u32 fpga_i2c_func(struct i2c_adapter *a) +{ + return I2C_FUNC_SMBUS_QUICK | + I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA| + I2C_FUNC_SMBUS_I2C_BLOCK; +} + +static const struct i2c_algorithm seastone2_i2c_algorithm = { + .smbus_xfer = fpga_i2c_access, + .functionality = fpga_i2c_func, +}; + +/** + * Create virtual I2C bus adapter for switch devices + * @param pdev platform device pointer + * @param portid virtual i2c port id for switch device mapping + * @param bus_number_offset bus offset for virtual i2c adapter in system + * @return i2c adapter. + * + * When bus_number_offset is -1, created adapter with dynamic bus number. + * Otherwise create adapter at i2c bus = bus_number_offset + portid. + */ +static struct i2c_adapter * seastone2_i2c_init(struct platform_device *pdev, int portid, int bus_number_offset) +{ + int error; + + struct i2c_adapter *new_adapter; + struct i2c_dev_data *new_data; + + new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL); + if (!new_adapter){ + printk(KERN_ALERT "Cannot alloc i2c adapter for %s", fpga_i2c_bus_dev[portid].calling_name); + return NULL; + } + + new_adapter->owner = THIS_MODULE; + new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + new_adapter->algo = &seastone2_i2c_algorithm; + /* If the bus offset is -1, use dynamic bus number */ + if (bus_number_offset == -1){ + new_adapter->nr = -1; + }else{ + new_adapter->nr = bus_number_offset + portid; + } + + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); + if (!new_data){ + printk(KERN_ALERT "Cannot alloc i2c data for %s", fpga_i2c_bus_dev[portid].calling_name); + kfree_sensitive(new_adapter); + return NULL; + } + + new_data->portid = portid; + new_data->pca9548.master_bus = fpga_i2c_bus_dev[portid].master_bus; + new_data->pca9548.switch_addr = fpga_i2c_bus_dev[portid].switch_addr; + new_data->pca9548.channel = fpga_i2c_bus_dev[portid].channel; + strscpy(new_data->pca9548.calling_name, fpga_i2c_bus_dev[portid].calling_name,sizeof(new_data->pca9548.calling_name)); + + snprintf(new_adapter->name, sizeof(new_adapter->name), + "SMBus I2C Adapter PortID: %s", new_data->pca9548.calling_name); + + void __iomem *i2c_freq_base_reg = fpga_dev.data_base_addr+I2C_MASTER_FREQ_1; + iowrite8(0x07,i2c_freq_base_reg+(new_data->pca9548.master_bus-1)*0x100); // 0x07 400kHz + i2c_set_adapdata(new_adapter,new_data); + error = i2c_add_numbered_adapter(new_adapter); + if(error < 0){ + printk(KERN_ALERT "Cannot add i2c adapter %s", new_data->pca9548.calling_name); + kfree_sensitive(new_adapter); + kfree_sensitive(new_data); + return NULL; + } + + return new_adapter; +}; + +// I/O resource need. +static struct resource seastone2_resources[] = { + { + .start = 0x10000000, + .end = 0x10001000, + .flags = IORESOURCE_MEM, + }, +}; + +static void seastone2_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device seastone2_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(seastone2_resources), + .resource = seastone2_resources, + .dev = { + .release = seastone2_dev_release, + } +}; + +/** + * Board info for QSFP/SFP+ eeprom. + * Note: Using sff8436 as I2C eeprom driver. + */ +static struct i2c_board_info sff8436_eeprom_info[] = { + { I2C_BOARD_INFO("optoe1", 0x50) }, + { I2C_BOARD_INFO("optoe2", 0x50) }, +}; + +static int seastone2_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + int portid_count; + uint8_t cpld1_version, cpld2_version; + uint16_t prev_i2c_switch = 0; + + /* The device class need to be instantiated before this function called */ + BUG_ON(fpgafwclass == NULL); + + fpga_data = devm_kzalloc(&pdev->dev, sizeof(struct seastone2_fpga_data), + GFP_KERNEL); + + if (!fpga_data) + return -ENOMEM; + + // Set default read address to VERSION + fpga_data->fpga_read_addr = fpga_dev.data_base_addr+FPGA_VERSION; + fpga_data->cpld1_read_addr = 0x00; + fpga_data->cpld2_read_addr = 0x00; + + mutex_init(&fpga_data->fpga_lock); + for(ret=I2C_MASTER_CH_1 ;ret <= I2C_MASTER_CH_TOTAL; ret++){ + mutex_init(&fpga_i2c_master_locks[ret-1]); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) { + printk(KERN_ERR "Specified Resource Not Available...\n"); + kfree_sensitive(fpga_data); + return -1; + } + + fpga = kobject_create_and_add("FPGA", &pdev->dev.kobj); + if (!fpga){ + kfree_sensitive(fpga_data); + return -ENOMEM; + } + + ret = sysfs_create_group(fpga, &fpga_attr_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create FPGA sysfs attributes\n"); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return ret; + } + + cpld1 = kobject_create_and_add("CPLD1", &pdev->dev.kobj); + if (!cpld1){ + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return -ENOMEM; + } + ret = sysfs_create_group(cpld1, &cpld1_attr_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create CPLD1 sysfs attributes\n"); + kobject_put(cpld1); + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return ret; + } + + cpld2 = kobject_create_and_add("CPLD2", &pdev->dev.kobj); + if (!cpld2){ + sysfs_remove_group(cpld1, &cpld1_attr_grp); + kobject_put(cpld1); + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return -ENOMEM; + } + ret = sysfs_create_group(cpld2, &cpld2_attr_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create CPLD2 sysfs attributes\n"); + kobject_put(cpld2); + sysfs_remove_group(cpld1, &cpld1_attr_grp); + kobject_put(cpld1); + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return ret; + } + + sff_dev = device_create(fpgafwclass, NULL, MKDEV(0,0), NULL, "sff_device"); + if (IS_ERR(sff_dev)){ + printk(KERN_ERR "Failed to create sff device\n"); + sysfs_remove_group(cpld2, &cpld2_attr_grp); + kobject_put(cpld2); + sysfs_remove_group(cpld1, &cpld1_attr_grp); + kobject_put(cpld1); + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return PTR_ERR(sff_dev); + } + + ret = sysfs_create_group(&sff_dev->kobj, &sff_led_test_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create SFF attributes\n"); + device_destroy(fpgafwclass, MKDEV(0,0)); + sysfs_remove_group(cpld2, &cpld2_attr_grp); + kobject_put(cpld2); + sysfs_remove_group(cpld1, &cpld1_attr_grp); + kobject_put(cpld1); + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return ret; + } + + ret = sysfs_create_link(&pdev->dev.kobj,&sff_dev->kobj,"SFF"); + if (ret != 0){ + sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp); + device_destroy(fpgafwclass, MKDEV(0,0)); + sysfs_remove_group(cpld2, &cpld2_attr_grp); + kobject_put(cpld2); + sysfs_remove_group(cpld1, &cpld1_attr_grp); + kobject_put(cpld1); + sysfs_remove_group(fpga, &fpga_attr_grp); + kobject_put(fpga); + kfree_sensitive(fpga_data); + return ret; + } + + for(portid_count=0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++){ + fpga_data->i2c_adapter[portid_count] = seastone2_i2c_init(pdev, portid_count, VIRTUAL_I2C_BUS_OFFSET); + } + + + /* Init SFF devices */ + for(portid_count=0; portid_count < SFF_PORT_TOTAL; portid_count++){ + struct i2c_adapter *i2c_adap = fpga_data->i2c_adapter[portid_count]; + if(i2c_adap){ + fpga_data->sff_devices[portid_count] = seastone2_sff_init(portid_count); + struct sff_device_data *sff_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]); + BUG_ON(sff_data == NULL); + if( sff_data->port_type == QSFP ){ + fpga_data->sff_i2c_clients[portid_count] = i2c_new_client_device(i2c_adap, &sff8436_eeprom_info[0]); + }else{ + fpga_data->sff_i2c_clients[portid_count] = i2c_new_client_device(i2c_adap, &sff8436_eeprom_info[1]); + } + sff_data = NULL; + sysfs_create_link(&fpga_data->sff_devices[portid_count]->kobj, + &fpga_data->sff_i2c_clients[portid_count]->dev.kobj, + "i2c"); + } + + } + + printk(KERN_INFO "Virtual I2C buses created\n"); + +#ifdef TEST_MODE + return 0; +#endif + fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD1_SLAVE_ADDR,0x00, + I2C_SMBUS_READ,0x00,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&cpld1_version); + fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX],CPLD2_SLAVE_ADDR,0x00, + I2C_SMBUS_READ,0x00,I2C_SMBUS_BYTE_DATA,(union i2c_smbus_data*)&cpld2_version); + + printk(KERN_INFO "CPLD1 VERSON: %2.2x\n", cpld1_version); + printk(KERN_INFO "CPLD2 VERSON: %2.2x\n", cpld2_version); + + /* Init I2C buses that has PCA9548 switch device. */ + for(portid_count = 0; portid_count < VIRTUAL_I2C_PORT_LENGTH; portid_count++){ + + struct i2c_dev_data *dev_data; + dev_data = i2c_get_adapdata(fpga_data->i2c_adapter[portid_count]); + unsigned char master_bus = dev_data->pca9548.master_bus; + unsigned char switch_addr = dev_data->pca9548.switch_addr; + unsigned char channel = dev_data->pca9548.channel; + + if(switch_addr != 0xFF){ + + if(prev_i2c_switch != ( (master_bus << 8) | switch_addr) ){ + // Found the bus with PCA9548, trying to clear all switch in it. + smbus_access(fpga_data->i2c_adapter[portid_count],switch_addr,0x00,I2C_SMBUS_WRITE,0x00,I2C_SMBUS_BYTE,NULL); + prev_i2c_switch = ( master_bus << 8 ) | switch_addr; + } + } + } + return 0; +} + +static int seastone2_drv_remove(struct platform_device *pdev) +{ + int portid_count; + struct sff_device_data *rem_data; + + for(portid_count=0; portid_count < SFF_PORT_TOTAL; portid_count++){ + sysfs_remove_link(&fpga_data->sff_devices[portid_count]->kobj,"i2c"); + i2c_unregister_device(fpga_data->sff_i2c_clients[portid_count]); + } + + for(portid_count=0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++){ + if(fpga_data->i2c_adapter[portid_count] != NULL){ + info(KERN_INFO "<%x>",fpga_data->i2c_adapter[portid_count]); + i2c_del_adapter(fpga_data->i2c_adapter[portid_count]); + } + } + + for (portid_count=0; portid_count < SFF_PORT_TOTAL; portid_count++){ + if(fpga_data->sff_devices[portid_count] != NULL){ + rem_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]); + device_unregister(fpga_data->sff_devices[portid_count]); + put_device(fpga_data->sff_devices[portid_count]); + kfree(rem_data); + } + } + + sysfs_remove_group(fpga, &fpga_attr_grp); + sysfs_remove_group(cpld1, &cpld1_attr_grp); + sysfs_remove_group(cpld2, &cpld2_attr_grp); + sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp); + kobject_put(fpga); + kobject_put(cpld1); + kobject_put(cpld2); + device_destroy(fpgafwclass, MKDEV(0,0)); + devm_kfree(&pdev->dev, fpga_data); + return 0; +} + +#ifdef TEST_MODE + #define FPGA_PCI_BAR_NUM 2 +#else + #define FPGA_PCI_BAR_NUM 0 +#endif + + + +static const struct pci_device_id fpga_id_table[] = { + { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) }, + { PCI_VDEVICE(TEST, TEST_PCIE_DEVICE_ID) }, + {0, } +}; + +MODULE_DEVICE_TABLE(pci, fpga_id_table); + +static int fpga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int err; + struct device *dev = &pdev->dev; + if ((err = pci_enable_device(pdev))) { + dev_err(dev, "pci_enable_device probe error %d for device %s\n", + err, pci_name(pdev)); + return err; + } + + if ((err = pci_request_regions(pdev, FPGA_PCI_NAME)) < 0) { + dev_err(dev, "pci_request_regions error %d\n", err); + goto pci_disable; + } + + /* bar0: data mmio region */ + fpga_dev.data_mmio_start = pci_resource_start(pdev, FPGA_PCI_BAR_NUM); + fpga_dev.data_mmio_len = pci_resource_len(pdev, FPGA_PCI_BAR_NUM); + fpga_dev.data_base_addr = pci_iomap(pdev, FPGA_PCI_BAR_NUM, 0); + if (!fpga_dev.data_base_addr) { + dev_err(dev, "cannot iomap region of size %lu\n", + (unsigned long)fpga_dev.data_mmio_len); + goto pci_release; + } + dev_info(dev, "data_mmio iomap base = 0x%lx \n", + (unsigned long)fpga_dev.data_base_addr); + dev_info(dev, "data_mmio_start = 0x%lx data_mmio_len = %lu\n", + (unsigned long)fpga_dev.data_mmio_start, + (unsigned long)fpga_dev.data_mmio_len); + + printk(KERN_INFO "FPGA PCIe driver probe OK.\n"); + printk(KERN_INFO "FPGA ioremap registers of size %lu\n",(unsigned long)fpga_dev.data_mmio_len); + printk(KERN_INFO "FPGA Virtual BAR %d at %8.8lx - %8.8lx\n",FPGA_PCI_BAR_NUM,(unsigned long)fpga_dev.data_base_addr,(unsigned long)fpga_dev.data_base_addr+ (unsigned long)fpga_dev.data_mmio_len); + printk(KERN_INFO ""); + uint32_t buff = ioread32(fpga_dev.data_base_addr); + printk(KERN_INFO "FPGA VERSION : %8.8x\n", buff); + fpgafw_init(); + return 0; + +reg_release: + pci_iounmap(pdev, fpga_dev.data_base_addr); +pci_release: + pci_release_regions(pdev); +pci_disable: + pci_disable_device(pdev); + return -EBUSY; +} + +static void fpga_pci_remove(struct pci_dev *pdev) +{ + fpgafw_exit(); + pci_iounmap(pdev, fpga_dev.data_base_addr); + pci_release_regions(pdev); + pci_disable_device(pdev); + printk(KERN_INFO "FPGA PCIe driver remove OK.\n"); +}; + +static struct pci_driver pci_dev_ops = { + .name = FPGA_PCI_NAME, + .probe = fpga_pci_probe, + .remove = fpga_pci_remove, + .id_table = fpga_id_table, +}; + + +static struct platform_driver seastone2_drv = { + .probe = seastone2_drv_probe, + .remove = __exit_p(seastone2_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +enum{ + READREG, + WRITEREG +}; + +struct fpga_reg_data { + uint32_t addr; + uint32_t value; +}; + +static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ + int ret = 0; + struct fpga_reg_data data; + mutex_lock(&fpga_data->fpga_lock); + +#ifdef TEST_MODE + static uint32_t status_reg; +#endif + // Switch function to read and write. + switch (cmd){ + case READREG: + if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0){ + mutex_unlock(&fpga_data->fpga_lock); + return -EFAULT; + } + data.value = ioread32(fpga_dev.data_base_addr+data.addr); + if (copy_to_user((void __user*)arg ,&data, sizeof(data)) != 0){ + mutex_unlock(&fpga_data->fpga_lock); + return -EFAULT; + } +#ifdef TEST_MODE + if(data.addr == 0x1210){ + switch (status_reg){ + case 0x0000 : status_reg=0x8000; + break; + + case 0x8080 : status_reg=0x80C0; + break; + case 0x80C0 : status_reg=0x80F0; + break; + case 0x80F0 : status_reg=0x80F8; + break; + + } + iowrite32(status_reg,fpga_dev.data_base_addr+0x1210); + } +#endif + + + break; + case WRITEREG: + if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0){ + mutex_unlock(&fpga_data->fpga_lock); + return -EFAULT; + } + iowrite32(data.value,fpga_dev.data_base_addr+data.addr); + +#ifdef TEST_MODE + if(data.addr == 0x1204){ + status_reg=0x8080; + iowrite32(status_reg,fpga_dev.data_base_addr+0x1210); + } +#endif + + break; + default: + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + mutex_unlock(&fpga_data->fpga_lock); + return ret; +} + + +const struct file_operations fpgafw_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = fpgafw_unlocked_ioctl, +}; + + +static int fpgafw_init(void){ + printk(KERN_INFO "Initializing the switchboard driver\n"); + // Try to dynamically allocate a major number for the device -- more difficult but worth it + majorNumber = register_chrdev(0, DEVICE_NAME, &fpgafw_fops); + if (majorNumber<0){ + printk(KERN_ALERT "Failed to register a major number\n"); + return majorNumber; + } + printk(KERN_INFO "Device registered correctly with major number %d\n", majorNumber); + + // Register the device class + fpgafwclass = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(fpgafwclass)){ // Check for error and clean up if there is + unregister_chrdev(majorNumber, DEVICE_NAME); + printk(KERN_ALERT "Failed to register device class\n"); + return PTR_ERR(fpgafwclass); // Correct way to return an error on a pointer + } + printk(KERN_INFO "Device class registered correctly\n"); + + // Register the device driver + fpgafwdev = device_create(fpgafwclass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME); + if (IS_ERR(fpgafwdev)){ // Clean up if there is an error + class_destroy(fpgafwclass); // Repeated code but the alternative is goto statements + unregister_chrdev(majorNumber, DEVICE_NAME); + printk(KERN_ALERT "Failed to create the FW upgrade device node\n"); + return PTR_ERR(fpgafwdev); + } + printk(KERN_INFO "FPGA fw upgrade device node created correctly\n"); // Made it! device was initialized + return 0; +} + +static void fpgafw_exit(void){ + device_destroy(fpgafwclass, MKDEV(majorNumber, 0)); // remove the device + class_unregister(fpgafwclass); // unregister the device class + class_destroy(fpgafwclass); // remove the device class + unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number + printk(KERN_INFO "Goodbye!\n"); +} + +int seastone2_init(void) +{ + int rc; + rc = pci_register_driver(&pci_dev_ops); + if (rc) + return rc; + if(fpga_dev.data_base_addr == NULL){ + printk(KERN_ALERT "FPGA PCIe device not found!\n"); + return -ENODEV; + } + platform_device_register(&seastone2_dev); + platform_driver_register(&seastone2_drv); + return 0; +} + +void seastone2_exit(void) +{ + platform_driver_unregister(&seastone2_drv); + platform_device_unregister(&seastone2_dev); + pci_unregister_driver(&pci_dev_ops); +} + +module_init(seastone2_init); +module_exit(seastone2_exit); + +MODULE_AUTHOR("Pradchaya P. pphuhcar@celestica.com"); +#ifdef SEASTONE2 +MODULE_DESCRIPTION("Celestica seastone2 platform driver"); +#else +MODULE_DESCRIPTION("Celestica questone2 platform driver"); +#endif +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/platform_sensors.py new file mode 100755 index 000000000000..b600d48e8fb0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/platform_sensors.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +# +# Silverstone platform sensors. This script get the sensor data from BMC +# using ipmitool and display them in lm-sensor alike format. +# +# The following data is support: +# 1. Temperature sensors +# 2. PSUs +# 3. Fan Drawers + +import sys +import logging +import subprocess + +IPMI_SDR_CMD = ['/usr/bin/ipmitool', 'sdr', 'elist'] +MAX_NUM_FANS = 4 +MAX_NUM_PSUS = 2 + +SENSOR_NAME = 0 +SENSOR_VAL = 4 + +sensor_dict = {} + +def ipmi_sensor_dump(cmd): + ''' Execute ipmitool command return dump output + exit if any error occur. + ''' + global sensor_dict + sensor_dump = '' + + try: + sensor_dump = subprocess.check_output(IPMI_SDR_CMD, universal_newlines=True) + except subprocess.CalledProcessError as e: + logging.error('Error! Failed to execute: {}'.format(cmd)) + sys.exit(1) + + for line in sensor_dump.splitlines(): + sensor_info = line.split('|') + sensor_dict[sensor_info[SENSOR_NAME].strip()] = sensor_info[SENSOR_VAL].strip() + + return True + +def get_reading_by_name(sensor_name, sdr_elist_dump): + found = '' + + for line in sdr_elist_dump.splitlines(): + line = line.decode() + if sensor_name in line: + found = line.strip() + break + + if not found: + logging.error('Cannot find sensor name:' + sensor_name) + + else: + try: + found = found.split('|')[4] + except IndexError: + logging.error('Cannot get sensor data of:' + sensor_name) + + logging.basicConfig(level=logging.DEBUG) + return found + + +def read_temperature_sensors(): + sensor_list = [\ + ('Base_Temp_U5', 'Baseboard Right Temp'),\ + ('Base_Temp_U7', 'Baseboard Left Temp'),\ + ('Switch_Temp_U31', 'ASIC External Front Temp'),\ + ('Switch_Temp_U30', 'ASIC External Rear Temp'),\ + ('Switch_Temp_U29', 'Switchboard Right Temp'),\ + ('Switch_Temp_U28', 'Switchboard Left Temp'),\ + ('CPU_Temp', 'CPU Internal Temp'),\ + ('Switch_U33_Temp', 'IR3595 Chip Temp'),\ + ('Switch_U21_Temp', 'IR3584 Chip Temp'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Temperature Sensors\n" + output += "Adapter: IPMI adapter\n" + for sensor in sensor_list: + output += sensor_format.format('{}:'.format(sensor[1]),\ + sensor_dict[sensor[0]],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_fan_sensors(num_fans): + + sensor_list = [\ + ('Fan{}_Status', 'Fan Drawer {} Status'),\ + ('Fan{}_Front', 'Fan {} front'),\ + ('Fan{}_Rear', 'Fan {} rear'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Fan Drawers\n" + output += "Adapter: IPMI adapter\n" + for fan_num in range(1, num_fans+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(fan_num) + display_sensor_name = sensor[1].format(fan_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_psu_sensors(num_psus): + + sensor_list = [\ + ('PSU{}_Status', 'PSU {} Status'),\ + ('PSU{}_Fan', 'PSU {} Fan 1'),\ + ('PSU{}_VIn', 'PSU {} Input Voltage'),\ + ('PSU{}_CIn', 'PSU {} Input Current'),\ + ('PSU{}_PIn', 'PSU {} Input Power'),\ + ('PSU{}_Temp1', 'PSU {} Ambient Temp'),\ + ('PSU{}_Temp2', 'PSU {} Hotspot Temp'),\ + ('PSU{}_VOut', 'PSU {} Output Voltage'),\ + ('PSU{}_COut', 'PSU {} Output Current'),\ + ('PSU{}_POut', 'PSU {} Output Power'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "PSU\n" + output += "Adapter: IPMI adapter\n" + for psu_num in range(1, num_psus+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format('L' if psu_num == 1 else 'R') + display_sensor_name = sensor[1].format(psu_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def main(): + output_string = '' + + if ipmi_sensor_dump(IPMI_SDR_CMD): + output_string += read_temperature_sensors() + output_string += read_psu_sensors(MAX_NUM_PSUS) + output_string += read_fan_sensors(MAX_NUM_FANS) + + print(output_string) + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/questone2_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/questone2_platform_shutdown.sh new file mode 100755 index 000000000000..e04cac54fa98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/questone2_platform_shutdown.sh @@ -0,0 +1,26 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +# BMC cold power-cyle +ipmitool chassis power cycle &> /dev/null + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/sensors new file mode 100755 index 000000000000..5d740a9eb7d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/scripts/sensors @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon python3 /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/setup.py b/platform/broadcom/sonic-platform-modules-cel/questone2/setup.py new file mode 100644 index 000000000000..1bac52a180ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Celestica B3010 platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/__init__.py new file mode 100644 index 000000000000..d3c24cb008dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import platform diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/chassis.py new file mode 100644 index 000000000000..85157d319298 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/chassis.py @@ -0,0 +1,464 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +try: + import sys + import time + import os + import re + import shutil + from sonic_platform_base.chassis_base import ChassisBase + from .helper import APIHelper + from sonic_platform_base.sfp_base import SfpBase + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_DRAWER = 4 +NUM_FAN_PER_DRAWER = 2 +NUM_PSU = 2 +NUM_THERMAL = 13 +NUM_SFP = 56 +NUM_COMPONENT = 9 + +SFP_PORT_START = 1 +SFP_PORT_END = 48 +QSFP_PORT_START = 49 +QSFP_PORT_END = 56 + +REBOOT_CAUSE_REG = "0xA106" +BASE_CPLD_PLATFORM = "sys_cpld" +BASE_GETREG_PATH = "/sys/devices/platform/{}/getreg".format(BASE_CPLD_PLATFORM) +IPMI_GET_SYS_STATUS_LED="ipmitool raw 0x3A 0x0C 0x00 0x02 0x62" +IPMI_SET_SYS_STATUS_LED="ipmitool raw 0x3A 0x0C 0x00 0x03 0x62 {}" + +ORG_HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +TMP_HW_REBOOT_CAUSE_FILE="/tmp/hw-reboot-cause.txt" + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + sfp_status_dict={} + + #led color status + SYSLED_COLOR_VAL_MAP = {\ + 'off': '0x33',\ + 'green': '0x10',\ + 'green_blink_1hz': '0x11',\ + 'amber': '0x20'\ + } + + SYSLED_VAL_COLOR_DESC_MAP = { + 0x33: 'off',\ + 0x10: 'green',\ + 0x11: 'green_blink_1hz',\ + 0x20: 'amber'\ + } + + def __init__(self): + ChassisBase.__init__(self) + self._api_helper = APIHelper() + self.sfp_module_initialized = False + self.fan_module_initialized = False + self._watchdog = None + self._airflow_direction = None + self.__initialize_eeprom() + + self.__initialize_thermals() + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_components() + + def __initialize_sfp(self): + if not self.sfp_module_initialized: + from sonic_platform.sfp import Sfp + for index in range(0, NUM_SFP): + sfp = Sfp(index) + self._sfp_list.append(sfp) + present = sfp.get_presence() + self.sfp_status_dict[sfp.index] = '1' if present else '0' + self.sfp_module_initialized = True + + def __initialize_psu(self): + from sonic_platform.psu import Psu + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_fan(self): + from sonic_platform.fan import Fan + from sonic_platform.fan_drawer import FanDrawer + for fand_index in range(0, NUM_FAN_DRAWER): + drawer_fan_list=[] + for fan_index in range(0, NUM_FAN_PER_DRAWER): + fan = Fan(fand_index, fan_index) + self._fan_list.append(fan) + drawer_fan_list.append(fan) + fan_drawer = FanDrawer(fand_index, drawer_fan_list) + self._fan_drawer_list.append(fan_drawer) + self.fan_module_initialized = True + + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Eeprom + self._eeprom = Eeprom() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def initizalize_system_led(self): + return True + + def get_status_led(self): + color_str = 'N/A' + status, output = self._api_helper.run_command(IPMI_GET_SYS_STATUS_LED) + if status: + color_val = int(output, 16) & 0x33 + color_str = self.SYSLED_VAL_COLOR_DESC_MAP.get(color_val, color_str) + + return color_str + + def set_status_led(self, color): + status = False + + color_val = self.SYSLED_COLOR_VAL_MAP.get(color, None) + if color_val != None: + cmd = IPMI_SET_SYS_STATUS_LED.format(color_val) + status, res = self._api_helper.run_command(cmd) + + return status + + 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.get_mac() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.get_serial() + + 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.get_eeprom() + + 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. + """ + hw_reboot_cause = self._api_helper.get_register_value( + BASE_GETREG_PATH, REBOOT_CAUSE_REG) + + + # This tmp copy is to retain the reboot-cause only for the current boot + if os.path.isfile(ORG_HW_REBOOT_CAUSE_FILE): + shutil.move(ORG_HW_REBOOT_CAUSE_FILE, TMP_HW_REBOOT_CAUSE_FILE) + + if hw_reboot_cause == "0x00" and os.path.isfile(TMP_HW_REBOOT_CAUSE_FILE): + with open(TMP_HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + if match is not None: + if match.group(1) == 'system': + return (self.REBOOT_CAUSE_NON_HARDWARE, 'System cold reboot') + + + if hw_reboot_cause == "0x99": + reboot_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC + description = 'ASIC Overload Reboot' + elif hw_reboot_cause == "0x88": + reboot_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU + description = 'CPU Overload Reboot' + elif hw_reboot_cause == "0x77": + reboot_cause = self.REBOOT_CAUSE_WATCHDOG + description = 'Hardware Watchdog Reset' + elif hw_reboot_cause == "0x55": + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'CPU Cold Reset' + elif hw_reboot_cause == "0x44": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'CPU Warm Reset' + elif hw_reboot_cause == "0x33": + # When NON_HARDWARE is used and device is powercycled via IPMI + # reboot cause computed as Unknown, Hence using HARDWARE_OTHER + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Soft-Set Cold Reset' + elif hw_reboot_cause == "0x22": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'Soft-Set Warm Reset' + elif hw_reboot_cause == "0x11": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power On Reset' + elif hw_reboot_cause == "0x00": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power Cycle Reset' + else: + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Hardware reason' + + return (reboot_cause, description) + + ############################################################## + ######################## SFP methods ######################### + ############################################################## + + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + Returns: + An integer, the number of sfps available on this chassis + """ + self.__initialize_sfp() + + return len(self._sfp_list) + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + self.__initialize_sfp() + + return self._sfp_list + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet1, 1 for Ethernet2 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + self.__initialize_sfp() + + try: + sfp = self._sfp_list[index - 1] + except IndexError: + sys.stderr.write("SFP index {} out of range (0-{})\n".format( + index, len(self._sfp_list) - 1)) + return sfp + + ############################################################## + ####################### Other methods ######################## + ############################################################## + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + if self._watchdog is None: + from sonic_platform.watchdog import Watchdog + self._watchdog = Watchdog() + + return self._watchdog + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._api_helper.hwsku + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._eeprom.get_pn() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self.get_serial_number() + + def get_revision(self): + """ + Retrieves the hardware revision for the chassis + Returns: + A string containing the hardware revision for this chassis. + """ + return self._eeprom.get_revision() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + ############################################################## + ###################### Event methods ######################### + ############################################################## + + 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): + - bool: True if call successful, False if not; + - dict: 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. + The known devices's device_id and device_event was defined as table below. + ----------------------------------------------------------------- + device | device_id | device_event | annotate + ----------------------------------------------------------------- + 'fan' '' '0' Fan removed + '1' Fan inserted + + 'sfp' '' '0' Sfp removed + '1' Sfp inserted + '2' I2C bus stuck + '3' Bad eeprom + '4' Unsupported cable + '5' High Temperature + '6' Bad cable + + 'voltage' '' '0' Vout normal + '1' Vout abnormal + -------------------------------------------------------------------- + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0', '12':'1'}, + 'voltage':{'U20':'0', 'U21':'1'}} + Indicates that: + fan 0 has been removed, fan 2 has been inserted. + sfp 11 has been removed, sfp 12 has been inserted. + monitored voltage U20 became normal, voltage U21 became abnormal. + Note: For sfp, when event 3-6 happened, the module will not be avalaible, + XCVRD shall stop to read eeprom before SFP recovered from error status. + """ + sfp_dict = {} + + SFP_REMOVED = '0' + SFP_INSERTED = '1' + + SFP_PRESENT = True + SFP_ABSENT = False + + start_time = time.time() + time_period = timeout/float(1000) #Convert msecs to secs + + while time.time() < (start_time + time_period) or timeout == 0: + for sfp in self._sfp_list: + port_idx = sfp.index + if self.sfp_status_dict[port_idx] == SFP_REMOVED and \ + sfp.get_presence() == SFP_PRESENT: + sfp_dict[port_idx] = SFP_INSERTED + self.sfp_status_dict[port_idx] = SFP_INSERTED + elif self.sfp_status_dict[port_idx] == SFP_INSERTED and \ + sfp.get_presence() == SFP_ABSENT: + sfp_dict[port_idx] = SFP_REMOVED + self.sfp_status_dict[port_idx] = SFP_REMOVED + + if sfp_dict: + return True, {'sfp':sfp_dict} + + time.sleep(0.5) + + return True, {'sfp':{}} # Timeout + + def get_airflow_direction(self): + if self._airflow_direction == None: + try: + vendor_extn = self._eeprom.get_vendor_extn() + airflow_type = vendor_extn.split()[2][2:4] # Either 0xFB or 0xBF + if airflow_type == 'FB': + direction = 'exhaust' + elif airflow_type == 'BF': + direction = 'intake' + else: + direction = 'N/A' + except (AttributeError, IndexError): + direction = 'N/A' + + self._airflow_direction = direction + + return self._airflow_direction + + def get_port_or_cage_type(self, index): + """ + Retrieves sfp port or cage type corresponding to physical port + + Args: + index: An integer (>=0), the index of the sfp to retrieve. + + Returns: + The masks of all types of port or cage that can be supported on the port + Types are defined in sfp_base.py + """ + if index in range(1, 48+1): + return (SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_SFP28 | \ + SfpBase.SFP_PORT_TYPE_BIT_SFP) + elif index in range(49, 56+1): + return SfpBase.SFP_PORT_TYPE_BIT_QSFP28 + else: + raise NotImplementedError + + diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/component.py new file mode 100644 index 000000000000..185a62ef6a60 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/component.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import os.path +import re + +try: + #from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NAME_IDX = 0 +DESC_IDX = 1 +VER_API_IDX = 2 + +BASE_CPLD_PLATFORM = "sys_cpld" +SW_CPLD_PLATFORM = "questone2" +PLATFORM_SYSFS_PATH = "/sys/devices/platform/" + +FPGA_GETREG_PATH = "{}/{}/FPGA/getreg".format( + PLATFORM_SYSFS_PATH, SW_CPLD_PLATFORM) +BASE_GETREG_PATH = "{}/{}/getreg".format( + PLATFORM_SYSFS_PATH, BASE_CPLD_PLATFORM) +SW_CPLD1_GETREG_PATH = "{}/{}/CPLD1/getreg".format( + PLATFORM_SYSFS_PATH, SW_CPLD_PLATFORM) +SW_CPLD2_GETREG_PATH = "{}/{}/CPLD2/getreg".format( + PLATFORM_SYSFS_PATH, SW_CPLD_PLATFORM) +BIOS_VER_PATH = "/sys/class/dmi/id/bios_version" + +BASE_CPLD_VER_REG = "0xA100" +COME_CPLD_VER_REG = "0xA1E0" +SW_CPLD_VER_REG = "0x00" +FPGA_VER_REG = "0x00" + +UNKNOWN_VER = "N/A" +ONIE_VER_CMD = "cat /host/machine.conf" +SSD_VER_CMD = "smartctl -i /dev/sda" + +class Component(): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + COMPONENT_LIST = [ + ("BIOS", "Basic input/output System", self.__get_bios_ver), + ("ONIE", "Open Network Install Environment", self.__get_onie_ver), + ("BMC", "Baseboard Management Controller", self.__get_bmc_ver), + ("FPGA", "FPGA for transceiver EEPROM access and other component I2C access", self.__get_fpga_ver), + ("CPLD COMe", "COMe board CPLD", self.__get_cpld_ver), + ("CPLD BASE", "CPLD for board functions, fan control and watchdog", self.__get_cpld_ver), + ("CPLD SW1", "CPLD for port control SFP(1-24)", self.__get_cpld_ver), + ("CPLD SW2", "CPLD for port control SFP(25-48) QSFP(49-56)", self.__get_cpld_ver), + ("SSD", "Solid State Drive - {}", self.__get_ssd_ver), + ] + + self.index = component_index + self.name = COMPONENT_LIST[self.index][NAME_IDX] + self.description = COMPONENT_LIST[self.index][DESC_IDX] + self.__get_version = COMPONENT_LIST[self.index][VER_API_IDX] + self._api_helper = APIHelper() + + def __get_bios_ver(self): + return self._api_helper.read_one_line_file(BIOS_VER_PATH) + + def __get_onie_ver(self): + onie_ver = "N/A" + status, raw_onie_data = self._api_helper.run_command(ONIE_VER_CMD) + if status: + ret = re.search(r"(?<=onie_version=).+[^\n]", raw_onie_data) + if ret != None: + onie_ver = ret.group(0) + return onie_ver + + def __get_bmc_ver(self): + cmd="ipmitool mc info | grep 'Firmware Revision'" + status, raw_ver=self._api_helper.run_command(cmd) + if status: + bmc_ver=raw_ver.split(':')[-1].strip() + return bmc_ver + else: + return UNKNOWN_VER + + def __get_fpga_ver(self): + version_raw = self._api_helper.get_register_value(FPGA_GETREG_PATH, FPGA_VER_REG) + return "{}.{}".format(int(version_raw[2:][:4], 16), int(version_raw[2:][4:], 16)) if version_raw else UNKNOWN_VER + + def __get_cpld_ver(self): + cpld_api_param = { + 'CPLD COMe': (BASE_GETREG_PATH, COME_CPLD_VER_REG), + 'CPLD BASE': (BASE_GETREG_PATH, BASE_CPLD_VER_REG), + 'CPLD SW1': (SW_CPLD1_GETREG_PATH, SW_CPLD_VER_REG), + 'CPLD SW2': (SW_CPLD2_GETREG_PATH, SW_CPLD_VER_REG), + } + api_param = cpld_api_param[self.name] + + cpld_ver = self._api_helper.get_register_value(api_param[0], api_param[1]) + return "{}.{}".format(int(cpld_ver[2], 16), int(cpld_ver[3], 16)) if cpld_ver else UNKNOWN_VER + + def __get_ssd_ver(self): + ssd_ver = "N/A" + status, raw_ssd_data = self._api_helper.run_command(SSD_VER_CMD) + if status: + ret = re.search(r"Firmware Version: +(.*)[^\\]", raw_ssd_data) + if ret != None: + ssd_ver = ret.group(1) + return ssd_ver + + def __get_ssd_model(self): + model = "N/A" + + status, raw_ssd_data = self._api_helper.run_command(SSD_VER_CMD) + if status: + ret = re.search(r"Device Model: +(.*)[^\\]", raw_ssd_data) + if ret != None: + try: + model = ret.group(1) + except (IndexError): + pass + return model + + 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 + """ + # For SSD get the model name from device + if self.name == "SSD": + return self.description.format(self.__get_ssd_model()) + + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + return self.__get_version() diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/eeprom.py new file mode 100644 index 000000000000..ff08cd949891 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/eeprom.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os + import sys + import re + import json + import fcntl + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +NULL = 'N/A' +EEPROM_TMP_FILE = '/tmp/eeprom_dump.json' + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + for i2cbus in range(2): + path_prefix = "/sys/class/i2c-adapter/i2c-{0}/".format(i2cbus) + with open(path_prefix + "name") as fd: + if 'SMBus iSMT adapter at ' in fd.readline(): + self._eeprom_path = path_prefix + "{0}-0056/eeprom".format(i2cbus) + break + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + try: + match = re.search('(0x[0-9a-fA-F]{2})\s+\d+\s+(.+)', line) + if match is not None: + idx = match.group(1) + value = match.group(2).rstrip('\0') + + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + eeprom_dict = {} + + if os.path.exists(EEPROM_TMP_FILE): + with open(EEPROM_TMP_FILE, 'r') as fd: + eeprom_dict = json.load(fd) + + return eeprom_dict + + original_stdout = sys.stdout + sys.stdout = StringIO() + rv = -1 + try: + rv = self.read_eeprom_db() + except BaseException: + pass + + if rv == 0: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + eeprom_dict = self.__parse_output(decode_output) + else: + e = self.read_eeprom() + if e is None: + sys.stdout = original_stdout + return {} + + self.decode_eeprom(e) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(e) + if not is_valid: + return {} + + eeprom_dict = self.__parse_output(decode_output) + + if len(eeprom_dict) != 0: + with open(EEPROM_TMP_FILE, 'w') as fd: + fcntl.flock(fd, fcntl.LOCK_EX) + json.dump(eeprom_dict, fd) + fcntl.flock(fd, fcntl.LOCK_UN) + + return eeprom_dict + + def get_eeprom(self): + return self._eeprom + + def get_product(self): + return self._eeprom.get('0x21', NULL) + + def get_pn(self): + return self._eeprom.get('0x22', NULL) + + def get_serial(self): + return self._eeprom.get('0x23', NULL) + + def get_mac(self): + return self._eeprom.get('0x24', NULL) + + def get_revision(self): + return self._eeprom.get('0x26', NULL) + + def get_vendor_extn(self): + return self._eeprom.get('0xFD', NULL) diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan.py new file mode 100644 index 000000000000..6a1faa44ebbe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.fan_base import FanBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NOT_AVAILABLE = 'N/A' + +FAN_NAME_TEMPLATE = "{}Fan{}{}" +NUM_FAN_TRAYS = 4 +NUM_FANS_PER_TRAY = 2 +FAN_SPEED_TOLERANCE = 20 +MAX_RPM_FRONT=23000 +MAX_RPM_REAR=20500 +MAX_RPM_PSU=22600 +FAN_DIR_BASE = 0x41 +FAN_LED_BASE = 0x04 +FAN_FRU_BASE = 0x05 +FAN_STATUS_BASE = 0x00 +FAN_SID_BASE = 0x80 +PSU_FAN_SID_BASE = 0x8a +PSU_FRU_BASE = 0x03 + + +IPMI_FAN_DIR="ipmitool raw 0x3a 0x0c 0x00 0x02 {}" +IPMI_GET_SPEED="ipmitool raw 0x04 0x2d {}" +IPMI_GET_CPLD_PWM="ipmitool raw 0x3a 0x0c 0x00 0x02 {}" +IPMI_GET_PRESENCE="ipmitool raw 0x3a 0x03 0x03 {}" +IPMI_GET_MODEL="ipmitool fru list {} | grep 'Board Part Number'" +IPMI_GET_SERIAL="ipmitool fru list {} | grep 'Board Serial'" +IPMI_GET_PSU_MODEL="ipmitool fru list {} | grep 'Product Name'" +IPMI_GET_PSU_SPEED="ipmitool raw 0x04 0x2d {}" +IPMI_SET_STATUS_LED="ipmitool raw 0x3a 0x0a {} {}" +IPMI_GET_STATUS_LED="ipmitool raw 0x3a 0x0b {}" + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + self.is_psu_fan = is_psu_fan + self._api_helper = APIHelper() + self.index = (self.fan_tray_index * 2) + self.fan_index + self.name = None + if self.is_psu_fan: + self.psu_index = psu_index + self.max_speed = MAX_RPM_PSU + self._fan_sid_offset = PSU_FAN_SID_BASE + self.psu_index + self._fan_status_offset = FAN_STATUS_BASE + NUM_FAN_TRAYS + self.psu_index + else: + self._fan_status_offset = FAN_STATUS_BASE + self.fan_tray_index + self._fan_fru_offset = FAN_FRU_BASE + self.fan_tray_index + self._fan_dir_offset = FAN_DIR_BASE + (self.fan_tray_index * 4) + if self.fan_tray_index > 1: + # Questone CPLD firmware is used and hence FAN 3 will be missing + # There are only 4 FAN trays in this platform + self._fan_dir_offset = self._fan_dir_offset + 4 + + self._fan_speed_offset = self._fan_dir_offset - 1 + self._fan_led_offset = FAN_LED_BASE + self.fan_tray_index + + if fan_index % 2 == 0: + # Front FAN + self.is_front = True + self.max_speed = MAX_RPM_FRONT + self._fan_sid_offset = FAN_SID_BASE + 1 + (self.fan_tray_index * NUM_FANS_PER_TRAY) + else: + # Rear FAN + self.is_front = False + self.max_speed = MAX_RPM_REAR + self._fan_sid_offset = FAN_SID_BASE + (self.fan_tray_index * NUM_FANS_PER_TRAY) + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = NOT_AVAILABLE + + if self.is_psu_fan: + cmd = IPMI_GET_PSU_MODEL.format(PSU_FRU_BASE + self.psu_index) + status, output = self._api_helper.run_command(cmd) + if status and output: + model = output.split(':')[-1] + if len(model) > 0: + if model[-2:] == ' B': + direction = self.FAN_DIRECTION_INTAKE + else: + direction = self.FAN_DIRECTION_EXHAUST + else: + cmd = IPMI_FAN_DIR.format(self._fan_dir_offset) + status, output = self._api_helper.run_command(cmd) + if status: + dir_num = int(output, 16) & 0x0C + if dir_num == 0x0: + direction = self.FAN_DIRECTION_EXHAUST + elif dir_num == 0x8: + direction = self.FAN_DIRECTION_INTAKE + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + speed = 0 + + if not self.is_psu_fan: + multiplier = 150.0 + else: + multiplier = 100.0 + + cmd = IPMI_GET_PSU_SPEED.format(self._fan_sid_offset) + status, output = self._api_helper.run_command(cmd) + if status: + raw_speed = output.split()[0] + rpm_speed = int(raw_speed, 16) * multiplier + speed = int((rpm_speed/self.max_speed) * 100) + + return speed + + 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) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + target_speed = 0 + + if self.is_psu_fan: + # Ignored for tolerance check + return self.get_speed() + + cmd = IPMI_GET_CPLD_PWM.format(self._fan_speed_offset) + status, output = self._api_helper.run_command(cmd) + if status: + fan_pwm = int(output, 16) + target_speed = round(fan_pwm / 255 * 100) + + return target_speed + + 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 + """ + return FAN_SPEED_TOLERANCE + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + Notes: + pwm setting mode must set as Manual + manual: systemctl stop fanctrl.service + auto: systemctl start fanctrl.service + """ + + # FAN speed is controlled by BCM always + return False + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + # There is no per Fan LED + return True + + def drawer_set_status_led(self, color): + status = False + + color_dict = {\ + self.STATUS_LED_COLOR_OFF: 0,\ + self.STATUS_LED_COLOR_AMBER: 1,\ + self.STATUS_LED_COLOR_RED: 1,\ + self.STATUS_LED_COLOR_GREEN: 2\ + } + + if not self.is_psu_fan: + cmd = IPMI_SET_STATUS_LED.format(self._fan_led_offset, color_dict.get(color, 0)) + status, _ = self._api_helper.run_command(cmd) + + return status + + + def get_status_led(self): + """ + Gets the state of the fan status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + + Note: + Output + STATUS_LED_COLOR_GREEN = "green" + STATUS_LED_COLOR_AMBER = "amber" + STATUS_LED_COLOR_RED = "red" + STATUS_LED_COLOR_OFF = "off" + + Input + 0x1: green + 0x2: red + 0x3: off + """ + status = NOT_AVAILABLE + color_dict = {\ + 0: self.STATUS_LED_COLOR_OFF,\ + 1: self.STATUS_LED_COLOR_AMBER,\ + 2: self.STATUS_LED_COLOR_GREEN\ + } + + if not self.is_psu_fan: + cmd = IPMI_GET_STATUS_LED.format(self._fan_led_offset) + status, output = self._api_helper.run_command(cmd) + if status: + color = int(output, 16) + status = color_dict.get(color, status) + + return status + + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + + if not self.name: + if not self.is_psu_fan: + psu_name = "" + fan_id = " {}".format(self.fan_tray_index + 1) + fan_type = " Front" if self.is_front else " Rear" + else: + psu_name = "PSU {} ".format(self.psu_index + 1) + fan_id = " {}".format(self.fan_tray_index + 1) + fan_type = "" + + self.name = FAN_NAME_TEMPLATE.format(psu_name, fan_id, fan_type) + + return self.name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + + presence = False + + cmd = IPMI_GET_PRESENCE.format(self._fan_status_offset) + status, output = self._api_helper.run_command(cmd) + if status and output == "00": + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model = NOT_AVAILABLE + + if not self.is_psu_fan: + cmd = IPMI_GET_MODEL.format(self._fan_fru_offset) + status, output = self._api_helper.run_command(cmd) + if status and output: + return output.split()[-1] + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + serial = NOT_AVAILABLE + + if not self.is_psu_fan: + cmd = IPMI_GET_SERIAL.format(self._fan_fru_offset) + status, output = self._api_helper.run_command(cmd) + if status and output: + return output.split()[-1] + + return serial + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() and self.get_speed() > 0 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + if not self.is_psu_fan: + return True + + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..14ea5c900506 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/fan_drawer.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +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): + + def __init__(self, index, fan_list): + FanDrawerBase.__init__(self) + + self._fan_list = fan_list + self._index = index + 1 + + 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[0].drawer_set_status_led(color) + + def get_status_led(self): + """ + Gets the state of the fan drawer LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._fan_list[0].get_status_led() + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return 'Drawer {}'.format(self._index) + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + return self._fan_list[0].get_presence() + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._fan_list[0].get_model() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._fan_list[0].get_serial() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self._fan_list[0].get_status() diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/helper.py new file mode 100644 index 000000000000..7bcbd70a0a7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/helper.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python + +import os +import struct +import subprocess +from mmap import * +from sonic_py_common.device_info import get_platform_and_hwsku + +SCALE = 16 +BIN_BITS = 8 +EMPTY_STRING = "" +HOST_CHK_CMD = "docker > /dev/null 2>&1" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = get_platform_and_hwsku() + + def get_register_value(self, getreg_path, register): + cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + return None + else: + return data + + def hex_to_bin(self, ini_string): + return bin(int(ini_string, SCALE)).zfill(BIN_BITS) + + def is_host(self): + rv, _ = subprocess.getstatusoutput(HOST_CHK_CMD) + return (rv == 0) + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def run_command(self, cmd): + status = True + result = "" + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def read_one_line_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + def search_file_by_contain(self, directory, search_str, file_start): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name.startswith(file_start) and search_str in self.read_txt_file(file_path): + return dirpath + return None + + def write_file(self, file_path, data): + try: + with open(file_path, 'w') as fd: + fd.write(str(data)) + return True + except Exception: + pass + return False + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def ipmi_fru_id(self, id, key=None): + status = True + result = "" + cmd = "ipmitool fru print {}".format(str( + id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key)) + + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + cmd = "ipmitool sensor thresh '{}' {} {}".format( + str(id), str(threshold_key), str(value)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def fru_decode_product_serial(self, data): + + if data and data[4] != 00: + start_product_info = ord(data[4]) * 8 + start_format_version = start_product_info + start_product_info = start_format_version + 1 + start_product_Lang_code = start_product_info + 1 + start_product_Manu_name = start_product_Lang_code + 1 + start_product_Manu_name_length = ord(data[start_product_Manu_name]) & 0x0F + start_product_name = start_product_Manu_name + start_product_Manu_name_length + 1 + start_product_name_length = ord(data[start_product_name]) & 0x0F + start_product_module_number = start_product_name + start_product_name_length +1 + start_product_module_number_length = ord(data[start_product_module_number]) & 0x0F + start_product_version = start_product_module_number + start_product_module_number_length +1 + start_product_version_length = ord(data[start_product_version]) & 0x0F + start_product_serial_number = start_product_version + start_product_version_length +1 + start_product_serial_number_length = ord(data[start_product_serial_number]) & 0x1F + return data[start_product_serial_number+1:start_product_serial_number+start_product_serial_number_length+1] + return "N/A" + + def fru_decode_product_model(self, data): + if data and data[4] != 00: + start_product_info = ord(data[4]) * 8 + start_format_version = start_product_info + start_product_info = start_format_version + 1 + start_product_lang_code = start_product_info + 1 + start_product_manu_name = start_product_lang_code + 1 + start_product_manu_name_length = ord(data[start_product_manu_name]) & 0x1F + start_product_name = start_product_manu_name + start_product_manu_name_length + 1 + start_product_name_length = ord(data[start_product_name]) & 0x1F + start_product_module_number = start_product_name + start_product_name_length + 1 + start_product_module_number_length = ord(data[start_product_module_number]) & 0x1F + return data[start_product_module_number + 1: start_product_module_number +start_product_module_number_length + 1] + return "N/A" + + def fru_decode_product_name(self, data): + + if data and data[4] != 00: + start_product_info = ord(data[4]) * 8 + start_format_version = start_product_info + start_product_info = start_format_version + 1 + start_product_Lang_code = start_product_info + 1 + start_product_Manu_name = start_product_Lang_code + 1 + start_product_Manu_name_length = ord(data[start_product_Manu_name]) & 0x0F + start_product_name = start_product_Manu_name + start_product_Manu_name_length + 1 + start_product_name_length = ord(data[start_product_name]) & 0x0F + return data[start_product_name+1: start_product_name+start_product_name_length+1] + + return "N/A" + + def read_eeprom_sysfs(self,sys_path,sysfs_file): + sysfs_path = os.path.join(sys_path, sysfs_file) + try: + with open(sysfs_path, mode='rb', buffering=0) as fd: + data = fd.read(256) + return data + except Exception: + pass + return None diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/pcie.py new file mode 100644 index 000000000000..2f7931d42b01 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/pcie.py @@ -0,0 +1,15 @@ +# +# pcie_base.py +# +# Abstract base class for implementing platform-specific +# PCIE functionality for SONiC +# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +class Pcie(PcieUtil): + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/platform.py new file mode 100644 index 000000000000..c9ba822ac0da --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/platform.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# 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): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/psu.py new file mode 100644 index 000000000000..8c36c61e1f98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/psu.py @@ -0,0 +1,265 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from .helper import APIHelper + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +IPMI_SENSOR_NETFN = "0x04" +IPMI_SENSOR_READ_CMD = "0x2D {}" +IPMI_SENSOR_THRESH_CMD = "0x27 {}" +IPMI_FRU_MODEL_KEY = "Product Name" +IPMI_FRU_SERIAL_KEY = "Product Serial" + +MAX_PSU_POWER = 550 #Watts +psu_ipmi_id = {\ + 1: {\ + "TEMP": "0x0d",\ + "VOUT": "0x0f",\ + "COUT": "0x10",\ + "POUT": "0x11",\ + "STATUS": "0x72",\ + "FRU": 3,\ + }, + 2: {\ + "TEMP": "0x17",\ + "VOUT": "0x19",\ + "COUT": "0x1a",\ + "POUT": "0x1b",\ + "STATUS": "0x73",\ + "FRU": 4,\ + } +} + +ANALOG_READ_OFFSET = 0 +EVENT_0_7_OFFSET = 2 +EVENT_8_14_OFFSET = 3 + +FRU_SERIAL = 4 +FRU_MODEL = 1 + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index+1 + # PSU has only one FAN + fan = Fan(0, 0, is_psu_fan=True, psu_index=psu_index) + self._fan_list.append(fan) + self._api_helper = APIHelper() + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = 0.0 + psu_vout_key = psu_ipmi_id[self.index]['VOUT'] + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_READ_CMD.format(psu_vout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx10^-1 + psu_voltage = int(value, 16) / 10.0 + + return psu_voltage + + def get_voltage_high_threshold(self): + return 12.6 + + def get_voltage_low_threshold(self): + return 11.4 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + psu_current = 0.0 + psu_cout_key = psu_ipmi_id[self.index]['COUT'] + status, output = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_cout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx3x10^-1 + psu_current = int(value, 16) * 3 / 10.0 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + psu_power = 0.0 + psu_pout_key = psu_ipmi_id[self.index]['POUT'] + status, output = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx5 + psu_power = int(value, 16) * 5 + return psu_power + + 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. + """ + return self.get_status() + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.get_presence(): + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return "blinking green" + else: + return "N/A" + + 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 + """ + # PSU's ambient temperature sensor is considered as the PSU temperature + psu_temp = 0.0 + psu_temp_id = psu_ipmi_id[self.index]['TEMP'] + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_READ_CMD.format(psu_temp_id)) + if status: + value = output.split()[ANALOG_READ_OFFSET] + psu_temp = float(int(value, 16)) + + return psu_temp + + 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 MAX_PSU_POWER + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return "PSU {}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + psu_presence = False + psu_pstatus_key = psu_ipmi_id[self.index]['STATUS'] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pstatus_key)) + status_byte = raw_status_read.split()[EVENT_0_7_OFFSET] + + if status: + psu_presence = True if int(status_byte, 16) & 0x01 == 0x01 else False + + return psu_presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model = "Unknown" + if self.get_presence(): + ipmi_fru_idx = psu_ipmi_id[self.index]['FRU'] + status, raw_model = self._api_helper.ipmi_fru_id( + ipmi_fru_idx, IPMI_FRU_MODEL_KEY) + + fru_pn_list = raw_model.split(':')[-1] + model = fru_pn_list.strip() + else: + model = "N/A" + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + serial = "Unknown" + if self.get_presence(): + ipmi_fru_idx = psu_ipmi_id[self.index]['FRU'] + status, raw_serial = self._api_helper.ipmi_fru_id( + ipmi_fru_idx, IPMI_FRU_SERIAL_KEY) + + fru_sr_list = raw_serial.split(':')[-1] + serial = fru_sr_list.strip() + else: + model = "N/A" + + return serial + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + psu_status = False + psu_pstatus_key = psu_ipmi_id[self.index]['STATUS'] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pstatus_key)) + status_byte = raw_status_read.split()[EVENT_0_7_OFFSET] + + if status: + psu_status = False if int(status_byte, 16) & 0x08 == 0x08 else True + + return psu_status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/sfp.py new file mode 100644 index 000000000000..66950af04200 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/sfp.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# +import time + +try: + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" + +QSFP_PORT_START = 49 +QSFP_PORT_END = 56 +SFP_PORT_START = 1 +SFP_PORT_END = 48 + +PORT_INFO_PATH = '/sys/class/questone2_fpga' +SFP_I2C_START = 2 + + +class Sfp(SfpOptoeBase): + """Platform-specific Sfp class""" + + # Path to QSFP sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + + def __init__(self, sfp_index): + SfpOptoeBase.__init__(self) + # Init index + self.index = sfp_index + 1 + self.sfp_type, self.port_name = self.__get_sfp_info() + self._api_helper = APIHelper() + self.platform = self._api_helper.platform + self.hwsku = self._api_helper.hwsku + + # Init eeprom path + self.eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'.format(SFP_I2C_START+sfp_index) + + def __get_sfp_info(self): + port_name = "Unknown" + sfp_type = "Unknown" + + if self.index >= QSFP_PORT_START and self.index <= QSFP_PORT_END: + sfp_type = QSFP_TYPE + port_name = sfp_type + str(self.index - QSFP_PORT_START + 1) + elif self.index >= SFP_PORT_START and self.index <= SFP_PORT_END: + sfp_type = SFP_TYPE + port_name = sfp_type + str(self.index) + return sfp_type, port_name + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.platform]) + hwsku_path = "/".join([platform_path, self.hwsku] + ) if self._api_helper.is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def get_eeprom_path(self): + return self.eeprom_path + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reg_status = self._api_helper.read_one_line_file( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_reset"])) + + return (int(reg_status) == 0) + + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type != QSFP_TYPE: + return False + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_reset"]), "w") + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(0)) + reg_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + # Flip the bit back high and write back to the register to take port out of reset + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_reset"]), "w") + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + + reg_file.seek(0) + reg_file.write(hex(1)) + reg_file.close() + + return True + + 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 + """ + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"]), "w") + except IOError as e: + return False + + if lpmode: + value=1 + else: + value=0 + reg_file.write(hex(value)) + reg_file.close() + + return True + + 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 + """ + + reg_status = self._api_helper.read_one_line_file( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"])) + + return (int(reg_status) == 1) + + def get_position_in_parent(self): + return self.index + + def is_replaceable(self): + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.physical_to_logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + # Get path for access port presence status + sysfs_filename = "sfp_modabs" if self.sfp_type == SFP_TYPE else "qsfp_modprs" + reg_path = "/".join([PORT_INFO_PATH, self.port_name, sysfs_filename]) + + content = self._api_helper.read_one_line_file(reg_path) + reg_value = int(content) + + return (reg_value == 0) + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() and not self.get_reset_status() diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/thermal.py similarity index 50% rename from device/celestica/x86_64-cel_silverstone-r0/sonic_platform/thermal.py rename to platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/thermal.py index 9ecf12218d50..d3d96b1e3e73 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/thermal.py @@ -19,9 +19,8 @@ IPMI_SENSOR_NETFN = "0x04" IPMI_SS_READ_CMD = "0x2D {}" IPMI_SS_THRESHOLD_CMD = "0x27 {}" -DEFUALT_LOWER_TRESHOLD = 0.0 HIGH_TRESHOLD_SET_KEY = "unc" - +DEFAULT_VAL = 'N/A' class Thermal(ThermalBase): """Platform-specific Thermal class""" @@ -30,26 +29,30 @@ def __init__(self, thermal_index): ThermalBase.__init__(self) self._api_helper = APIHelper() self.index = thermal_index - self.THERMAL_LIST = [ - ('TEMP_FAN_U52', 'Fan Tray Middle Temperature Sensor', '0x00'), - ('TEMP_FAN_U17', 'Fan Tray Right Temperature Sensor', '0x01'), - ('TEMP_SW_U52', 'Switchboard Left Inlet Temperature Sensor', '0x02'), - ('TEMP_SW_U16', 'Switchboard Right Inlet Temperature Sensor', '0x03'), - ('TEMP_BB_U3', 'Baseboard Temperature Sensor', '0x04'), - ('TEMP_CPU', 'CPU Internal Temperature Sensor', '0x05'), - ('TEMP_SW_Internal', 'ASIC Internal Temperature Sensor', '0x61'), - ('SW_U04_Temp', 'IR3595 Chip Left Temperature Sensor', '0x4F'), - ('SW_U14_Temp', 'IR3595 Chip Right Temperature Sensor', '0x56'), - ('SW_U4403_Temp', 'IR3584 Chip Temperature Sensor', '0x5D'), + thermal_list = [\ + ('Base_Temp_U5', '0x01', 'Baseboard Right Temp'),\ + ('Base_Temp_U7', '0x02', 'Baseboard Left Temp'),\ + ('Switch_Temp_U31', '0x03', 'ASIC External Front Temp'),\ + ('Switch_Temp_U30', '0x04', 'ASIC External Rear Temp'),\ + ('Switch_Temp_U29', '0x05', 'Switchboard Right Temp'),\ + ('Switch_Temp_U28', '0x06', 'Switchboard Left Temp'),\ + ('CPU_Temp', '0x07', 'CPU Internal Temp'),\ + ('Switch_U33_Temp', '0x4C', 'IR3595 Chip Temp'),\ + ('Switch_U21_Temp', '0x56', 'IR3584 Chip Temp'),\ + ('PSUL_Temp1', '0x0D', 'PSU 1 Ambient Temp'),\ + ('PSUL_Temp2', '0x0E', 'PSU 1 Hotspot Temp'),\ + ('PSUR_Temp1', '0x17', 'PSU 2 Ambient Temp'),\ + ('PSUR_Temp2', '0x18', 'PSU 2 Hotspot Temp'),\ ] - self.sensor_id = self.THERMAL_LIST[self.index][0] - self.sensor_des = self.THERMAL_LIST[self.index][1] - self.sensor_reading_addr = self.THERMAL_LIST[self.index][2] + self.sensor_id = thermal_list[self.index][0] + self.sensor_reading_addr = thermal_list[self.index][1] + self.sensor_name = thermal_list[self.index][2] - def __set_threshold(self, key, value): - print('{} {}'.format(key, value)) + temp = self.get_temperature(True) + self.minimum_thermal = temp + self.maximum_thermal = temp - def get_temperature(self): + def get_temperature(self, skip_record=False): """ Retrieves current temperature reading from thermal Returns: @@ -62,7 +65,20 @@ def get_temperature(self): if status and len(raw_ss_read.split()) > 0: ss_read = raw_ss_read.split()[0] temperature = float(int(ss_read, 16)) - return temperature + + if temperature != 0.0: + if not skip_record: + # Record maximum + if temperature > self.maximum_thermal: + self.maximum_thermal = temperature + + # Record minimum + if temperature < self.minimum_thermal: + self.minimum_thermal = temperature + + return temperature + else: + return DEFAULT_VAL def get_high_threshold(self): """ @@ -77,7 +93,10 @@ def get_high_threshold(self): if status and len(raw_up_thres_read.split()) > 6: ss_read = raw_up_thres_read.split()[4] high_threshold = float(int(ss_read, 16)) - return high_threshold + if high_threshold != 0.0: + return high_threshold + else: + return DEFAULT_VAL def get_low_threshold(self): """ @@ -86,7 +105,7 @@ def get_low_threshold(self): A float number, the low threshold temperature of thermal in Celsius up to nearest thousandth of one degree Celsius, e.g. 30.125 """ - return DEFUALT_LOWER_TRESHOLD + return DEFAULT_VAL def set_high_threshold(self, temperature): """ @@ -97,7 +116,8 @@ def set_high_threshold(self, temperature): Returns: A boolean, True if threshold is set successfully, False if not """ - status, ret_txt = self._api_helper.ipmi_set_ss_thres(self.sensor_id, HIGH_TRESHOLD_SET_KEY, temperature) + status, ret_txt = self._api_helper.ipmi_set_ss_thres( + self.sensor_id, HIGH_TRESHOLD_SET_KEY, temperature) return status def set_low_threshold(self, temperature): @@ -111,37 +131,61 @@ def set_low_threshold(self, temperature): """ return False - def get_name(self): + def get_high_critical_threshold(self): """ - Retrieves the name of the thermal device - Returns: - string: The name of the thermal device + 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 """ - return self.THERMAL_LIST[self.index][0] + high_critical_threshold = 0.0 + status, raw_up_thres_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr)) + if status and len(raw_up_thres_read.split()) > 6: + ss_read = raw_up_thres_read.split()[5] + high_critical_threshold = float(int(ss_read, 16)) + if high_critical_threshold != 0.0: + return high_critical_threshold + else: + return DEFAULT_VAL - def get_presence(self): + def get_minimum_recorded(self): """ - Retrieves the presence of the device + Retrieves the minimum recorded temperature of thermal Returns: - bool: True if device is present, False if not + A float number, the minimum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 """ - return True if self.get_temperature() > 0 else False + return self.minimum_thermal - def get_model(self): + def get_maximum_recorded(self): """ - Retrieves the model number (or part number) of the device + Retrieves the maximum recorded temperature of thermal Returns: - string: Model/part number of device + A float number, the maximum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return self.maximum_thermal + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device """ - return self.sensor_des + return self.sensor_name - def get_serial(self): + def get_presence(self): """ - Retrieves the serial number of the device + Retrieves the presence of the device Returns: - string: Serial number of device + bool: True if device is present, False if not """ - return "Unknown" + return True if self.get_temperature() > 0 else False def get_status(self): """ @@ -150,3 +194,11 @@ def get_status(self): A boolean value, True if device is operating properly, False if not """ return self.get_presence() + + def is_replaceable(self): + """ + Retrieves whether thermal module is replaceable + Returns: + A boolean value, True if replaceable, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/watchdog.py new file mode 100644 index 000000000000..562b2177b442 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/sonic_platform/watchdog.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica Qeastone2 +# +# Watchdog contains an implementation of SONiC Platform Base API +# +############################################################################# +import subprocess + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +I2C_WDT_BUS_ID=60 +I2C_WDT_DEV_ID=0x0d +I2C_WDT_RESET_SRC_REG=0x06 +I2C_WDT_CTRL_REG=0x81 +I2C_WDT_SET_TIMER_L_REG=0x82 +I2C_WDT_SET_TIMER_M_REG=0x83 +I2C_WDT_SET_TIMER_H_REG=0x84 +I2C_WDT_ARM_REG=0x85 +I2C_WDT_TIMER_L_REG=0x86 +I2C_WDT_TIMER_M_REG=0x87 +I2C_WDT_TIMER_H_REG=0x88 + +WDT_ENABLE=0x1 +WDT_DISABLE=0x0 +WDT_KEEPALIVE=0x1 +WDT_COMMON_ERROR=-1 +DEFAULT_TIMEOUT=180 + +class Watchdog(WatchdogBase): + + def __init__(self): + # Set default value + self.armed = True if self._active() else False + self.timeout = self._gettimeout() + #self._disable() + + def _i2cget_cmd(self, reg): + cmd = "i2cget -y -f {} {} {} b".format(I2C_WDT_BUS_ID, I2C_WDT_DEV_ID, + reg) + return cmd + + def _i2cset_cmd(self, reg, val): + cmd = "i2cset -y -f {} {} {} {}".format(I2C_WDT_BUS_ID, I2C_WDT_DEV_ID, + reg, val) + return cmd + + def _getstatusoutput(self, cmd): + ret,data = subprocess.getstatusoutput(cmd) + status = 0 + if ret != 0: + status = ret + + return status, data + + def _active(self): + """ + WDT is active or not + """ + status, data = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_CTRL_REG)) + if status: + pass + return True if data == "0x01" else False + + def _enable(self): + """ + Turn on the watchdog timer + """ + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_CTRL_REG, + WDT_ENABLE)) + if status: + pass + + def _disable(self): + """ + Turn off the watchdog timer + """ + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_CTRL_REG, + WDT_DISABLE)) + if status: + pass + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + self._settimeleft(0) + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_ARM_REG, + WDT_KEEPALIVE)) + if status: + pass + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + ms = seconds * 1000 + ms_low_byte = ms & 0xff + ms_media_byte = (ms >> 8) & 0xff + ms_high_byte = (ms >> 16) & 0xff + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_SET_TIMER_L_REG, + ms_low_byte)) + if status: + pass + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_SET_TIMER_M_REG, + ms_media_byte)) + if status: + pass + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_SET_TIMER_H_REG, + ms_high_byte)) + if status: + pass + return self._gettimeout() + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + data = [0, 0, 0] + status, data[0] = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_SET_TIMER_L_REG)) + if status: + pass + status, data[1] = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_SET_TIMER_M_REG)) + if status: + pass + status, data[2] = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_SET_TIMER_H_REG)) + if status: + pass + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + + return seconds + + def _settimeleft(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + ms = seconds * 1000 + ms_low_byte = ms & 0xff + ms_media_byte = (ms >> 8) & 0xff + ms_high_byte = (ms >> 16) & 0xff + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_TIMER_L_REG, + ms_low_byte)) + if status: + pass + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_TIMER_M_REG, + ms_media_byte)) + if status: + pass + status, data = self._getstatusoutput(self._i2cset_cmd(I2C_WDT_TIMER_H_REG, + ms_high_byte)) + if status: + pass + + def _gettimeleft(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + data = [0, 0, 0] + status, data[0] = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_TIMER_L_REG)) + if status: + pass + status, data[1] = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_TIMER_M_REG)) + if status: + pass + status, data[2] = self._getstatusoutput(self._i2cget_cmd(I2C_WDT_TIMER_H_REG)) + if status: + pass + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + + return (self.timeout - seconds) if (self.timeout > seconds) else -1 + + ################################################################# + + 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. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + if self.armed: + self._keepalive() + else: + self._settimeout(seconds) + self._keepalive() + self._enable() + self.armed = True + ret = self.timeout + except IOError as e: + pass + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + 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. + """ + + timeleft = WDT_COMMON_ERROR + + if self.armed: + try: + timeleft = self._gettimeleft() + except IOError: + pass + + return timeleft diff --git a/platform/broadcom/sonic-platform-modules-cel/questone2/systemd/platform-modules-questone2.service b/platform/broadcom/sonic-platform-modules-cel/questone2/systemd/platform-modules-questone2.service new file mode 100644 index 000000000000..c6ad69112edb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/questone2/systemd/platform-modules-questone2.service @@ -0,0 +1,13 @@ +[Unit] +Description=Celestica questone2 platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-questone2 start +ExecStop=-/etc/init.d/platform-modules-questone2 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c index 07ab42c21686..593a8655aacb 100644 --- a/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c @@ -375,4 +375,4 @@ module_exit(baseboard_cpld_exit); MODULE_AUTHOR("Pradchaya Phucharoen "); MODULE_DESCRIPTION("Celestica Seastone2 Baseboard CPLD Driver"); -MODULE_LICENSE("GPL"); \ No newline at end of file +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/platform_sensors.py new file mode 100755 index 000000000000..559a4315a30f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/platform_sensors.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +# +# Silverstone platform sensors. This script get the sensor data from BMC +# using ipmitool and display them in lm-sensor alike format. +# +# The following data is support: +# 1. Temperature sensors +# 2. PSUs +# 3. Fan Drawers + +import sys +import logging +import subprocess + +IPMI_SDR_CMD = ['/usr/bin/ipmitool', 'sdr', 'elist'] +MAX_NUM_FANS = 4 +MAX_NUM_PSUS = 2 + +SENSOR_NAME = 0 +SENSOR_VAL = 4 + +sensor_dict = {} + +def ipmi_sensor_dump(cmd): + ''' Execute ipmitool command return dump output + exit if any error occur. + ''' + global sensor_dict + sensor_dump = '' + + try: + sensor_dump = subprocess.check_output(IPMI_SDR_CMD, universal_newlines=True) + except subprocess.CalledProcessError as e: + logging.error('Error! Failed to execute: {}'.format(cmd)) + sys.exit(1) + + for line in sensor_dump.splitlines(): + sensor_info = line.split('|') + sensor_dict[sensor_info[SENSOR_NAME].strip()] = sensor_info[SENSOR_VAL].strip() + + return True + +def get_reading_by_name(sensor_name, sdr_elist_dump): + found = '' + + for line in sdr_elist_dump.splitlines(): + line = line.decode() + if sensor_name in line: + found = line.strip() + break + + if not found: + logging.error('Cannot find sensor name:' + sensor_name) + + else: + try: + found = found.split('|')[4] + except IndexError: + logging.error('Cannot get sensor data of:' + sensor_name) + + logging.basicConfig(level=logging.DEBUG) + return found + + +def read_temperature_sensors(): + sensor_list = [\ + ('Base_Temp_U5', 'Baseboard Right Temp'),\ + ('Base_Temp_U7', 'Baseboard Left Temp'),\ + ('Switch_Temp_U1', 'ASIC External Front Temp'),\ + ('Switch_Temp_U18', 'ASIC External Rear Temp'),\ + ('Switch_Temp_U28', 'Switchboard Right Temp'),\ + ('Switch_Temp_U29', 'Switchboard Left Temp'),\ + ('CPU_Temp', 'CPU Internal Temp'),\ + ('Switch_U33_Temp', 'IR3595 Chip Temp'),\ + ('Switch_U21_Temp', 'IR3584 Chip Temp'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Temperature Sensors\n" + output += "Adapter: IPMI adapter\n" + for sensor in sensor_list: + output += sensor_format.format('{}:'.format(sensor[1]),\ + sensor_dict[sensor[0]],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_fan_sensors(num_fans): + + sensor_list = [\ + ('Fan{}_Status', 'Fan Drawer {} Status'),\ + ('Fan{}_Front', 'Fan {} front'),\ + ('Fan{}_Rear', 'Fan {} rear'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Fan Drawers\n" + output += "Adapter: IPMI adapter\n" + for fan_num in range(1, num_fans+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(fan_num) + display_sensor_name = sensor[1].format(fan_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_psu_sensors(num_psus): + + sensor_list = [\ + ('PSU{}_Status', 'PSU {} Status'),\ + ('PSU{}_Fan', 'PSU {} Fan 1'),\ + ('PSU{}_VIn', 'PSU {} Input Voltage'),\ + ('PSU{}_CIn', 'PSU {} Input Current'),\ + ('PSU{}_PIn', 'PSU {} Input Power'),\ + ('PSU{}_Temp1', 'PSU {} Ambient Temp'),\ + ('PSU{}_Temp2', 'PSU {} Hotspot Temp'),\ + ('PSU{}_VOut', 'PSU {} Output Voltage'),\ + ('PSU{}_COut', 'PSU {} Output Current'),\ + ('PSU{}_POut', 'PSU {} Output Power'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "PSU\n" + output += "Adapter: IPMI adapter\n" + for psu_num in range(1, num_psus+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format('L' if psu_num == 1 else 'R') + display_sensor_name = sensor[1].format(psu_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def main(): + output_string = '' + + if ipmi_sensor_dump(IPMI_SDR_CMD): + output_string += read_temperature_sensors() + output_string += read_psu_sensors(MAX_NUM_PSUS) + output_string += read_fan_sensors(MAX_NUM_FANS) + + print(output_string) + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/seastone2_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/seastone2_platform_shutdown.sh new file mode 100755 index 000000000000..e04cac54fa98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/seastone2_platform_shutdown.sh @@ -0,0 +1,26 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +# BMC cold power-cyle +ipmitool chassis power cycle &> /dev/null + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/sensors new file mode 100755 index 000000000000..5d740a9eb7d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/scripts/sensors @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon python3 /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/setup.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/setup.py new file mode 100644 index 000000000000..8d253086b26d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/setup.py @@ -0,0 +1,31 @@ +from setuptools import setup + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Celestica Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Wirut Getbamrung', + maintainer_email='wgetbumr@celestica.com', + packages=[ + 'sonic_platform', + ], + package_dir={ + 'sonic_platform': 'sonic_platform'}, + 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.9', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/__init__.py new file mode 100644 index 000000000000..d3c24cb008dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import platform diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/chassis.py new file mode 100644 index 000000000000..56664cc6e8f2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/chassis.py @@ -0,0 +1,457 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +try: + import sys + import time + import os + import re + import shutil + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform_base.sfp_base import SfpBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_DRAWER = 4 +NUM_FAN_PER_DRAWER = 2 +NUM_PSU = 2 +NUM_THERMAL = 13 +NUM_SFP = 33 +NUM_COMPONENT = 9 + +REBOOT_CAUSE_REG = "0xA106" +BASE_CPLD_PLATFORM = "baseboard" +BASE_GETREG_PATH = "/sys/devices/platform/{}/getreg".format(BASE_CPLD_PLATFORM) +IPMI_GET_SYS_STATUS_LED="ipmitool raw 0x3A 0x0C 0x00 0x02 0x62" +IPMI_SET_SYS_STATUS_LED="ipmitool raw 0x3A 0x0C 0x00 0x03 0x62 {}" + +ORG_HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +TMP_HW_REBOOT_CAUSE_FILE="/tmp/hw-reboot-cause.txt" + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + sfp_status_dict={} + + #led color status + SYSLED_COLOR_VAL_MAP = {\ + 'off': '0x33',\ + 'green': '0x10',\ + 'green_blink_1hz': '0x11',\ + 'amber': '0x20'\ + } + + SYSLED_VAL_COLOR_DESC_MAP = { + 0x33: 'off',\ + 0x10: 'green',\ + 0x11: 'green_blink_1hz',\ + 0x20: 'amber'\ + } + + def __init__(self): + ChassisBase.__init__(self) + self._api_helper = APIHelper() + self.sfp_module_initialized = False + self.fan_module_initialized = False + self._watchdog = None + self._airflow_direction = None + self.__initialize_eeprom() + + self.__initialize_thermals() + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_components() + + def __initialize_sfp(self): + if not self.sfp_module_initialized: + from sonic_platform.sfp import Sfp + for index in range(0, NUM_SFP): + sfp = Sfp(index) + self._sfp_list.append(sfp) + present = sfp.get_presence() + self.sfp_status_dict[sfp.index] = '1' if present else '0' + self.sfp_module_initialized = True + + def __initialize_psu(self): + from sonic_platform.psu import Psu + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_fan(self): + from sonic_platform.fan import Fan + from sonic_platform.fan_drawer import FanDrawer + for fand_index in range(0, NUM_FAN_DRAWER): + drawer_fan_list=[] + for fan_index in range(0, NUM_FAN_PER_DRAWER): + fan = Fan(fand_index, fan_index) + self._fan_list.append(fan) + drawer_fan_list.append(fan) + fan_drawer = FanDrawer(fand_index, drawer_fan_list) + self._fan_drawer_list.append(fan_drawer) + self.fan_module_initialized = True + + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Eeprom + self._eeprom = Eeprom() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def initizalize_system_led(self): + return True + + def get_status_led(self): + color_str = 'N/A' + status, output = self._api_helper.run_command(IPMI_GET_SYS_STATUS_LED) + if status: + color_val = int(output, 16) & 0x33 + color_str = self.SYSLED_VAL_COLOR_DESC_MAP.get(color_val, color_str) + + return color_str + + def set_status_led(self, color): + status = False + + color_val = self.SYSLED_COLOR_VAL_MAP.get(color, None) + if color_val != None: + cmd = IPMI_SET_SYS_STATUS_LED.format(color_val) + status, res = self._api_helper.run_command(cmd) + + return status + + 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.get_mac() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.get_serial() + + 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.get_eeprom() + + 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. + """ + hw_reboot_cause = self._api_helper.get_register_value( + BASE_GETREG_PATH, REBOOT_CAUSE_REG) + + + # This tmp copy is to retain the reboot-cause only for the current boot + if os.path.isfile(ORG_HW_REBOOT_CAUSE_FILE): + shutil.move(ORG_HW_REBOOT_CAUSE_FILE, TMP_HW_REBOOT_CAUSE_FILE) + + if hw_reboot_cause == "0x33" and os.path.isfile(TMP_HW_REBOOT_CAUSE_FILE): + with open(TMP_HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + if match is not None: + if match.group(1) == 'system': + return (self.REBOOT_CAUSE_NON_HARDWARE, 'System cold reboot') + + + if hw_reboot_cause == "0x99": + reboot_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC + description = 'ASIC Overload Reboot' + elif hw_reboot_cause == "0x88": + reboot_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU + description = 'CPU Overload Reboot' + elif hw_reboot_cause == "0x77": + reboot_cause = self.REBOOT_CAUSE_WATCHDOG + description = 'Hardware Watchdog Reset' + elif hw_reboot_cause == "0x55": + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'CPU Cold Reset' + elif hw_reboot_cause == "0x44": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'CPU Warm Reset' + elif hw_reboot_cause == "0x33": + # When NON_HARDWARE is used and device is powercycled via IPMI + # reboot cause computed as Unknown, Hence using HARDWARE_OTHER + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Soft-Set Cold Reset' + elif hw_reboot_cause == "0x22": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = 'Soft-Set Warm Reset' + elif hw_reboot_cause == "0x11": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power On Reset' + elif hw_reboot_cause == "0x00": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = 'Power Cycle Reset' + else: + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Hardware reason' + + return (reboot_cause, description) + + ############################################################## + ######################## SFP methods ######################### + ############################################################## + + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + Returns: + An integer, the number of sfps available on this chassis + """ + self.__initialize_sfp() + + return len(self._sfp_list) + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + self.__initialize_sfp() + + return self._sfp_list + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet1, 1 for Ethernet2 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + self.__initialize_sfp() + + try: + sfp = self._sfp_list[index - 1] + except IndexError: + sys.stderr.write("SFP index {} out of range (0-{})\n".format( + index, len(self._sfp_list) - 1)) + return sfp + + ############################################################## + ####################### Other methods ######################## + ############################################################## + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + if self._watchdog is None: + from sonic_platform.watchdog import Watchdog + self._watchdog = Watchdog() + + return self._watchdog + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._api_helper.hwsku + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._eeprom.get_pn() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self.get_serial_number() + + def get_revision(self): + """ + Retrieves the hardware revision for the chassis + Returns: + A string containing the hardware revision for this chassis. + """ + return self._eeprom.get_revision() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + ############################################################## + ###################### Event methods ######################### + ############################################################## + + 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): + - bool: True if call successful, False if not; + - dict: 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. + The known devices's device_id and device_event was defined as table below. + ----------------------------------------------------------------- + device | device_id | device_event | annotate + ----------------------------------------------------------------- + 'fan' '' '0' Fan removed + '1' Fan inserted + + 'sfp' '' '0' Sfp removed + '1' Sfp inserted + '2' I2C bus stuck + '3' Bad eeprom + '4' Unsupported cable + '5' High Temperature + '6' Bad cable + + 'voltage' '' '0' Vout normal + '1' Vout abnormal + -------------------------------------------------------------------- + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0', '12':'1'}, + 'voltage':{'U20':'0', 'U21':'1'}} + Indicates that: + fan 0 has been removed, fan 2 has been inserted. + sfp 11 has been removed, sfp 12 has been inserted. + monitored voltage U20 became normal, voltage U21 became abnormal. + Note: For sfp, when event 3-6 happened, the module will not be avalaible, + XCVRD shall stop to read eeprom before SFP recovered from error status. + """ + sfp_dict = {} + + SFP_REMOVED = '0' + SFP_INSERTED = '1' + + SFP_PRESENT = True + SFP_ABSENT = False + + start_time = time.time() + time_period = timeout/float(1000) #Convert msecs to secs + + while time.time() < (start_time + time_period) or timeout == 0: + for sfp in self._sfp_list: + port_idx = sfp.index + if self.sfp_status_dict[port_idx] == SFP_REMOVED and \ + sfp.get_presence() == SFP_PRESENT: + sfp_dict[port_idx] = SFP_INSERTED + self.sfp_status_dict[port_idx] = SFP_INSERTED + elif self.sfp_status_dict[port_idx] == SFP_INSERTED and \ + sfp.get_presence() == SFP_ABSENT: + sfp_dict[port_idx] = SFP_REMOVED + self.sfp_status_dict[port_idx] = SFP_REMOVED + + if sfp_dict: + return True, {'sfp':sfp_dict} + + time.sleep(0.5) + + return True, {'sfp':{}} # Timeout + + def get_airflow_direction(self): + if self._airflow_direction == None: + try: + vendor_extn = self._eeprom.get_vendor_extn() + airflow_type = vendor_extn.split()[2][2:4] # Either 0xFB or 0xBF + if airflow_type == 'FB': + direction = 'exhaust' + elif airflow_type == 'BF': + direction = 'intake' + else: + direction = 'N/A' + except (AttributeError, IndexError): + direction = 'N/A' + + self._airflow_direction = direction + + return self._airflow_direction + + def get_port_or_cage_type(self, index): + """ + Retrieves sfp port or cage type corresponding to physical port + + Args: + index: An integer (>=0), the index of the sfp to retrieve. + + Returns: + The masks of all types of port or cage that can be supported on the port + Types are defined in sfp_base.py + """ + if index in range(1, 32+1): + return SfpBase.SFP_PORT_TYPE_BIT_QSFP28 + elif index == 33: + return SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS + else: + raise NotImplementedError + + diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/component.py new file mode 100644 index 000000000000..1f82f87e6731 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/component.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import os.path +import re + +try: + #from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NAME_IDX = 0 +DESC_IDX = 1 +VER_API_IDX = 2 + +BASE_CPLD_PLATFORM = "baseboard" +SW_CPLD_PLATFORM = "switchboard" +PLATFORM_SYSFS_PATH = "/sys/devices/platform/" + +FPGA_GETREG_PATH = "{}/{}/FPGA/getreg".format( + PLATFORM_SYSFS_PATH, SW_CPLD_PLATFORM) +BASE_GETREG_PATH = "{}/{}/getreg".format( + PLATFORM_SYSFS_PATH, BASE_CPLD_PLATFORM) +SW_CPLD1_GETREG_PATH = "{}/{}/CPLD1/getreg".format( + PLATFORM_SYSFS_PATH, SW_CPLD_PLATFORM) +SW_CPLD2_GETREG_PATH = "{}/{}/CPLD2/getreg".format( + PLATFORM_SYSFS_PATH, SW_CPLD_PLATFORM) +BIOS_VER_PATH = "/sys/class/dmi/id/bios_version" + +BASE_CPLD_VER_REG = "0xA100" +COME_CPLD_VER_REG = "0xA1E0" +SW_CPLD_VER_REG = "0x00" +FPGA_VER_REG = "0x00" + +UNKNOWN_VER = "N/A" +ONIE_VER_CMD = "cat /host/machine.conf" +SSD_VER_CMD = "smartctl -i /dev/sda" + +class Component(): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + COMPONENT_LIST = [ + ("BIOS", "Basic input/output System", self.__get_bios_ver), + ("ONIE", "Open Network Install Environment", self.__get_onie_ver), + ("BMC", "Baseboard Management Controller", self.__get_bmc_ver), + ("FPGA", "FPGA for transceiver EEPROM access and other component I2C access", self.__get_fpga_ver), + ("CPLD COMe", "COMe board CPLD", self.__get_cpld_ver), + ("CPLD BASE", "CPLD for board functions, fan control and watchdog", self.__get_cpld_ver), + ("CPLD SW1", "CPLD for port control QSFP(1-16)", self.__get_cpld_ver), + ("CPLD SW2", "CPLD for port control QSFP(17-32) SFP(33)", self.__get_cpld_ver), + ("SSD", "Solid State Drive - {}", self.__get_ssd_ver), + ] + + self.index = component_index + self.name = COMPONENT_LIST[self.index][NAME_IDX] + self.description = COMPONENT_LIST[self.index][DESC_IDX] + self.__get_version = COMPONENT_LIST[self.index][VER_API_IDX] + self._api_helper = APIHelper() + + def __get_bios_ver(self): + return self._api_helper.read_one_line_file(BIOS_VER_PATH) + + def __get_onie_ver(self): + onie_ver = "N/A" + status, raw_onie_data = self._api_helper.run_command(ONIE_VER_CMD) + if status: + ret = re.search(r"(?<=onie_version=).+[^\n]", raw_onie_data) + if ret != None: + onie_ver = ret.group(0) + return onie_ver + + def __get_bmc_ver(self): + cmd="ipmitool mc info | grep 'Firmware Revision'" + status, raw_ver=self._api_helper.run_command(cmd) + if status: + bmc_ver=raw_ver.split(':')[-1].strip() + return bmc_ver + else: + return UNKNOWN_VER + + def __get_fpga_ver(self): + version_raw = self._api_helper.get_register_value(FPGA_GETREG_PATH, FPGA_VER_REG) + return "{}.{}".format(int(version_raw[2:][:4], 16), int(version_raw[2:][4:], 16)) if version_raw else UNKNOWN_VER + + def __get_cpld_ver(self): + cpld_api_param = { + 'CPLD COMe': (BASE_GETREG_PATH, COME_CPLD_VER_REG), + 'CPLD BASE': (BASE_GETREG_PATH, BASE_CPLD_VER_REG), + 'CPLD SW1': (SW_CPLD1_GETREG_PATH, SW_CPLD_VER_REG), + 'CPLD SW2': (SW_CPLD2_GETREG_PATH, SW_CPLD_VER_REG), + } + api_param = cpld_api_param[self.name] + + cpld_ver = self._api_helper.get_register_value(api_param[0], api_param[1]) + return "{}.{}".format(int(cpld_ver[2], 16), int(cpld_ver[3], 16)) if cpld_ver else UNKNOWN_VER + + def __get_ssd_ver(self): + ssd_ver = "N/A" + status, raw_ssd_data = self._api_helper.run_command(SSD_VER_CMD) + if status: + ret = re.search(r"Firmware Version: +(.*)[^\\]", raw_ssd_data) + if ret != None: + ssd_ver = ret.group(1) + return ssd_ver + + def __get_ssd_model(self): + model = "N/A" + + status, raw_ssd_data = self._api_helper.run_command(SSD_VER_CMD) + if status: + ret = re.search(r"Device Model: +(.*)[^\\]", raw_ssd_data) + if ret != None: + try: + model = ret.group(1) + except (IndexError): + pass + return model + + 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 + """ + # For SSD get the model name from device + if self.name == "SSD": + return self.description.format(self.__get_ssd_model()) + + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + return self.__get_version() diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/eeprom.py new file mode 100644 index 000000000000..32afdc2751d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/eeprom.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os + import sys + import re + import json + import fcntl + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +NULL = 'N/A' +EEPROM_TMP_FILE = '/tmp/eeprom_dump.json' + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + for i2cbus in range(2): + path_prefix = "/sys/class/i2c-adapter/i2c-{}/".format(i2cbus) + with open(path_prefix + "name") as fd: + if 'SMBus iSMT adapter at ' in fd.readline(): + self._eeprom_path = path_prefix + "{}-0056/eeprom".format(i2cbus) + break + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + try: + match = re.search('(0x[0-9a-fA-F]{2})\s+\d+\s+(.+)', line) + if match is not None: + idx = match.group(1) + value = match.group(2).rstrip('\0') + + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + eeprom_dict = {} + + if os.path.exists(EEPROM_TMP_FILE): + with open(EEPROM_TMP_FILE, 'r') as fd: + eeprom_dict = json.load(fd) + + return eeprom_dict + + original_stdout = sys.stdout + sys.stdout = StringIO() + rv = -1 + try: + rv = self.read_eeprom_db() + except BaseException: + pass + + if rv == 0: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + eeprom_dict = self.__parse_output(decode_output) + else: + e = self.read_eeprom() + if e is None: + sys.stdout = original_stdout + return {} + + self.decode_eeprom(e) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(e) + if not is_valid: + return {} + + eeprom_dict = self.__parse_output(decode_output) + + if len(eeprom_dict) != 0: + with open(EEPROM_TMP_FILE, 'w') as fd: + fcntl.flock(fd, fcntl.LOCK_EX) + json.dump(eeprom_dict, fd) + fcntl.flock(fd, fcntl.LOCK_UN) + + return eeprom_dict + + def get_eeprom(self): + return self._eeprom + + def get_product(self): + return self._eeprom.get('0x21', NULL) + + def get_pn(self): + return self._eeprom.get('0x22', NULL) + + def get_serial(self): + return self._eeprom.get('0x23', NULL) + + def get_mac(self): + return self._eeprom.get('0x24', NULL) + + def get_revision(self): + return self._eeprom.get('0x26', NULL) + + def get_vendor_extn(self): + return self._eeprom.get('0xFD', NULL) diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan.py new file mode 100644 index 000000000000..2b577ac40287 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.fan_base import FanBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NOT_AVAILABLE = 'N/A' + +FAN_NAME_TEMPLATE = "{}Fan{}{}" +NUM_FAN_TRAYS = 4 +NUM_FANS_PER_TRAY = 2 +FAN_SPEED_TOLERANCE = 20 +MAX_RPM_FRONT=23000 +MAX_RPM_REAR=20500 +MAX_RPM_PSU=22600 +FAN_DIR_BASE = 0x41 +FAN_LED_BASE = 0x04 +FAN_FRU_BASE = 0x05 +FAN_STATUS_BASE = 0x00 +FAN_SID_BASE = 0x80 +PSU_FAN_SID_BASE = 0x8a +PSU_FRU_BASE = 0x03 + + +IPMI_FAN_DIR="ipmitool raw 0x3a 0x0c 0x00 0x02 {}" +IPMI_GET_SPEED="ipmitool raw 0x04 0x2d {}" +IPMI_GET_CPLD_PWM="ipmitool raw 0x3a 0x0c 0x00 0x02 {}" +IPMI_GET_PRESENCE="ipmitool raw 0x3a 0x03 0x03 {}" +IPMI_GET_MODEL="ipmitool fru list {} | grep 'Board Part Number'" +IPMI_GET_SERIAL="ipmitool fru list {} | grep 'Board Serial'" +IPMI_GET_PSU_MODEL="ipmitool fru list {} | grep 'Product Name'" +IPMI_GET_PSU_SPEED="ipmitool raw 0x04 0x2d {}" +IPMI_SET_STATUS_LED="ipmitool raw 0x3a 0x0a {} {}" +IPMI_GET_STATUS_LED="ipmitool raw 0x3a 0x0b {}" + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + self.is_psu_fan = is_psu_fan + self._api_helper = APIHelper() + self.index = (self.fan_tray_index * 2) + self.fan_index + self.name = None + if self.is_psu_fan: + self.psu_index = psu_index + self.max_speed = MAX_RPM_PSU + self._fan_sid_offset = PSU_FAN_SID_BASE + self.psu_index + self._fan_status_offset = FAN_STATUS_BASE + NUM_FAN_TRAYS + self.psu_index + else: + self._fan_status_offset = FAN_STATUS_BASE + self.fan_tray_index + self._fan_fru_offset = FAN_FRU_BASE + self.fan_tray_index + self._fan_dir_offset = FAN_DIR_BASE + (self.fan_tray_index * 4) + if self.fan_tray_index > 1: + # Questone CPLD firmware is used and hence FAN 3 will be missing + # There are only 4 FAN trays in this platform + self._fan_dir_offset = self._fan_dir_offset + 4 + + self._fan_speed_offset = self._fan_dir_offset - 1 + self._fan_led_offset = FAN_LED_BASE + self.fan_tray_index + + if fan_index % 2 == 0: + # Front FAN + self.is_front = True + self.max_speed = MAX_RPM_FRONT + self._fan_sid_offset = FAN_SID_BASE + 1 + (self.fan_tray_index * NUM_FANS_PER_TRAY) + else: + # Rear FAN + self.is_front = False + self.max_speed = MAX_RPM_REAR + self._fan_sid_offset = FAN_SID_BASE + (self.fan_tray_index * NUM_FANS_PER_TRAY) + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = NOT_AVAILABLE + + if self.is_psu_fan: + cmd = IPMI_GET_PSU_MODEL.format(PSU_FRU_BASE + self.psu_index) + status, output = self._api_helper.run_command(cmd) + if status and output: + model = output.split(':')[-1] + if len(model) > 0: + if model[-2:] == ' B': + direction = self.FAN_DIRECTION_INTAKE + else: + direction = self.FAN_DIRECTION_EXHAUST + else: + cmd = IPMI_FAN_DIR.format(self._fan_dir_offset) + status, output = self._api_helper.run_command(cmd) + if status: + dir_num = int(output, 16) & 0x0C + if dir_num == 0x0: + direction = self.FAN_DIRECTION_EXHAUST + elif dir_num == 0x8: + direction = self.FAN_DIRECTION_INTAKE + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + speed = 0 + + if not self.is_psu_fan: + multiplier = 150.0 + else: + multiplier = 100.0 + + cmd = IPMI_GET_PSU_SPEED.format(self._fan_sid_offset) + status, output = self._api_helper.run_command(cmd) + if status: + raw_speed = output.split()[0] + rpm_speed = int(raw_speed, 16) * multiplier + speed = int((rpm_speed/self.max_speed) * 100) + + return speed + + 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) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + target_speed = 0 + + if self.is_psu_fan: + # Ignored for tolerance check + return self.get_speed() + + cmd = IPMI_GET_CPLD_PWM.format(self._fan_speed_offset) + status, output = self._api_helper.run_command(cmd) + if status: + fan_pwm = int(output, 16) + target_speed = round(fan_pwm / 255 * 100) + + return target_speed + + 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 + """ + return FAN_SPEED_TOLERANCE + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + Notes: + pwm setting mode must set as Manual + manual: systemctl stop fanctrl.service + auto: systemctl start fanctrl.service + """ + + # FAN speed is controlled by BCM always + return False + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + # There is no per Fan LED + return True + + def drawer_set_status_led(self, color): + status = False + + color_dict = {\ + self.STATUS_LED_COLOR_OFF: 0,\ + self.STATUS_LED_COLOR_AMBER: 1,\ + self.STATUS_LED_COLOR_RED: 1,\ + self.STATUS_LED_COLOR_GREEN: 2\ + } + + if not self.is_psu_fan: + cmd = IPMI_SET_STATUS_LED.format(self._fan_led_offset, color_dict.get(color, 0)) + status, _ = self._api_helper.run_command(cmd) + + return status + + + def get_status_led(self): + """ + Gets the state of the fan status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + + Note: + Output + STATUS_LED_COLOR_GREEN = "green" + STATUS_LED_COLOR_AMBER = "amber" + STATUS_LED_COLOR_RED = "red" + STATUS_LED_COLOR_OFF = "off" + + Input + 0x1: green + 0x2: red + 0x3: off + """ + status = NOT_AVAILABLE + color_dict = {\ + 0: self.STATUS_LED_COLOR_OFF,\ + 1: self.STATUS_LED_COLOR_AMBER,\ + 2: self.STATUS_LED_COLOR_GREEN\ + } + + if not self.is_psu_fan: + cmd = IPMI_GET_STATUS_LED.format(self._fan_led_offset) + status, output = self._api_helper.run_command(cmd) + if status: + color = int(output, 16) + status = color_dict.get(color, status) + + return status + + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + + if not self.name: + if not self.is_psu_fan: + psu_name = "" + fan_id = " {}".format(self.fan_tray_index + 1) + fan_type = " Front" if self.is_front else " Rear" + else: + psu_name = "PSU {} ".format(self.psu_index + 1) + fan_id = " {}".format(self.fan_tray_index + 1) + fan_type = "" + + self.name = FAN_NAME_TEMPLATE.format(psu_name, fan_id, fan_type) + + return self.name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + + presence = False + + cmd = IPMI_GET_PRESENCE.format(self._fan_status_offset) + status, output = self._api_helper.run_command(cmd) + if status and output == "00": + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model = NOT_AVAILABLE + + if not self.is_psu_fan: + cmd = IPMI_GET_MODEL.format(self._fan_fru_offset) + status, output = self._api_helper.run_command(cmd) + if status and output: + return output.split()[-1] + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + serial = NOT_AVAILABLE + + if not self.is_psu_fan: + cmd = IPMI_GET_SERIAL.format(self._fan_fru_offset) + status, output = self._api_helper.run_command(cmd) + if status and output: + return output.split()[-1] + + return serial + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() and self.get_speed() > 0 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + if not self.is_psu_fan: + return True + + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..aea952d5822a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/fan_drawer.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +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): + + def __init__(self, index, fan_list): + FanDrawerBase.__init__(self) + + self._fan_list = fan_list + self._index = index + 1 + + 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[0].drawer_set_status_led(color) + + def get_status_led(self): + """ + Gets the state of the fan drawer LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._fan_list[0].get_status_led() + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return 'Drawer {}'.format(self._index) + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + return self._fan_list[0].get_presence() + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._fan_list[0].get_model() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._fan_list[0].get_serial() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self._fan_list[0].get_status() + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/helper.py new file mode 100644 index 000000000000..7bcbd70a0a7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/helper.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python + +import os +import struct +import subprocess +from mmap import * +from sonic_py_common.device_info import get_platform_and_hwsku + +SCALE = 16 +BIN_BITS = 8 +EMPTY_STRING = "" +HOST_CHK_CMD = "docker > /dev/null 2>&1" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = get_platform_and_hwsku() + + def get_register_value(self, getreg_path, register): + cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + return None + else: + return data + + def hex_to_bin(self, ini_string): + return bin(int(ini_string, SCALE)).zfill(BIN_BITS) + + def is_host(self): + rv, _ = subprocess.getstatusoutput(HOST_CHK_CMD) + return (rv == 0) + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def run_command(self, cmd): + status = True + result = "" + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def read_one_line_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + def search_file_by_contain(self, directory, search_str, file_start): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name.startswith(file_start) and search_str in self.read_txt_file(file_path): + return dirpath + return None + + def write_file(self, file_path, data): + try: + with open(file_path, 'w') as fd: + fd.write(str(data)) + return True + except Exception: + pass + return False + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def ipmi_fru_id(self, id, key=None): + status = True + result = "" + cmd = "ipmitool fru print {}".format(str( + id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key)) + + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + cmd = "ipmitool sensor thresh '{}' {} {}".format( + str(id), str(threshold_key), str(value)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def fru_decode_product_serial(self, data): + + if data and data[4] != 00: + start_product_info = ord(data[4]) * 8 + start_format_version = start_product_info + start_product_info = start_format_version + 1 + start_product_Lang_code = start_product_info + 1 + start_product_Manu_name = start_product_Lang_code + 1 + start_product_Manu_name_length = ord(data[start_product_Manu_name]) & 0x0F + start_product_name = start_product_Manu_name + start_product_Manu_name_length + 1 + start_product_name_length = ord(data[start_product_name]) & 0x0F + start_product_module_number = start_product_name + start_product_name_length +1 + start_product_module_number_length = ord(data[start_product_module_number]) & 0x0F + start_product_version = start_product_module_number + start_product_module_number_length +1 + start_product_version_length = ord(data[start_product_version]) & 0x0F + start_product_serial_number = start_product_version + start_product_version_length +1 + start_product_serial_number_length = ord(data[start_product_serial_number]) & 0x1F + return data[start_product_serial_number+1:start_product_serial_number+start_product_serial_number_length+1] + return "N/A" + + def fru_decode_product_model(self, data): + if data and data[4] != 00: + start_product_info = ord(data[4]) * 8 + start_format_version = start_product_info + start_product_info = start_format_version + 1 + start_product_lang_code = start_product_info + 1 + start_product_manu_name = start_product_lang_code + 1 + start_product_manu_name_length = ord(data[start_product_manu_name]) & 0x1F + start_product_name = start_product_manu_name + start_product_manu_name_length + 1 + start_product_name_length = ord(data[start_product_name]) & 0x1F + start_product_module_number = start_product_name + start_product_name_length + 1 + start_product_module_number_length = ord(data[start_product_module_number]) & 0x1F + return data[start_product_module_number + 1: start_product_module_number +start_product_module_number_length + 1] + return "N/A" + + def fru_decode_product_name(self, data): + + if data and data[4] != 00: + start_product_info = ord(data[4]) * 8 + start_format_version = start_product_info + start_product_info = start_format_version + 1 + start_product_Lang_code = start_product_info + 1 + start_product_Manu_name = start_product_Lang_code + 1 + start_product_Manu_name_length = ord(data[start_product_Manu_name]) & 0x0F + start_product_name = start_product_Manu_name + start_product_Manu_name_length + 1 + start_product_name_length = ord(data[start_product_name]) & 0x0F + return data[start_product_name+1: start_product_name+start_product_name_length+1] + + return "N/A" + + def read_eeprom_sysfs(self,sys_path,sysfs_file): + sysfs_path = os.path.join(sys_path, sysfs_file) + try: + with open(sysfs_path, mode='rb', buffering=0) as fd: + data = fd.read(256) + return data + except Exception: + pass + return None diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/pcie.py new file mode 100644 index 000000000000..2f7931d42b01 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/pcie.py @@ -0,0 +1,15 @@ +# +# pcie_base.py +# +# Abstract base class for implementing platform-specific +# PCIE functionality for SONiC +# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +class Pcie(PcieUtil): + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/platform.py new file mode 100644 index 000000000000..c9ba822ac0da --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/platform.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# 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): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/psu.py new file mode 100644 index 000000000000..362463883ad9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/psu.py @@ -0,0 +1,273 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from .helper import APIHelper + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +IPMI_SENSOR_NETFN = "0x04" +IPMI_SENSOR_READ_CMD = "0x2D {}" +IPMI_SENSOR_THRESH_CMD = "0x27 {}" +IPMI_FRU_MODEL_KEY = "Product Name" +IPMI_FRU_SERIAL_KEY = "Product Serial" + +MAX_PSU_POWER = 550 #Watts +psu_ipmi_id = {\ + 1: {\ + "TEMP": "0x0d",\ + "VOUT": "0x0f",\ + "COUT": "0x10",\ + "POUT": "0x11",\ + "STATUS": "0x72",\ + "FRU": 3,\ + }, + 2: {\ + "TEMP": "0x17",\ + "VOUT": "0x19",\ + "COUT": "0x1a",\ + "POUT": "0x1b",\ + "STATUS": "0x73",\ + "FRU": 4,\ + } +} + +ANALOG_READ_OFFSET = 0 +EVENT_0_7_OFFSET = 2 +EVENT_8_14_OFFSET = 3 + +FRU_SERIAL = 4 +FRU_MODEL = 1 + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index+1 + # PSU has only one FAN + fan = Fan(0, 0, is_psu_fan=True, psu_index=psu_index) + self._fan_list.append(fan) + self._api_helper = APIHelper() + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = 0.0 + psu_vout_key = psu_ipmi_id[self.index]['VOUT'] + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_READ_CMD.format(psu_vout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx10^-1 + psu_voltage = int(value, 16) / 10.0 + + return psu_voltage + + def get_voltage_high_threshold(self): + return 12.6 + + def get_voltage_low_threshold(self): + return 11.4 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + psu_current = 0.0 + psu_cout_key = psu_ipmi_id[self.index]['COUT'] + status, output = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_cout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx3x10^-1 + psu_current = int(value, 16) * 3 / 10.0 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + psu_power = 0.0 + psu_pout_key = psu_ipmi_id[self.index]['POUT'] + status, output = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx5 + psu_power = int(value, 16) * 5 + return psu_power + + 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. + """ + return self.get_status() + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.get_presence(): + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return "blinking green" + else: + return "N/A" + + 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 + """ + # PSU's ambient temperature sensor is considered as the PSU temperature + psu_temp = 0.0 + psu_temp_id = psu_ipmi_id[self.index]['TEMP'] + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_READ_CMD.format(psu_temp_id)) + if status: + value = output.split()[ANALOG_READ_OFFSET] + psu_temp = float(int(value, 16)) + + return psu_temp + + 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 MAX_PSU_POWER + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return "PSU {}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + psu_presence = False + psu_pstatus_key = psu_ipmi_id[self.index]['STATUS'] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pstatus_key)) + status_byte = raw_status_read.split()[EVENT_0_7_OFFSET] + + if status: + psu_presence = True if int(status_byte, 16) & 0x01 == 0x01 else False + + return psu_presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model = "Unknown" + if self.get_presence(): + ipmi_fru_idx = psu_ipmi_id[self.index]['FRU'] + status, raw_model = self._api_helper.ipmi_fru_id( + ipmi_fru_idx, IPMI_FRU_MODEL_KEY) + + fru_pn_list = raw_model.split(':')[-1] + model = fru_pn_list.strip() + else: + model = "N/A" + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + serial = "Unknown" + if self.get_presence(): + ipmi_fru_idx = psu_ipmi_id[self.index]['FRU'] + status, raw_serial = self._api_helper.ipmi_fru_id( + ipmi_fru_idx, IPMI_FRU_SERIAL_KEY) + + fru_sr_list = raw_serial.split(':')[-1] + serial = fru_sr_list.strip() + else: + model = "N/A" + + return serial + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + psu_status = False + psu_pstatus_key = psu_ipmi_id[self.index]['STATUS'] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pstatus_key)) + status_byte = raw_status_read.split()[EVENT_0_7_OFFSET] + + if status: + psu_status = False if int(status_byte, 16) & 0x08 == 0x08 else True + + return psu_status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_direction(self): + """ + Return the airflow direction of PSU FAN + Returns: + string: 'intake' or 'exhaust' + """ + self diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/sfp.py new file mode 100644 index 000000000000..9de0aea6277f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/sfp.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# +import time + +try: + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" + +QSFP_PORT_START = 1 +QSFP_PORT_END = 32 +SFP_PORT_START = 33 +SFP_PORT_END = 33 + +PORT_INFO_PATH = '/sys/class/seastone2_fpga' +SFP_I2C_START = 2 + + +class Sfp(SfpOptoeBase): + """Platform-specific Sfp class""" + + # Path to QSFP sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + + def __init__(self, sfp_index): + SfpOptoeBase.__init__(self) + # Init index + self.index = sfp_index + 1 + self.sfp_type, self.port_name = self.__get_sfp_info() + self._api_helper = APIHelper() + self.platform = self._api_helper.platform + self.hwsku = self._api_helper.hwsku + + # Init eeprom path + self.eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'.format(SFP_I2C_START+sfp_index) + + def __get_sfp_info(self): + port_name = "Unknown" + sfp_type = "Unknown" + + if self.index >= QSFP_PORT_START and self.index <= QSFP_PORT_END: + sfp_type = QSFP_TYPE + port_name = sfp_type + str(self.index) + elif self.index >= SFP_PORT_START and self.index <= SFP_PORT_END: + sfp_type = SFP_TYPE + port_name = sfp_type + str(self.index - SFP_PORT_START + 1) + + return sfp_type, port_name + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.platform]) + hwsku_path = "/".join([platform_path, self.hwsku] + ) if self._api_helper.is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def get_eeprom_path(self): + return self.eeprom_path + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reg_status = self._api_helper.read_one_line_file( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_reset"])) + + return (int(reg_status) == 0) + + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type != QSFP_TYPE: + return False + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_reset"]), "w") + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(0)) + reg_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + # Flip the bit back high and write back to the register to take port out of reset + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_reset"]), "w") + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + + reg_file.seek(0) + reg_file.write(hex(1)) + reg_file.close() + + return True + + 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 + """ + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"]), "w") + except IOError as e: + return False + + if lpmode: + value=1 + else: + value=0 + reg_file.write(hex(value)) + reg_file.close() + + return True + + 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 + """ + + reg_status = self._api_helper.read_one_line_file( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"])) + + return (int(reg_status) == 1) + + def get_position_in_parent(self): + return self.index + + def is_replaceable(self): + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.physical_to_logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + # Get path for access port presence status + sysfs_filename = "sfp_modabs" if self.sfp_type == SFP_TYPE else "qsfp_modprs" + reg_path = "/".join([PORT_INFO_PATH, self.port_name, sysfs_filename]) + + content = self._api_helper.read_one_line_file(reg_path) + reg_value = int(content) + + return (reg_value == 0) + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() and not self.get_reset_status() diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/thermal.py new file mode 100644 index 000000000000..1db171329a02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/thermal.py @@ -0,0 +1,204 @@ +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import re +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +IPMI_SENSOR_NETFN = "0x04" +IPMI_SS_READ_CMD = "0x2D {}" +IPMI_SS_THRESHOLD_CMD = "0x27 {}" +HIGH_TRESHOLD_SET_KEY = "unc" +DEFAULT_VAL = 'N/A' + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self._api_helper = APIHelper() + self.index = thermal_index + thermal_list = [\ + ('Base_Temp_U5', '0x01', 'Baseboard Right Temp'),\ + ('Base_Temp_U7', '0x02', 'Baseboard Left Temp'),\ + ('Switch_Temp_U1', '0x03', 'ASIC External Front Temp'),\ + ('Switch_Temp_U18', '0x04', 'ASIC External Rear Temp'),\ + ('Switch_Temp_U28', '0x05', 'Switchboard Right Temp'),\ + ('Switch_Temp_U29', '0x06', 'Switchboard Left Temp'),\ + ('CPU_Temp', '0x07', 'CPU Internal Temp'),\ + ('Switch_U33_Temp', '0x4C', 'IR3595 Chip Temp'),\ + ('Switch_U21_Temp', '0x56', 'IR3584 Chip Temp'),\ + ('PSUL_Temp1', '0x0D', 'PSU 1 Ambient Temp'),\ + ('PSUL_Temp2', '0x0E', 'PSU 1 Hotspot Temp'),\ + ('PSUR_Temp1', '0x17', 'PSU 2 Ambient Temp'),\ + ('PSUR_Temp2', '0x18', 'PSU 2 Hotspot Temp'),\ + ] + self.sensor_id = thermal_list[self.index][0] + self.sensor_reading_addr = thermal_list[self.index][1] + self.sensor_name = thermal_list[self.index][2] + + temp = self.get_temperature(True) + self.minimum_thermal = temp + self.maximum_thermal = temp + + def get_temperature(self, skip_record=False): + """ + 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 + """ + temperature = 0.0 + status, raw_ss_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(self.sensor_reading_addr)) + if status and len(raw_ss_read.split()) > 0: + ss_read = raw_ss_read.split()[0] + temperature = float(int(ss_read, 16)) + + if temperature != 0.0: + if not skip_record: + # Record maximum + if temperature > self.maximum_thermal: + self.maximum_thermal = temperature + + # Record minimum + if temperature < self.minimum_thermal: + self.minimum_thermal = temperature + + return temperature + else: + return DEFAULT_VAL + + 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 + """ + high_threshold = 0.0 + status, raw_up_thres_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr)) + if status and len(raw_up_thres_read.split()) > 6: + ss_read = raw_up_thres_read.split()[4] + high_threshold = float(int(ss_read, 16)) + if high_threshold != 0.0: + return high_threshold + else: + return DEFAULT_VAL + + 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 + """ + return DEFAULT_VAL + + 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 + """ + status, ret_txt = self._api_helper.ipmi_set_ss_thres( + self.sensor_id, HIGH_TRESHOLD_SET_KEY, temperature) + return status + + 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 + """ + 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 + """ + high_critical_threshold = 0.0 + status, raw_up_thres_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr)) + if status and len(raw_up_thres_read.split()) > 6: + ss_read = raw_up_thres_read.split()[5] + high_critical_threshold = float(int(ss_read, 16)) + if high_critical_threshold != 0.0: + return high_critical_threshold + else: + return DEFAULT_VAL + + 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 + """ + return 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 + """ + return self.maximum_thermal + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.sensor_name + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True if self.get_temperature() > 0 else False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() + + def is_replaceable(self): + """ + Retrieves whether thermal module is replaceable + Returns: + A boolean value, True if replaceable, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/watchdog.py new file mode 100644 index 000000000000..2290119674cb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/sonic_platform/watchdog.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica Seastone2 +# +# Watchdog contains an implementation of SONiC Platform Base API +# +############################################################################# +import subprocess +import syslog +import fcntl + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PLATFORM_CPLD_PATH = '/sys/devices/platform/baseboard/{}' +I2C_WDT_ARM_REG='0xA181' +I2C_WDT_SET_TIMER_L_REG='0xA182' +I2C_WDT_SET_TIMER_M_REG='0xA183' +I2C_WDT_SET_TIMER_H_REG='0xA184' +I2C_WDT_KEEPALIVE_REG='0xA185' +I2C_WDT_TIMER_L_REG='0xA186' +I2C_WDT_TIMER_M_REG='0xA187' +I2C_WDT_TIMER_H_REG='0xA188' + +WDT_ENABLE=0x1 +WDT_DISABLE=0x0 +WDT_KEEPALIVE=0x1 +WDT_COMMON_ERROR=-1 +DEFAULT_TIMEOUT=180 + +class Watchdog(WatchdogBase): + + def __init__(self): + # Set default value + self.armed = True if self._is_active() else False + self.timeout = self._gettimeout() + #self._disable() + + def _get_lpc_reg(self, reg): + file_path = PLATFORM_CPLD_PATH.format('getreg') + value = None + status = False + + try: + fd = open(file_path, "w+") + # Acquire an exclusive lock on the file + fcntl.flock(fd, fcntl.LOCK_EX) + fd.write(reg) + fd.flush() + fd.seek(0) + value = fd.readline().rstrip() + status = True + except (IOError, PermissionError, FileNotFoundError): + syslog.syslog(syslog.LOG_ERR, "Baseboard LPC getreg failed with {}",format(e)) + value = None + status = False + finally: + fcntl.flock(fd, fcntl.LOCK_UN) + fd.close() + + return status, value + + def _set_lpc_reg(self, reg, val): + status = False + file_path = PLATFORM_CPLD_PATH.format('setreg') + value = '{} {}'.format(reg, hex(val)) + + try: + fd = open(file_path, 'w') + fcntl.flock(fd, fcntl.LOCK_EX) + fd.write(value) + status = True + except (IOError, PermissionError, FileNotFoundError): + syslog.syslog(syslog.LOG_ERR, "Baseboard LPC setreg failed with {}",format(e)) + value = None + status = False + finally: + fcntl.flock(fd, fcntl.LOCK_UN) + fd.close() + + return status + + def _is_active(self): + """ + WDT is active or not + """ + status, data = self._get_lpc_reg(I2C_WDT_ARM_REG) + if status and data == "0x01": + return True + + return False + + def _enable(self): + """ + Turn on the watchdog timer + """ + self._settimeleft(0) + return self._set_lpc_reg(I2C_WDT_ARM_REG, WDT_ENABLE) + + def _disable(self): + """ + Turn off the watchdog timer + """ + return self._set_lpc_reg(I2C_WDT_ARM_REG, WDT_DISABLE) + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + self._settimeleft(0) + return self._set_lpc_reg(I2C_WDT_KEEPALIVE_REG, WDT_KEEPALIVE) + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + ms = seconds * 1000 + ms_low_byte = ms & 0xff + ms_media_byte = (ms >> 8) & 0xff + ms_high_byte = (ms >> 16) & 0xff + self._set_lpc_reg(I2C_WDT_SET_TIMER_L_REG, ms_low_byte) + self._set_lpc_reg(I2C_WDT_SET_TIMER_M_REG, ms_media_byte) + self._set_lpc_reg(I2C_WDT_SET_TIMER_H_REG, ms_high_byte) + + return self._gettimeout() + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + data = [0, 0, 0] + status, data[0] = self._get_lpc_reg(I2C_WDT_SET_TIMER_L_REG) + if not status: + return 0 + status, data[1] = self._get_lpc_reg(I2C_WDT_SET_TIMER_M_REG) + if not status: + return 0 + status, data[2] = self._get_lpc_reg(I2C_WDT_SET_TIMER_H_REG) + if not status: + return 0 + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + + return seconds + + def _settimeleft(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + ms = seconds * 1000 + ms_low_byte = ms & 0xff + ms_media_byte = (ms >> 8) & 0xff + ms_high_byte = (ms >> 16) & 0xff + self._set_lpc_reg(I2C_WDT_TIMER_L_REG, ms_low_byte) + self._set_lpc_reg(I2C_WDT_TIMER_M_REG, ms_media_byte) + self._set_lpc_reg(I2C_WDT_TIMER_H_REG, ms_high_byte) + + return True + + def _gettimeleft(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + data = [0, 0, 0] + status, data[0] = self._get_lpc_reg(I2C_WDT_TIMER_L_REG) + if not status: + return 0 + status, data[1] = self._get_lpc_reg(I2C_WDT_TIMER_M_REG) + if not status: + return 0 + status, data[2] = self._get_lpc_reg(I2C_WDT_TIMER_H_REG) + if not status: + return 0 + seconds = int((int(data[2], 16) << 16 + | int(data[1], 16) << 8 + | int(data[0], 16)) / 1000) + + return (self.timeout - seconds) if (self.timeout > seconds) else 0 + + ################################################################# + + 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. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + if self.armed: + self._keepalive() + else: + status = self._enable() + if not status: + syslog.syslog(syslog.LOG_ERR, "Enable watchdog failed") + return ret + + self.armed = True + + ret = self.timeout + except IOError: + pass + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + status = self._disable() + if status: + self.armed = False + disarmed = True + else: + syslog.syslog(syslog.LOG_ERR, "Disable watchdog failed") + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + 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. + """ + + timeleft = WDT_COMMON_ERROR + + if self.armed: + try: + timeleft = self._gettimeleft() + except IOError: + pass + + return timeleft diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/Makefile new file mode 100644 index 000000000000..641690d4871e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/Makefile @@ -0,0 +1,11 @@ +TARGET:= pddf_custom_fan_driver_module +$(TARGET)-objs := ./fan_driver/pddf_custom_fan_api.o ./fan_driver/pddf_custom_fan_driver.o + +TARGET1:= pddf_custom_led_module +$(TARGET1)-objs := ./led_driver/pddf_custom_led_module.o + +TARGET2:= pddf_custom_psu_driver_module +$(TARGET2)-objs := ./psu_driver/pddf_psu_api.o ./psu_driver/pddf_psu_driver.o + +obj-m := $(TARGET).o $(TARGET1).o $(TARGET2).o +obj-m += pddf_custom_fpga_algo.o pddf_custom_fpga_extend.o tps536c7.o pddf_custom_wdt.o pddf_custom_lpc_basecpld.o diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_api.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_api.c new file mode 100644 index 000000000000..6777690361b1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_api.c @@ -0,0 +1,656 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description of various APIs related to FAN component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_custom_fan_defs.h" +#include "pddf_custom_fan_driver.h" + +/*#define FAN_DEBUG*/ +#ifdef FAN_DEBUG +#define fan_dbg(...) printk(__VA_ARGS__) +#else +#define fan_dbg(...) +#endif + +extern void *get_device_table(char *name); + +void get_fan_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + default: + break; + } + + return; +} + + +int fan_update_hw(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + +int fan_update_attr(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + if (time_after(jiffies, info->last_updated + HZ + HZ / 2) || !info->valid) + { + dev_dbg(&client->dev, "Starting pddf_fan update\n"); + info->valid = 0; + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_get function fails for %s attribute.ret %d\n", __FUNCTION__, udata->aname, status); + } + + + info->last_updated = jiffies; + info->valid = 1; + } + + mutex_unlock(&info->update_lock); + + return 0; +} + +ssize_t fan_show_default(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); + FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data); + FAN_DATA_ATTR *usr_data = NULL; + struct fan_attr_info *attr_info = NULL; + int i, status=0; + char new_str[ATTR_NAME_LEN] = ""; + FAN_SYSFS_ATTR_DATA *ptr = NULL; + + for (i=0;inum_attr;i++) + { + ptr = (FAN_SYSFS_ATTR_DATA *)pdata->fan_attrs[i].access_data; + get_fan_duplicate_sysfs(ptr->index , new_str); + if (strcmp(attr->dev_attr.attr.name, pdata->fan_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0) + { + attr_info = &data->attr_info[i]; + usr_data = &pdata->fan_attrs[i]; + strscpy(new_str, "", ATTR_NAME_LEN); + } + } + + if (attr_info==NULL || usr_data==NULL) + { + printk(KERN_ERR "%s is not supported attribute for this client\n", usr_data->aname); + goto exit; + } + + fan_update_attr(dev, attr_info, usr_data); + + /*Decide the o/p based on attribute type */ + switch(attr->index) + { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + case FAN7_PRESENT: + case FAN8_PRESENT: + case FAN9_PRESENT: + case FAN10_PRESENT: + case FAN11_PRESENT: + case FAN12_PRESENT: + case FAN13_PRESENT: + case FAN14_PRESENT: + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + case FAN7_DIRECTION: + case FAN8_DIRECTION: + case FAN9_DIRECTION: + case FAN10_DIRECTION: + case FAN11_DIRECTION: + case FAN12_DIRECTION: + case FAN13_DIRECTION: + case FAN14_DIRECTION: + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + case FAN7_INPUT: + case FAN8_INPUT: + case FAN9_INPUT: + case FAN10_INPUT: + case FAN11_INPUT: + case FAN12_INPUT: + case FAN13_INPUT: + case FAN14_INPUT: + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + case FAN9_PWM: + case FAN10_PWM: + case FAN11_PWM: + case FAN12_PWM: + case FAN13_PWM: + case FAN14_PWM: + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + case FAN7_FAULT: + case FAN8_FAULT: + case FAN9_FAULT: + case FAN10_FAULT: + case FAN11_FAULT: + case FAN12_FAULT: + case FAN13_FAULT: + case FAN14_FAULT: + status = attr_info->val.intval; + break; + default: + fan_dbg(KERN_ERR "%s: Unable to find the attribute index for %s\n", __FUNCTION__, usr_data->aname); + status = 0; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t fan_store_default(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 fan_data *data = i2c_get_clientdata(client); + FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data); + FAN_DATA_ATTR *usr_data = NULL; + struct fan_attr_info *attr_info = NULL; + int i, ret ; + uint32_t val; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->fan_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + attr_info = &data->attr_info[i]; + usr_data = &pdata->fan_attrs[i]; + } + } + + if (attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + case FAN9_PWM: + case FAN10_PWM: + case FAN11_PWM: + case FAN12_PWM: + case FAN13_PWM: + case FAN14_PWM: + ret = kstrtoint(buf, 10, &val); + if (ret) + { + printk(KERN_ERR "%s: Unable to convert string into value for %s\n", __FUNCTION__, usr_data->aname); + return ret; + } + /*Update the value of attr_info here, and use it to update the HW values*/ + attr_info->val.intval = val; + break; + default: + printk(KERN_ERR "%s: Unable to find the attr index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + + fan_dbg(KERN_ERR "%s: pwm to be set is %d\n", __FUNCTION__, val); + fan_update_hw(dev, attr_info, usr_data); + +exit: + return count; +} + +int fan_cpld_client_read(FAN_DATA_ATTR *udata) +{ + int status = -1; + + if (udata!=NULL) + { + if (udata->len==1) + { + status = board_i2c_cpld_read(udata->devaddr , udata->offset); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + status = i2c_smbus_read_word_swapped(client_ptr, udata->offset); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD read yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + } + + return status; +} + +int fan_cpld_client_write(FAN_DATA_ATTR *udata, uint32_t val) +{ + int status = 0; + + if (udata->len==1) + { + status = board_i2c_cpld_write(udata->devaddr, udata->offset, val); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + status = i2c_smbus_write_byte_data(client_ptr, udata->offset, val_lsb); + if (status==0) status = i2c_smbus_write_byte_data(client_ptr, udata->offset+1, val_hsb); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD write yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + return status; +} + +int fan_fpgai2c_client_read(FAN_DATA_ATTR *udata) +{ + int status = -1; + + if (udata!=NULL) + { + if (udata->len==1) + { + status = board_i2c_fpga_read(udata->devaddr , udata->offset); + /*printk(KERN_ERR "### Reading offset 0x%x from 0x%x device ... val 0x%x\n", udata->offset, udata->devaddr, status);*/ + } + else + { + /* Get the I2C client for the FPGAI2C */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + status = i2c_smbus_read_word_swapped(client_ptr, udata->offset); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block FPGAI2C read yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + } + + return status; +} + +int fan_fpgai2c_client_write(FAN_DATA_ATTR *udata, uint32_t val) +{ + int status = 0; + + if (udata->len==1) + { + status = board_i2c_fpga_write(udata->devaddr, udata->offset, val); + } + else + { + /* Get the I2C client for the FPGAI2C */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + status = i2c_smbus_write_byte_data(client_ptr, udata->offset, val_lsb); + if (status==0) status = i2c_smbus_write_byte_data(client_ptr, udata->offset+1, val_hsb); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block FPGAI2C write yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + return status; +} + + +int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + val = fan_fpgai2c_client_read(udata); + } + else + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + if (val < 0) + status = val; + else + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + + + return status; +} + +int sonic_i2c_get_fan_rpm_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + val = fan_fpgai2c_client_read(udata); + } + else + { + if (udata->len == 1) + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + else if (udata->len ==2) + { + val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset); + + } + } + + if (val < 0) + status = val; + else + { + if (udata->is_divisor) + painfo->val.intval = udata->mult / (val >> 3); + else + painfo->val.intval = udata->mult * val; + } + + return status; +} + + +int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + val = fan_fpgai2c_client_read(udata); + } + else + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + if (val < 0) + status = val; + else + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + + return status; +} + + +int sonic_i2c_set_fan_pwm_default(struct i2c_client *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + val = painfo->val.intval & udata->mask; + + if (val > 255) + { + return -EINVAL; + } + + if (strcmp(udata->devtype, "cpld") == 0) + { + status = fan_cpld_client_write(udata, val); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + status = fan_fpgai2c_client_write(udata, val); + } + else + { + if (udata->len == 1) + status = i2c_smbus_write_byte_data(client, udata->offset, val); + else if (udata->len == 2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + status = i2c_smbus_write_byte_data(client, udata->offset, val_lsb); + if (status == 0) status = i2c_smbus_write_byte_data(client, udata->offset+1, val_hsb); + } + else + { + printk(KERN_DEBUG "%s: pwm should be of len 1/2 bytes. Not setting the pwm as the length is %d\n", __FUNCTION__, udata->len); + } + } + + return status; +} + + +int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + val = fan_fpgai2c_client_read(udata); + } + else + { + if (udata->len == 1) + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + else if (udata->len ==2) + { + val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset); + + } + } + + if (val < 0) + status = val; + else + { + val = val & udata->mask; + painfo->val.intval = val; + } + return status; +} + +int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + /*Assuming fan fault to be denoted by 1 byte only*/ + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + val = fan_fpgai2c_client_read(udata); + } + else + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + if (val < 0) + status = val; + else + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + return status; +} + + +int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + + /*Dummy func for now - check the respective platform modules*/ + return 0; +} \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_defs.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_defs.h new file mode 100644 index 000000000000..24a91a291e8c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_defs.h @@ -0,0 +1,93 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description: + * Platform FAN defines/structures header file + */ + +#ifndef __PDDF_FAN_DEFS_H__ +#define __PDDF_FAN_DEFS_H__ + + +#define MAX_NUM_FAN 7 +#define MAX_FAN_ATTRS 128 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct FAN_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum fan_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // Type of FAN controller, i.e EMC2305, EMC2302, or FAN-CPLD etc + char devname[DEV_TYPE_LEN]; // Name of the device from where this informatin is to be read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + int mult; // Multiplication factor to get the actual data + uint8_t is_divisor; // Check if the value is a divisor and mult is dividend + void *access_data; + +}FAN_DATA_ATTR; + + +typedef struct FAN_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, FAN_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, FAN_DATA_ATTR *adata, void *data); + void *data; +} FAN_SYSFS_ATTR_DATA; + +typedef struct FAN_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + FAN_SYSFS_ATTR_DATA *a_ptr; +} FAN_SYSFS_ATTR_DATA_ENTRY; + + +/* FAN CLIENT DATA - PLATFORM DATA FOR FAN CLIENT */ +typedef struct FAN_DATA +{ + int num_fantrays; // num of fans controlled by this fan client + FAN_DATA_ATTR fan_attr; + int len; // no of valid attributes for this fan client + FAN_DATA_ATTR fan_attrs[MAX_FAN_ATTRS]; +}FAN_DATA; + +typedef struct FAN_PDATA +{ + int num_fantrays; // num of fans controlled by this fan client + int len; // no of valid attributes for this fan client + FAN_DATA_ATTR *fan_attrs; +}FAN_PDATA; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern int board_i2c_fpga_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_fpga_write(unsigned short cpld_addr, u8 reg, u8 value); +#endif \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.c new file mode 100644 index 000000000000..1db3573c1c20 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.c @@ -0,0 +1,523 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * A pddf kernel driver module for a FAN controller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include "pddf_custom_fan_defs.h" +#include "pddf_custom_fan_driver.h" +#include "../../../../../pddf/i2c/modules/include/pddf_fan_api.h" + +#define DRVNAME "pddf_costom_fan" + +struct pddf_ops_t pddf_fan_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = pddf_fan_post_probe_default, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_fan_ops); + + + +FAN_SYSFS_ATTR_DATA data_fan1_present = {FAN1_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_present); +FAN_SYSFS_ATTR_DATA data_fan2_present = {FAN2_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_present); +FAN_SYSFS_ATTR_DATA data_fan3_present = {FAN3_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_present); +FAN_SYSFS_ATTR_DATA data_fan4_present = {FAN4_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_present); +FAN_SYSFS_ATTR_DATA data_fan5_present = {FAN5_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_present); +FAN_SYSFS_ATTR_DATA data_fan6_present = {FAN6_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_present); +FAN_SYSFS_ATTR_DATA data_fan7_present = {FAN7_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_present); +FAN_SYSFS_ATTR_DATA data_fan8_present = {FAN8_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_present); +FAN_SYSFS_ATTR_DATA data_fan9_present = {FAN9_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_present); +FAN_SYSFS_ATTR_DATA data_fan10_present = {FAN10_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_present); +FAN_SYSFS_ATTR_DATA data_fan11_present = {FAN11_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_present); +FAN_SYSFS_ATTR_DATA data_fan12_present = {FAN12_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_present); +FAN_SYSFS_ATTR_DATA data_fan13_present = {FAN13_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_present); +FAN_SYSFS_ATTR_DATA data_fan14_present = {FAN14_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_present); + + +FAN_SYSFS_ATTR_DATA data_fan1_direction = {FAN1_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_direction); +FAN_SYSFS_ATTR_DATA data_fan2_direction = {FAN2_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_direction); +FAN_SYSFS_ATTR_DATA data_fan3_direction = {FAN3_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_direction); +FAN_SYSFS_ATTR_DATA data_fan4_direction = {FAN4_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_direction); +FAN_SYSFS_ATTR_DATA data_fan5_direction = {FAN5_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_direction); +FAN_SYSFS_ATTR_DATA data_fan6_direction = {FAN6_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_direction); +FAN_SYSFS_ATTR_DATA data_fan7_direction = {FAN7_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_direction); +FAN_SYSFS_ATTR_DATA data_fan8_direction = {FAN8_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_direction); +FAN_SYSFS_ATTR_DATA data_fan9_direction = {FAN9_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_direction); +FAN_SYSFS_ATTR_DATA data_fan10_direction = {FAN10_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_direction); +FAN_SYSFS_ATTR_DATA data_fan11_direction = {FAN11_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_direction); +FAN_SYSFS_ATTR_DATA data_fan12_direction = {FAN12_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_direction); +FAN_SYSFS_ATTR_DATA data_fan13_direction = {FAN13_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_direction); +FAN_SYSFS_ATTR_DATA data_fan14_direction = {FAN14_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_direction); + + +FAN_SYSFS_ATTR_DATA data_fan1_input = {FAN1_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_input); +FAN_SYSFS_ATTR_DATA data_fan2_input = {FAN2_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_input); +FAN_SYSFS_ATTR_DATA data_fan3_input = {FAN3_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_input); +FAN_SYSFS_ATTR_DATA data_fan4_input = {FAN4_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_input); +FAN_SYSFS_ATTR_DATA data_fan5_input = {FAN5_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_input); +FAN_SYSFS_ATTR_DATA data_fan6_input = {FAN6_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_input); +FAN_SYSFS_ATTR_DATA data_fan7_input = {FAN7_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_input); +FAN_SYSFS_ATTR_DATA data_fan8_input = {FAN8_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_input); +FAN_SYSFS_ATTR_DATA data_fan9_input = {FAN9_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_input); +FAN_SYSFS_ATTR_DATA data_fan10_input = {FAN10_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_input); +FAN_SYSFS_ATTR_DATA data_fan11_input = {FAN11_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_input); +FAN_SYSFS_ATTR_DATA data_fan12_input = {FAN12_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_input); +FAN_SYSFS_ATTR_DATA data_fan13_input = {FAN13_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_input); +FAN_SYSFS_ATTR_DATA data_fan14_input = {FAN14_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_input); + +FAN_SYSFS_ATTR_DATA data_fan1_pwm = {FAN1_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_pwm); +FAN_SYSFS_ATTR_DATA data_fan2_pwm = {FAN2_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_pwm); +FAN_SYSFS_ATTR_DATA data_fan3_pwm = {FAN3_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_pwm); +FAN_SYSFS_ATTR_DATA data_fan4_pwm = {FAN4_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_pwm); +FAN_SYSFS_ATTR_DATA data_fan5_pwm = {FAN5_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_pwm); +FAN_SYSFS_ATTR_DATA data_fan6_pwm = {FAN6_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_pwm); +FAN_SYSFS_ATTR_DATA data_fan7_pwm = {FAN7_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_pwm); +FAN_SYSFS_ATTR_DATA data_fan8_pwm = {FAN8_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_pwm); +FAN_SYSFS_ATTR_DATA data_fan9_pwm = {FAN9_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_pwm); +FAN_SYSFS_ATTR_DATA data_fan10_pwm = {FAN10_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_pwm); +FAN_SYSFS_ATTR_DATA data_fan11_pwm = {FAN11_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_pwm); +FAN_SYSFS_ATTR_DATA data_fan12_pwm = {FAN12_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_pwm); +FAN_SYSFS_ATTR_DATA data_fan13_pwm = {FAN13_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_pwm); +FAN_SYSFS_ATTR_DATA data_fan14_pwm = {FAN14_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_pwm); + + +FAN_SYSFS_ATTR_DATA data_fan1_fault = {FAN1_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_fault); +FAN_SYSFS_ATTR_DATA data_fan2_fault = {FAN2_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_fault); +FAN_SYSFS_ATTR_DATA data_fan3_fault = {FAN3_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_fault); +FAN_SYSFS_ATTR_DATA data_fan4_fault = {FAN4_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_fault); +FAN_SYSFS_ATTR_DATA data_fan5_fault = {FAN5_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_fault); +FAN_SYSFS_ATTR_DATA data_fan6_fault = {FAN6_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_fault); +FAN_SYSFS_ATTR_DATA data_fan7_fault = {FAN7_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_fault); +FAN_SYSFS_ATTR_DATA data_fan8_fault = {FAN8_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_fault); +FAN_SYSFS_ATTR_DATA data_fan9_fault = {FAN9_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_fault); +FAN_SYSFS_ATTR_DATA data_fan10_fault = {FAN10_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_fault); +FAN_SYSFS_ATTR_DATA data_fan11_fault = {FAN11_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_fault); +FAN_SYSFS_ATTR_DATA data_fan12_fault = {FAN12_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_fault); +FAN_SYSFS_ATTR_DATA data_fan13_fault = {FAN13_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_fault); +FAN_SYSFS_ATTR_DATA data_fan14_fault = {FAN14_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_fault); + + +FAN_SYSFS_ATTR_DATA_ENTRY fan_sysfs_attr_data_tbl[]= +{ + { "fan1_present", &data_fan1_present}, + { "fan2_present", &data_fan2_present}, + { "fan3_present", &data_fan3_present}, + { "fan4_present", &data_fan4_present}, + { "fan5_present", &data_fan5_present}, + { "fan6_present", &data_fan6_present}, + { "fan7_present", &data_fan7_present}, + { "fan8_present", &data_fan8_present}, + { "fan9_present", &data_fan9_present}, + { "fan10_present", &data_fan10_present}, + { "fan11_present", &data_fan11_present}, + { "fan12_present", &data_fan12_present}, + { "fan13_present", &data_fan13_present}, + { "fan14_present", &data_fan14_present}, + { "fan1_direction", &data_fan1_direction}, + { "fan2_direction", &data_fan2_direction}, + { "fan3_direction", &data_fan3_direction}, + { "fan4_direction", &data_fan4_direction}, + { "fan5_direction", &data_fan5_direction}, + { "fan6_direction", &data_fan6_direction}, + { "fan7_direction", &data_fan7_direction}, + { "fan8_direction", &data_fan8_direction}, + { "fan9_direction", &data_fan9_direction}, + { "fan10_direction", &data_fan10_direction}, + { "fan11_direction", &data_fan11_direction}, + { "fan12_direction", &data_fan12_direction}, + { "fan13_direction", &data_fan13_direction}, + { "fan14_direction", &data_fan14_direction}, + { "fan1_input", &data_fan1_input}, + { "fan2_input", &data_fan2_input}, + { "fan3_input", &data_fan3_input}, + { "fan4_input", &data_fan4_input}, + { "fan5_input", &data_fan5_input}, + { "fan6_input", &data_fan6_input}, + { "fan7_input", &data_fan7_input}, + { "fan8_input", &data_fan8_input}, + { "fan9_input", &data_fan9_input}, + { "fan10_input", &data_fan10_input}, + { "fan11_input", &data_fan11_input}, + { "fan12_input", &data_fan12_input}, + { "fan13_input", &data_fan13_input}, + { "fan14_input", &data_fan14_input}, + { "fan1_pwm", &data_fan1_pwm}, + { "fan2_pwm", &data_fan2_pwm}, + { "fan3_pwm", &data_fan3_pwm}, + { "fan4_pwm", &data_fan4_pwm}, + { "fan5_pwm", &data_fan5_pwm}, + { "fan6_pwm", &data_fan6_pwm}, + { "fan7_pwm", &data_fan7_pwm}, + { "fan8_pwm", &data_fan8_pwm}, + { "fan9_pwm", &data_fan9_pwm}, + { "fan10_pwm", &data_fan10_pwm}, + { "fan11_pwm", &data_fan11_pwm}, + { "fan12_pwm", &data_fan12_pwm}, + { "fan13_pwm", &data_fan13_pwm}, + { "fan14_pwm", &data_fan14_pwm}, + { "fan1_fault", &data_fan1_fault}, + { "fan2_fault", &data_fan2_fault}, + { "fan3_fault", &data_fan3_fault}, + { "fan4_fault", &data_fan4_fault}, + { "fan5_fault", &data_fan5_fault}, + { "fan6_fault", &data_fan6_fault}, + { "fan7_fault", &data_fan7_fault}, + { "fan8_fault", &data_fan8_fault}, + { "fan9_fault", &data_fan9_fault}, + { "fan10_fault", &data_fan10_fault}, + { "fan11_fault", &data_fan11_fault}, + { "fan12_fault", &data_fan12_fault}, + { "fan13_fault", &data_fan13_fault}, + { "fan14_fault", &data_fan14_fault}, +}; + +void *get_fan_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(fan_sysfs_attr_data_tbl)/sizeof(fan_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, fan_sysfs_attr_data_tbl[i].name) ==0) + { + return &fan_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_fan_access_data); + + + +static int pddf_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct fan_data *data; + int status=0,i,num, j=0; + FAN_PDATA *fan_platform_data; + FAN_DATA_ATTR *data_attr; + FAN_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_fan_ops.pre_probe) + { + status = (pddf_fan_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + /* Add support for a pre probe function */ + data = kzalloc(sizeof(struct fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + + /*Take control of the platform data*/ + fan_platform_data = (FAN_PDATA *)(client->dev.platform_data); + num = fan_platform_data->len; + data->num_attr = num; + + for (i=0;ifan_attrs + i; + sysfs_data_entry = get_fan_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + continue; + } + + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->fan_attribute_list[i] = &dy_ptr->dev_attr.attr; + strscpy(data->attr_info[i].name, data_attr->aname, ATTR_NAME_LEN); + data->attr_info[i].valid = 0; + mutex_init(&data->attr_info[i].update_lock); + + /*Create a duplicate entry*/ + get_fan_duplicate_sysfs(dy_ptr->index, new_str); + if (strcmp(new_str,"")) + { + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, new_str, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->fan_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strscpy(new_str, "", ATTR_NAME_LEN); + } + } + data->fan_attribute_list[i+j] = NULL; + data->fan_attribute_group.attrs = data->fan_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->fan_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_fan_ops.post_probe) + { + status = (pddf_fan_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0; data->fan_attribute_list[i]!=NULL; i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i]; + kfree(ptr); + } + pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); +exit: + return status; +} + +static void pddf_fan_remove(struct i2c_client *client) +{ + int i = 0, ret = 0; + struct sensor_device_attribute *ptr = NULL; + struct fan_data *data = i2c_get_clientdata(client); + FAN_PDATA *platdata = (FAN_PDATA *)client->dev.platform_data; + FAN_DATA_ATTR *platdata_sub = platdata->fan_attrs; + + if (pddf_fan_ops.pre_remove) + { + ret = (pddf_fan_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group); + for (i=0; data->fan_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i]; + kfree(ptr); + } + pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_fan_ops.post_remove) + { + ret = (pddf_fan_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id pddf_fan_id[] = { + { "fan_ctrl", 0 }, + { "fan_cpld", 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pddf_fan_id); + +static struct i2c_driver pddf_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = pddf_fan_probe, + .remove = pddf_fan_remove, + .id_table = pddf_fan_id, + .address_list = normal_i2c, +}; + +static int __init pddf_fan_init(void) +{ + int status = 0; + + if (pddf_fan_ops.pre_init) + { + status = (pddf_fan_ops.pre_init)(); + if (status!=0) + return status; + } + + status = i2c_add_driver(&pddf_fan_driver); + if (status!=0) + return status; + + if (pddf_fan_ops.post_init) + { + status = (pddf_fan_ops.post_init)(); + if (status!=0) + return status; + } + return status; + +} + +static void __exit pddf_fan_exit(void) +{ + if (pddf_fan_ops.pre_exit) (pddf_fan_ops.pre_exit)(); + i2c_del_driver(&pddf_fan_driver); + if (pddf_fan_ops.post_exit) (pddf_fan_ops.post_exit)(); +} + +module_init(pddf_fan_init); +module_exit(pddf_fan_exit); + +MODULE_AUTHOR("Broadcom, yajiang@celestica.com"); +MODULE_DESCRIPTION("pddf_fan driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.h new file mode 100644 index 000000000000..7dc1a2931c3a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/pddf_custom_fan_driver.h @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * FAN driver related data structures + */ +#ifndef __PDDF_FAN_DRIVER_H__ +#define __PDDF_FAN_DRIVER_H__ + +enum fan_sysfs_attributes { + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN7_PRESENT, + FAN8_PRESENT, + FAN9_PRESENT, + FAN10_PRESENT, + FAN11_PRESENT, + FAN12_PRESENT, + FAN13_PRESENT, + FAN14_PRESENT, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN7_DIRECTION, + FAN8_DIRECTION, + FAN9_DIRECTION, + FAN10_DIRECTION, + FAN11_DIRECTION, + FAN12_DIRECTION, + FAN13_DIRECTION, + FAN14_DIRECTION, + FAN1_INPUT, + FAN2_INPUT, + FAN3_INPUT, + FAN4_INPUT, + FAN5_INPUT, + FAN6_INPUT, + FAN7_INPUT, + FAN8_INPUT, + FAN9_INPUT, + FAN10_INPUT, + FAN11_INPUT, + FAN12_INPUT, + FAN13_INPUT, + FAN14_INPUT, + FAN1_PWM, + FAN2_PWM, + FAN3_PWM, + FAN4_PWM, + FAN5_PWM, + FAN6_PWM, + FAN7_PWM, + FAN8_PWM, + FAN9_PWM, + FAN10_PWM, + FAN11_PWM, + FAN12_PWM, + FAN13_PWM, + FAN14_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + FAN7_FAULT, + FAN8_FAULT, + FAN9_FAULT, + FAN10_FAULT, + FAN11_FAULT, + FAN12_FAULT, + FAN13_FAULT, + FAN14_FAULT, + FAN_MAX_ATTR +}; +/* Each client has this additional data */ +struct fan_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; + +struct fan_data { + struct device *hwmon_dev; + int num_attr; + struct attribute *fan_attribute_list[MAX_FAN_ATTRS]; + struct attribute_group fan_attribute_group; + struct fan_attr_info attr_info[MAX_FAN_ATTRS]; +}; + +#endif \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/readme.txt b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/readme.txt new file mode 100644 index 000000000000..923733e858c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/fan_driver/readme.txt @@ -0,0 +1,4 @@ +5/23/2023: Added information about the seventh fan drawers + pddf_custom_fan_driver_module:Using + pddf_fan_driver_module:Abandoned + -yajiang@celestica.com diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_defs.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_defs.h new file mode 100644 index 000000000000..e786e567d433 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_defs.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * Platform LED related defines and structures + */ + + +/***************************************** + * kobj list + *****************************************/ + +struct kobject *platform_kobj=NULL; +struct kobject *led_kobj=NULL; + +struct kobject *state_attr_kobj=NULL; +struct kobject *cur_state_kobj=NULL; + +/***************************************** + * Static Data provided from user + * space JSON data file + *****************************************/ +#define NAME_SIZE 32 +#define VALUE_SIZE 5 +typedef enum { + STATUS_LED_COLOR_OFF=0, + STATUS_LED_COLOR_GREEN=1, + STATUS_LED_COLOR_YELLOW=2, + STATUS_LED_COLOR_RED=3, + STATUS_LED_COLOR_BLUE=4, + STATUS_LED_COLOR_GREEN_BLINK=5, + STATUS_LED_COLOR_YELLOW_BLINK=6, + STATUS_LED_COLOR_RED_BLINK=7, + STATUS_LED_COLOR_BLUE_BLINK=8, + STATUS_LED_COLOR_AMBER, + STATUS_LED_COLOR_AMBER_BLINK, + MAX_LED_STATUS +}LED_STATUS; + +char* LED_STATUS_STR[] = { + "off", + "green", + "yellow", + "red", + "blue", + "green_blink", + "yellow_blink", + "red_blink", + "blue_blink", + "amber", + "amber_blink" +}; + + +typedef struct +{ + char bits[NAME_SIZE]; + int pos; + int mask_bits; +}MASK_BITS; + +typedef struct +{ + int swpld_addr; + int swpld_addr_offset; + MASK_BITS bits; + u8 reg_values[VALUE_SIZE]; + char value[NAME_SIZE]; + char attr_devtype[NAME_SIZE]; + char attr_devname[NAME_SIZE]; +} LED_DATA; + +typedef struct +{ + int state; + char color[NAME_SIZE]; +/* S3IP System LED RW sysfs */ + int sys_led; + int bmc_led; + int fan_led; + int psu_led; + int loc_led; +/* S3IP Power LED RO sysfs */ + int psu1_led; + int psu2_led; +/* S3IP Fantray LED RO sysfs */ + int fantray1_led; + int fantray2_led; + int fantray3_led; + int fantray4_led; + int fantray5_led; + int fantray6_led; + int fantray7_led; +} CUR_STATE_DATA; + +typedef struct +{ + CUR_STATE_DATA cur_state; + char device_name[NAME_SIZE]; + int index; + LED_DATA data[MAX_LED_STATUS]; + int swpld_addr; + int swpld_addr_offset; + char attr_devtype[NAME_SIZE]; + char attr_devname[NAME_SIZE]; +} LED_OPS_DATA; + +typedef enum{ + LED_SYS, + LED_PSU, + LED_FAN, + LED_FANTRAY, + LED_DIAG, + LED_LOC, + LED_BMC, + LED_TYPE_MAX +} LED_TYPE; +char* LED_TYPE_STR[LED_TYPE_MAX] = +{ + "LED_SYS", + "LED_PSU", + "LED_FAN", + "LED_FANTRAY", + "LED_DIAG", + "LED_LOC", + "LED_BMC" +}; + +/***************************************** + * Data exported from kernel for + * user space plugin to get/set + *****************************************/ +#define PDDF_LED_DATA_ATTR( _prefix, _name, _mode, _show, _store, _type, _len, _addr) \ + struct pddf_data_attribute pddf_dev_##_prefix##_attr_##_name = { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .type = _type , \ + .len = _len , \ + .addr = _addr } diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_module.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_module.c new file mode 100644 index 000000000000..8f0da48b4d98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/led_driver/pddf_custom_led_module.c @@ -0,0 +1,873 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * A pddf kernel module to manage various LEDs of a switch + */ + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include +#include +#include "pddf_custom_led_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include +#include +#include + +#define DEBUG 0 +#define MAX_PSU_NUM 2 +#define MAX_FANTRAY_NUM 7 +LED_OPS_DATA sys_led_ops_data[1]={0}; +LED_OPS_DATA psu_led_ops_data[MAX_PSU_NUM]={0}; +LED_OPS_DATA diag_led_ops_data[1]= {0}; +LED_OPS_DATA fan_led_ops_data[1]= {0}; +LED_OPS_DATA loc_led_ops_data[1]= {0}; +LED_OPS_DATA bmc_led_ops_data[1]= {0}; +LED_OPS_DATA fantray_led_ops_data[MAX_FANTRAY_NUM]={0}; +LED_OPS_DATA temp_data={0}; +LED_OPS_DATA* dev_list[LED_TYPE_MAX] = { + sys_led_ops_data, + psu_led_ops_data, + fan_led_ops_data, + fantray_led_ops_data, + diag_led_ops_data, + loc_led_ops_data, + bmc_led_ops_data, + NULL +}; +int num_psus = 0; +int num_fantrays = 0; + +extern int board_i2c_cpld_read_new(unsigned short cpld_addr, char *name, u8 reg); +extern int board_i2c_cpld_write_new(unsigned short cpld_addr, char *name, u8 reg, u8 value); +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int board_i2c_fpga_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_fpga_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern ssize_t show_pddf_s3ip_data(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t store_pddf_s3ip_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +static LED_STATUS find_state_index(const char* state_str) { + int index; + char *ptr = (char *)state_str; + while (*ptr && *ptr!= '\n' && *ptr !='\0') ptr++; + *ptr='\0'; + for ( index = 0; index < MAX_LED_STATUS; index++) { + if (strcmp(state_str, LED_STATUS_STR[index]) == 0 ) { + return index; + } + } + return MAX_LED_STATUS; +} + +static LED_TYPE get_dev_type(char* name) +{ + LED_TYPE ret = LED_TYPE_MAX; + if(strcasecmp(name, "SYS_LED") == 0) { + ret = LED_SYS; + } else if(strcasecmp(name, "FAN_LED") == 0) { + ret = LED_FAN; + } else if(strstr(name, "PSU_LED")) { + ret = LED_PSU; + } else if(strcasecmp(name, "DIAG_LED") == 0) { + ret = LED_DIAG; + } else if(strcasecmp(name, "LOC_LED") == 0) { + ret = LED_LOC; + } else if(strstr(name, "FANTRAY_LED")) { + ret = LED_FANTRAY; + } +#if DEBUG > 1 + pddf_dbg(LED, KERN_INFO "LED get_dev_type: %s; %d\n", name, ret); +#endif + return (ret); +} +static int dev_index_check(LED_TYPE type, int index) +{ +#if DEBUG + pddf_dbg(LED, "dev_index_check: type:%s[%d] index:%d num_psus:%d num_fantrays:%d\n", + LED_TYPE_STR[type], type, index, num_psus, num_fantrays); +#endif + switch(type) + { + case LED_PSU: + if(index >= MAX_PSU_NUM) return (-1); + break; + case LED_FANTRAY: + if(index >= MAX_FANTRAY_NUM) return (-1); + break; + default: + if(index >= 1) return (-1); + break; + } + return (0); +} + +static LED_OPS_DATA* find_led_ops_data(struct device_attribute *da) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr = (LED_OPS_DATA*)_ptr->addr; + LED_TYPE led_type; + if(!ptr || strlen(ptr->device_name) == 0 ) return (NULL); + + if((led_type=get_dev_type(ptr->device_name)) == LED_TYPE_MAX) { + printk(KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__); + return (NULL); + } + if(dev_index_check(led_type, ptr->index) == -1) { + printk(KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%s;%d\n", __func__, ptr->index, ptr->device_name, led_type); + return (NULL); + } +#if DEBUG > 1 + pddf_dbg(LED, "find_led_ops_data: name:%s; index=%d tempAddr:%p actualAddr:%p\n", + ptr->device_name, ptr->index, ptr, dev_list[led_type]+ptr->index); +#endif + return (dev_list[led_type]+ptr->index); +} + +static void print_led_data(LED_OPS_DATA *ptr, LED_STATUS state) +{ + int i = 0; + if(!ptr) return ; + pddf_dbg(LED, KERN_INFO "Print %s index:%d num_psus:%d num_fantrays:%d ADDR=%p\n", + ptr->device_name, ptr->index, num_psus, num_fantrays, ptr); + pddf_dbg(LED, KERN_INFO "\tindex: %d\n", ptr->index); + pddf_dbg(LED, KERN_INFO "\tdevtype/devname: %s:%s\n", ptr->attr_devtype, ptr->attr_devname); + pddf_dbg(LED, KERN_INFO "\tcur_state: %d; %s \n", ptr->cur_state.state, ptr->cur_state.color); + for (i = 0; i< MAX_LED_STATUS; i++) { + if(ptr->data[i].swpld_addr && (i == state || state == -1)) { + pddf_dbg(LED, KERN_INFO "\t\t[%s]: addr/offset:0x%x;0x%x color:%s; value:[%s][0x%x][0x%x] mask_bits: 0x%x;" + "pos:%d attr_devtype:%s attr_devname:%s\n",LED_STATUS_STR[i], ptr->data[i].swpld_addr, + ptr->data[i].swpld_addr_offset, LED_STATUS_STR[i], ptr->data[i].value, + ptr->data[i].reg_values[0], ptr->data[i].reg_values[1], ptr->data[i].bits.mask_bits, + ptr->data[i].bits.pos, ptr->data[i].attr_devtype, ptr->data[i].attr_devname); + } + } +} + +ssize_t get_status_led(struct device_attribute *da) +{ + int ret=0; + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + uint32_t color_val=0, sys_val=0; + int state=0; + int cpld_type=0; + int j; + + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: device: %s %d not configured\n", __func__, + temp_data_ptr->device_name, temp_data_ptr->index); + return (-1); + } + + if (strcmp(ops_ptr->attr_devtype, "cpld") == 0) { + cpld_type = 1; + sys_val = board_i2c_cpld_read_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset); + } else if (strcmp(ops_ptr->attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return (-1); + } + + if (sys_val < 0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x read failed\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return sys_val; + } + + strscpy(temp_data.cur_state.color, "None", NAME_SIZE); + for (state=0; statedata[state].bits.mask_bits); + for (j = 0; j < VALUE_SIZE && ops_ptr->data[state].reg_values[j] != 0xff; j++) { + if ((color_val ^ (ops_ptr->data[state].reg_values[j] << ops_ptr->data[state].bits.pos)) == 0) { + strscpy(temp_data.cur_state.color, LED_STATUS_STR[state], NAME_SIZE); + break; + } + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "Get : %s:%d addr/offset:0x%x; 0x%x devtype:%s;%s value=0x%x [%s]\n", + ops_ptr->device_name, ops_ptr->index, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, + ops_ptr->attr_devtype, cpld_type? "cpld": "fpgai2c", sys_val, temp_data.cur_state.color); +#endif + return(ret); +} + +ssize_t set_status_led(struct device_attribute *da) +{ + int ret=0; + uint32_t sys_val=0, new_val=0, read_val=0; + LED_STATUS cur_state = MAX_LED_STATUS; + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + char* _buf=temp_data_ptr->cur_state.color; + int cpld_type = 0; + + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: device: %s %d not configured\n", + __func__, ops_ptr->device_name, ops_ptr->index); + return (-1); + } + + pddf_dbg(LED, KERN_ERR "%s: Set [%s;%d] color[%s]\n", __func__, + temp_data_ptr->device_name, temp_data_ptr->index, + temp_data_ptr->cur_state.color); + cur_state = find_state_index(_buf); + + if (cur_state == MAX_LED_STATUS) { + pddf_dbg(LED, KERN_ERR "ERROR %s: not supported: %s\n", _buf, __func__); + return (-1); + } + + if (ops_ptr->data[cur_state].swpld_addr != 0x0) { + if (strcmp(ops_ptr->data[cur_state].attr_devtype, "cpld") == 0) { + cpld_type = 1; + sys_val = board_i2c_cpld_read_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset); + } else if (strcmp(ops_ptr->data[cur_state].attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype); + return (-1); + } + + if (sys_val < 0){ + return sys_val; + } + + + new_val = (sys_val & ops_ptr->data[cur_state].bits.mask_bits) | + (ops_ptr->data[cur_state].reg_values[0] << ops_ptr->data[cur_state].bits.pos); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s state %d; %s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, cur_state, _buf); + return (-1); + } + + if (strcmp(ops_ptr->data[cur_state].attr_devtype, "cpld") == 0) { + ret = board_i2c_cpld_write_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset, new_val); + read_val = board_i2c_cpld_read_new(ops_ptr->swpld_addr, ops_ptr->attr_devname, ops_ptr->swpld_addr_offset); + } else if (strcmp(ops_ptr->data[cur_state].attr_devtype, "fpgai2c") == 0) { + ret = board_i2c_fpga_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, (uint8_t)new_val); + read_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype); + return (-1); + } + +#if DEBUG + pddf_dbg(LED, KERN_ERR "Set color:%s; 0x%x:0x%x sys_val:0x%x new_val:0x%x devtype:%s w_ret:0x%x read:0x%x devtype:%s\n", + LED_STATUS_STR[cur_state], ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, sys_val, new_val, + cpld_type? "cpld":"fpgai2c", ret, read_val, ops_ptr->data[cur_state].attr_devtype); +#endif + + return(ret); +} + + +ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, + char *buf) +{ + int ret = 0; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + switch (ptr->type) + { + case PDDF_CHAR: + ret = sprintf(buf, "%s\n", ptr->addr); + break; + case PDDF_INT_DEC: + ret = sprintf(buf, "%d\n", *(int*)(ptr->addr)); + break; + case PDDF_INT_HEX: + ret = sprintf(buf, "0x%x\n", *(int*)(ptr->addr)); + break; + case PDDF_USHORT: + ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr)); + break; + case PDDF_UINT32: + ret = sprintf(buf, "0x%x\n", *(uint32_t *)(ptr->addr)); + break; + default: + break; + } +#if DEBUG > 1 + pddf_dbg(LED, "[ READ ] DATA ATTR PTR [%s] TYPE:%d, Value:[%s]\n", + ptr->dev_attr.attr.name, ptr->type, buf); +#endif + return ret; +} + +ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0, num = 0; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + switch (ptr->type) + { + case PDDF_CHAR: + memcpy(ptr->addr, buf, strlen(buf)-1); // to discard newline char form buf + ptr->addr[strlen(buf)-1] = '\0'; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_CHAR VALUE:%s\n", + ptr->dev_attr.attr.name, ptr->addr); +#endif + break; + case PDDF_INT_DEC: + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_DEC VALUE:%d\n", + ptr->dev_attr.attr.name, *(int *)(ptr->addr)); +#endif + break; + case PDDF_INT_HEX: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_HEX VALUE:0x%x\n", + ptr->dev_attr.attr.name, *(int *)(ptr->addr)); +#endif + break; + case PDDF_USHORT: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(unsigned short *)(ptr->addr) = (unsigned short)num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_USHORT VALUE:%x\n", + ptr->dev_attr.attr.name, *(unsigned short *)(ptr->addr)); +#endif + break; + case PDDF_UINT32: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(uint32_t *)(ptr->addr) = (uint32_t)num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_UINT32 VALUE:%d\n", + ptr->dev_attr.attr.name, *(uint32_t *)(ptr->addr)); +#endif + break; + default: + break; + } + return count; +} + +ssize_t show_pddf_s3ip_data(struct device *dev, struct device_attribute *da, + char *buf) +{ + int ret = 0; + pddf_dbg(LED, KERN_ERR " %s", __FUNCTION__); + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + if (_ptr == NULL) { + pddf_dbg(LED, KERN_ERR "%s return", __FUNCTION__); + return -1; + } + LED_OPS_DATA* ops_ptr=(LED_OPS_DATA*)_ptr->addr; + uint32_t color_val=0, sys_val=0; + int state=0, j; + int cpld_type=0; + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: device: %s %d not configured\n", __func__, + ops_ptr->device_name, ops_ptr->index); + return (-1); + } + if ( strcmp(ops_ptr->attr_devtype, "cpld") == 0) { + cpld_type=1; + sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else if ( strcmp(ops_ptr->attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return (-1); + } + + if (sys_val < 0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x read failed\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return sys_val; + } + for (state=0; statedata[state].bits.mask_bits); + for (j = 0; j < VALUE_SIZE && ops_ptr->data[state].reg_values[j] != 0xff; j++) { + if ((color_val ^ (ops_ptr->data[state].reg_values[j] << ops_ptr->data[state].bits.pos))==0) { + ret = sprintf(buf, "%d\n", state); + break; + } + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "Get : %s:%d addr/offset:0x%x; 0x%x devtype:%s;%s value=0x%x [%d]\n", + ops_ptr->device_name, ops_ptr->index, ops_ptr->swpld_addr, + ops_ptr->swpld_addr_offset, ops_ptr->attr_devtype, cpld_type? "cpld": "fpgai2c", sys_val, state); +#endif + return ret; +} + +ssize_t store_pddf_s3ip_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0; + int cur_state = 0; + uint32_t sys_val=0, new_val=0, read_val=0; + int cpld_type=0; + + pddf_dbg(LED, KERN_ERR "%s: %s;%d", __FUNCTION__, buf, cur_state); + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + ret = kstrtoint(buf,10,&cur_state); + if (_ptr == NULL || cur_state >= MAX_LED_STATUS || ret !=0) { + pddf_dbg(LED, KERN_ERR "%s return", __FUNCTION__); + return -1; + } + LED_OPS_DATA* ops_ptr=(LED_OPS_DATA*)_ptr->addr; + + if ( strcmp(ops_ptr->attr_devtype, "cpld") == 0) { + cpld_type=1; + sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else if ( strcmp(ops_ptr->attr_devtype, "fpgai2c") == 0) { + sys_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s 0x%x:0x%x not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return (-1); + } + + new_val = (sys_val & ops_ptr->data[cur_state].bits.mask_bits) | + (ops_ptr->data[cur_state].reg_values[0] << ops_ptr->data[cur_state].bits.pos); + + if ( strcmp(ops_ptr->data[cur_state].attr_devtype, "cpld") == 0) { + ret = board_i2c_cpld_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, new_val); + read_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else if ( strcmp(ops_ptr->data[cur_state].attr_devtype, "fpgai2c") == 0) { + ret = board_i2c_fpga_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, (uint8_t)new_val); + read_val = board_i2c_fpga_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d devtype:%s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, ops_ptr->attr_devtype); + return (-1); + } + +#if DEBUG + pddf_dbg(LED, KERN_INFO "Set color:%s; 0x%x:0x%x sys_val:0x%x new_val:0x%x devtype:%s w_ret:0x%x read:0x%x devtype:%s\n", + LED_STATUS_STR[cur_state], ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, + sys_val, new_val, cpld_type? "cpld":"fpgai2c", ret, read_val, ops_ptr->data[cur_state].attr_devtype); +#endif + return count; +} + + +static int load_led_ops_data(struct device_attribute *da, LED_STATUS state) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr = (LED_OPS_DATA*)_ptr->addr; + LED_TYPE led_type; + LED_OPS_DATA* ops_ptr = NULL; + int i = 0; + char *token = NULL, *value_ptr = NULL; + + if(!ptr || strlen(ptr->device_name)==0 ) { + pddf_dbg(LED, KERN_INFO "SYSTEM_LED: load_led_ops_data return -1 device_name:%s\n", ptr? ptr->device_name:"NULL"); + return(-1); + } + + if(ptr->device_name) + { + pddf_dbg(LED, KERN_INFO "[%s]: load_led_ops_data: index=%d addr=0x%x;0x%x devtype:%s devname=%s valu=%s\n", + ptr->device_name, ptr->index, ptr->swpld_addr, ptr->swpld_addr_offset, ptr->attr_devtype, ptr->attr_devname, ptr->data[0].value); + } + if((led_type=get_dev_type(ptr->device_name))==LED_TYPE_MAX) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__); + return(-1); + } + if(dev_index_check(led_type, ptr->index)==-1) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%d\n", __func__, ptr->index, led_type); + return(-1); + } + ops_ptr = dev_list[led_type]+ptr->index; + + memcpy(ops_ptr->device_name, ptr->device_name, sizeof(ops_ptr->device_name)); + ops_ptr->index = ptr->index; + memcpy(&ops_ptr->data[state], &ptr->data[0], sizeof(LED_DATA)); + ops_ptr->data[state].swpld_addr = ptr->swpld_addr; + ops_ptr->data[state].swpld_addr_offset = ptr->swpld_addr_offset; + ops_ptr->swpld_addr = ptr->swpld_addr; + ops_ptr->swpld_addr_offset = ptr->swpld_addr_offset; + memcpy(ops_ptr->data[state].attr_devtype, ptr->attr_devtype, sizeof(ops_ptr->data[state].attr_devtype)); + memcpy(ops_ptr->data[state].attr_devname, ptr->attr_devname, sizeof(ops_ptr->data[state].attr_devname)); + memcpy(ops_ptr->attr_devtype, ptr->attr_devtype, sizeof(ops_ptr->attr_devtype)); + memcpy(ops_ptr->attr_devname, ptr->attr_devname, sizeof(ops_ptr->attr_devname)); +#ifdef __STDC_LIB_EXT1__ + memset_s(ops_ptr->data[state].reg_values, sizeof(ops_ptr->data[state].reg_values), 0xff, sizeof(ops_ptr->data[state].reg_values)); +#else + memset(ops_ptr->data[state].reg_values, 0xff, sizeof(ops_ptr->data[state].reg_values)); +#endif + value_ptr = kzalloc(sizeof(ops_ptr->data[state].value), GFP_KERNEL); + if (value_ptr) { + memcpy(value_ptr, ops_ptr->data[state].value, sizeof(ops_ptr->data[state].value)); + while((token = strsep((char**)&value_ptr,";")) != NULL && i < VALUE_SIZE) { + if (kstrtou8(token, 16, &ops_ptr->data[state].reg_values[i])) { + pddf_dbg(LED, KERN_ERR "load_led_ops_data: [%s] conversion error\n", token); + } + i++; + } + kfree(value_ptr); + } + + print_led_data(dev_list[led_type]+ptr->index, state); + + memset(ptr, 0, sizeof(LED_OPS_DATA)); + return (0); +} + +static int show_led_ops_data(struct device_attribute *da) +{ + LED_OPS_DATA* ops_ptr = find_led_ops_data(da); + print_led_data(ops_ptr, -1); + return(0); +} + +static int verify_led_ops_data(struct device_attribute *da) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + + if(ops_ptr) + memcpy(ptr, ops_ptr, sizeof(LED_OPS_DATA)); + else + { + pddf_dbg(LED, "SYSTEM_LED: verify_led_ops_data: Failed to find ops_ptr name:%s; index=%d\n", ptr->device_name, ptr->index); + } + return (0); +} + + +ssize_t dev_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ +#if DEBUG + pddf_dbg(LED, KERN_INFO "dev_operation [%s]\n", buf); +#endif + if(strncmp(buf, "show", strlen("show")) == 0) { + show_led_ops_data(da); + } + else if(strncmp(buf, "verify", strlen("verify")) == 0) { + verify_led_ops_data(da); + } + else if(strncmp(buf, "get_status", strlen("get_status")) == 0) { + get_status_led(da); + } + else if(strncmp(buf, "set_status", strlen("set_status")) == 0) { + set_status_led(da); + } + else { + LED_STATUS index = find_state_index(buf); + if (index < MAX_LED_STATUS) { + load_led_ops_data(da, index); + } else { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s\n", __FUNCTION__, buf); + } + } + return (count); +} + +ssize_t store_config_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret, num; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + if(strncmp(ptr->dev_attr.attr.name, "num_psus", strlen("num_psus")) == 0) { + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n", + ptr->dev_attr.attr.name, num, num_psus); +#endif + return(count); + } + if (strncmp(ptr->dev_attr.attr.name, "num_fantrays", strlen("num_fantrays")) ==0) { + ret = kstrtoint(buf, 10, &num); + if (ret == 0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n", + ptr->dev_attr.attr.name, num, num_fantrays); +#endif + return (count); + } + return (count); +} + +ssize_t store_bits_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int len = 0, num1 = 0, num2 = 0, i=0, rc1=0, rc2=0; + char mask=0xFF; + char *pptr=NULL; + char bits[NAME_SIZE]; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + MASK_BITS* bits_ptr=(MASK_BITS*)(ptr->addr); + memcpy(bits_ptr->bits, buf, strlen(buf)-1); // to discard newline char form buf + bits_ptr->bits[strlen(buf)-1] = '\0'; + if((pptr=strstr(buf,":")) != NULL) { + len = pptr-buf; + sprintf(bits, buf); + bits[len] = '\0'; + rc1 = kstrtoint(bits, 16, &num1); + if (rc1 == 0) + { + sprintf(bits, ++pptr); + rc2 = kstrtoint(bits, 16, &num2); + if (rc2 == 0) + { + for (i=num2; i<=num1; i++) { + mask &= ~(1 << i); + } + bits_ptr->mask_bits = mask; + bits_ptr->pos = num2; + } + } + } else { + rc1 = kstrtoint(buf, 16, &num1); + if (rc1 == 0) + { + bits_ptr->mask_bits = mask & ~(1 << num1); + bits_ptr->pos = num1; + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR Bits [%s] VALUE:%s mask:0x%x; pos:0x%x\n", + ptr->dev_attr.attr.name, bits_ptr->bits, bits_ptr->mask_bits, bits_ptr->pos); +#endif + return (count); +} + +/************************************************************************** + * platform/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(platform, num_psus, S_IWUSR|S_IRUGO, show_pddf_data, + store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_psus); +PDDF_LED_DATA_ATTR(platform, num_fantrays, S_IWUSR|S_IRUGO, show_pddf_data, + store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_fantrays); + +struct attribute* attrs_platform[]={ + &pddf_dev_platform_attr_num_psus.dev_attr.attr, + &pddf_dev_platform_attr_num_fantrays.dev_attr.attr, + NULL, +}; +struct attribute_group attr_group_platform={ + .attrs = attrs_platform, +}; + +/************************************************************************** + * led/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(dev, device_name, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.device_name); +PDDF_LED_DATA_ATTR(dev, attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.attr_devtype); +PDDF_LED_DATA_ATTR(dev, attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.attr_devname); +PDDF_LED_DATA_ATTR(dev, index, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&temp_data.index); +PDDF_LED_DATA_ATTR(dev, swpld_addr, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr); +PDDF_LED_DATA_ATTR(dev, swpld_addr_offset, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr_offset); +PDDF_LED_DATA_ATTR(dev, dev_ops , S_IWUSR, NULL, + dev_operation, PDDF_CHAR, NAME_SIZE, (void*)&temp_data); + +struct attribute* attrs_dev[] = { + &pddf_dev_dev_attr_device_name.dev_attr.attr, + &pddf_dev_dev_attr_attr_devtype.dev_attr.attr, + &pddf_dev_dev_attr_attr_devname.dev_attr.attr, + &pddf_dev_dev_attr_index.dev_attr.attr, + &pddf_dev_dev_attr_swpld_addr.dev_attr.attr, + &pddf_dev_dev_attr_swpld_addr_offset.dev_attr.attr, + &pddf_dev_dev_attr_dev_ops.dev_attr.attr, + NULL, +}; + +struct attribute_group attr_group_dev = { + .attrs = attrs_dev, +}; + +/************************************************************************** + * state_attr/ attributes + **************************************************************************/ +#define LED_DEV_STATE_ATTR_GROUP(name, func) \ + PDDF_LED_DATA_ATTR(name, bits, S_IWUSR|S_IRUGO, show_pddf_data, \ + store_bits_data, PDDF_CHAR, NAME_SIZE, func.bits.bits); \ + PDDF_LED_DATA_ATTR(name, value, S_IWUSR|S_IRUGO, show_pddf_data, \ + store_pddf_data, PDDF_CHAR, NAME_SIZE, func.value); \ + struct attribute* attrs_##name[]={ \ + &pddf_dev_##name##_attr_bits.dev_attr.attr, \ + &pddf_dev_##name##_attr_value.dev_attr.attr, \ + NULL, \ + }; \ + struct attribute_group attr_group_##name={ \ + .attrs = attrs_##name, \ + }; \ + + +LED_DEV_STATE_ATTR_GROUP(state_attr, (void*)&temp_data.data[0]) + +/************************************************************************** + * cur_state/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(cur_state, color, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.cur_state.color); +PDDF_LED_DATA_ATTR(cur_state, sys_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void*)&sys_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, loc_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, NAME_SIZE, (void*)&loc_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, bmc_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void*)&bmc_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, fan_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_led_ops_data); +PDDF_LED_DATA_ATTR(cur_state, psu_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), NULL); +PDDF_LED_DATA_ATTR(cur_state, psu1_led, S_IRUGO, show_pddf_s3ip_data, + NULL, PDDF_INT_DEC, sizeof(int), (void *)&psu_led_ops_data[0]); +PDDF_LED_DATA_ATTR(cur_state, psu2_led, S_IRUGO, show_pddf_s3ip_data, + NULL, PDDF_INT_DEC, sizeof(int), (void *)&psu_led_ops_data[1]); +PDDF_LED_DATA_ATTR(cur_state, fantray1_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[0]); +PDDF_LED_DATA_ATTR(cur_state, fantray2_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[1]); +PDDF_LED_DATA_ATTR(cur_state, fantray3_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[2]); +PDDF_LED_DATA_ATTR(cur_state, fantray4_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[3]); +PDDF_LED_DATA_ATTR(cur_state, fantray5_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[4]); +PDDF_LED_DATA_ATTR(cur_state, fantray6_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[5]); +PDDF_LED_DATA_ATTR(cur_state, fantray7_led, S_IWUSR|S_IRUGO, show_pddf_s3ip_data, + store_pddf_s3ip_data, PDDF_INT_DEC, sizeof(int), (void *)&fantray_led_ops_data[6]); + + +struct attribute* attrs_cur_state[] = { + &pddf_dev_cur_state_attr_color.dev_attr.attr, + &pddf_dev_cur_state_attr_sys_led.dev_attr.attr, + &pddf_dev_cur_state_attr_loc_led.dev_attr.attr, + &pddf_dev_cur_state_attr_bmc_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fan_led.dev_attr.attr, + &pddf_dev_cur_state_attr_psu_led.dev_attr.attr, + &pddf_dev_cur_state_attr_psu1_led.dev_attr.attr, + &pddf_dev_cur_state_attr_psu2_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray1_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray2_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray3_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray4_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray5_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray6_led.dev_attr.attr, + &pddf_dev_cur_state_attr_fantray7_led.dev_attr.attr, + NULL, +}; + +struct attribute_group attr_group_cur_state={ + .attrs = attrs_cur_state, +}; + +/*************************************************************************/ +#define KOBJ_FREE(obj) \ + if(obj) kobject_put(obj); \ + +void free_kobjs(void) +{ + KOBJ_FREE(cur_state_kobj) + KOBJ_FREE(state_attr_kobj) + KOBJ_FREE(led_kobj) + KOBJ_FREE(platform_kobj) +} + +int KBOJ_CREATE(char* name, struct kobject* parent, struct kobject** child) +{ + if (parent) { + *child = kobject_create_and_add(name, parent); + } else { + printk(KERN_ERR "PDDF_LED ERROR to create %s kobj; null parent\n", name); + free_kobjs(); + return (-ENOMEM); + } + return (0); +} + +int LED_DEV_ATTR_CREATE(struct kobject *kobj, const struct attribute_group *attr, const char* name) +{ + int status = sysfs_create_group(kobj, attr); + if(status) { + pddf_dbg(LED, KERN_ERR "Driver ERROR: sysfs_create %s failed rc=%d\n", name, status); + } + return (status); +} + + +static int __init led_init(void) { + struct kobject *device_kobj; + pddf_dbg(LED, KERN_INFO "PDDF GENERIC LED MODULE init..\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + KBOJ_CREATE("platform", device_kobj, &platform_kobj); + KBOJ_CREATE("led", device_kobj, &led_kobj); + KBOJ_CREATE("state_attr", led_kobj, &state_attr_kobj); + KBOJ_CREATE("cur_state", led_kobj, &cur_state_kobj); + + LED_DEV_ATTR_CREATE(platform_kobj, &attr_group_platform, "attr_group_platform"); + LED_DEV_ATTR_CREATE(led_kobj, &attr_group_dev, "attr_group_dev"); + LED_DEV_ATTR_CREATE(state_attr_kobj, &attr_group_state_attr, "attr_group_state_attr"); + LED_DEV_ATTR_CREATE(cur_state_kobj, &attr_group_cur_state, "attr_group_cur_state"); + return (0); +} + + +static void __exit led_exit(void) { + pddf_dbg(LED, "PDDF GENERIC LED MODULE exit..\n"); + free_kobjs(); +} + +module_init(led_init); +module_exit(led_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_algo.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_algo.c new file mode 100644 index 000000000000..2c93c36f3f42 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_algo.c @@ -0,0 +1,634 @@ +/* +* +* Licensed under the GNU General Public License Version 2 +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +/* +* pddf_xilinx_device_7021_algo.c +* Description: +* A sample i2c driver algorithms for Xilinx Corporation Device 7021 FPGA adapters +* +*********************************************************************************/ +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../pddf/i2c/modules/include/pddf_i2c_algo.h" + +#define DEBUG 0 + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#define XIIC_MSB_OFFSET 0 +#define XIIC_REG_OFFSET (0x100 + XIIC_MSB_OFFSET) + +/* + * Register offsets in bytes from RegisterBase. Three is added to the + * base offset to access LSB (IBM style) of the word + */ +#define XIIC_CR_REG_OFFSET (0x00 + XIIC_REG_OFFSET) /* Control Register */ +#define XIIC_SR_REG_OFFSET (0x04 + XIIC_REG_OFFSET) /* Status Register */ +#define XIIC_DTR_REG_OFFSET (0x08 + XIIC_REG_OFFSET) /* Data Tx Register */ +#define XIIC_DRR_REG_OFFSET (0x0C + XIIC_REG_OFFSET) /* Data Rx Register */ +#define XIIC_ADR_REG_OFFSET (0x10 + XIIC_REG_OFFSET) /* Address Register */ +#define XIIC_TFO_REG_OFFSET (0x14 + XIIC_REG_OFFSET) /* Tx FIFO Occupancy */ +#define XIIC_RFO_REG_OFFSET (0x18 + XIIC_REG_OFFSET) /* Rx FIFO Occupancy */ +#define XIIC_TBA_REG_OFFSET (0x1C + XIIC_REG_OFFSET) /* 10 Bit Address reg */ +#define XIIC_RFD_REG_OFFSET (0x20 + XIIC_REG_OFFSET) /* Rx FIFO Depth reg */ +#define XIIC_GPO_REG_OFFSET (0x24 + XIIC_REG_OFFSET) /* Output Register */ + +/* Control Register masks */ +#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */ +#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */ +#define XIIC_CR_MSMS_MASK 0x04 /* Master starts Txing=1 */ +#define XIIC_CR_DIR_IS_TX_MASK 0x08 /* Dir of tx. Txing=1 */ +#define XIIC_CR_NO_ACK_MASK 0x10 /* Tx Ack. NO ack = 1 */ +#define XIIC_CR_REPEATED_START_MASK 0x20 /* Repeated start = 1 */ +#define XIIC_CR_GENERAL_CALL_MASK 0x40 /* Gen Call enabled = 1 */ + +/* Status Register masks */ +#define XIIC_SR_GEN_CALL_MASK 0x01 /* 1=a mstr issued a GC */ +#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x02 /* 1=when addr as slave */ +#define XIIC_SR_BUS_BUSY_MASK 0x04 /* 1 = bus is busy */ +#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x08 /* 1=Dir: mstr <-- slave */ +#define XIIC_SR_TX_FIFO_FULL_MASK 0x10 /* 1 = Tx FIFO full */ +#define XIIC_SR_RX_FIFO_FULL_MASK 0x20 /* 1 = Rx FIFO full */ +#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x40 /* 1 = Rx FIFO empty */ +#define XIIC_SR_TX_FIFO_EMPTY_MASK 0x80 /* 1 = Tx FIFO empty */ + +/* Interrupt Status Register masks Interrupt occurs when... */ +#define XIIC_INTR_ARB_LOST_MASK 0x01 /* 1 = arbitration lost */ +#define XIIC_INTR_TX_ERROR_MASK 0x02 /* 1=Tx error/msg complete */ +#define XIIC_INTR_TX_EMPTY_MASK 0x04 /* 1 = Tx FIFO/reg empty */ +#define XIIC_INTR_RX_FULL_MASK 0x08 /* 1=Rx FIFO/reg=OCY level */ +#define XIIC_INTR_BNB_MASK 0x10 /* 1 = Bus not busy */ +#define XIIC_INTR_AAS_MASK 0x20 /* 1 = when addr as slave */ +#define XIIC_INTR_NAAS_MASK 0x40 /* 1 = not addr as slave */ +#define XIIC_INTR_TX_HALF_MASK 0x80 /* 1 = TX FIFO half empty */ + +/* The following constants specify the depth of the FIFOs */ +#define IIC_RX_FIFO_DEPTH 16 /* Rx fifo capacity */ +#define IIC_TX_FIFO_DEPTH 16 /* Tx fifo capacity */ + +/* + * Tx Fifo upper bit masks. + */ +#define XIIC_TX_DYN_START_MASK 0x0100 /* 1 = Set dynamic start */ +#define XIIC_TX_DYN_STOP_MASK 0x0200 /* 1 = Set dynamic stop */ + +/* + * The following constants define the register offsets for the Interrupt + * registers. There are some holes in the memory map for reserved addresses + * to allow other registers to be added and still match the memory map of the + * interrupt controller registers + */ +#define XIIC_IISR_OFFSET 0x20 /* Interrupt Status Register */ +#define XIIC_RESETR_OFFSET 0x40 /* Reset Register */ + +#define XIIC_RESET_MASK 0xAUL + +#define XIIC_PM_TIMEOUT 1000 /* ms */ +/* timeout waiting for the controller to respond */ +#define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000)) + +struct fpgalogic_i2c { + void __iomem *base; + u32 reg_shift; + u32 reg_io_width; + wait_queue_head_t wait; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + int ip_clock_khz; + int bus_clock_khz; + void (*reg_set)(struct fpgalogic_i2c *i2c, int reg, u8 value); + u8 (*reg_get)(struct fpgalogic_i2c *i2c, int reg); + u32 timeout; + struct mutex lock; +}; +static struct fpgalogic_i2c fpgalogic_i2c[I2C_PCI_MAX_BUS]; +extern void __iomem * fpga_ctl_addr; +extern int (*ptr_fpgapci_read)(uint32_t); +extern int (*ptr_fpgapci_write)(uint32_t, uint32_t); +extern int (*pddf_i2c_pci_add_numbered_bus)(struct i2c_adapter *, int); +static int xiic_reinit(struct fpgalogic_i2c *i2c); + +void i2c_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * i2c_release_mutex - release mutex + */ +void i2c_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static inline void xiic_setreg32(struct fpgalogic_i2c *i2c, int reg, int value) +{ + (void)iowrite32(value, i2c->base + reg); +} + +static inline int xiic_getreg32(struct fpgalogic_i2c *i2c, int reg) +{ + u32 ret; + + ret = ioread32(i2c->base + reg); + + return ret; +} + +static inline void xiic_irq_clr(struct fpgalogic_i2c *i2c, u32 mask) +{ + u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + + xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); +} + +static int xiic_clear_rx_fifo(struct fpgalogic_i2c *i2c) +{ + u8 sr; + unsigned long timeout; + + timeout = jiffies + XIIC_I2C_TIMEOUT; + for (sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); + !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); + sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET)) { + xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + if (time_after(jiffies, timeout)) { + printk("Failed to clear rx fifo\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +/** + * Wait until something change in a given register + * @i2c: ocores I2C device instance + * @reg: register to query + * @mask: bitmask to apply on register value + * @val: expected result + * @timeout: timeout in jiffies + * + * Timeout is necessary to avoid to stay here forever when the chip + * does not answer correctly. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int poll_wait(struct fpgalogic_i2c *i2c, + int reg, u8 mask, u8 val, + const unsigned long timeout) +{ + unsigned long j; + u8 status = 0; + + j = jiffies + timeout; + while (1) { + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, reg); + mutex_unlock(&i2c->lock); + if ((status & mask) == val) + break; + if (time_after(jiffies, j)) + return -ETIMEDOUT; + cpu_relax(); + cond_resched(); + } + return 0; +} + +/** + * Wait until is possible to process some data + * @i2c: ocores I2C device instance + * + * Used when the device is in polling mode (interrupts disabled). + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_poll_wait(struct fpgalogic_i2c *i2c) +{ + u8 mask = 0, status = 0; + int err = 0; + int val = 0; + int tmp = 0; + mutex_lock(&i2c->lock); + if (i2c->state == STATE_DONE) { + /* transfer is over */ + mask = XIIC_SR_BUS_BUSY_MASK; + } else if (i2c->state == STATE_WRITE || i2c->state == STATE_START){ + /* on going transfer */ + if (0 == i2c->msg->len){ + mask = XIIC_INTR_TX_ERROR_MASK; + } else { + mask = XIIC_SR_TX_FIFO_FULL_MASK; + } + } + else if (i2c->state == STATE_READ){ + /* on going receive */ + mask = XIIC_SR_TX_FIFO_EMPTY_MASK | XIIC_SR_RX_FIFO_EMPTY_MASK; + } + mutex_unlock(&i2c->lock); + // printk("Wait for: 0x%x\n", mask); + + /* + * once we are here we expect to get the expected result immediately + * so if after 50ms we timeout then something is broken. + */ + + if (1 == i2c->nmsgs && 0 == i2c->msg->len && i2c->state == STATE_START && !(i2c->msg->flags & I2C_M_RD)) { /* for i2cdetect I2C_SMBUS_QUICK mode*/ + err = poll_wait(i2c, XIIC_IISR_OFFSET, mask, mask, msecs_to_jiffies(50)); + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); + mutex_unlock(&i2c->lock); + if (0 != err) { /* AXI IIC as an transceiver , if ever an XIIC_INTR_TX_ERROR_MASK interrupt happens, means no such i2c device */ + err = 0; + } else { + err = -ETIMEDOUT; + } + } + else { + if (mask & XIIC_SR_TX_FIFO_EMPTY_MASK){ + err = poll_wait(i2c, XIIC_SR_REG_OFFSET, mask, XIIC_SR_TX_FIFO_EMPTY_MASK, msecs_to_jiffies(50)); + mask &= ~XIIC_SR_TX_FIFO_EMPTY_MASK; + } + if (0 == err){ + err = poll_wait(i2c, XIIC_SR_REG_OFFSET, mask, 0, msecs_to_jiffies(50)); + } + mutex_lock(&i2c->lock); + status = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + + if ((status & XIIC_INTR_ARB_LOST_MASK) || + ((status & XIIC_INTR_TX_ERROR_MASK) && + !(status & XIIC_INTR_RX_FULL_MASK) && + !(i2c->msg->flags & I2C_M_RD))) { /* AXI IIC as an transceiver , if ever an XIIC_INTR_TX_ERROR_MASK interrupt happens, return */ + err = -ETIMEDOUT; + + if (status & XIIC_INTR_ARB_LOST_MASK) { + val = xiic_getreg32(i2c, XIIC_CR_REG_OFFSET); + tmp = XIIC_CR_MSMS_MASK; + val &=(~tmp); + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, val); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, XIIC_INTR_ARB_LOST_MASK); + printk("%s: TRANSFER STATUS ERROR, ISR: bit 0x%x happens\n", + __func__, XIIC_INTR_ARB_LOST_MASK); + } + if (status & XIIC_INTR_TX_ERROR_MASK) { + int sta = 0; + int cr = 0; + sta = xiic_getreg32(i2c,XIIC_SR_REG_OFFSET); + cr = xiic_getreg32(i2c,XIIC_CR_REG_OFFSET); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, XIIC_INTR_TX_ERROR_MASK); + printk("%s: TRANSFER STATUS ERROR, ISR: bit 0x%x happens; SR: bit 0x%x; CR: bit 0x%x\n", + __func__, status, sta, cr); + } + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + (void)xiic_reinit(i2c); + mutex_unlock(&i2c->lock); + return err; + } + mutex_unlock(&i2c->lock); + } + + if (err) + printk("%s: STATUS timeout, bit 0x%x did not clear in 50ms\n", + __func__, status); + return err; +} + +static void ocores_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + //unsigned long flags; + u16 val; + + /* + * If we spin here because we are in timeout, so we are going + * to be in STATE_ERROR. See ocores_process_timeout() + */ + mutex_lock(&i2c->lock); + // printk("STATE: %d\n", i2c->state); + + if (i2c->state == STATE_START) { + i2c->state =(msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + /* if it's the time sequence is 'start bit + address + read bit + stop bit' */ + if (i2c->state == STATE_READ){ + /* it's the last message so we include dynamic stop bit with length */ + val = msg->len | XIIC_TX_DYN_STOP_MASK; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, val); + goto out; + } + } + if (i2c->state == STATE_READ){ + /* suit for I2C_FUNC_SMBUS_BLOCK_DATA */ + if (msg->flags & I2C_M_RECV_LEN) { + msg->len = xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + msg->flags &= ~I2C_M_RECV_LEN; + msg->buf[i2c->pos++] = msg->len; + } + else { + msg->buf[i2c->pos++] = xiic_getreg32(i2c, XIIC_DRR_REG_OFFSET); + } + } else if (i2c->state == STATE_WRITE){ + /* if it reaches the last byte data to be sent */ + if ((i2c->pos == msg->len - 1) && (i2c->nmsgs == 1)){ + val = msg->buf[i2c->pos++] | XIIC_TX_DYN_STOP_MASK; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, val); + i2c->state = STATE_DONE; + goto out; + /* if it is not the last byte data to be sent */ + } else if (i2c->pos < msg->len) { + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, msg->buf[i2c->pos++]); + goto out; + } + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->pos = 0; + if (i2c->nmsgs) { + i2c->msg++; + msg = i2c->msg; + if (!(msg->flags & I2C_M_NOSTART)) /* send start? */{ + i2c->state = STATE_START; + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK); + goto out; + } + } else { /* end? */ + i2c->state = STATE_DONE; + goto out; + } + } + +out: + mutex_unlock(&i2c->lock); + return ; +} + + +static int fpgai2c_poll(struct fpgalogic_i2c *i2c, + struct i2c_msg *msgs, int num) +{ + int ret = 0; + // u8 ctrl; + + mutex_lock(&i2c->lock); + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + /* Set receive Fifo depth to maximum (zero based). */ + xiic_setreg32(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + + /* Reset Tx Fifo. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + + /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); + + /* set i2c clock as 100Hz. */ + //xiic_setreg32(i2c, 0x13c, 0x7C); + + /* make sure RX fifo is empty */ + ret = xiic_clear_rx_fifo(i2c); + if (ret){ + mutex_unlock(&i2c->lock); + return ret; + } + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + // printk("STATE: %d\n", i2c->state); + + if (msgs->len == 0 && num == 1){ /* suit for i2cdetect time sequence */ + u8 status = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + xiic_irq_clr(i2c, status); + /* send out the 1st byte data and stop bit */ + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msgs) | XIIC_TX_DYN_START_MASK | XIIC_TX_DYN_STOP_MASK); + } else { + /* send out the 1st byte data */ + xiic_setreg32(i2c, XIIC_DTR_REG_OFFSET, i2c_8bit_addr_from_msg(msgs) | XIIC_TX_DYN_START_MASK); + } + mutex_unlock(&i2c->lock); + while (1) { + int err; + + err = ocores_poll_wait(i2c); + if (err) { + i2c->state = STATE_ERROR; + break; + }else if (i2c->state == STATE_DONE){ + break; + } + ocores_process(i2c); + } + + return (i2c->state == STATE_DONE) ? num : -EIO; +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int err = -EIO; + u8 retry = 0, max_retry = 0; + + if( ( (1 == msgs->len && (msgs->flags & I2C_M_RD)) || (0 == msgs->len && !(msgs->flags & I2C_M_RD)) ) && num == 1 ) /* I2C_SMBUS_QUICK or I2C_SMBUS_BYTE */ + max_retry = 1; + else + max_retry = 5; // retry 5 times if receive a NACK or other errors + while( (-EIO == err) && (retry < max_retry)) + { + err = fpgai2c_poll(i2c, msgs, num); + retry++; + } + + return err; + +} + +static u32 fpgai2c_func(struct i2c_adapter *adap) +{ +/* a typical full-I2C adapter would use the following */ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm fpgai2c_algorithm= { + .master_xfer = fpgai2c_xfer, /*write I2C messages */ + .functionality = fpgai2c_func, /* what the adapter supports */ +}; + +static int xiic_reinit(struct fpgalogic_i2c *i2c) +{ + int ret; + int val = 0; + + /* Soft reset IIC controller. */ + xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + + /* Set receive Fifo depth to maximum (zero based). */ + xiic_setreg32(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + + /* Reset Tx Fifo. */ + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + + /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ + val |= XIIC_CR_ENABLE_DEVICE_MASK; + //val |= XIIC_CR_TX_FIFO_RESET_MASK; + //val |= XIIC_CR_MSMS_MASK; + val |= XIIC_CR_DIR_IS_TX_MASK; + xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, val); + + /* make sure RX fifo is empty */ + ret = xiic_clear_rx_fifo(i2c); + if (ret) + return ret; + + return 0; +} + +static int fpgai2c_init(struct fpgalogic_i2c *i2c) +{ + // int prescale; + // int diff; + // u8 ctrl; + int ret; + + + //i2c->reg_set = xiic_setreg32; + //i2c->reg_get = xiic_getreg32; + + ret = xiic_reinit(i2c); + if (ret < 0) { + printk("Cannot xiic_reinit\n"); + return ret; + } + + /* Initialize interrupt handlers if not already done */ + init_waitqueue_head(&i2c->wait); + return 0; +} + +static int adap_data_init(struct i2c_adapter *adap, int i2c_ch_index) +{ + struct fpgapci_devdata *pci_privdata = 0; + pci_privdata = (struct fpgapci_devdata*) dev_get_drvdata(adap->dev.parent); + + if (pci_privdata == 0) { + printk("[%s]: ERROR pci_privdata is 0\n", __FUNCTION__); + return -1; + } +#if DEBUG + pddf_dbg(FPGA, KERN_INFO "[%s] index: [%d] fpga_data__base_addr:0x%0x8lx" + " fpgapci_bar_len:0x%08lx fpga_i2c_ch_base_addr:0x%08lx ch_size=0x%x supported_i2c_ch=%d", + __FUNCTION__, i2c_ch_index, pci_privdata->fpga_data_base_addr, + pci_privdata->bar_length, pci_privdata->fpga_i2c_ch_base_addr, + pci_privdata->fpga_i2c_ch_size, pci_privdata->max_fpga_i2c_ch); +#endif + if (i2c_ch_index >= pci_privdata->max_fpga_i2c_ch || pci_privdata->max_fpga_i2c_ch > I2C_PCI_MAX_BUS) { + printk("[%s]: ERROR i2c_ch_index=%d max_ch_index=%d out of range: %d\n", + __FUNCTION__, i2c_ch_index, pci_privdata->max_fpga_i2c_ch, I2C_PCI_MAX_BUS); + return -1; + } +#ifdef __STDC_LIB_EXT1__ + memset_s(&fpgalogic_i2c[i2c_ch_index], sizeof(fpgalogic_i2c[0]), 0, sizeof(fpgalogic_i2c[0])); +#else + memset(&fpgalogic_i2c[i2c_ch_index], 0, sizeof(fpgalogic_i2c[0])); +#endif + + fpgalogic_i2c[i2c_ch_index].base = pci_privdata->fpga_i2c_ch_base_addr + + i2c_ch_index* pci_privdata->fpga_i2c_ch_size; + mutex_init(&fpgalogic_i2c[i2c_ch_index].lock); + fpgai2c_init(&fpgalogic_i2c[i2c_ch_index]); + + + adap->algo_data = &fpgalogic_i2c[i2c_ch_index]; + i2c_set_adapdata(adap, &fpgalogic_i2c[i2c_ch_index]); + return 0; +} + +static int pddf_i2c_pci_add_numbered_bus_default (struct i2c_adapter *adap, int i2c_ch_index) +{ + int ret = 0; + + adap_data_init(adap, i2c_ch_index); + adap->algo = &fpgai2c_algorithm; + + ret = i2c_add_numbered_adapter(adap); + return ret; +} + +/* + * FPGAPCI APIs + */ +int board_i2c_fpgapci_read(uint32_t offset) +{ + int data; + data=ioread32(fpga_ctl_addr+offset); + return data; +} + + +int board_i2c_fpgapci_write(uint32_t offset, uint32_t value) +{ + iowrite32(value, fpga_ctl_addr+offset); + return (0); +} + + +static int __init pddf_xilinx_device_7021_algo_init(void) +{ + pddf_dbg(FPGA, KERN_INFO "[%s]\n", __FUNCTION__); + pddf_i2c_pci_add_numbered_bus = pddf_i2c_pci_add_numbered_bus_default; + ptr_fpgapci_read = board_i2c_fpgapci_read; + ptr_fpgapci_write = board_i2c_fpgapci_write; + return 0; +} + +static void __exit pddf_xilinx_device_7021_algo_exit(void) +{ + pddf_dbg(FPGA, KERN_INFO "[%s]\n", __FUNCTION__); + + pddf_i2c_pci_add_numbered_bus = NULL; + ptr_fpgapci_read = NULL; + ptr_fpgapci_write = NULL; + return; +} + + +module_init (pddf_xilinx_device_7021_algo_init); +module_exit (pddf_xilinx_device_7021_algo_exit); +MODULE_DESCRIPTION("Xilinx Corporation Device 7021 FPGAPCIe I2C-Bus algorithm"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_extend.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_extend.c new file mode 100644 index 000000000000..7f7f19068aa2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_fpga_extend.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * fpga-cls.c - front panel port control. + * + * Pradchaya Phucharoen + * Copyright (C) 2019 Celestica Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../../../../pddf/i2c/modules/include/pddf_i2c_algo.h" + +#define XILINX_FPGA_VERSION 0x0000 +#define XILINX_FPGA_SCRATCH 0x0004 +#define XILINX_FPGA_REG_SIZE 0x2000 + + +/* + * fpga_priv - port fpga private data + * @dev: device for reference + * @base: virtual base address + * @num_ports: number of front panel ports + * @fp_devs: list of front panel port devices + */ +struct fpga_priv { + void __iomem *base; + struct mutex fpga_lock; // For FPGA internal lock + void __iomem * fpga_read_addr; +}; + +extern void __iomem * fpga_ctl_addr; + +/** + * Show the value of the register set by 'set_fpga_reg_address' + * If the address is not set by 'set_fpga_reg_address' first, + * The version register is selected by default. + * @param buf register value in hextring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + // read data from the address + uint32_t data; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + data = ioread32(fpga->fpga_read_addr); + return sprintf(buf, "0x%8.8x\n", data); +} +/** + * Store the register address + * @param buf address wanted to be read value of + * @return number of bytes stored, or an error code + */ +static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t addr; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + addr = (uint32_t)strtoul(buf, &last, 16); + if (addr == 0 && buf == last) { + return -EINVAL; + } + fpga->fpga_read_addr = fpga->base + addr; + return count; +} +/** + * Show value of fpga scratch register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + + return sprintf(buf, "0x%8.8x\n", ioread32(fpga->base + XILINX_FPGA_SCRATCH) & 0xffffffff); +} +/** + * Store value of fpga scratch register + * @param buf scratch register value passing from user space + * @return number of bytes stored, or an error code + */ +static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + uint32_t data; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + data = (uint32_t)strtoul(buf, &last, 16); + if (data == 0 && buf == last) { + return -EINVAL; + } + iowrite32(data, fpga->base + XILINX_FPGA_SCRATCH); + return count; +} + +/** + * Show value of fpga version register + * @param buf register value in hexstring + * @return number of bytes read, or an error code + */ +static ssize_t get_fpga_version(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fpga_priv *fpga = dev_get_drvdata(dev); + + return sprintf(buf, "0x%8.8x\n", ioread32(fpga->base + XILINX_FPGA_VERSION) & 0xffffffff); +} + + +/** + * Store a value in a specific register address + * @param buf the value and address in format '0xhhhh 0xhhhhhhhh' + * @return number of bytes sent by user space, or an error code + */ +static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // register are 4 bytes + uint32_t addr; + uint32_t value; + uint32_t mode = 8; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + struct fpga_priv *fpga = dev_get_drvdata(dev); + + strscpy(clone, buf, count); + mutex_lock(&fpga->fpga_lock); + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + addr = (uint32_t)strtoul(tok, &last, 16); + if (addr == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + value = (uint32_t)strtoul(tok, &last, 16); + if (value == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mode = 32; + } else { + mode = (uint32_t)strtoul(tok, &last, 10); + if (mode == 0 && tok == last) { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + } + if (mode == 32) { + iowrite32(value, fpga->base + addr); + } else if (mode == 8) { + iowrite8(value, fpga->base + addr); + } else { + mutex_unlock(&fpga->fpga_lock); + return -EINVAL; + } + mutex_unlock(&fpga->fpga_lock); + return count; +} + +/** + * Read all FPGA register in binary mode. + * @param buf Raw transceivers port startus and control register values + * @return number of bytes read, or an error code + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i = 0; + ssize_t status; + u8 read_reg; + struct device *dev = kobj_to_dev(kobj); + struct fpga_priv *fpga = dev_get_drvdata(dev); + + if ( off + count > XILINX_FPGA_REG_SIZE ) { + return -EINVAL; + } + mutex_lock(&fpga->fpga_lock); + while (i < count) { + read_reg = ioread8(fpga->base + off + i); + buf[i++] = read_reg; + } + status = count; + mutex_unlock(&fpga->fpga_lock); + return status; +} + + +/* FPGA attributes */ +static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address); +static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value); +static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch); +static DEVICE_ATTR( version, 0400, get_fpga_version, NULL); +static BIN_ATTR_RO( dump, XILINX_FPGA_REG_SIZE); + +static struct bin_attribute *fpga_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute *fpga_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_scratch.attr, + &dev_attr_version.attr, + &dev_attr_setreg.attr, + NULL, +}; + +static struct attribute_group fpga_attr_grp = { + .attrs = fpga_attrs, + .bin_attrs = fpga_bin_attrs, +}; + + +static int cls_fpga_probe(struct platform_device *pdev) +{ + + struct fpga_priv *fpga; + int ret = -ENOMEM; + + if (!fpga_ctl_addr){ + printk(KERN_WARNING, "fpga_ctl_addr is null"); + return ret; + } + + fpga = devm_kzalloc(&pdev->dev, sizeof(struct fpga_priv), GFP_KERNEL); + if (!fpga){ + ret = -ENOMEM; + goto err_exit; + } + + mutex_init(&fpga->fpga_lock); + dev_set_drvdata(&pdev->dev, fpga); + fpga->base = fpga_ctl_addr; + + printk("FPGA version: 0x%x\n", ioread32(fpga->base + XILINX_FPGA_VERSION)); + + ret = sysfs_create_group(&pdev->dev.kobj, &fpga_attr_grp); + if (ret != 0) { + printk(KERN_ERR "Cannot create FPGA system sysfs attributes\n"); + goto err_remove_fpga; + } + + return 0; + +err_remove_fpga: + sysfs_remove_group(&pdev->dev.kobj, &fpga_attr_grp); +mem_unmap: + iounmap(fpga->base); +err_exit: + return ret; + +} + +static int cls_fpga_remove(struct platform_device *pdev) +{ + struct fpga_priv *fpga = dev_get_drvdata(&pdev->dev); + + sysfs_remove_group(&pdev->dev.kobj, &fpga_attr_grp); + iounmap(fpga->base); + return 0; +} + +static void fpga_dev_release( struct device * dev) +{ + return; +} +static struct resource cls_fpga_resources[] = { + { + .start = NULL, + .end = NULL, + .flags = IORESOURCE_IO, + }, +}; + +static struct platform_device cls_fpga_dev = { + .name = "fpga_sysfs", + .id = -1, + .num_resources = ARRAY_SIZE(cls_fpga_resources), + .resource = cls_fpga_resources, + .dev = { + .release = fpga_dev_release, + } +}; + +static struct platform_driver cls_fpga_driver = { + .probe = cls_fpga_probe, + .remove = cls_fpga_remove, + .driver = { + .name = "fpga_sysfs", + }, +}; + +static int __init drv_init(void) +{ + int rc = 0; + + rc = platform_device_register(&cls_fpga_dev); + rc += platform_driver_register(&cls_fpga_driver); + printk("fpga drv_init:%d\n", rc); + return rc; +} + +static void __exit drv_exit(void) +{ + platform_driver_unregister(&cls_fpga_driver); + platform_device_unregister(&cls_fpga_dev); + printk("fpga drv_exit.\n"); +} + +module_init(drv_init); +module_exit(drv_exit); + +MODULE_AUTHOR("Nicholas Wu"); +MODULE_DESCRIPTION("Celestica fpga control driver"); +MODULE_VERSION("2.0.0"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:cls-fpga"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_lpc_basecpld.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_lpc_basecpld.c new file mode 100644 index 000000000000..08a9831785c9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_lpc_basecpld.c @@ -0,0 +1,441 @@ +/* + * cpld_b .c - The CPLD driver for the Base Board of cloverstone + * The driver implement sysfs to access CPLD register on the baseboard of cloverstone via LPC bus. + * Copyright (C) 2018 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "sys_cpld" +/** + * CPLD register address for read and write. + */ +#define VERSION_ADDR 0xA100 +#define BMC_PRESENT_ADDR 0xA108 +#define SCRATCH_ADDR 0xA101 +#define SYS_LED_ADDR 0xA162 +#define CPLD_REGISTER_SIZE 0xFF + +struct cpld_b_data { + struct mutex cpld_lock; + uint16_t read_addr; +}; + +struct cpld_b_data *cpld_data; + +/** + * Read the value from scratch register as hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf,"0x%2.2x\n", data); +} + +/** + * Set scratch register with specific hex string. + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long data; + char *last; + + mutex_lock(&cpld_data->cpld_lock); + data = (uint16_t)strtoul(buf,&last,16); + if(data == 0 && buf == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + outb(data, SCRATCH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(scratch); + + +/* CPLD version attributes */ +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + unsigned char value = 0; + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + value = inb(VERSION_ADDR); + len = sprintf(buf, "%d.%d\n", value >> 4, value & 0x0F); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RO(version); + + +/* BMC Present Status */ +static ssize_t bmc_present_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + unsigned char value = 0; + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + value = inb(BMC_PRESENT_ADDR); + len = sprintf(buf, "%d\n", value & 0x0F); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RO(bmc_present); + + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint16_t addr; + char *last; + + addr = (uint16_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + cpld_data->read_addr = addr; + return count; +} + +static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + // CPLD register is one byte + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} +static DEVICE_ATTR_RW(getreg); + +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint16_t addr; + uint8_t value; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + + strscpy(clone, buf, count); + + mutex_lock(&cpld_data->cpld_lock); + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + addr = (uint16_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + value = (uint8_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + outb(value,addr); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_WO(setreg); + +/** + * Read all CPLD register in binary mode. + * @return number of byte read. + */ +static ssize_t dump_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + unsigned long i=0; + ssize_t status; + + mutex_lock(&cpld_data->cpld_lock); +begin: + if(i < count){ + buf[i++] = inb(VERSION_ADDR + off); + off++; + msleep(1); + goto begin; + } + status = count; +exit: + mutex_unlock(&cpld_data->cpld_lock); + return status; +} +static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE); + +/** + * Show system led status - on/off/1k/4k + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0x3; + return sprintf(buf, "%s\n", + data == 0x03 ? "off" : data == 0x02 ? "4k" : data ==0x01 ? "1k": "on"); +} + +/** + * Set the status of system led - on/off/1k/4k + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status,data; + if(sysfs_streq(buf, "off")){ + led_status = 0x03; + }else if(sysfs_streq(buf, "4k")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "1k")){ + led_status = 0x01; + }else if(sysfs_streq(buf, "on")){ + led_status = 0x00; + }else{ + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + data = data & ~(0x3); + data = data | led_status; + + /* if bit[5:4] is not configured to 01(green) or 10(yellow), + led will be off after set this filed */ + if(led_status == 0x00 && (0x0 == (data >> 4 & 0x3) || 0x3 == (data >> 4 & 0x3))){ + data = data & ~(0x3 << 4); + data = data | (0x01 << 4); /* set bit[5:4] to 01(green) defaultly */ + } else if(led_status == 0x01 || led_status == 0x02){ + data = data & ~(0x3 << 4); /* set bit[5:4] to 00(blink) defaultly */ + } + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(sys_led); + +/** + * Show system led color - both/green/yellow/none + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return Hex string read from scratch register. + */ +static ssize_t sys_led_color_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + data = (data >> 4) & 0x3; + return sprintf(buf, "%s\n", + data == 0x03 ? "off" : data == 0x02 ? "yellow" : data ==0x01 ? "green": "both"); +} + +/** + * Set the color of system led - both/green/yellow/none + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t sys_led_color_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char led_status,data; + if(sysfs_streq(buf, "off")){ + led_status = 0x03; + }else if(sysfs_streq(buf, "yellow")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "green")){ + led_status = 0x01; + }else if(sysfs_streq(buf, "both")){ + led_status = 0x00; + }else{ + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(SYS_LED_ADDR); + data = data & ~( 0x3 << 4); + data = data | (led_status << 4); + outb(data, SYS_LED_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} +static DEVICE_ATTR_RW(sys_led_color); + +static struct attribute *cpld_b_attrs[] = { + &dev_attr_bmc_present.attr, + &dev_attr_version.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_sys_led.attr, + &dev_attr_sys_led_color.attr, + NULL, +}; + +static struct bin_attribute *cpld_b_bin_attrs[] = { + &bin_attr_dump, + NULL, +}; + +static struct attribute_group cpld_b_attrs_grp = { + .attrs = cpld_b_attrs, + .bin_attrs = cpld_b_bin_attrs, +}; + +static struct resource cpld_b_resources[] = { + { + .start = 0xA100, + .end = 0xA1FF, + .flags = IORESOURCE_IO, + }, +}; + +static void cpld_b_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cpld_b_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cpld_b_resources), + .resource = cpld_b_resources, + .dev = { + .release = cpld_b_dev_release, + } +}; + +static int cpld_b_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int err = 0; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_b_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + cpld_data->read_addr = VERSION_ADDR; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (unlikely(!res)) { + printk(KERN_ERR "Specified Resource Not Available...\n"); + return -ENODEV; + } + + err = sysfs_create_group(&pdev->dev.kobj, &cpld_b_attrs_grp); + if (err) { + printk(KERN_ERR "Cannot create sysfs for baseboard CPLD\n"); + return err; + } + return 0; +} + +static int cpld_b_drv_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &cpld_b_attrs_grp); + return 0; +} + +static struct platform_driver cpld_b_drv = { + .probe = cpld_b_drv_probe, + .remove = __exit_p(cpld_b_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cpld_b_init(void) +{ + // Register platform device and platform driver + platform_device_register(&cpld_b_dev); + platform_driver_register(&cpld_b_drv); + return 0; +} + +void cpld_b_exit(void) +{ + // Unregister platform device and platform driver + platform_driver_unregister(&cpld_b_drv); + platform_device_unregister(&cpld_b_dev); +} + +module_init(cpld_b_init); +module_exit(cpld_b_exit); + + +MODULE_AUTHOR("Celestica Inc."); +MODULE_DESCRIPTION("LPC CPLD baseboard driver"); +MODULE_VERSION("2.0.0"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/modules/pddf_custom_wdt.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_wdt.c similarity index 85% rename from platform/broadcom/sonic-platform-modules-cel/belgite/modules/pddf_custom_wdt.c rename to platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_wdt.c index 21ef0de9f31c..b26aabba64cd 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/modules/pddf_custom_wdt.c +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_custom_wdt.c @@ -37,29 +37,25 @@ #define WDT_CONTROL_BASE 0xA100 #define TEST_SCRATCH_REG 0xA101 -#define REBOOT_CAUSE_REG 0xA105 -#define WDT_SET_TIMER_H_BIT_REG 0xA161 -#define WDT_SET_TIMER_M_BIT_REG 0xA162 -#define WDT_SET_TIMER_L_BIT_REG 0xA163 -#define WDT_TIMER_H_BIT_REG 0xA164 -#define WDT_TIMER_M_BIT_REG 0xA165 -#define WDT_TIMER_L_BIT_REG 0xA166 -#define WDT_ENABLE_REG 0xA167 -#define WDT_FEED_REG 0xA168 -#define WDT_PUNCH_REG 0xA169 +#define REBOOT_CAUSE_REG 0xA106 +#define WDT_SET_TIMER_H_BIT_REG 0xA181 +#define WDT_SET_TIMER_M_BIT_REG 0xA182 +#define WDT_SET_TIMER_L_BIT_REG 0xA183 +#define WDT_TIMER_H_BIT_REG 0xA184 +#define WDT_TIMER_M_BIT_REG 0xA185 +#define WDT_TIMER_L_BIT_REG 0xA186 +#define WDT_ENABLE_REG 0xA187 +#define WDT_FEED_REG 0xA188 +#define WDT_PUNCH_REG 0xA189 #define WDT_START_FEED 0x01 #define WDT_STOP_FEED 0x00 -#define POWER_CYCLE_RESET 0x00 + #define POWER_ON_RESET 0x11 #define SOFT_SET_WARM_RESET 0x22 #define SOFT_SET_COLD_RESET 0x33 #define CPU_WARM_RESET 0x44 -#define CPU_COLD_RESET 0x55 -#define CPU_GPIO_WARM_RESET 0x66 -#define WDT_RESET 0x77 -#define CPU_OVERLOAD_RESET 0x88 -#define INSUFFICIENT_FAN_SPEED_RESET 0xAA +#define WDT_RESET 0x66 #define MAX_TIMER_VALUE 0xffffff @@ -84,10 +80,10 @@ struct wdt_data { struct cpld_wdt_private { struct platform_device *pdev; - struct watchdog_device wddev; + struct watchdog_device wddev; struct cdev cdev; - struct miscdevice mdev; - bool suspended; + struct miscdevice mdev; + bool suspended; struct wdt_data wdat; }; @@ -271,10 +267,10 @@ static const struct watchdog_info ident = { static ssize_t identity_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); if(!wdt) return -EINVAL; - return sprintf(buf, "%s\n", wdt->wdat.ident.identity); + return sprintf(buf, "%s\n", wdt->wdat.ident.identity); } static DEVICE_ATTR_RO(identity); @@ -283,12 +279,12 @@ static DEVICE_ATTR_RO(identity); static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct cpld_wdt_private *wdt = dev_get_drvdata(dev); + struct cpld_wdt_private *wdt = dev_get_drvdata(dev); bool state = watchdog_is_running(wdt); if(true == state) return sprintf(buf, "active\n"); else - return sprintf(buf, "inactive\n"); + return sprintf(buf, "inactive\n"); } static DEVICE_ATTR_RO(state); @@ -309,11 +305,10 @@ static DEVICE_ATTR_RO(status); static ssize_t reason_show(struct device *dev, struct device_attribute *attr, char *buf) { - char bootstatus; + char bootstatus; struct cpld_wdt_private *wdt = dev_get_drvdata(dev); - if(!wdt) - return -EINVAL; - + if(!wdt) + return -EINVAL; bootstatus = watchdog_get_reason(wdt); return sprintf(buf, "0x%02x\n", bootstatus); @@ -344,7 +339,7 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, unsigned int timeout; struct cpld_wdt_private *wdt = dev_get_drvdata(dev); if(!wdt) - return -EINVAL; + return -EINVAL; timeout = watchdog_get_timeout(wdt); @@ -371,7 +366,7 @@ static int watchdog_open(struct inode *inode, struct file *file) { struct cpld_wdt_private *wdt; - wdt = container_of(file->private_data, struct cpld_wdt_private, mdev); + wdt = container_of(file->private_data, struct cpld_wdt_private, mdev); /* If the watchdog is alive we don't need to start it again */ @@ -384,15 +379,13 @@ static int watchdog_open(struct inode *inode, struct file *file) __module_get(THIS_MODULE); wdt->wdat.expect_close = 0; - - return nonseekable_open(inode, file); } static int watchdog_release(struct inode *inode, struct file *file) { struct cpld_wdt_private *p; - p = container_of(file->private_data, struct cpld_wdt_private, mdev); + p = container_of(file->private_data, struct cpld_wdt_private, mdev); if(!p) return -EINVAL; @@ -523,8 +516,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, new_timeout = new_timeout*1000; if (watchdog_set_timeout(p, new_timeout)) return -EINVAL; - - val = watchdog_get_timeout(p); + val = watchdog_get_timeout(p); return put_user(val, uarg.i); case WDIOC_GETTIMEOUT: val = watchdog_get_timeout(p); @@ -578,15 +570,12 @@ static int cpld_wdt_probe(struct platform_device *pdev) p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); if (!p) - return -ENOMEM; - - + return -ENOMEM; mutex_init(&(p->wdat.lock)); - - p->wdat.ident.options = WDIOC_SETTIMEOUT - | WDIOF_MAGICCLOSE - | WDIOF_KEEPALIVEPING - | WDIOC_GETTIMELEFT; + p->wdat.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING + | WDIOC_GETTIMELEFT; snprintf(p->wdat.ident.identity, sizeof(p->wdat.ident.identity), "%s", DRV_NAME); @@ -597,13 +586,12 @@ static int cpld_wdt_probe(struct platform_device *pdev) pr_info("Watchdog CPLD Version:0x%02x\n", ver); - if (timeout) { - if (timeout <= 0 - || timeout > max_timeout) { + if (timeout) { + if (timeout <= 0 || timeout > max_timeout) { pr_err("starting timeout out of range\n"); err = -EINVAL; return err; - } + } //watchdog_start(p); @@ -617,68 +605,48 @@ static int cpld_wdt_probe(struct platform_device *pdev) if (nowayout) __module_get(THIS_MODULE); - pr_info("watchdog started with initial timeout of %u Second(s)\n", - timeout/1000); - } + pr_info("watchdog started with initial timeout of %u Second(s)\n", timeout/1000); + } err = watchdog_set_timeout(p, timeout); if (err) return err; - err = register_reboot_notifier(&watchdog_notifier); + err = register_reboot_notifier(&watchdog_notifier); if (err) return err; - p->mdev = watchdog_miscdev; - err = misc_register(&p->mdev); + p->mdev = watchdog_miscdev; + err = misc_register(&p->mdev); if (err) { - pr_err("cannot register miscdev on minor=%d\n", - watchdog_miscdev.minor); - return err;; - } - - /*p->wdat.res = platform_get_resource(pdev, IORESOURCE_IO, WDT_CONTROL_BASE); - if (!p->wdat.res) - return -ENODEV; + pr_err("cannot register miscdev on minor=%d\n", watchdog_miscdev.minor); + return err; + } - if (!devm_request_region(dev, p->wdat.res->start, - resource_size(p->wdat.res), - pdev->name)) { - return -EBUSY; - } - */ err = sysfs_create_group(&pdev->dev.kobj, &wdt_group); - if (err) { - printk(KERN_ERR "Cannot create sysfs for cpld_wdt.\n"); - return err; - } + if (err) { + printk(KERN_ERR "Cannot create sysfs for cpld_wdt.\n"); + return err; + } - platform_set_drvdata(pdev, p); - dev_set_drvdata(dev, p); + platform_set_drvdata(pdev, p); + dev_set_drvdata(dev, p); - pr_info("initialized. sec (nowayout=%d)\n", - nowayout); + pr_info("initialized. sec (nowayout=%d)\n", + nowayout); return 0; } static int cpld_wdt_remove(struct platform_device *pdev) { - struct cpld_wdt_private *p = platform_get_drvdata(pdev); - /* - if (!nowayout) - watchdog_stop(&p->wddev); - */ - if(!p) - return 0; - + struct cpld_wdt_private *p = platform_get_drvdata(pdev); + + if (p) { sysfs_remove_group(&pdev->dev.kobj, &wdt_group); - misc_deregister(&p->mdev); - - unregister_reboot_notifier(&watchdog_notifier); - - return 0; - + unregister_reboot_notifier(&watchdog_notifier); + } + return 0; } static struct platform_driver cpld_wdt_driver = { @@ -722,14 +690,14 @@ static int __init cpld_wdt_init_module(void) pr_info("Platform Device/Driver Register Failed. err:%d\n", err); pr_info("CPLD WatchDog Timer Driver v%s\n", DRV_VERSION); - return err; + return err; } static void __exit cpld_wdt_cleanup_module(void) { - platform_driver_unregister(&cpld_wdt_driver); + platform_driver_unregister(&cpld_wdt_driver); platform_device_unregister(&cpld_wdt_dev); - pr_info("Watchdog Module Unloaded\n"); + pr_info("Watchdog Module Unloaded\n"); } module_init(cpld_wdt_init_module); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pmbus.h new file mode 100644 index 000000000000..cb6dbe29c0bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pmbus.h @@ -0,0 +1,504 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + */ + +#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_WRITE_PROTECT = 0x10, + + 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, + + PMBUS_MFR_VIN_MIN = 0xA0, + PMBUS_MFR_VIN_MAX = 0xA1, + PMBUS_MFR_IIN_MAX = 0xA2, + PMBUS_MFR_PIN_MAX = 0xA3, + PMBUS_MFR_VOUT_MIN = 0xA4, + PMBUS_MFR_VOUT_MAX = 0xA5, + PMBUS_MFR_IOUT_MAX = 0xA6, + PMBUS_MFR_POUT_MAX = 0xA7, + + PMBUS_IC_DEVICE_ID = 0xAD, + PMBUS_IC_DEVICE_REV = 0xAE, + + PMBUS_MFR_MAX_TEMP_1 = 0xC0, + PMBUS_MFR_MAX_TEMP_2 = 0xC1, + PMBUS_MFR_MAX_TEMP_3 = 0xC2, + +/* + * 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, + + /* + * RPM and PWM Fan control + * + * Drivers wanting to expose PWM control must define the behaviour of + * PMBUS_VIRT_PWM_[1-4] and PMBUS_VIRT_PWM_ENABLE_[1-4] in the + * {read,write}_word_data callback. + * + * pmbus core provides a default implementation for + * PMBUS_VIRT_FAN_TARGET_[1-4]. + * + * TARGET, PWM and PWM_ENABLE members must be defined sequentially; + * pmbus core uses the difference between the provided register and + * it's _1 counterpart to calculate the FAN/PWM ID. + */ + PMBUS_VIRT_FAN_TARGET_1, + PMBUS_VIRT_FAN_TARGET_2, + PMBUS_VIRT_FAN_TARGET_3, + PMBUS_VIRT_FAN_TARGET_4, + PMBUS_VIRT_PWM_1, + PMBUS_VIRT_PWM_2, + PMBUS_VIRT_PWM_3, + PMBUS_VIRT_PWM_4, + PMBUS_VIRT_PWM_ENABLE_1, + PMBUS_VIRT_PWM_ENABLE_2, + PMBUS_VIRT_PWM_ENABLE_3, + PMBUS_VIRT_PWM_ENABLE_4, + + /* Samples for average + * + * Drivers wanting to expose functionality for changing the number of + * samples used for average values should implement support in + * {read,write}_word_data callback for either PMBUS_VIRT_SAMPLES if it + * applies to all types of measurements, or any number of specific + * PMBUS_VIRT_*_SAMPLES registers to allow for individual control. + */ + PMBUS_VIRT_SAMPLES, + PMBUS_VIRT_IN_SAMPLES, + PMBUS_VIRT_CURR_SAMPLES, + PMBUS_VIRT_POWER_SAMPLES, + PMBUS_VIRT_TEMP_SAMPLES, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * WRITE_PROTECT + */ +#define PB_WP_ALL BIT(7) /* all but WRITE_PROTECT */ +#define PB_WP_OP BIT(6) /* all but WP, OPERATION, PAGE */ +#define PB_WP_VOUT BIT(5) /* all but WP, OPERATION, PAGE, VOUT, ON_OFF */ + +#define PB_WP_ANY (PB_WP_ALL | PB_WP_OP | PB_WP_VOUT) + +/* + * 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) + +enum pmbus_fan_mode { percent = 0, rpm }; + +/* + * 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_VIN_OFF BIT(3) +#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_PWM, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ +#define PMBUS_PHASES 10 /* Maximum number of phases per page */ + +/* 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) +#define PMBUS_HAVE_PWM12 BIT(20) +#define PMBUS_HAVE_PWM34 BIT(21) +#define PMBUS_HAVE_SAMPLES BIT(22) + +#define PMBUS_PHASE_VIRTUAL BIT(30) /* Phases on this page are virtual */ +#define PMBUS_PAGE_VIRTUAL BIT(31) /* Page is virtual */ + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + u8 phases[PMBUS_PAGES]; /* Number of phases per page */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version[PMBUS_PAGES]; /* vrm version per page */ + /* + * 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 */ + u32 pfunc[PMBUS_PHASES];/* Functionality, per phase */ + /* + * 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 phase, + 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; + + /* custom attributes */ + const struct attribute_group **groups; +}; + +/* 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, int page, int phase); +int pmbus_read_word_data(struct i2c_client *client, int page, int phase, + u8 reg); +int pmbus_write_word_data(struct i2c_client *client, int 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, struct pmbus_driver_info *info); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); +int pmbus_get_fan_rate_device(struct i2c_client *client, int page, int id, + enum pmbus_fan_mode mode); +int pmbus_get_fan_rate_cached(struct i2c_client *client, int page, int id, + enum pmbus_fan_mode mode); +int pmbus_update_fan(struct i2c_client *client, int page, int id, + u8 config, u8 mask, u16 command); +struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.c new file mode 100644 index 000000000000..338417125569 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.c @@ -0,0 +1,478 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description of various APIs related to PSU component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_psu_defs.h" +#include "pddf_psu_driver.h" + + +#define PSU_REG_VOUT_MODE 0x20 +#define PSU_REG_READ_VOUT 0x8b + +/*#define PSU_DEBUG*/ +#ifdef PSU_DEBUG +#define psu_dbg(...) printk(__VA_ARGS__) +#else +#define psu_dbg(...) +#endif + + +void get_psu_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + case PSU_V_OUT: + strscpy(str, "in3_input", ATTR_NAME_LEN); + break; + case PSU_I_OUT: + strscpy(str, "curr2_input", ATTR_NAME_LEN); + break; + case PSU_P_OUT: + strscpy(str, "power2_input", ATTR_NAME_LEN); + break; + case PSU_FAN1_SPEED: + strscpy(str, "fan1_input", ATTR_NAME_LEN); + break; + case PSU_TEMP1_INPUT: + strscpy(str, "temp1_input", ATTR_NAME_LEN); + break; + default: + break; + } + + return; +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static u8 psu_get_vout_mode(struct i2c_client *client) +{ + u8 status = 0, retry = 10; + uint8_t offset = PSU_REG_VOUT_MODE; + + while (retry) + { + status = i2c_smbus_read_byte_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + printk(KERN_ERR "%s: Get PSU Vout mode failed\n", __func__); + return 0; + } + else + { + /*printk(KERN_ERR "%s: vout_mode reg value 0x%x\n", __func__, status);*/ + return status; + } +} + +static u16 psu_get_v_out(struct i2c_client *client) +{ + u16 status = 0, retry = 10; + uint8_t offset = PSU_REG_READ_VOUT; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + printk(KERN_ERR "%s: Get PSU Vout failed\n", __func__); + return 0; + } + else + { + /*printk(KERN_ERR "%s: vout reg value 0x%x\n", __func__, status);*/ + return status; + } +} + +int psu_update_hw(struct device *dev, struct psu_attr_info *info, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + + +int psu_update_attr(struct device *dev, struct psu_attr_info *data, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data=NULL; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) + { + dev_dbg(&client->dev, "Starting update for %s\n", data->name); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: pre_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, data); + if (status!=0) + dev_warn(&client->dev, "%s: post_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return 0; +} + +ssize_t psu_show_default(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); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i, status=0; + u16 value = 0; + u8 vout_mode = 0; + int exponent, mantissa; + int multiplier = 1000; + char new_str[ATTR_NAME_LEN] = ""; + PSU_SYSFS_ATTR_DATA *ptr = NULL; + + for (i=0;inum_attr;i++) + { + ptr = (PSU_SYSFS_ATTR_DATA *)pdata->psu_attrs[i].access_data; + get_psu_duplicate_sysfs(ptr->index , new_str); + if ( strcmp(attr->dev_attr.attr.name, pdata->psu_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0 ) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + strscpy(new_str, "", ATTR_NAME_LEN); + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) + { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + psu_update_attr(dev, sysfs_attr_info, usr_data); + + switch(attr->index) + { + case PSU_PRESENT: + case PSU_POWER_GOOD: + status = sysfs_attr_info->val.intval; + return sprintf(buf, "%d\n", status); + break; + case PSU_MODEL_NAME: + case PSU_MFR_ID: + case PSU_SERIAL_NUM: + case PSU_FAN_DIR: + return sprintf(buf, "%s\n", sysfs_attr_info->val.strval); + break; + case PSU_V_OUT: + value = psu_get_v_out(client); + vout_mode = psu_get_vout_mode(client); + if ((vout_mode >> 5) == 0) + exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f); + else + exponent = 0; + + mantissa = value; + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + + case PSU_V_OUT_MIN: + case PSU_V_OUT_MAX: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + vout_mode = psu_get_vout_mode(client); + if ((vout_mode >> 5) == 0) + exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f); + else + exponent = 0; + mantissa = two_complement_to_int(value & 0xffff, 16, 0xffff); + + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + case PSU_I_OUT: + case PSU_V_IN: + case PSU_I_IN: + case PSU_P_OUT_MAX: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + break; + case PSU_P_IN: + case PSU_P_OUT: + multiplier = 1000000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + case PSU_FAN1_SPEED: + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent)); + else + return sprintf(buf, "%d\n", (mantissa) / (1 << -exponent)); + + break; + case PSU_TEMP1_INPUT: + case PSU_TEMP1_HIGH_THRESHOLD: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + default: + printk(KERN_ERR "%s: Unable to find attribute index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t psu_store_default(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 psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->psu_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + /*No write attributes for now in PSU*/ + default: + goto exit; + } + + psu_update_hw(dev, sysfs_attr_info, usr_data); + +exit: + return count; +} + +extern int board_i2c_cpld_read_new(unsigned short cpld_addr, char *name, u8 reg); +int sonic_i2c_get_psu_byte_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0; + int val = 0; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + + + if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0) + { + val = board_i2c_cpld_read_new(adata->devaddr, adata->devname, adata->offset); + if (val < 0){ + return val; + } + padata->val.intval = ((val & adata->mask) == adata->cmpval); + psu_dbg(KERN_ERR "%s: byte_value = 0x%x\n", __FUNCTION__, padata->val.intval); + } + + return status; +} + +int sonic_i2c_get_psu_block_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char buf[32]=""; //temporary placeholder for block data + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, buf); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + buf[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read block of data from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + buf[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strscpy(padata->val.strval, buf+1, data_len-1); + else + strscpy(padata->val.strval, buf, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, buf block: %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_word_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read a word from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: word value : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.h new file mode 100644 index 000000000000..24e4ea02e7ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_api.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * PSU driver related api declarations + */ + +#ifndef __PDDF_PSU_API_H__ +#define __PDDF_PSU_API_H__ + +extern void get_psu_duplicate_sysfs(int idx, char *str); +extern ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +extern int sonic_i2c_get_psu_byte_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_block_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_word_default(void *client, PSU_DATA_ATTR *adata, void *data); + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_defs.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_defs.h new file mode 100644 index 000000000000..60e81a9f5878 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_defs.h @@ -0,0 +1,90 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description: + * Platform PSU defines/structures header file + */ + +#ifndef __PDDF_PSU_DEFS_H__ +#define __PDDF_PSU_DEFS_H__ + + +#define MAX_NUM_PSU 5 +#define MAX_PSU_ATTRS 32 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct PSU_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum psu_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute + char devname[DEV_TYPE_LEN]; // Name of the device from where this sysfs attr is read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + void *access_data; + +}PSU_DATA_ATTR; + +typedef struct PSU_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, PSU_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, PSU_DATA_ATTR *adata, void *data); + void *data; +} PSU_SYSFS_ATTR_DATA; + +typedef struct PSU_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + PSU_SYSFS_ATTR_DATA *a_ptr; +} PSU_SYSFS_ATTR_DATA_ENTRY; + + +/* PSU CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */ +typedef struct PSU_DATA +{ + int idx; // psu index + int num_psu_fans; + PSU_DATA_ATTR psu_attr; + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR psu_attrs[MAX_PSU_ATTRS]; +}PSU_DATA; + +typedef struct PSU_PDATA +{ + int idx; // psu index + int num_psu_fans; // num of fans supported by the PSU + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR *psu_attrs; +}PSU_PDATA; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.c new file mode 100644 index 000000000000..fa5d31a0866a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.c @@ -0,0 +1,398 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * A pddf kernel module driver for PSU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_defs.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_driver.h" +#include "../../../../../pddf/i2c/modules/include/pddf_psu_api.h" + + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +struct pddf_ops_t pddf_psu_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = NULL, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_psu_ops); + + +PSU_SYSFS_ATTR_DATA access_psu_present = {PSU_PRESENT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_byte_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_present); + +PSU_SYSFS_ATTR_DATA access_psu_model_name = {PSU_MODEL_NAME, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_model_name); + +PSU_SYSFS_ATTR_DATA access_psu_power_good = {PSU_POWER_GOOD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_byte_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_power_good); + +PSU_SYSFS_ATTR_DATA access_psu_mfr_id = {PSU_MFR_ID, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_mfr_id); + +PSU_SYSFS_ATTR_DATA access_psu_serial_num = {PSU_SERIAL_NUM, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_serial_num); + +PSU_SYSFS_ATTR_DATA access_psu_fan_dir = {PSU_FAN_DIR, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_block_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan_dir); + +PSU_SYSFS_ATTR_DATA access_psu_v_out = {PSU_V_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out); + +PSU_SYSFS_ATTR_DATA access_psu_v_out_min = {PSU_V_OUT_MIN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out_min); + +PSU_SYSFS_ATTR_DATA access_psu_v_out_max = {PSU_V_OUT_MAX, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out_max); + +PSU_SYSFS_ATTR_DATA access_psu_i_out = {PSU_I_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out = {PSU_P_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out_max = {PSU_P_OUT_MAX, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out_max); + +PSU_SYSFS_ATTR_DATA access_psu_fan1_speed_rpm = {PSU_FAN1_SPEED, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan1_speed_rpm); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_input = {PSU_TEMP1_INPUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_input); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_high_threshold = {PSU_TEMP1_HIGH_THRESHOLD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_high_threshold); + +PSU_SYSFS_ATTR_DATA access_psu_v_in = {PSU_V_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_in); + +PSU_SYSFS_ATTR_DATA access_psu_i_in = {PSU_I_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_in); + +PSU_SYSFS_ATTR_DATA access_psu_p_in = {PSU_P_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_word_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_in); + +PSU_SYSFS_ATTR_DATA_ENTRY psu_sysfs_attr_data_tbl[]= +{ + { "psu_present", &access_psu_present}, + { "psu_model_name", &access_psu_model_name}, + { "psu_power_good" , &access_psu_power_good}, + { "psu_mfr_id" , &access_psu_mfr_id}, + { "psu_serial_num" , &access_psu_serial_num}, + { "psu_fan_dir" , &access_psu_fan_dir}, + { "psu_v_out" , &access_psu_v_out}, + { "psu_v_out_min" , &access_psu_v_out_min}, + { "psu_v_out_max" , &access_psu_v_out_max}, + { "psu_i_out" , &access_psu_i_out}, + { "psu_p_out" , &access_psu_p_out}, + { "psu_p_out_max" , &access_psu_p_out_max}, + { "psu_fan1_speed_rpm" , &access_psu_fan1_speed_rpm}, + { "psu_temp1_input" , &access_psu_temp1_input}, + { "psu_temp1_high_threshold" , &access_psu_temp1_high_threshold}, + { "psu_v_in" , &access_psu_v_in}, + { "psu_i_in" , &access_psu_i_in}, + { "psu_p_in" , &access_psu_p_in} +}; + +void *get_psu_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(psu_sysfs_attr_data_tbl)/sizeof(psu_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, psu_sysfs_attr_data_tbl[i].name) ==0) + { + return &psu_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_psu_access_data); + + +static int psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct psu_data *data; + int status =0; + int i,num, j=0; + PSU_PDATA *psu_platform_data; + PSU_DATA_ATTR *data_attr; + PSU_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_psu_ops.pre_probe) + { + status = (pddf_psu_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + /* Take control of the platform data */ + psu_platform_data = (PSU_PDATA *)(client->dev.platform_data); + num = psu_platform_data->len; + data->index = psu_platform_data->idx - 1; + data->num_psu_fans = psu_platform_data->num_psu_fans; + data->num_attr = num; + + + + /* Create and Add supported attr in the 'attributes' list */ + for (i=0; ipsu_attrs + i; + sysfs_data_entry = get_psu_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + continue; + } + + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[i] = &dy_ptr->dev_attr.attr; + strscpy(data->attr_info[i].name, data_attr->aname, ATTR_NAME_LEN); + data->attr_info[i].valid = 0; + mutex_init(&data->attr_info[i].update_lock); + + /*Create a duplicate entry*/ + get_psu_duplicate_sysfs(dy_ptr->index, new_str); + if (strcmp(new_str,"")) + { + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strscpy((char *)dy_ptr->dev_attr.attr.name, new_str, ATTR_NAME_LEN); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strscpy(new_str,"", ATTR_NAME_LEN); + } + } + data->psu_attribute_list[i+j] = NULL; + data->psu_attribute_group.attrs = data->psu_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->psu_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_psu_ops.post_probe) + { + status = (pddf_psu_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0;data->psu_attribute_list[i]!=NULL;i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + } + kfree(data); +exit: + return status; +} + +static void psu_remove(struct i2c_client *client) +{ + int i=0, ret = 0; + struct psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *platdata = (PSU_PDATA *)client->dev.platform_data; // use dev_get_platdata() + PSU_DATA_ATTR *platdata_sub = platdata->psu_attrs; + struct sensor_device_attribute *ptr = NULL; + + if (pddf_psu_ops.pre_remove) + { + ret = (pddf_psu_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); + for (i=0; data->psu_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + } + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_psu_ops.post_remove) + { + ret = (pddf_psu_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } +} + +enum psu_intf +{ + eeprom_intf, + smbus_intf +}; + +static const struct i2c_device_id psu_id[] = { + {"psu_eeprom", eeprom_intf}, + {"psu_pmbus", smbus_intf}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, psu_id); + +static struct i2c_driver psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "psu", + }, + .probe = psu_probe, + .remove = psu_remove, + .id_table = psu_id, + .address_list = normal_i2c, +}; + +int example_fun(void) +{ + pddf_dbg(PSU, KERN_ERR "CALLING FUN...\n"); + return 0; +} +EXPORT_SYMBOL(example_fun); + + +int psu_init(void) +{ + int status = 0; + + if (pddf_psu_ops.pre_init) + { + status = (pddf_psu_ops.pre_init)(); + if (status!=0) + return status; + } + + pddf_dbg(PSU, KERN_ERR "GENERIC_PSU_DRIVER.. init Invoked..\n"); + status = i2c_add_driver(&psu_driver); + if (status!=0) + return status; + + if (pddf_psu_ops.post_init) + { + status = (pddf_psu_ops.post_init)(); + if (status!=0) + return status; + } + + return status; +} +EXPORT_SYMBOL(psu_init); + +void psu_exit(void) +{ + pddf_dbg(PSU, "GENERIC_PSU_DRIVER.. exit\n"); + if (pddf_psu_ops.pre_exit) (pddf_psu_ops.pre_exit)(); + i2c_del_driver(&psu_driver); + if (pddf_psu_ops.post_exit) (pddf_psu_ops.post_exit)(); +} +EXPORT_SYMBOL(psu_exit); + +module_init(psu_init); +module_exit(psu_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.h new file mode 100644 index 000000000000..a94cf7441dbc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/psu_driver/pddf_psu_driver.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can 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. + * + * + * Description + * PSU driver data structures + */ +#ifndef __PDDF_PSU_DRIVER_H__ +#define __PDDF_PSU_DRIVER_H__ + +enum psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_MFR_ID, + PSU_SERIAL_NUM, + PSU_FAN_DIR, + PSU_V_OUT, + PSU_V_OUT_MIN, + PSU_V_OUT_MAX, + PSU_I_OUT, + PSU_P_OUT, /* This is in micro watts to comply with lm-sensors */ + PSU_P_OUT_MAX, + PSU_FAN1_SPEED, + PSU_TEMP1_INPUT, + PSU_TEMP1_HIGH_THRESHOLD, + PSU_V_IN, + PSU_I_IN, + PSU_P_IN, + PSU_ATTR_MAX +}; + + +/* Every client has psu_data which is divided into per attribute data */ +struct psu_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status; + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; +struct psu_data { + struct device *hwmon_dev; + u8 index; + int num_psu_fans; + int num_attr; + struct attribute *psu_attribute_list[MAX_PSU_ATTRS]; + struct attribute_group psu_attribute_group; + struct psu_attr_info attr_info[MAX_PSU_ATTRS]; +}; + + +#endif diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/tps536c7.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/tps536c7.c new file mode 100644 index 000000000000..3709503e621e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/tps536c7.c @@ -0,0 +1,133 @@ +/* + * Hardware monitoring driver for Texas Instruments TPS536C7 + * + * Copyright (c) 2017 Mellanox Technologies. All rights reserved. + * Copyright (c) 2017 Vadim Pasternak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include "pmbus.h" + + +#define TPS536C7_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */ +#define TPS536C7_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */ +#define TPS536C7_PROT_VR13_10MV 0x04 /* VR13.0 mode, 10-mV DAC */ +#define TPS536C7_PROT_IMVP8_5MV 0x05 /* IMVP8 mode, 5-mV DAC */ +#define TPS536C7_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */ +#define TPS536C7_PAGE_NUM 1 + +static int tps536c7_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + u8 buf[I2C_SMBUS_BLOCK_MAX]; + int phases_a = 0, phases_b = 0; + int i, ret; + + + return 1; + + ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf); + if (ret < 0) + return ret; + + dev_err(&client->dev, "jjj device ID: %s\n", buf); + if (strncmp("TI\x53\x6C\x70", buf, 5)) { + dev_err(&client->dev, "Unexpected device ID: %s\n", buf); + return -ENODEV; + } + #if 0 + ret = i2c_smbus_read_block_data(client, TPS53676_USER_DATA_03, buf); + if (ret < 0) + return ret; + for (i = 0; i < 2 * TPS53676_MAX_PHASES; i += 2) { + if (buf[i + 1] & 0x80) { + if (buf[i] & 0x08) + phases_b++; + else + phases_a++; + } + } + + info->format[PSC_VOLTAGE_OUT] = linear; + info->pages = 1; + info->phases[0] = phases_a; + if (phases_b > 0) { + info->pages = 2; + info->phases[1] = phases_b; + } + #endif + + return 0; +} + +static struct pmbus_driver_info tps536c7_info = { + .pages = TPS536C7_PAGE_NUM, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_TEMPERATURE] = linear, + .format[PSC_CURRENT_OUT] = linear, + .format[PSC_POWER] = linear, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_POUT, + .identify = tps536c7_identify, +}; + +static int tps536c7_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memcpy(info, &tps536c7_info, sizeof(*info)); + + //return pmbus_do_probe(client, id, info); + return pmbus_do_probe(client, info); +} + +static const struct i2c_device_id tps536c7_id[] = { + {"tps536c7", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tps536c7_id); + +static const struct of_device_id tps536c7_of_match[] = { + {.compatible = "ti,tps536c7"}, + {} +}; +MODULE_DEVICE_TABLE(of, tps536c7_of_match); + +static struct i2c_driver tps536c7_driver = { + .driver = { + .name = "tps536c7", + .of_match_table = of_match_ptr(tps536c7_of_match), + }, + .probe = tps536c7_probe, + //.remove = pmbus_do_remove, + .id_table = tps536c7_id, +}; + +module_i2c_driver(tps536c7_driver); + +MODULE_AUTHOR("Vadim Pasternak "); +MODULE_DESCRIPTION("PMBus driver for Texas Instruments TPS536C7"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/setup.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/setup.py new file mode 100644 index 000000000000..34b109b5bbfd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/setup.py @@ -0,0 +1,27 @@ +import os +from setuptools import setup +os.listdir + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Celestica Platforms based on PDDF', + license='Apache 2.0', + author='SONiC Team', + author_email='yajiang@celestica.com', + url='https://github.com/Azure/sonic-buildimage', + packages=['sonic_platform'], + 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.9', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/__init__.py new file mode 100644 index 000000000000..21d9cd445e31 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/__init__.py @@ -0,0 +1,4 @@ +# All the derived classes for PDDF +__all__ = ["platform", "chassis", "sfp", "psu", "thermal"] +from . import platform +from . import chassis diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/chassis.py new file mode 100644 index 000000000000..747b35aabd4c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/chassis.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/7/22 15:37 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + +try: + import sys + import time + import syslog + import subprocess + import os + import re + import shutil + from . import helper + from . import component + from .watchdog import Watchdog + from sonic_platform_pddf_base.pddf_chassis import PddfChassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BMC_EXIST = helper.APIHelper().get_bmc_status() + +REBOOT_CAUSE_PATH = "/sys/devices/platform/cpld_wdt/reason" +SET_SYS_STATUS_LED = "0x3A 0x39 0x02 0x00 {}" + +ORG_HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +TMP_HW_REBOOT_CAUSE_FILE="/tmp/hw-reboot-cause.txt" + + +class Chassis(PddfChassis): + """ + PDDF Platform-specific Chassis class + """ + sfp_status_dict = {} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + self.helper = helper.APIHelper() + PddfChassis.__init__(self, pddf_data, pddf_plugin_data) + self._watchdog = None + self._airflow_direction = None + + for port_idx in range(1, self.platform_inventory['num_ports'] + 1): + present = self.get_sfp(port_idx).get_presence() + self.sfp_status_dict[port_idx] = '1' if present else '0' + for index in range(self.platform_inventory['num_component']): + component_obj = component.Component(index) + self._component_list.append(component_obj) + + @staticmethod + def _getstatusoutput(cmd): + status = 0 + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = ret + if data[-1:] == '\n': + data = data[:-1] + + return status, data + + @staticmethod + def initizalize_system_led(): + return True + + def get_status_led(self): + return self.get_system_led("SYS_LED") + + def set_status_led(self, color): + if color == self.get_status_led(): + return False + + if BMC_EXIST: + sys_led_color_map = { + 'off': '00', + 'green': '01', + 'amber': '02', + 'amber_blink_1hz': '03', + 'amber_blink_4hz': '04', + 'green_blink_1hz': '05', + 'green_blink_4hz': '06', + 'alternate_blink_1hz': '07', + 'alternate_blink_4hz': '08' + } + color_val = sys_led_color_map.get(color.lower(), None) + if color_val is None: + print("SYS LED color %s not support!" % color) + return False + + status, _ = self.helper.ipmi_raw(SET_SYS_STATUS_LED.format(color_val)) + + return status + else: + result = self.set_system_led("SYS_LED", color) + return result + + def get_sfp(self, index): + """ + Retrieves sfp represented by (1-based) index + For Quanta the index in sfputil.py starts from 1, so override + Args: + index: An integer, the index (1-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 1. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + if index == 0: + raise IndexError + sfp = self._sfp_list[index - 1] + except IndexError: + sys.stderr.write("override: SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + + return sfp + + 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. + REBOOT_CAUSE_POWER_LOSS = "Power Loss" + REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU" + REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC" + REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other" + REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" + REBOOT_CAUSE_WATCHDOG = "Watchdog" + REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" + REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" + """ + reboot_cause = self.helper.read_txt_file(REBOOT_CAUSE_PATH) or "Unknown" + + # This tmp copy is to retain the reboot-cause only for the current boot + if os.path.isfile(ORG_HW_REBOOT_CAUSE_FILE): + shutil.move(ORG_HW_REBOOT_CAUSE_FILE, TMP_HW_REBOOT_CAUSE_FILE) + + if reboot_cause == "0x33" and os.path.isfile(TMP_HW_REBOOT_CAUSE_FILE): + with open(TMP_HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + if match is not None: + if match.group(1) == 'system': + return (self.REBOOT_CAUSE_NON_HARDWARE, 'System cold reboot') + + reboot_cause_description = { + '0x11': (self.REBOOT_CAUSE_POWER_LOSS, "Power on Reset"), + '0x22': (self.REBOOT_CAUSE_NON_HARDWARE, "Soft-set CPU warm reset"), + '0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, "CPU cold reset"), + '0x44': (self.REBOOT_CAUSE_NON_HARDWARE, "CPU warm reset"), + '0x66': (self.REBOOT_CAUSE_WATCHDOG, "Hardware Watchdog Reset"), + + } + prev_reboot_cause = reboot_cause_description.get(reboot_cause, + (self.REBOOT_CAUSE_NON_HARDWARE, "Unknown reason")) + return prev_reboot_cause + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + try: + + if self._watchdog is None: + # Create the watchdog Instance + self._watchdog = Watchdog() + except Exception as E: + syslog.syslog(syslog.LOG_ERR, "Fail to load watchdog due to {}".format(E)) + return self._watchdog + + def get_change_event(self, timeout=0): + sfp_dict = {} + + sfp_removed = '0' + sfp_inserted = '1' + + sfp_present = True + sfp_absent = False + + start_time = time.time() + time_period = timeout / float(1000) # Convert msecs to secss + + while time.time() < (start_time + time_period) or timeout == 0: + for port_idx in range(1, self.platform_inventory['num_ports'] + 1): + if self.sfp_status_dict[port_idx] == sfp_removed and \ + self.get_sfp(port_idx).get_presence() == sfp_present: + sfp_dict[port_idx] = sfp_inserted + self.sfp_status_dict[port_idx] = sfp_inserted + elif self.sfp_status_dict[port_idx] == sfp_inserted and \ + self.get_sfp(port_idx).get_presence() == sfp_absent: + sfp_dict[port_idx] = sfp_removed + self.sfp_status_dict[port_idx] = sfp_removed + + if sfp_dict: + return True, {'sfp': sfp_dict} + + time.sleep(0.5) + + return True, {'sfp': {}} # Timeout + + def get_revision(self): + """ + Retrieves the hardware revision for the chassis + Returns: + A string containing the hardware revision for this chassis. + """ + return self._eeprom.get_revision() + + def get_airflow_direction(self): + if self._airflow_direction == None: + try: + vendor_extn = self._eeprom.get_vendor_extn() + airflow_type = vendor_extn.split()[2][2:4] # either 0xfb or 0xbf + if airflow_type == 'FB': + direction = 'exhaust' + elif airflow_type == 'BF': + direction = 'intake' + else: + direction = 'N/A' + except (AttributeError, IndexError): + direction = 'N/A' + + self._airflow_direction = direction + + return self._airflow_direction diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/component.py new file mode 100644 index 000000000000..3ce7e20fb0b1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/component.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/7/21 17:09 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +try: + from sonic_platform_base.component_base import ComponentBase + from . import helper + import re +except ImportError as e: + raise ImportError(str(e) + "- required module not found") +BMC_EXIST = helper.APIHelper().get_bmc_status() +FPGA_VERSION_PATH = "/sys/bus/platform/devices/fpga_sysfs/version" +Bios_Version_Cmd = "dmidecode -t bios | grep Version" +ONIE_Version_Cmd = "cat /host/machine.conf" +SSD_Version_Cmd = "smartctl -i /dev/sda" +ASIC_PCIE_VERSION_CMD = "bcmcmd 'pciephy fw version' | grep 'PCIe FW version' | cut -d ' ' -f 4" + +if BMC_EXIST: + Check_Bios_Boot = "ipmitool raw 0x3a 0x25 0x02" + Fan_CPLD_Cmd = "ipmitool raw 0x3a 0x64 02 01 00" + COME_CPLD_Cmd = "ipmitool raw 0x3a 0x3e 1 0x1a 1 0xe0" + Sys_Cpld_Cmd = "ipmitool raw 0x3a 0x64 0x00 0x01 0x00" + Sw_Cpld1_Cmd = "i2cget -y -f 108 0x30 0 | tr a-z A-Z | cut -d 'X' -f 2" + Sw_Cpld2_Cmd = "i2cget -y -f 108 0x31 0 | tr a-z A-Z | cut -d 'X' -f 2" + Main_BMC_Cmd = "0x32 0x8f 0x08 0x01" + Backup_BMC_Cmd = "0x32 0x8f 0x08 0x01" + + COMPONENT_NAME_LIST = ["BIOS", "ONIE", "BMC", "FPGA", "CPLD COMe", "CPLD BASE", + "CPLD SW1", "CPLD SW2", "CPLD FAN", "ASIC PCIe", "SSD"] + COMPONENT_DES_LIST = ["Basic Input/Output system", + "Open Network Install Environment", + "Baseboard Management Controller", + "FPGA for transceiver EEPROM access and other component I2C access", + "COMe board CPLD", + "CPLD for board functions and watchdog", + "CPLD for port control QSFP(1-16)", + "CPLD for port control QSFP(17-32) SFP(33-34)", + "CPLD for fan control and status", + "ASIC PCIe Firmware", + "Solid State Drive"] +else: + Check_Bios_Boot = "i2cget -y -f 100 0x0d 0x70 | tr a-z A-Z | cut -d 'X' -f 2" + Fan_CPLD_Cmd = "i2cget -y -f 107 0x0d 0x00 | tr a-z A-Z | cut -d 'X' -f 2" + COME_CPLD_Cmd = "i2cget -y -f 104 0x0d 0xe0 | tr a-z A-Z | cut -d 'X' -f 2" + Sys_Cpld_Cmd = "i2cget -y -f 100 0x0d 0x00 | tr a-z A-Z | cut -d 'X' -f 2" + Sw_Cpld1_Cmd = "i2cget -y -f 108 0x30 0x00 | tr a-z A-Z | cut -d 'X' -f 2" + Sw_Cpld2_Cmd = "i2cget -y -f 108 0x31 0x00 | tr a-z A-Z | cut -d 'X' -f 2" + + COMPONENT_NAME_LIST = ["BIOS", "ONIE", "BMC", "FPGA", "CPLD COMe", "CPLD BASE", + "CPLD SW1", "CPLD SW2", "CPLD FAN", "SSD"] + + COMPONENT_DES_LIST = ["Basic Input/Output system", + "Open Network Install Environment", + "Baseboard Management Controller", + "FPGA for transceiver EEPROM access and other component I2C access", + "COMe board CPLD", + "CPLD for board functions and watchdog", + "CPLD for port control QSFP(1-16)", + "CPLD for port control QSFP(17-32) SFP(33-34)", + "CPLD for fan control and status", + "Solid State Drive"] + + + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + ComponentBase.__init__(self) + self.index = component_index + self.helper = helper.APIHelper() + self.name = self.get_name() + + def __get_bios_version(self): + """ + Get Bios version by command 'dmidecode -t bios | grep Version' + return: Bios Version + """ + status, result = self.helper.run_command(Check_Bios_Boot) + bios_version = "N/A" + if not status: + print("Fail! Unable to get the current Main bios or backup bios!") + return bios_version + status_ver, version_str = self.helper.run_command(Bios_Version_Cmd) + if not status: + print("Fail! Unable to get the bios version!") + return bios_version + + bios_version = re.findall(r"Version:(.*)", version_str)[0] + if result.strip() == "01" and self.name == "BIOS": + return bios_version.strip() + + elif result.strip() == "03" and self.name == "BIOS": + return bios_version.strip() + else: + return "N/A" + + def __get_onie_version(self): + """ + Get ONIE Version" + """ + onie_version = "N/A" + status, raw_onie_data = self.helper.run_command(ONIE_Version_Cmd) + if status: + ret = re.search(r"(?<=onie_version=).+[^\n]", raw_onie_data) + if ret != None: + onie_version = ret.group(0) + return onie_version + + def __get_cpld_version(self): + """ + Get Come cpld/Fan cpld/Sys cpld/Switch 1 cpld/Switch 2 cpld version + """ + version = "N/A" + cpld_version_dict = { + "CPLD COMe": COME_CPLD_Cmd, + "CPLD FAN": Fan_CPLD_Cmd, + "CPLD SW1": Sw_Cpld1_Cmd, + "CPLD SW2": Sw_Cpld2_Cmd, + "CPLD BASE": Sys_Cpld_Cmd, + } + if self.name in cpld_version_dict.keys(): + version_cmd = cpld_version_dict[self.name] + status, ver = self.helper.run_command(version_cmd) + if not status: + print("Fail! Can't get %s version by command:%s" % (self.name, version_cmd)) + return version + version1 = int(ver.strip()) / 10 + version2 = int(ver.strip()) % 10 + version = "%d.%d" % (version1, version2) + return version + + def __get_fpga_version(self): + """ + Get fpga version by fpga version bus path. + """ + status, fpga_version = self.helper.run_command("cat %s" % FPGA_VERSION_PATH) + if not status: + return "N/A" + return fpga_version.replace("0x", "") + + def __get_bmc_version(self): + """ + Get main/backup bmc version + """ + version = "N/A" + cmd = Main_BMC_Cmd if self.name == "Main_BMC" else Backup_BMC_Cmd + status, result = self.helper.ipmi_raw(cmd) + if not status: + print("Fail! Can't get the %s version by command:%s" % (self.name, cmd)) + return version + str_1 = str(int(result.strip().split(" ")[0])) + str_2 = str(int(result.strip().split(" ")[1], 16)) + version = "%s.%s" % (str_1, str_2) + return version + + def __get_asic_pcie_ver(self): + status, raw_ver=self.helper.run_command(ASIC_PCIE_VERSION_CMD) + if status: + return raw_ver + else: + return "N/A" + + def __get_ssd_version(self): + ssd_version = "N/A" + status, raw_ssd_data = self.helper.run_command(SSD_Version_Cmd) + if status: + ret = re.search(r"Firmware Version: +(.*)[^\\]", raw_ssd_data) + if ret != None: + ssd_version = ret.group(1) + return ssd_version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_NAME_LIST[self.index] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_DES_LIST[self.index] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + + if "BIOS" in self.name: + fw_version = self.__get_bios_version() + elif "ONIE" in self.name: + fw_version = self.__get_onie_version() + elif "CPLD" in self.name: + fw_version = self.__get_cpld_version() + elif self.name == "FPGA": + fw_version = self.__get_fpga_version() + elif "BMC" in self.name: + fw_version = self.__get_bmc_version() + elif self.name == "ASIC PCIe": + fw_version = self.__get_asic_pcie_ver() + elif "SSD" in self.name: + fw_version = self.__get_ssd_version() + return fw_version + + @staticmethod + def install_firmware(image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + return False + + @staticmethod + def update_firmware(image_path): + # Not support + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/eeprom.py new file mode 100644 index 000000000000..838328e321be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/eeprom.py @@ -0,0 +1,78 @@ +try: + import os + from sonic_platform_pddf_base.pddf_eeprom import PddfEeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +EEPROM_TMP_FILE = '/tmp/eeprom_dump.bin' + +class Eeprom(PddfEeprom): + _TLV_DISPLAY_VENDOR_EXT = True + _TLV_INFO_MAX_LEN = 256 + pddf_obj = {} + plugin_data = {} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + + # system EEPROM always has device name EEPROM1 + self.eeprom_path = self.pddf_obj.get_path("EEPROM1", "eeprom") + if self.eeprom_path is None: + return + + super(PddfEeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + if os.path.exists(EEPROM_TMP_FILE): + with open(EEPROM_TMP_FILE, 'rb') as b_fd: + self.eeprom_data = bytearray(b_fd.read()) + else: + self.eeprom_data = self.read_eeprom() + with open(EEPROM_TMP_FILE, 'wb') as b_fd: + b_fd.write(self.eeprom_data) + os.chmod(EEPROM_TMP_FILE, 0o444) + except Exception as E: + self.eeprom_data = "N/A" + raise RuntimeError("PddfEeprom is not Programmed - Error: {}".format(str(E))) + 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) < self._TLV_INFO_MAX_LEN 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: + name = "Vendor Extension" + value = "" + if self._TLV_DISPLAY_VENDOR_EXT: + for c in tlv[2:2 + tlv[1]]: + value += "0x%02X " % c + 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 get_revision(self): + return self.eeprom_tlv_dict.get('0x26', 'N/A') + + def get_vendor_extn(self): + return self.eeprom_tlv_dict.get('0xFD', 'N/A') diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan.py new file mode 100644 index 000000000000..ad90dfdf7b20 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/7/21 16:36 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +try: + from sonic_platform_pddf_base.pddf_fan import PddfFan + from . import helper + import re +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BMC_EXIST = helper.APIHelper().get_bmc_status() +Fan_Direction_Cmd = "0x3a 0x62 {}" +SET_FAN_STATUS_LED_CMD = "0x3A 0x39 0x02 {} {}" + + +class Fan(PddfFan): + """PDDF Platform-Specific Fan class""" + + def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): + # idx is 0-based + PddfFan.__init__(self, tray_idx, fan_idx, pddf_data, pddf_plugin_data, is_psu_fan, psu_index) + self.helper = helper.APIHelper() + + def get_presence(self): + """ + Retrieves the presence of fan + """ + return super().get_presence() + + 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 + """ + return 15 if "PSU" in self.get_name() else 25 + + def is_under_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_min_th = target_speed * (1 - float(speed_tolerance) / 100) + if speed < speed_min_th: + return True + else: + return False + + def is_over_speed(self): + speed = float(self.get_speed()) + target_speed = float(self.get_target_speed()) + speed_tolerance = self.get_speed_tolerance() + + speed_max_th = target_speed * (1 + float(speed_tolerance) / 100) + if speed > speed_max_th: + return True + else: + return False + + def set_status_led(self,color): + if self.is_psu_fan: + return super().set_status_led(color) + + if color == self.get_status_led(): + return False + + if BMC_EXIST: + fan_led_color_map = { + 'off': '00', + 'green': '01', + 'amber': '02', + 'red': '02' + } + + fan_index_val = hex(self.fantray_index + 3) + + color_val = fan_led_color_map.get(color.lower(), None) + + if fan_index_val is None: + return False + + if color_val is None: + return False + + status, _ = self.helper.ipmi_raw(SET_FAN_STATUS_LED_CMD.format(fan_index_val,color_val)) + + return status + else: + return self.set_system_led("SYS_LED", color) diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..babf6580ae3b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/fan_drawer.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/2/18 15:45 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + + +try: + from sonic_platform_pddf_base.pddf_fan_drawer import PddfFanDrawer +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(PddfFanDrawer): + """PDDF Platform-Specific Fan-Drawer class""" + + def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None): + # idx is 0-based + PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/helper.py new file mode 100644 index 000000000000..94783ed18ac5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/helper.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/2/28 plugins:10 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +import os +import json +import struct +import subprocess +from sonic_py_common import device_info +from mmap import * + +HOST_CHK_CMD = "docker > /dev/null 2>&1" +EMPTY_STRING = "" + + +class APIHelper(object): + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + @staticmethod + def is_host(): + return os.system(HOST_CHK_CMD) == 0 + + @staticmethod + def pci_get_value(resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + @staticmethod + def run_command(cmd): + status = True + result = "" + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + @staticmethod + def run_interactive_command(cmd): + try: + subprocess.call(cmd) + except: + return False + return True + + @staticmethod + def read_txt_file(file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + @staticmethod + def read_one_line_file(file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + @staticmethod + def write_txt_file(file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception as E: + print(str(E)) + return False + return True + + def get_cpld_reg_value(self, getreg_path, register): + cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register) + status, result = self.run_command(cmd) + return result if status else None + + @staticmethod + def ipmi_raw(cmd): + status = True + result = "" + cmd = "ipmitool raw {}".format(str(cmd)) + ret, raw_data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = raw_data + return status, result + + @staticmethod + def ipmi_fru_id(key_id, key=None): + status = True + result = "" + cmd = "ipmitool fru print {}".format(str( + key_id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(key_id), str(key)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + return status, result + + @staticmethod + def ipmi_set_ss_thres(id, threshold_key, value): + status = True + result = "" + cmd = "ipmitool sensor thresh '{}' {} {}".format( + str(id), str(threshold_key), str(value)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + return status, result + + @staticmethod + def get_bmc_status(): + """ + get bmc present by pddf-device.json + return: True(present), False(absent) + """ + pddf_device_path = '/usr/share/sonic/platform/pddf/pddf-device.json' + with open(pddf_device_path) as f: + json_data = json.load(f) + bmc_present = json_data["PLATFORM"]["bmc_present"] + return True if bmc_present == "True" else False diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/platform.py new file mode 100644 index 000000000000..8595e80692df --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/platform.py @@ -0,0 +1,23 @@ +############################################################################# +# PDDF +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + from sonic_platform_pddf_base.pddf_platform import PddfPlatform +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PddfPlatform): + """ + PDDF Platform-Specific Platform Class + """ + + def __init__(self): + PddfPlatform.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/psu.py new file mode 100644 index 000000000000..033307568b31 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/psu.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/7/20 13:46 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +try: + from sonic_platform_pddf_base.pddf_psu import PddfPsu + import re + import os + from . import helper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BMC_EXIST = helper.APIHelper().get_bmc_status() + + +class Psu(PddfPsu): + """PDDF Platform-Specific PSU class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) + self.helper = helper.APIHelper() + if BMC_EXIST: + from . import sensor_list_config + if not os.path.exists(sensor_list_config.Sensor_List_Info): + cmd = "ipmitool sensor list > %s" % sensor_list_config.Sensor_List_Info + self.helper.run_command(cmd) + + @staticmethod + def get_capacity(): + return 550 + + @staticmethod + def get_type(): + return 'AC' + + @staticmethod + def get_revision(): + """ + Get PSU HW Revision by read psu eeprom data. + return: HW Revision or 'N/A' + """ + return "N/A" + + + diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sensor_list_config.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sensor_list_config.py new file mode 100644 index 000000000000..8c75e5480a73 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sensor_list_config.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*-# + +# @Time : 2023/4/13 9:29 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + +# The path of sensor list information file +Sensor_List_Info = "/tmp/sensor_info.log" + +# The Sensor list information refresh interval +Sensor_Info_Update_Period_Secs = 60 diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sfp.py new file mode 100644 index 000000000000..89af6f6de14b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/sfp.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +try: + import ast + from sonic_platform_pddf_base.pddf_sfp import PddfSfp + from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CmisApi +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Sfp(PddfSfp): + """ + PDDF Platform-Specific Sfp class + """ + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + + def get_presence(self): + presence = PddfSfp.get_presence(self) + if not presence and self._xcvr_api != None: + self._xcvr_api = None + + return presence + + def get_xcvr_api(self): + if self._xcvr_api is None and self.get_presence(): + self.refresh_xcvr_api() + + # Find and update the right optoe driver + api_to_driver_map = {\ + 'Sff8636Api': 'optoe1',\ + 'Sff8472Api': 'optoe2',\ + 'CmisApi': 'optoe3',\ + 'CCmisApi': 'optoe3',\ + 'Sff8436Api': 'sff8436'\ + } + create_dev = False + path_list = self.eeprom_path.split('/') + name_path = '/'.join(path_list[:-1]) + '/name' + del_dev_path = '/'.join(path_list[:-2]) + '/delete_device' + new_dev_path = '/'.join(path_list[:-2]) + '/new_device' + api_name = type(self._xcvr_api).__name__ + new_driver = api_to_driver_map.get(api_name, 'optoe1') + + try: + with open(name_path, 'r') as fd: + cur_driver = fd.readline().strip() + except FileNotFoundError: + create_dev = True + else: + if cur_driver != new_driver: + with open(del_dev_path, 'w') as fd: + fd.write("0x50") + create_dev = True + + if create_dev: + with open(new_dev_path, 'w') as fd: + fd.write("{} 0x50".format(new_driver)) + + if api_name == 'Sff8636Api' or \ + api_name == 'Sff8436Api': + self.write_eeprom(93,1,bytes([0x04])) + + return self._xcvr_api + + def get_platform_media_key(self, transceiver_dict, port_speed, lane_count): + api = self.get_xcvr_api() + api_name = type(api).__name__ + if api_name in ['CmisApi', 'CCmisApi']: + is_cmis = True + else: + is_cmis = False + + # Per lane speed + media_key = str(int(port_speed / lane_count)) + if is_cmis: + media_compliance_code = transceiver_dict['specification_compliance'] + if 'copper' in media_compliance_code: + media_len = transceiver_dict['cable_length'] + media_key += '-copper-' + str(media_len) + 'M' + else: + media_key += '-optical' + else: + media_compliance_dict = ast.literal_eval(transceiver_dict['specification_compliance']) + eth_compliance_str = '10/40G Ethernet Compliance Code' + ext_compliance_str = 'Extended Specification Compliance' + media_compliance_code = '' + if eth_compliance_str in media_compliance_dict: + media_compliance_code = media_compliance_dict[eth_compliance_str] + if ext_compliance_str in media_compliance_dict: + media_compliance_code = media_compliance_code + ' ' + media_compliance_dict[ext_compliance_str] + if 'CR' in media_compliance_code or "copper" in transceiver_dict['specification_compliance'].lower(): + media_len = transceiver_dict['cable_length'] + media_key += '-copper-' + str(media_len) + 'M' + else: + media_key += '-optical' + + return {\ + 'vendor_key': '',\ + 'media_key': media_key,\ + 'lane_speed_key': ''\ + } diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/thermal.py new file mode 100644 index 000000000000..572a82be48c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/thermal.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# @Company :Celestica +# @Time : 2023/7/24 13:32 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + +try: + from sonic_platform_pddf_base.pddf_thermal import PddfThermal + from . import helper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BMC_EXIST = helper.APIHelper().get_bmc_status() +FAN_STATUS_INFO_CMD = "i2cget -y -f 107 0x0d 0x26" + + +class Thermal(PddfThermal): + """PDDF Platform-Specific Thermal class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): + self.helper = helper.APIHelper() + PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal=is_psu_thermal, + psu_index=psu_index) + + def get_high_critical_threshold(self): + """ + Rewrite the method of obtaining PSU high critical in pddf_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 + """ + if BMC_EXIST: + from . import sensor_list_config + if not self.is_psu_thermal: + output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_crit_threshold") + if not output: + return None + + if output['status'].isalpha(): + attr_value = None + else: + attr_value = float(output['status']) + + if output['mode'] == 'bmc': + return attr_value + else: + return float(attr_value / 1000) + else: + info = self.helper.read_txt_file(sensor_list_config.Sensor_List_Info) + for line in info.splitlines(): + if "PSU%d_Temp1" % self.thermals_psu_index in line: + return float(line.split("|")[8]) + else: + return super().get_high_critical_threshold() + + def get_high_threshold(self): + if BMC_EXIST: + return super().get_high_threshold() + else: + status, fan_info = self.helper.run_command(FAN_STATUS_INFO_CMD) + if not status: + return None + thermal_name = self.get_name() + fan_dir = "B2F" if (bin(int(fan_info, 16)))[-2:-1] == "0" else "F2B" + value = self.plugin_data["THERMAL"]["NONE_BMC"]["temp1_high_threshold"][thermal_name][fan_dir] + return float(value) if value.isdigit() else None + diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/watchdog.py new file mode 100644 index 000000000000..7e4fc599dda2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/pddf/sonic_platform/watchdog.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python + +############################################################################# +# +# Watchdog contains an implementation of SONiC Platform Base Watchdog API +# +############################################################################# +import fcntl +import os +import array + +try: + from . import helper + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +""" ioctl constants """ +IO_WRITE = 0x40000000 +IO_READ = 0x80000000 +IO_READ_WRITE = 0xC0000000 +IO_SIZE_INT = 0x00040000 +IO_SIZE_40 = 0x00280000 +IO_TYPE_WATCHDOG = ord('W') << 8 + +WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG +WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG +WDWR_INT = IO_READ_WRITE | IO_SIZE_INT | IO_TYPE_WATCHDOG + +""" Watchdog ioctl commands """ +WDIOC_GETSUPPORT = 0 | WDR_40 +WDIOC_GETSTATUS = 1 | WDR_INT +WDIOC_GETBOOTSTATUS = 2 | WDR_INT +WDIOC_GETTEMP = 3 | WDR_INT +WDIOC_SETOPTIONS = 4 | WDR_INT +WDIOC_KEEPALIVE = 5 | WDR_INT +WDIOC_SETTIMEOUT = 6 | WDWR_INT +WDIOC_GETTIMEOUT = 7 | WDR_INT +WDIOC_SETPRETIMEOUT = 8 | WDWR_INT +WDIOC_GETPRETIMEOUT = 9 | WDR_INT +WDIOC_GETTIMELEFT = 10 | WDR_INT + +""" Watchdog status constants """ +WDIOS_DISABLECARD = 0x0001 +WDIOS_ENABLECARD = 0x0002 + +WDT_COMMON_ERROR = -1 +WD_MAIN_IDENTITY = "cpld_wdt" +WDT_SYSFS_PATH = "/sys/class/watchdog/" + +DEFAULT_TIMEOUT = 180 +watchdog = 0 + + +class Watchdog(WatchdogBase): + watchdog = None + + def __init__(self): + global watchdog + self.helper = helper.APIHelper() + self.status_path = "/sys/devices/platform/cpld_wdt/status" + self.state_path = "/sys/devices/platform/cpld_wdt/state" + self.timeout_path = "/sys/devices/platform/cpld_wdt/timeout" + # Set default value + state = self.helper.read_txt_file(self.state_path) + self.armed = True if state == "active" else False + self.timeout = DEFAULT_TIMEOUT + if not watchdog: + watchdog = os.open("/dev/cpld_wdt", os.O_RDWR) + self.watchdog = watchdog + + def _enable(self): + """ + Turn on the watchdog timer + """ + req = array.array('h', [WDIOS_ENABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _disable(self): + """ + Turn off the watchdog timer + """ + req = array.array('h', [WDIOS_DISABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _keep_alive(self): + """ + Keep alive watchdog timer + """ + fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE) + + def _set_timeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + req = array.array('I', [seconds]) + fcntl.ioctl(self.watchdog, WDIOC_SETTIMEOUT, req, True) + return int(req[0]) + + def _get_timeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True) + + return int(req[0]) + + def _get_time_left(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMELEFT, req, True) + + return int(req[0]) + + ################################################################# + + 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. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._set_timeout(seconds) + + if self.armed: + self._keep_alive() + else: + self._enable() + self.armed = True + + ret = self.timeout + except IOError: + pass + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + 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. + """ + + time_left = WDT_COMMON_ERROR + + if self.armed: + try: + time_left = self._get_time_left() + except IOError: + pass + + return time_left + + def __del__(self): + """ + Close watchdog + """ + + if self.watchdog is not None: + os.close(self.watchdog) + diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_post_device_create.sh b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_post_device_create.sh new file mode 100755 index 000000000000..4e078f27639c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_post_device_create.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# install custom fpga device. + +sleep 3 +modprobe pddf_custom_fpga_extend + +bmc_present=`cat /usr/share/sonic/device/x86_64-cel_silverstone_v2-r0/bmc_status` +#Set off Alarm LED +if [[ "$bmc_present" == "True" ]]; then + # Set all LEDs to Manual control + ipmitool raw 0x3a 0x42 0x02 0x00 &> /dev/null + + # Set Alarm LED to OFF + ipmitool raw 0x3a 0x39 0x02 0x01 0x00 &> /dev/null + + #Set CPLD Fan LED register to BMC control + ipmitool raw 0x3a 0x64 0x00 0x02 0x65 0x10 &> /dev/null +else + i2cset -f -y 100 0x0d 0x63 0x33 &> /dev/null +fi diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_pre_driver_install.sh b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_pre_driver_install.sh new file mode 100755 index 000000000000..4330f7c21382 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pddf_pre_driver_install.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Has customized those drivers,so rename them to lose effect +psu_driver=pddf_psu_driver_module.ko +fan_driver=pddf_fan_driver_module.ko +ker_name=$(uname -r) +driver_path=/usr/lib/modules/${ker_name}/extra/ +if [ -e ${driver_path}${psu_driver} ]; then + mv ${driver_path}${psu_driver} ${driver_path}${psu_driver}-bk +fi + +if [ -e ${driver_path}${fan_driver} ]; then + mv ${driver_path}${fan_driver} ${driver_path}${fan_driver}-bk +fi +echo 'pddf psu,fan driver module has rename now' diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/platform_sensors.py new file mode 100755 index 000000000000..8e0dfe90c063 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/platform_sensors.py @@ -0,0 +1,180 @@ +#!/usr/bin/python +# +# Silverstone-v2 platform sensors. This script get the sensor data from BMC +# using ipmitool and display them in lm-sensor alike format. +# +# The following data is support: +# 1. Temperature sensors +# 2. PSUs +# 3. Fan Drawers + +import sys +import logging +import subprocess + +IPMI_SDR_CMD = ['/usr/bin/ipmitool', 'sdr', 'elist'] +MAX_NUM_FANS = 7 +MAX_NUM_PSUS = 2 + +SENSOR_NAME = 0 +SENSOR_VAL = 4 + +sensor_dict = {} + +def ipmi_sensor_dump(cmd): + ''' Execute ipmitool command return dump output + exit if any error occur. + ''' + global sensor_dict + sensor_dump = '' + + try: + sensor_dump = subprocess.check_output(IPMI_SDR_CMD, universal_newlines=True) + except subprocess.CalledProcessError as e: + logging.error('Error! Failed to execute: {}'.format(cmd)) + sys.exit(1) + + for line in sensor_dump.splitlines(): + sensor_info = line.split('|') + sensor_dict[sensor_info[SENSOR_NAME].strip()] = sensor_info[SENSOR_VAL].strip() + + return True + +def get_reading_by_name(sensor_name, sdr_elist_dump): + ''' + Search for the match sensor name, return sensor + reading value and unit, return object epmtry string + if search not match. + + The output of sensor dump: + TEMP_FB_U52 | 00h | ok | 7.1 | 31 degrees C + TEMP_FB_U17 | 01h | ok | 7.1 | 27 degrees C + TEMP_SW_U52 | 02h | ok | 7.1 | 30 degrees C + Fan2_Status | 07h | ok | 29.2 | Present + Fan2_Front | 0Eh | ok | 29.2 | 12000 RPM + Fan2_Rear | 46h | ok | 29.2 | 14700 RPM + PSU2_Status | 39h | ok | 10.2 | Presence detected + PSU2_Fan | 3Dh | ok | 10.2 | 16000 RPM + PSU2_VIn | 3Ah | ok | 10.2 | 234.30 Volts + PSU2_CIn | 3Bh | ok | 10.2 | 0.80 Amps + ''' + found = '' + + for line in sdr_elist_dump.splitlines(): + line = line.decode() + if sensor_name in line: + found = line.strip() + break + + if not found: + logging.error('Cannot find sensor name:' + sensor_name) + + else: + try: + found = found.split('|')[4] + except IndexError: + logging.error('Cannot get sensor data of:' + sensor_name) + + logging.basicConfig(level=logging.DEBUG) + return found + + +def read_temperature_sensors(): + sensor_list = [\ + ('TEMP_FB_U52', 'Fanboard Center Temp'),\ + ('TEMP_FB_U17', 'Fanboard Right Temp'),\ + ('TEMP_SW_U52', 'Switchboard Left Temp'),\ + ('TEMP_SW_U16', 'Switchboard Right Temp'),\ + ('TEMP_CPU', 'CPU Internal Temp'),\ + ('TEMP_SW_Internal', 'ASIC Internal Temp'),\ + ('VDD_CORE_Temp', 'TPS536C7 Chip Temp'),\ + ('XP3R3V_R_Temp', 'MP2975 3.3v Chip Right Temp'),\ + ('XP3R3V_L_Temp', 'MP2975 3.3v Chip Left Temp'),\ + ('XP0R8V_Temp', 'MP2975 0.8v Chip Temp')\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Temperature Sensors\n" + output += "Adapter: IPMI adapter\n" + for sensor in sensor_list: + output += sensor_format.format('{}:'.format(sensor[1]),\ + sensor_dict[sensor[0]],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_fan_sensors(num_fans): + + sensor_list = [\ + ('Fan{}_Status', 'Fan Drawer {} Status'),\ + ('Fan{}_Front', 'Fan {} front'),\ + ('Fan{}_Rear', 'Fan {} rear'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "Fan Drawers\n" + output += "Adapter: IPMI adapter\n" + for fan_num in range(1, num_fans+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(fan_num) + display_sensor_name = sensor[1].format(fan_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def read_psu_sensors(num_psus): + + sensor_list = [\ + ('PSU{}_Status', 'PSU {} Status'),\ + ('PSU{}_Fan', 'PSU {} Fan 1'),\ + ('PSU{}_VIn', 'PSU {} Input Voltage'),\ + ('PSU{}_CIn', 'PSU {} Input Current'),\ + ('PSU{}_PIn', 'PSU {} Input Power'),\ + ('PSU{}_Temp1', 'PSU {} Temp1'),\ + ('PSU{}_Temp2', 'PSU {} Temp2'),\ + ('PSU{}_Temp3', 'PSU {} Temp3'),\ + ('PSU{}_VOut', 'PSU {} Output Voltage'),\ + ('PSU{}_COut', 'PSU {} Output Current'),\ + ('PSU{}_POut', 'PSU {} Output Power'),\ + ] + + output = '' + sensor_format = '{0:{width}}{1}\n' + # Find max length of sensor calling name + max_name_width = max(len(sensor[1]) for sensor in sensor_list) + + output += "PSU\n" + output += "Adapter: IPMI adapter\n" + for psu_num in range(1, num_psus+1): + for sensor in sensor_list: + ipmi_sensor_name = sensor[0].format(psu_num) + display_sensor_name = sensor[1].format(psu_num) + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ + width=str(max_name_width+1)) + output += '\n' + return output + +def main(): + output_string = '' + + if ipmi_sensor_dump(IPMI_SDR_CMD): + output_string += read_temperature_sensors() + output_string += read_psu_sensors(MAX_NUM_PSUS) + output_string += read_fan_sensors(MAX_NUM_FANS) + + print(output_string) + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pre_pddf_init.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pre_pddf_init.py new file mode 100755 index 000000000000..74f0e1ea91cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/pre_pddf_init.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/7/24 9:34 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Load pddf_custom_lpc_basecpld.ko, after confirming the BMC is in place, +# load different configuration files, and finally remove the driver. + +import subprocess +import os +import os.path + + +class PrePddfInit(object): + def __init__(self): + self.ker_path = "/usr/lib/modules/{}/extra" + self.lpc_basecpld_name = "pddf_custom_lpc_basecpld" + self.lpc_basecpld_ko = "pddf_custom_lpc_basecpld.ko" + self.bmc_exist_cmd = "/sys/bus/platform/devices/sys_cpld/bmc_present" + self.platform_name = "x86_64-cel_silverstone_v2-r0" + self.bmc_present = False + + @staticmethod + def run_command(cmd): + status = True + result = "" + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data + + return status, result + + def get_kernel_path(self): + """ + get the kernel object complete path + :return: + """ + sta_, res_ = self.run_command("uname -r") + if sta_: + return self.ker_path.format(res_) + else: + return None + + def install_lpc_basecpld(self): + """ + install lpc basecpld driver + """ + ker_path = self.get_kernel_path() + if ker_path: + self.run_command("insmod %s/%s" % (ker_path, self.lpc_basecpld_ko)) + + def uninstall_lpc_basecpld(self): + self.run_command("rmmod %s" % self.lpc_basecpld_name) + + def get_bmc_status(self): + """ + get bmc status + """ + self.install_lpc_basecpld() + if os.path.exists(self.bmc_exist_cmd): + # "1": "absent", "0": "present" + sta, res = self.run_command("cat %s" % self.bmc_exist_cmd) + self.bmc_present = False if res == "1" else True + self.uninstall_lpc_basecpld() + + def choose_pddf_device_json(self): + """ + Depending on the state of the BMC, different pddf-device.json file configurations will be used: + 1.BMC exist: cp pddf-device.json-bmc pddf-device.json + 2.None BMC : cp pddf-device.json-nonebmc pddf-device.json + """ + device_name = "pddf-device.json-bmc" if self.bmc_present else "pddf-device.json-nonebmc" + device_path = "/usr/share/sonic/device/%s/pddf/" % self.platform_name + self.run_command("cp %s%s %spddf-device.json" % (device_path, device_name, device_path)) + + def choose_platform_components(self): + """ + Depending on the state of the BMC, different platform_components.json file configurations will be used: + 1.BMC exist: cp platform_components.json-bmc platform_components.json + 2.None BMC : cp platform_components.json-nonebmc platform_components.json + """ + # ./usr/share/sonic/device/x86_64-cel_silverstone_v2-r0/platform_components.json + device_name = "platform_components.json-bmc" if self.bmc_present else "platform_components.json-nonebmc" + device_path = "/usr/share/sonic/device/%s/" % self.platform_name + self.run_command("cp %s%s %splatform_components.json" % (device_path, device_name, device_path)) + + def main(self): + self.get_bmc_status() + self.choose_pddf_device_json() + self.choose_platform_components() + with open("/usr/share/sonic/device/%s/bmc_status" % self.platform_name, 'w') as fp: + fp.write(str(self.bmc_present)) + + +if __name__ == '__main__': + if not os.path.isfile("/usr/share/sonic/device/x86_64-cel_silverstone_v2-r0/bmc_status"): + pre_init = PrePddfInit() + pre_init.main() diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/sensors new file mode 100755 index 000000000000..5d740a9eb7d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/sensors @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon python3 /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/silverstone_v2_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/silverstone_v2_platform_shutdown.sh new file mode 100755 index 000000000000..03bc2fcf9730 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/scripts/silverstone_v2_platform_shutdown.sh @@ -0,0 +1,39 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +bmc_present=`cat /usr/share/sonic/device/x86_64-cel_silverstone_v2-r0/bmc_status` + +if [[ "$bmc_present" == "True" ]]; then + # Set all LEDs to BMC's control + ipmitool raw 0x3a 0x42 0x02 0x01 &> /dev/null + + # BMC cold power-cyle + ipmitool chassis power cycle &> /dev/null +else + # Set System LED to booting pattern + i2cset -f -y 100 0x0d 0x62 0x02 &> /dev/null + + # CPLD cold power-cyle + i2cset -f -y 100 0x0d 0x64 0x00 &> /dev/null +fi + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/service/belgite-pddf-platform-monitor.service b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/service/silverstone-v2-pddf-platform-monitor.service similarity index 58% rename from platform/broadcom/sonic-platform-modules-cel/belgite/service/belgite-pddf-platform-monitor.service rename to platform/broadcom/sonic-platform-modules-cel/silverstone-v2/service/silverstone-v2-pddf-platform-monitor.service index 233971ae784d..a63f5fe71ccd 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/service/belgite-pddf-platform-monitor.service +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/service/silverstone-v2-pddf-platform-monitor.service @@ -1,11 +1,13 @@ [Unit] -Description=Belgite Platform Monitoring service +Description=Silverstone-V2 Platform background monitor service Before=pmon.service After=pddf-platform-init.service DefaultDependencies=no [Service] -ExecStart=/usr/local/bin/belgite_pddf_monitor.py +ExecStart=/usr/local/bin/pddf_fan_control_sensor_refresh.py +Restart=always +RestartSec=30s KillSignal=SIGKILL SuccessExitStatus=SIGKILL diff --git a/platform/broadcom/sonic-platform-modules-cel/belgite/systemd/pddf-platform-init.service b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/systemd/pddf-platform-init.service similarity index 89% rename from platform/broadcom/sonic-platform-modules-cel/belgite/systemd/pddf-platform-init.service rename to platform/broadcom/sonic-platform-modules-cel/silverstone-v2/systemd/pddf-platform-init.service index 249fa2e89764..021f7b283a1a 100644 --- a/platform/broadcom/sonic-platform-modules-cel/belgite/systemd/pddf-platform-init.service +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/systemd/pddf-platform-init.service @@ -6,6 +6,7 @@ DefaultDependencies=no [Service] Type=oneshot +ExecStartPre=/usr/local/bin/pre_pddf_init.py ExecStart=/usr/local/bin/pddf_util.py install ExecStop=/usr/local/bin/pddf_util.py clean RemainAfterExit=yes diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/CPUPIDRegulation.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/CPUPIDRegulation.py new file mode 100755 index 000000000000..8ad50341cd9a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/CPUPIDRegulation.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/19 17:01 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Perform fan PWM PID control according to the CPU temperature provided by the Thermal team + +try: + import os + import sys + import getopt + import subprocess + import statistics + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Defaults +FUNCTION_NAME = 'FanControl' +DUTY_MAX = 100 +CPU_TEMP_MAX = 130 +CPU_MAJOR_ALARM = 105 +TEMP_DIFF = 15 # abs(Tk - Tk-1) limit +CPU_TEMPERATURE = "cat /sys/class/thermal/thermal_zone0/temp" + +# PID Defaults Value +PWM_LIST = [35] # [PWMk-1] +T_LIST = [] # [Tk-2, Tk-1, Tk] +Kp = 1.8 +Ki = 0.3 +Kd = 0 +SET_POINT = 96 +PWM_MIN = 35 +PWM_MAX = 100 + + +class CPUPIDRegulation(object): + """ + Make a class we can use to capture stdout and sterr in the log + """ + # static temp var + _ori_temp = 0 + _new_perc = DUTY_MAX / 2 + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + init_fan_temperature = [0, 0] + + def __init__(self): + """Needs a logger and a logger level.""" + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + + @staticmethod + def get_cpu_temperature(): + """ + Get CPU temperature + """ + try: + temp = int(os.popen(CPU_TEMPERATURE).read().strip()) / 1000 + return temp + except Exception: + return False + + def exception_data_handling(self): + """ + Get the temperature of CPU, and confirm whether the obtained value meets the conditions: + 1. The temperature range is 0~130; + 2. The temperature difference from the last time is within 15 + Otherwise, loop 5 times to get the temperature value again: + 1. if can't get the int value of temperature, return False; + 2. all temperatures are int, return the temperatures average value + """ + re_try = False + cpu_temp = self.get_cpu_temperature() + if cpu_temp is False: + re_try = True + elif cpu_temp not in range(CPU_TEMP_MAX+1): + re_try = True + elif T_LIST and abs(cpu_temp - T_LIST[-1]) > TEMP_DIFF: + re_try = True + + if re_try: + error_temp_list = list() + for _ in range(5): + cpu_temp = self.get_cpu_temperature() + if (type(cpu_temp) is int) and \ + (cpu_temp in range(CPU_TEMP_MAX+1)) and \ + (abs(cpu_temp - T_LIST[-1]) <= TEMP_DIFF): + return cpu_temp + else: + error_temp_list.append(cpu_temp) + if False in error_temp_list: + return False + return statistics.mean(error_temp_list) + return cpu_temp + + def pid_control(self): + """ + PID adjustment according to Switch Internal Temperature + :return: fans pwm + """ + cpu_temp = self.exception_data_handling() + if not cpu_temp: + return DUTY_MAX + if cpu_temp >= CPU_MAJOR_ALARM: + self.syslog.warning("High temperature warning: CPU temperature %sC, Major Alarm %sC" + % (cpu_temp, CPU_MAJOR_ALARM)) + if len(T_LIST) < 2: + T_LIST.append(float(cpu_temp)) + return PWM_LIST[0] + else: + T_LIST.append(float(cpu_temp)) + pwm_k = PWM_LIST[0] + Kp * (T_LIST[2] - T_LIST[1]) + \ + Ki * (T_LIST[2] - SET_POINT) + \ + Kd * (T_LIST[2] - 2 * T_LIST[1] + T_LIST[0]) + if pwm_k < PWM_MIN: + pwm_k = PWM_MIN + elif pwm_k > PWM_MAX: + pwm_k = PWM_MAX + PWM_LIST[0] = pwm_k + T_LIST.pop(0) + return pwm_k diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanControl.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanControl.py new file mode 100755 index 000000000000..f7fe5e82b898 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanControl.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/19 17:44 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Fan control strategy main program + +try: + import re + import os + import sys + import getopt + import subprocess + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform + from . import CPUPIDRegulation + from . import FanLinearAdjustment + from . import SwitchInternalPIDRegulation +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +FUNCTION_NAME = "FanControl" +ERROR_COLOR = "amber" +NORMAL_COLOR = "green" +DUTY_MAX = 100 +FAN_NUMBER = 7 +PSU_NUMBER = 2 +SENSOR_NUMBER = 6 +Fan_Front_MAX = 40000 +Fan_Front_MIN = 7800 +Fan_Rear_MAX = 37800 +Fan_Rear_MIN = 6600 + + +class FanControl(object): + """ + Make a class we can use to capture stdout in the log + """ + # static temp var + _ori_temp = 0 + _new_perc = DUTY_MAX / 2 + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + init_fan_temperature = [0, 0] + + def __init__(self): + self.FanLinearAdjustment = FanLinearAdjustment.FanLinearAdjustment(DUTY_MAX, FAN_NUMBER, PSU_NUMBER, SENSOR_NUMBER) + self.SwitchInternalPIDRegulation = SwitchInternalPIDRegulation.SwitchInternalPIDRegulation() + self.CPUPIDRegulation = CPUPIDRegulation.CPUPIDRegulation() + # Needs a logger and a logger level + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + + def get_psu_status(self, fan_duty_list): + """ + Get PSU Status.If one PSU not OK, all of the fans pwm will increase to 100 + :param fan_duty_list: A list.TO app the fans target pwm + """ + psu_presence_list = [True, True] + try: + pus_info = os.popen("i2cget -y -f 100 0x0d 0x60").read().strip() + psus_present = bin(int(pus_info, 16))[6:8] + for psu_index in range(PSU_NUMBER): + psu_presence = True if psus_present[psu_index] == "0" else False + if not psu_presence: + psu_presence_list[psu_index] = False + self.syslog.warning( + "psu%s was error,presence:%s" % (psu_index + 1, str(psu_presence))) + else: + psu_presence_list[psu_index] = True + if False in psu_presence_list: + fan_duty_list.append(DUTY_MAX) + except Exception: + pass + + def get_fan_status(self): + """ + Get all of fans status(fan drawer) + :return: A list indicating the status of all groups fans + """ + fan_presence_list = [True, True, True, True, True, True, True] # Default state: fans are OK + for fan_drawer_index in range(FAN_NUMBER): + try: + fan_presence = self.platform_chassis_obj.get_fan_drawer(fan_drawer_index).get_presence() + fan_status = self.platform_chassis_obj.get_fan_drawer(fan_drawer_index).get_status() + if not all([fan_presence, fan_status]): + fan_presence_list[fan_drawer_index] = False + self.syslog.warning("Fan Drawer-%s has error,presence:%s, status:%s" + % (fan_drawer_index + 1, fan_presence, fan_status)) + except Exception: + pass + return fan_presence_list + + def check_fans_presence(self): + """ + check all fans presence or not + """ + fans_inserted_list = self.get_fan_status() + fans_inserted_num = fans_inserted_list.count(True) + if fans_inserted_num == 0: # all fans broken, cpld will power off + self.syslog.critical("No fans inserted!!! Severe overheating hazard. " + "Please insert Fans immediately or power off the device") + + def set_fans_pwm_by_rpm(self, fan_duty_list): + """ + Set fans pwm by fans rpm. If all fans normal or 1 fan broken, + manage the fans follow thermal policy. + More than 1 fans broken, Will increase the fan speed to 100% + :param fan_duty_list: A list.TO app the fans target pwm + """ + fan_rpm_error_list = list() + for fan in self.platform_chassis_obj.get_all_fans(): + fan_name = fan.get_name() + fan_speed_rpm = fan.get_speed_rpm() + if fan_name.endswith("1") and (fan_speed_rpm not in range(Fan_Front_MIN, Fan_Front_MAX + 1)): + fan_rpm_error_list.append(fan_name) + if fan_name.endswith("2") and (fan_speed_rpm not in range(Fan_Rear_MIN, Fan_Rear_MAX + 1)): + fan_rpm_error_list.append(fan_name) + if not fan_rpm_error_list: + for fan_drawer_index in range(FAN_NUMBER): + self.platform_chassis_obj.get_fan_drawer(fan_drawer_index).set_status_led(NORMAL_COLOR) + return None + if len(fan_rpm_error_list) >= 2: + self.syslog.warning("%s rpm less than the set minimum speed. " + "Will increase the fan speed to 100%%" % fan_rpm_error_list) + fan_duty_list.append(DUTY_MAX) + else: + self.syslog.warning("%s rpm less than the set minimum speed. Fans pwm isn't changed" % fan_rpm_error_list) + + fan_modules_index_list = list(set(int(re.findall(r"Fantray(\d)_\d", x)[0]) for x in fan_rpm_error_list)) + for error_fan_drawer in fan_modules_index_list: + self.platform_chassis_obj.get_fan_drawer(error_fan_drawer-1).set_status_led(ERROR_COLOR) + + self.syslog.warning("The STA front panel light will be set to %s" % ERROR_COLOR) + self.platform_chassis_obj.set_status_led(ERROR_COLOR) + + def get_linear_pid_pwm(self, fan_duty_list): + """ + Get the pwm value of liner regulation, cpu pid adjustment, switch internal pid adjustment + :param fan_duty_list: A list.TO app the fans target pwm + """ + linear_regulation = self.FanLinearAdjustment.linear_control() + cpu_pid_adjustment = self.CPUPIDRegulation.pid_control() + sw_pid_adjustment = self.SwitchInternalPIDRegulation.pid_control() + fan_duty_list.append(linear_regulation) + fan_duty_list.append(cpu_pid_adjustment) + fan_duty_list.append(sw_pid_adjustment) + + def manage_fans(self): + """ + Set the fan speed according to the Fan Control Strategy + """ + fan_duty_speed_list = list() + + # Fan speed setting judgment-PSU + self.get_psu_status(fan_duty_speed_list) + + # Fan speed setting judgment-FAN presence + self.check_fans_presence() + + # Fan speed setting judgment-FAN SPEED + self.set_fans_pwm_by_rpm(fan_duty_speed_list) + + # Fan speed setting judgment-linear and cpu pid and sw pid + self.get_linear_pid_pwm(fan_duty_speed_list) + + self._new_perc = max(fan_duty_speed_list) + if self._new_perc < 35: + self._new_perc = 35 + if self._new_perc > 100: + self._new_perc = 100 + + for fan in self.platform_chassis_obj.get_all_fans(): + fan.set_speed(self._new_perc) + + +def handler(signum, frame): + logging.warning('Cause signal %d, will set all fan speed to max.' % signum) + platform_chassis = platform.Platform().get_chassis() + set_error = list() + fan_index = 1 + for fan in platform_chassis.get_all_fans(): + set_stat = fan.set_speed(DUTY_MAX) + fan_drawer = fan_index//2 + if not set_stat: + set_error.append(fan_drawer) + fan_index += 1 + if set_error: + logging.error('Fail. Set Fantray %s to (%d) failed' % (list(set(set_error)), DUTY_MAX)) + sys.exit(0) + + +def main(): + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = FanControl() + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(2) diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanLinearAdjustment.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanLinearAdjustment.py new file mode 100755 index 000000000000..fac9ba9253ff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/FanLinearAdjustment.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/16 17:00 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Fan PWM confirmation according to Thermal team's fan linear control strategy + +try: + import sys + import getopt + import subprocess + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Defaults +FUNCTION_NAME = "FanControl" + + +class FanLinearAdjustment(object): + """ + Make a class we can use to capture stdout in the log + """ + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + init_fan_temperature = [0, 0] + + def __init__(self, duty_max, fan_num, psu_num, sensor_num): + self.duty_max = duty_max + self.fan_num = fan_num + self.psu_num = psu_num + self.sensor_num = sensor_num + self.last_pwm = 0 + # Needs a logger and a logger level + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + + def get_all_temperature(self): + """ + Get U16 and U17 temperature by thermal API + return: [TEMP_SW_U16 temperature, TEMP_FB_U17 temperature] + """ + all_temperature_list = list() + for sensor_index in range(self.sensor_num): + temp = self.platform_chassis_obj.get_thermal(sensor_index).get_temperature() + if temp is None or str(temp).strip() == "": + for count in range(5): # retry to get the temperature + temp = self.platform_chassis_obj.get_thermal(sensor_index).get_temperature() + try: + float(temp) + break + except ValueError: + pass + else: + return None + all_temperature_list.append(temp) + u16_temperature = all_temperature_list[4] + u17_temperature = all_temperature_list[5] + return [u16_temperature, u17_temperature] + + def get_fan_pwm_by_temperature(self, temp_list): + """ + According to the sensor temperature, the temperature rise and fall are judged, + and the fan speed with the highest speed is selected + :param temp_list: Sensor temperature list + :return: According to the sensor temperature, select the maximum expected fan value at each point(int) + """ + fan_direction = "NA" + for fan in self.platform_chassis_obj.get_all_fans(): + fan_status = fan.get_status() + if fan_status: + fan_direction = fan.get_direction() + break + all_temp = self.get_all_temperature() + if all_temp is None: + # According to Thermal suggestion, when the temperature can't be + # obtained, set the fan to full speed + self.syslog.warning("Can't get TEMP_FB_U17/TEMP_SW_U16, Will increase the fan speed to 100%%") + return self.duty_max + + # B2F=intake: U17 temperature, F2B-EXHAUST: U16 temperature + sensor_index = 1 if fan_direction.lower() == "intake" else 0 + sensor_temp = float(all_temp[sensor_index]) + update_temp_sensor = True + diff_temp = temp_list[sensor_index] - all_temp[sensor_index] + if diff_temp > 0: + update_temp_sensor = False + + if sensor_index == 0: + if not update_temp_sensor: # U16 temperature down + b = 919 / 6 + if sensor_temp <= 37: + sensor_temp_pwm = 38 + elif sensor_temp >= 49: + sensor_temp_pwm = self.duty_max + else: + sensor_temp_pwm = int((31 / 6) * sensor_temp - b) + else: # U16 temperature up + b = 506 / 3 + if sensor_temp <= 40: + sensor_temp_pwm = 38 + elif sensor_temp >= 52: + sensor_temp_pwm = self.duty_max + else: + sensor_temp_pwm = int((31 / 6) * sensor_temp - b) + return self.choose_pwm(update_temp_sensor, self.last_pwm, sensor_temp_pwm) + else: + if not update_temp_sensor: # U17 temperature down + b = 20 + if sensor_temp <= 23: + sensor_temp_pwm = 40 + elif sensor_temp >= 46: + sensor_temp_pwm = self.duty_max + else: + sensor_temp_pwm = int((60 / 23) * sensor_temp - b) + else: # U17 temperature up + b = 640 / 23 + if sensor_temp <= 23: + sensor_temp_pwm = 40 + elif sensor_temp >= 49: + sensor_temp_pwm = self.duty_max + else: + sensor_temp_pwm = int((60 / 23) * sensor_temp - b) + return self.choose_pwm(update_temp_sensor, self.last_pwm, sensor_temp_pwm) + + @staticmethod + def choose_pwm(status, last_pwm, now_pwm): + """ + choose the pwm with Thermal rules + :param status: Temperature rises (True) or falls(False) + :param last_pwm:last pwm value + :param now_pwm:Calculated pwm from current temperature + :return:int.The pwm value + """ + if status: + return last_pwm if last_pwm >= now_pwm else now_pwm + else: + return now_pwm if last_pwm >= now_pwm else last_pwm + + def linear_control(self): + """ + According to linear adjustment return the fans pwm + :return: fans pwm + """ + new_perc = self.get_fan_pwm_by_temperature(self.init_fan_temperature) + self.init_fan_temperature = self.get_all_temperature() + self.last_pwm = new_perc + return new_perc diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/SwitchInternalPIDRegulation.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/SwitchInternalPIDRegulation.py new file mode 100755 index 000000000000..96f96b20369a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/SwitchInternalPIDRegulation.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# @Time : 2023/6/19 16:26 +# @Mail : yajiang@celestica.com +# @Author : jiang tao +# @Function: Perform fan PWM PID control according to the Switch Internal temperature provided by the Thermal team + +try: + import os + import sys + import getopt + import subprocess + import statistics + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from sonic_platform import platform +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Defaults +FUNCTION_NAME = 'FanControl' +DUTY_MAX = 100 +SW_TEMP_MAX = 150 +SW_MAJOR_ALARM = 110 +SW_SHUTDOWN = 124 +TEMP_DIFF = 15 # abs(Tk - Tk-1) limit +SWITCH_INTERNAL_PATH = "/sys/devices/platform/fpga_sysfs/getreg" + +# PID Defaults Value +PWM_LIST = [35] # [PWMk-1] +T_LIST = [] # [Tk-2, Tk-1, Tk] +Kp = 3 +Ki = 0.3 +Kd = 0.5 +SET_POINT = 100 +PWM_MIN = 35 +PWM_MAX = 100 + + +class SwitchInternalPIDRegulation(object): + """ + Make a class we can use to capture stdout in the log + """ + _new_perc = DUTY_MAX / 2 + syslog = logging.getLogger("[" + FUNCTION_NAME + "]") + + def __init__(self): + # Needs a logger and a logger level + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address='/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + self.syslog.setLevel(logging.WARNING) + self.syslog.addHandler(sys_handler) + self.platform_chassis_obj = platform.Platform().get_chassis() + + def get_switch_internal_temperature(self): + """ + Get Switch internal temperature + """ + try: + subprocess.run("echo 0x78 > {}".format(SWITCH_INTERNAL_PATH)) + ret,value_1 = subprocess.getstatusoutput("cat {}".format(SWITCH_INTERNAL_PATH)) + value_1 = value_1.strip() + + subprocess.run("echo 0x80 > {}".format(SWITCH_INTERNAL_PATH)) + ret,value_2 = subprocess.getstatusoutput("cat {}".format(SWITCH_INTERNAL_PATH)) + value_2 = value_2.strip() + + freq = int(value_2, 16) + freq = freq * 256 + int(value_1, 16) + temp = (434100 - ((12500000 / freq - 1) * 535)) / 1000 + return int(temp) + except Exception as E: + self.syslog.warning("Can't Get switch internal temperature! Cause:%s" % str(E)) + return False + + def exception_data_handling(self): + """ + Get the temperature of Switch Internal, and confirm whether the obtained value meets the conditions: + 1. The temperature range is 0~150; + 2. The temperature difference from the last time is within 15 + Otherwise, loop 5 times to get the temperature value again: + 1. if can't get the int value of temperature, return False; + 2. all temperatures are int, return the temperatures average value + """ + re_try = False + sw_temp = self.get_switch_internal_temperature() + if sw_temp is False: + re_try = True + elif sw_temp not in range(SW_TEMP_MAX+1): + re_try = True + elif T_LIST and abs(sw_temp - T_LIST[-1]) > TEMP_DIFF: + re_try = True + + if re_try: + error_temp_list = list() + while len(error_temp_list) < 5: + sw_temp = self.get_switch_internal_temperature() + if (type(sw_temp) is int) and \ + (sw_temp in range(SW_TEMP_MAX+1)) and \ + (abs(sw_temp - T_LIST[-1]) <= TEMP_DIFF): + return sw_temp + else: + error_temp_list.append(sw_temp) + if False in error_temp_list: + return False + return statistics.mean(error_temp_list) + return sw_temp + + def pid_control(self): + """ + PID adjustment according to Switch Internal Temperature + :return: fans pwm + """ + sw_temp = self.exception_data_handling() + if not sw_temp: + return DUTY_MAX + sw_temp = sw_temp + 3 + if sw_temp >= SW_MAJOR_ALARM: + self.syslog.warning("High temperature warning: switch internal temperature %sC, Major Alarm %sC" + % (sw_temp, SW_MAJOR_ALARM)) + if sw_temp >= SW_SHUTDOWN: + self.syslog.critical("The Switch Internal temperature exceeds %sC, " + "the Switch board will be powered off. And will reboot now" % SW_SHUTDOWN) + os.popen("i2cset -y -f 100 0x0d 0x40 0x00") + os.popen("i2cset -y -f 100 0x0d 0x40 0x01") + os.popen("reboot") + if len(T_LIST) < 2: + T_LIST.append(float(sw_temp)) + return PWM_LIST[0] + else: + T_LIST.append(float(sw_temp)) + pwm_k = PWM_LIST[0] + Kp * (T_LIST[2] - T_LIST[1]) + \ + Ki * (T_LIST[2] - SET_POINT) + \ + Kd * (T_LIST[2] - 2 * T_LIST[1] + T_LIST[0]) + if pwm_k < PWM_MIN: + pwm_k = PWM_MIN + elif pwm_k > PWM_MAX: + pwm_k = PWM_MAX + PWM_LIST[0] = pwm_k + T_LIST.pop(0) + return pwm_k diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/__init__.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/__init__.py new file mode 100755 index 000000000000..fd2df8085779 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/FanControl/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*-# + +# @Time : 2023/6/20 16:01 +# @Mail : yajiang@celestica.com +# @Author : jiang tao diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_fan_control_sensor_refresh.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_fan_control_sensor_refresh.py new file mode 100755 index 000000000000..d2e2b7f271f4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_fan_control_sensor_refresh.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*-# + +# @Time : 2023/7/31 13:15 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + +import sys +import time +import json +sys.path.append(r"/usr/local/bin") +from FanControl import FanControl +import pddf_sensor_list_refresh + + +pddf_device_path = '/usr/share/sonic/platform/pddf/pddf-device.json' +with open(pddf_device_path) as f: + json_data = json.load(f) +bmc_present = json_data["PLATFORM"]["bmc_present"] +# Wait for a while to ensure that the corresponding system files are ready +time.sleep(30) +if bmc_present == "False": + FanControl.main() + +if bmc_present == "True": + pddf_sensor_list_refresh.main() diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_sensor_list_refresh.py b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_sensor_list_refresh.py new file mode 100755 index 000000000000..a320878bd242 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/utils/pddf_sensor_list_refresh.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*-# + +# @Time : 2023/4/13 9:46 +# @Mail : yajiang@celestica.com +# @Author : jiang tao + +import os +import time + +try: + from sonic_platform import sensor_list_config + from sonic_py_common import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +sensor_info_path = sensor_list_config.Sensor_List_Info +refresh_interval = sensor_list_config.Sensor_Info_Update_Period_Secs + +log = logger.Logger() + + +def write_sensor_list_info(): + """ + Write the log of the command 'ipmitool sensor list' in sensor_info.log + """ + try: + info = os.popen("ipmitool sensor list").read() + if "System_Event" in info: + with open(sensor_info_path, "w") as f: + f.write(info) + except Exception as E: + log.log_error(str(E)) + + +def main(): + while 1: + write_sensor_list_info() + time.sleep(refresh_interval) diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf b/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf index cb8dcf640ba3..001538945867 100644 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf @@ -9,7 +9,7 @@ i2c-ismt i2c-dev i2c-mux i2c-smbus +coretemp -i2c-mux-pca954x ipmi_devintf -ipmi_si \ No newline at end of file +ipmi_si diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile index f6ad4d9ba4d1..44b9b6147e57 100644 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile @@ -1 +1 @@ -obj-m := baseboard-lpc.o mc24lc64t.o switchboard.o \ No newline at end of file +obj-m := baseboard-lpc.o mc24lc64t.o cls-switchboard.o xcvr-cls.o switch_cpld.o cls-i2c-mux-pca954x.o diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c index b6291f7d3ce4..50f9e2d886bc 100644 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c @@ -98,7 +98,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr, c mutex_lock(&cpld_data->cpld_lock); version = inb(VERSION_ADDR); mutex_unlock(&cpld_data->cpld_lock); - return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F); + return sprintf(buf, "%x.%x\n", version >> 4, version & 0x0F); } static DEVICE_ATTR_RO(version); @@ -430,4 +430,4 @@ module_exit(cpld_b_exit); MODULE_AUTHOR("Celestica Inc."); MODULE_DESCRIPTION("Celestica Silverstone CPLD baseboard driver"); MODULE_VERSION("0.2.0"); -MODULE_LICENSE("GPL"); \ No newline at end of file +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-i2c-mux-pca954x.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-i2c-mux-pca954x.c new file mode 100644 index 000000000000..87c51c15ad97 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-i2c-mux-pca954x.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * I2C multiplexer + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This module supports the PCA954x and PCA984x series of I2C multiplexer/switch + * chips made by NXP Semiconductors. + * This includes the: + * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547, + * PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849. + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cls-pca954x.h" + +#define PCA954X_MAX_NCHANS 8 + +#define PCA954X_IRQ_OFFSET 4 + +enum pca_type { + pca_9540, + pca_9542, + pca_9543, + pca_9544, + pca_9545, + pca_9546, + pca_9547, + pca_9548, + pca_9846, + pca_9847, + pca_9848, + pca_9849, +}; + +struct chip_desc { + u8 nchans; + u8 enable; /* used for muxes only */ + u8 has_irq; + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi + } muxtype; + struct i2c_device_identity id; +}; + +struct pca954x { + const struct chip_desc *chip; + + u8 last_chan; /* last register value */ + /* MUX_IDLE_AS_IS, MUX_IDLE_DISCONNECT or >= 0 for channel */ + s32 idle_state; + + 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, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9542] = { + .nchans = 2, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9543] = { + .nchans = 2, + .has_irq = 1, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9544] = { + .nchans = 4, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9545] = { + .nchans = 4, + .has_irq = 1, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9546] = { + .nchans = 4, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9547] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9548] = { + .nchans = 8, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [pca_9846] = { + .nchans = 4, + .muxtype = pca954x_isswi, + .id = { + .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS, + .part_id = 0x10b, + }, + }, + [pca_9847] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + .id = { + .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS, + .part_id = 0x108, + }, + }, + [pca_9848] = { + .nchans = 8, + .muxtype = pca954x_isswi, + .id = { + .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS, + .part_id = 0x10a, + }, + }, + [pca_9849] = { + .nchans = 4, + .enable = 0x4, + .muxtype = pca954x_ismux, + .id = { + .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS, + .part_id = 0x109, + }, + }, +}; + +static const struct i2c_device_id pca954x_id[] = { + { "cls_pca9540", pca_9540 }, + { "cls_pca9542", pca_9542 }, + { "cls_pca9543", pca_9543 }, + { "cls_pca9544", pca_9544 }, + { "cls_pca9545", pca_9545 }, + { "cls_pca9546", pca_9546 }, + { "cls_pca9547", pca_9547 }, + { "cls_pca9548", pca_9548 }, + { "cls_pca9846", pca_9846 }, + { "cls_pca9847", pca_9847 }, + { "cls_pca9848", pca_9848 }, + { "cls_pca9849", pca_9849 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +static const struct of_device_id pca954x_of_match[] = { + { .compatible = "nxp,cls_pca9540", .data = &chips[pca_9540] }, + { .compatible = "nxp,cls_pca9542", .data = &chips[pca_9542] }, + { .compatible = "nxp,cls_pca9543", .data = &chips[pca_9543] }, + { .compatible = "nxp,cls_pca9544", .data = &chips[pca_9544] }, + { .compatible = "nxp,cls_pca9545", .data = &chips[pca_9545] }, + { .compatible = "nxp,cls_pca9546", .data = &chips[pca_9546] }, + { .compatible = "nxp,cls_pca9547", .data = &chips[pca_9547] }, + { .compatible = "nxp,cls_pca9548", .data = &chips[pca_9548] }, + { .compatible = "nxp,cls_pca9846", .data = &chips[pca_9846] }, + { .compatible = "nxp,cls_pca9847", .data = &chips[pca_9847] }, + { .compatible = "nxp,cls_pca9848", .data = &chips[pca_9848] }, + { .compatible = "nxp,cls_pca9849", .data = &chips[pca_9849] }, + {} +}; +MODULE_DEVICE_TABLE(of, pca954x_of_match); + +/* 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) +{ + union i2c_smbus_data dummy; + + return __i2c_smbus_xfer(adap, client->addr, client->flags, + I2C_SMBUS_WRITE, val, + I2C_SMBUS_BYTE, &dummy); +} + +static u8 pca954x_regval(struct pca954x *data, u8 chan) +{ + /* We make switches look like muxes, not sure how to be smarter. */ + if (data->chip->muxtype == pca954x_ismux) + return chan | data->chip->enable; + else + return 1 << chan; +} + +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; + u8 regval; + int ret = 0; + + regval = pca954x_regval(data, chan); + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = pca954x_reg_write(muxc->parent, client, regval); + data->last_chan = ret < 0 ? 0 : regval; + } + + 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; + s32 idle_state; + + idle_state = READ_ONCE(data->idle_state); + if (idle_state >= 0) + /* Set the mux back to a predetermined channel */ + return pca954x_select_chan(muxc, idle_state); + + if (idle_state == MUX_IDLE_DISCONNECT) { + /* Deselect active channel */ + data->last_chan = 0; + return pca954x_reg_write(muxc->parent, client, + data->last_chan); + } + + /* otherwise leave as-is */ + + return 0; +} + +static ssize_t idle_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + + return sprintf(buf, "%d\n", READ_ONCE(data->idle_state)); +} + +static ssize_t idle_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int val; + int ret; + + ret = kstrtoint(buf, 0, &val); + if (ret < 0) + return ret; + + if (val != MUX_IDLE_AS_IS && val != MUX_IDLE_DISCONNECT && + (val < 0 || val >= data->chip->nchans)) + return -EINVAL; + + i2c_lock_bus(muxc->parent, I2C_LOCK_SEGMENT); + + WRITE_ONCE(data->idle_state, val); + /* + * Set the mux into a state consistent with the new + * idle_state. + */ + if (data->last_chan || val != MUX_IDLE_DISCONNECT) + ret = pca954x_deselect_mux(muxc, 0); + + i2c_unlock_bus(muxc->parent, I2C_LOCK_SEGMENT); + + return ret < 0 ? ret : count; +} + +static DEVICE_ATTR_RW(idle_state); + +static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) +{ + struct pca954x *data = dev_id; + unsigned long pending; + int ret, i; + + ret = i2c_smbus_read_byte(data->client); + if (ret < 0) + return IRQ_NONE; + + pending = (ret >> PCA954X_IRQ_OFFSET) & (BIT(data->chip->nchans) - 1); + for_each_set_bit(i, &pending, data->chip->nchans) + handle_nested_irq(irq_linear_revmap(data->irq, i)); + + return IRQ_RETVAL(pending); +} + +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_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, 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); + if (!irq) { + dev_err(&client->dev, "failed irq create map\n"); + return -EINVAL; + } + irq_set_chip_data(irq, data); + irq_set_chip_and_handler(irq, &pca954x_irq_chip, + handle_simple_irq); + } + + return 0; +} + +static void pca954x_cleanup(struct i2c_mux_core *muxc) +{ + 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); +} + +static int pca954x_init(struct i2c_client *client, struct pca954x *data) +{ + int ret; + + if (data->idle_state >= 0) + data->last_chan = pca954x_regval(data, data->idle_state); + else + data->last_chan = 0; /* Disconnect multiplexer */ + + ret = i2c_smbus_write_byte(client, data->last_chan); + if (ret < 0) + data->last_chan = 0; + + return ret; +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_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 device *dev = &client->dev; + struct gpio_desc *gpio; + struct i2c_mux_core *muxc; + struct pca954x *data; + int num, force; + int ret; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, 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; + + /* Reset the mux if a reset GPIO is specified. */ + gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + if (gpio) { + udelay(1); + gpiod_set_value_cansleep(gpio, 0); + /* Give the chip some time to recover. */ + udelay(1); + } + + data->chip = device_get_match_data(dev); + if (!data->chip) + data->chip = &chips[id->driver_data]; + + if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) { + struct i2c_device_identity id; + + ret = i2c_get_device_id(client, &id); + if (ret && ret != -EOPNOTSUPP) + return ret; + + if (!ret && + (id.manufacturer_id != data->chip->id.manufacturer_id || + id.part_id != data->chip->id.part_id)) { + dev_warn(dev, "unexpected device id %03x-%03x-%x\n", + id.manufacturer_id, id.part_id, + id.die_revision); + return -ENODEV; + } + } + + data->idle_state = MUX_IDLE_AS_IS; + if (device_property_read_u32(dev, "idle-state", &data->idle_state)) { + if (device_property_read_bool(dev, "i2c-mux-idle-disconnect")) + data->idle_state = MUX_IDLE_DISCONNECT; + } + + /* + * Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to a channel + * or disconnected state. + */ + ret = pca954x_init(client, data); + if (ret < 0) { + dev_warn(dev, "probe failed\n"); + return -ENODEV; + } + + ret = pca954x_irq_setup(muxc); + if (ret) + goto fail_cleanup; + + /* Now create an adapter for each channel */ + for (num = 0; num < data->chip->nchans; num++) { + force = 0; /* dynamic adap number */ + if (pdata) { + if (num < pdata->num_modes) { + /* force static number */ + force = pdata->modes[num].adap_id; + } else + /* discard unconfigured channels */ + break; + } + + ret = i2c_mux_add_adapter(muxc, force, num, 0); + if (ret) + goto fail_cleanup; + } + + if (data->irq) { + ret = devm_request_threaded_irq(dev, data->client->irq, + NULL, pca954x_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, + "pca954x", data); + if (ret) + goto fail_cleanup; + } + + /* + * The attr probably isn't going to be needed in most cases, + * so don't fail completely on error. + */ + device_create_file(dev, &dev_attr_idle_state); + + dev_info(dev, "registered %d multiplexed busses for I2C %s %s\n", + num, data->chip->muxtype == pca954x_ismux + ? "mux" : "switch", client->name); + + return 0; + +fail_cleanup: + pca954x_cleanup(muxc); + return ret; +} + +static void pca954x_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + device_remove_file(&client->dev, &dev_attr_idle_state); + + pca954x_cleanup(muxc); +} + +#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); + int ret; + + ret = pca954x_init(client, data); + if (ret < 0) + dev_err(&client->dev, "failed to verify mux presence\n"); + + return ret; +} +#endif + +static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume); + +static struct i2c_driver pca954x_driver = { + .driver = { + .name = "cls_pca954x", + .pm = &pca954x_pm, + .of_match_table = pca954x_of_match, + }, + .probe = pca954x_probe, + .remove = pca954x_remove, + .id_table = pca954x_id, +}; + +module_i2c_driver(pca954x_driver); + +MODULE_AUTHOR("Rodolfo Giometti "); +MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-pca954x.h b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-pca954x.h new file mode 100644 index 000000000000..2aaacf97cbac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-pca954x.h @@ -0,0 +1,44 @@ +/* + * + * cls-pca954x.h - I2C multiplexer/switch support + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * Michael Lawnick + * + * This program is free software; you can 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 _CLS_I2C_PCA954X_H +#define _CLS_I2C_PCA954X_H + +/* Platform data for the PCA954x I2C multiplexers */ + +/* Per channel initialisation data: + * @adap_id: bus number for the adapter. 0 = don't care + * + */ +struct pca954x_platform_mode { + int adap_id; +}; + +/* Per mux/switch data, used with i2c_register_board_info */ +struct pca954x_platform_data { + struct pca954x_platform_mode *modes; + int num_modes; +}; + +#endif /* _CLS_I2C_PCA954X_H */ diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-switchboard.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-switchboard.c new file mode 100644 index 000000000000..35ffc722e5a8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/cls-switchboard.c @@ -0,0 +1,542 @@ +/* + * cls-switchboard.c - PCI device driver for Silverstone Switch board FPGA. + * + * Author: Pradchaya Phucharoen + * + * Copyright (C) 2019 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xcvr-cls.h" +#include "cls-pca954x.h" + +#define MOD_VERSION "2.1.2" +#define DRV_NAME "cls-switchboard" + +#define I2C_MUX_CHANNEL(_ch, _adap_id) \ + [_ch] = { .adap_id = _adap_id } + +#define FPGA_PCIE_DEVICE_ID 0x7021 +#define MMIO_BAR 0 +#define I2C_BUS_OFS 9 + +/* I2C ocore configurations */ +#define OCORE_REGSHIFT 2 +#define OCORE_IP_CLK_khz 62500 +#define OCORE_BUS_CLK_khz 100 +#define OCORE_REG_IO_WIDTH 1 + +/* Optical port xcvr configuration */ +#define XCVR_REG_SHIFT 2 +#define XCVR_NUM_PORT 34 +#define XCVR_PORT_REG_SIZE 0x10 + +/* i2c_bus_config - an i2c-core resource and platform data + * @id - I2C bus device ID, for identification. + * @res - resources for an i2c-core device. + * @num_res - size of the resources. + * @pdata - a platform data of an i2c-core device. + */ +struct i2c_bus_config { + int id; + struct resource *res; + ssize_t num_res; + struct ocores_i2c_platform_data pdata; +}; + +/* switchbrd_priv - switchboard private data */ +struct switchbrd_priv { + unsigned long base; + int num_i2c_bus; + struct platform_device **i2cbuses_pdev; + struct platform_device *regio_pdev; + struct platform_device *spiflash_pdev; + struct platform_device *xcvr_pdev; +}; + +/* I2C bus speed param */ +static int bus_clock_master_1 = 100; +module_param(bus_clock_master_1, int, 0660); +MODULE_PARM_DESC(bus_clock_master_1, + "I2C master 1 bus speed in KHz 50/80/100/200/400"); + +static int bus_clock_master_2 = 100; +module_param(bus_clock_master_2, int, 0660); +MODULE_PARM_DESC(bus_clock_master_2, + "I2C master 2 bus speed in KHz 50/80/100/200/400"); + +static int bus_clock_master_3 = 100; +module_param(bus_clock_master_3, int, 0660); +MODULE_PARM_DESC(bus_clock_master_3, + "I2C master 3 bus speed in KHz 50/80/100/200/400"); + +static int bus_clock_master_4 = 100; +module_param(bus_clock_master_4, int, 0660); +MODULE_PARM_DESC(bus_clock_master_4, + "I2C master 4 bus speed in KHz 50/80/100/200/400"); + +static int bus_clock_master_5 = 100; +module_param(bus_clock_master_5, int, 0660); +MODULE_PARM_DESC(bus_clock_master_5, + "I2C master 5 bus speed in KHz 50/80/100/200/400"); + +// NOTE: Silverstone i2c channel mapping is very wierd!!! +/* PCA9548 channel config on MASTER BUS 3 */ +static struct pca954x_platform_mode i2c_mux_70_modes[] = { + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 23), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 26), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 27), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 28), + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 29), + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 30), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 31), + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 32) +}; + +static struct pca954x_platform_mode i2c_mux_71_modes[] = { + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 1), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 2), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 3), + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 4), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 5), + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 6), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 15), + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 8) +}; + +static struct pca954x_platform_mode i2c_mux_72_modes[] = { + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 17), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 18), + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 19), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 20), + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 21), + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 22), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 25), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 24) +}; + +static struct pca954x_platform_mode i2c_mux_73_modes[] = { + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 9), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 10), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 11), + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 12), + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 13), + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 14), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 7), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 16) +}; + +static struct pca954x_platform_data om_muxes[] = { + { + .modes = i2c_mux_70_modes, + .num_modes = ARRAY_SIZE(i2c_mux_70_modes), + }, + { + .modes = i2c_mux_71_modes, + .num_modes = ARRAY_SIZE(i2c_mux_71_modes), + }, + { + .modes = i2c_mux_72_modes, + .num_modes = ARRAY_SIZE(i2c_mux_72_modes), + }, + { + .modes = i2c_mux_73_modes, + .num_modes = ARRAY_SIZE(i2c_mux_73_modes), + }, +}; + +/* Optical Module bus 3 i2c muxes info */ +static struct i2c_board_info i2c_info_3[] = { + { + I2C_BOARD_INFO("cls_pca9548", 0x70), + .platform_data = &om_muxes[0], + }, + { + I2C_BOARD_INFO("cls_pca9548", 0x71), + .platform_data = &om_muxes[1], + }, + { + I2C_BOARD_INFO("cls_pca9548", 0x72), + .platform_data = &om_muxes[2], + }, + { + I2C_BOARD_INFO("cls_pca9548", 0x73), + .platform_data = &om_muxes[3], + }, +}; + +/* RESOURCE SEPERATES BY FUNCTION */ +/* Resource IOMEM for i2c bus 1 */ +static struct resource cls_i2c_res_1[] = { + { + .start = 0x800, .end = 0x81F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 2 */ +static struct resource cls_i2c_res_2[] = { + { + .start = 0x820, .end = 0x83F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 3 */ +static struct resource cls_i2c_res_3[] = { + { + .start = 0x840, .end = 0x85F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 4 */ +static struct resource cls_i2c_res_4[] = { + { + .start = 0x860, .end = 0x87F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 5 */ +static struct resource cls_i2c_res_5[] = { + { + .start = 0x880, .end = 0x89F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for reg access */ +static struct resource reg_io_res[] = { + { + .start = 0x00, .end = 0xFF, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for spi flash firmware upgrade */ +static struct resource spi_flash_res[] = { + { + .start = 0x1200, .end = 0x121F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for front panel XCVR */ +static struct resource xcvr_res[] = { + { + .start = 0x4000, .end = 0x421F, + .flags = IORESOURCE_MEM,}, +}; + +static struct i2c_bus_config i2c_bus_configs[] = { + { + .id = 1, + .res = cls_i2c_res_1, + .num_res = ARRAY_SIZE(cls_i2c_res_1), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, + { + .id = 2, + .res = cls_i2c_res_2, + .num_res = ARRAY_SIZE(cls_i2c_res_2), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, + { + .id = 3, + .res = cls_i2c_res_3, + .num_res = ARRAY_SIZE(cls_i2c_res_3), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = ARRAY_SIZE(i2c_info_3), + .devices = i2c_info_3, + }, + }, + { + .id = 4, + .res = cls_i2c_res_4, + .num_res = ARRAY_SIZE(cls_i2c_res_4), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, + { + .id = 5, + .res = cls_i2c_res_5, + .num_res = ARRAY_SIZE(cls_i2c_res_5), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, +}; + +/* xcvr front panel mapping */ +static struct port_info front_panel_ports[] = { + {"QSFP1", 1, QSFP}, + {"QSFP2", 2, QSFP}, + {"QSFP3", 3, QSFP}, + {"QSFP4", 4, QSFP}, + {"QSFP5", 5, QSFP}, + {"QSFP6", 6, QSFP}, + {"QSFP7", 7, QSFP}, + {"QSFP8", 8, QSFP}, + {"QSFP9", 9, QSFP}, + {"QSFP10", 10, QSFP}, + {"QSFP11", 11, QSFP}, + {"QSFP12", 12, QSFP}, + {"QSFP13", 13, QSFP}, + {"QSFP14", 14, QSFP}, + {"QSFP15", 15, QSFP}, + {"QSFP16", 16, QSFP}, + {"QSFP17", 17, QSFP}, + {"QSFP18", 18, QSFP}, + {"QSFP19", 19, QSFP}, + {"QSFP20", 20, QSFP}, + {"QSFP21", 21, QSFP}, + {"QSFP22", 22, QSFP}, + {"QSFP23", 23, QSFP}, + {"QSFP24", 24, QSFP}, + {"QSFP25", 25, QSFP}, + {"QSFP26", 26, QSFP}, + {"QSFP27", 27, QSFP}, + {"QSFP28", 28, QSFP}, + {"QSFP29", 29, QSFP}, + {"QSFP30", 30, QSFP}, + {"QSFP31", 31, QSFP}, + {"QSFP32", 32, QSFP}, + {"SFP1", 33, SFP}, + {"SFP2", 34, SFP} + /* END OF LIST */ +}; + +static struct cls_xcvr_platform_data xcvr_data = { + .port_reg_size = 0x10, + .num_ports = ARRAY_SIZE(front_panel_ports), + .devices = front_panel_ports, +}; + + +// TODO: Add a platform configuration struct, and use probe as a factory, +// so xcvr, fwupgrade device can configured as options. + +static int cls_fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + + struct switchbrd_priv *priv; + struct platform_device **i2cbuses_pdev; + struct platform_device *regio_pdev; + struct platform_device *xcvr_pdev; + unsigned long rstart; + int num_i2c_bus, i; + int err; + + err = pci_enable_device(dev); + if (err){ + dev_err(&dev->dev, "Failed to enable PCI device\n"); + goto err_exit; + } + + /* Check for valid MMIO address */ + rstart = pci_resource_start(dev, MMIO_BAR); + if (!rstart) { + dev_err(&dev->dev, "Switchboard base address uninitialized, " + "check FPGA\n"); + err = -ENODEV; + goto err_disable_device; + } + + dev_dbg(&dev->dev, "BAR%d res: 0x%lx-0x%llx\n", MMIO_BAR, + rstart, pci_resource_end(dev, MMIO_BAR)); + + priv = devm_kzalloc(&dev->dev, + sizeof(struct switchbrd_priv), GFP_KERNEL); + if (!priv){ + err = -ENOMEM; + goto err_disable_device; + } + + pci_set_drvdata(dev, priv); + num_i2c_bus = ARRAY_SIZE(i2c_bus_configs); + i2cbuses_pdev = devm_kzalloc( + &dev->dev, + num_i2c_bus * sizeof(struct platform_device*), + GFP_KERNEL); + + reg_io_res[0].start += rstart; + reg_io_res[0].end += rstart; + + xcvr_res[0].start += rstart; + xcvr_res[0].end += rstart; + + regio_pdev = platform_device_register_resndata( + &dev->dev, "cls-swbrd-io", + -1, + reg_io_res, ARRAY_SIZE(reg_io_res), + NULL, 0); + + if (IS_ERR(regio_pdev)) { + dev_err(&dev->dev, "Failed to register cls-swbrd-io\n"); + err = PTR_ERR(regio_pdev); + goto err_disable_device; + } + + xcvr_pdev = platform_device_register_resndata( + NULL, + "cls-xcvr", + -1, + xcvr_res, + ARRAY_SIZE(xcvr_res), + &xcvr_data, + sizeof(xcvr_data)); + + if (IS_ERR(xcvr_pdev)) { + dev_err(&dev->dev, "Failed to register xcvr node\n"); + err = PTR_ERR(xcvr_pdev); + goto err_unregister_regio; + } + + for(i = 0; i < num_i2c_bus; i++){ + + i2c_bus_configs[i].res[0].start += rstart; + i2c_bus_configs[i].res[0].end += rstart; + + switch (i + 1) { + case 1: + i2c_bus_configs[i].pdata.bus_khz = bus_clock_master_1; + break; + case 2: + i2c_bus_configs[i].pdata.bus_khz = bus_clock_master_2; + break; + case 3: + i2c_bus_configs[i].pdata.bus_khz = bus_clock_master_3; + break; + case 4: + i2c_bus_configs[i].pdata.bus_khz = bus_clock_master_4; + break; + case 5: + i2c_bus_configs[i].pdata.bus_khz = bus_clock_master_5; + break; + default: + i2c_bus_configs[i].pdata.bus_khz = OCORE_BUS_CLK_khz; + } + + dev_dbg(&dev->dev, "i2c-bus.%d: 0x%llx - 0x%llx\n", + i2c_bus_configs[i].id, + i2c_bus_configs[i].res[0].start, + i2c_bus_configs[i].res[0].end); + + i2cbuses_pdev[i] = platform_device_register_resndata( + &dev->dev, "ocores-i2c", + i2c_bus_configs[i].id, + i2c_bus_configs[i].res, + i2c_bus_configs[i].num_res, + &i2c_bus_configs[i].pdata, + sizeof(i2c_bus_configs[i].pdata)); + + if (IS_ERR(i2cbuses_pdev[i])) { + dev_err(&dev->dev, "Failed to register ocores-i2c.%d\n", + i2c_bus_configs[i].id); + err = PTR_ERR(i2cbuses_pdev[i]); + goto err_unregister_ocore; + } + } + + priv->base = rstart; + priv->num_i2c_bus = num_i2c_bus; + priv->i2cbuses_pdev = i2cbuses_pdev; + priv->regio_pdev = regio_pdev; + priv->xcvr_pdev = xcvr_pdev; + return 0; + +err_unregister_ocore: + for(i = 0; i < num_i2c_bus; i++){ + if(priv->i2cbuses_pdev[i]){ + platform_device_unregister(priv->i2cbuses_pdev[i]); + } + } +err_unregister_xcvr: + platform_device_unregister(xcvr_pdev); +err_unregister_regio: + platform_device_unregister(regio_pdev); +err_disable_device: + pci_disable_device(dev); +err_exit: + return err; +} + +static int cls_fpga_remove(struct pci_dev *dev) +{ + int i; + struct switchbrd_priv *priv = pci_get_drvdata(dev); + + for(i = 0; i < priv->num_i2c_bus; i++){ + if(priv->i2cbuses_pdev[i]) + platform_device_unregister(priv->i2cbuses_pdev[i]); + } + platform_device_unregister(priv->xcvr_pdev); + platform_device_unregister(priv->regio_pdev); + pci_disable_device(dev); + return 0; +}; + +static const struct pci_device_id pci_clsswbrd[] = { + { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) }, + {0, } +}; + +MODULE_DEVICE_TABLE(pci, pci_clsswbrd); + +static struct pci_driver clsswbrd_pci_driver = { + .name = DRV_NAME, + .id_table = pci_clsswbrd, + .probe = cls_fpga_probe, + .remove = cls_fpga_remove, +}; + +module_pci_driver(clsswbrd_pci_driver); + +MODULE_AUTHOR("Pradchaya P."); +MODULE_DESCRIPTION("Celestica Silverstone switchboard driver"); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switch_cpld.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switch_cpld.c new file mode 100644 index 000000000000..b1900d03245e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switch_cpld.c @@ -0,0 +1,416 @@ +/* + * switch_cpld.c - i2c driver for Silverstone switchboard CPLD1/CPLD2 + * provides sysfs interfaces to access CPLD register and control port LEDs + * + * Author: Budsakol Sirirattanasakul + * + * Copyright (C) 2019 Celestica Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +#define CPLD1_ADDR 0x30 +#define CPLD2_ADDR 0x31 + +#define SCRATCH_ADDR 0x01 +#define LED_OPMODE 0x09 +#define LED_TEST 0x0A + +struct switch_cpld_data { + struct mutex lock; + struct i2c_client *client; + struct i2c_client *client2; + uint8_t read_addr; +}; + +static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int value; + + value = i2c_smbus_read_byte_data(client, data->read_addr); + if (value < 0) + return value; + + return sprintf(buf, "0x%.2x\n", value); +} + +static ssize_t getreg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + uint8_t value; + ssize_t status; + struct switch_cpld_data *data = dev_get_drvdata(dev); + + status = kstrtou8(buf, 0, &value); + if (status != 0) + return status; + + data->read_addr = value; + + return size; +} + +static ssize_t setreg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + uint8_t addr, value; + ssize_t status; + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + char *tok; + + tok = strsep((char **)&buf, " "); + if (tok == NULL) + return -EINVAL; + status = kstrtou8(tok, 0, &addr); + if (status != 0) + return status; + + tok = strsep((char **)&buf, " "); + if (tok == NULL) + return -EINVAL; + status = kstrtou8(tok, 0, &value); + if (status != 0) + return status; + + status = i2c_smbus_write_byte_data(client, addr, value); + if (status == 0) + status = size; + return status; +} + +static ssize_t scratch_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int value; + + value = i2c_smbus_read_byte_data(client, SCRATCH_ADDR); + if (value < 0) + return value; + + return sprintf(buf, "0x%.2x\n", value); +} + +static ssize_t scratch_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + uint8_t value; + ssize_t status; + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + + status = kstrtou8(buf, 0, &value); + if (status != 0) + return status; + status = i2c_smbus_write_byte_data(client, SCRATCH_ADDR, value); + if (status == 0) + status = size; + return status; +} + +DEVICE_ATTR_RW(getreg); +DEVICE_ATTR_WO(setreg); +DEVICE_ATTR_RW(scratch); + +static struct attribute *switch_cpld_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_scratch.attr, + NULL, +}; +ATTRIBUTE_GROUPS(switch_cpld); + +static ssize_t port_led_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int led_mode_1, led_mode_2; + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client1 = data->client; + struct i2c_client *client2 = data->client2; + + led_mode_1 = i2c_smbus_read_byte_data(client1, LED_OPMODE); + if (led_mode_1 < 0) + return led_mode_1; + + led_mode_2 = i2c_smbus_read_byte_data(client2, LED_OPMODE); + if (led_mode_2 < 0) + return led_mode_2; + + return sprintf(buf, "%s %s\n", + led_mode_1 ? "test" : "normal", + led_mode_2 ? "test" : "normal"); +} + +static ssize_t port_led_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int status; + uint8_t led_mode; + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client1 = data->client; + struct i2c_client *client2 = data->client2; + + if (sysfs_streq(buf, "test")) + led_mode = 0x01; + else if (sysfs_streq(buf, "normal")) + led_mode = 0x00; + else + return -EINVAL; + + status = i2c_smbus_write_byte_data(client1, LED_OPMODE, led_mode); + if (status != 0) { + return status; + } + + status = i2c_smbus_write_byte_data(client2, LED_OPMODE, led_mode); + if (status != 0) { + return status; + } + + return size; +} + +static ssize_t port_led_color_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int led_color1, led_color2; + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client1 = data->client; + struct i2c_client *client2 = data->client2; + + led_color1 = i2c_smbus_read_byte_data(client1, LED_TEST); + if (led_color1 < 0) + return led_color1; + + led_color2 = i2c_smbus_read_byte_data(client2, LED_TEST); + if (led_color2 < 0) + return led_color2; + + return sprintf(buf, "%s %s\n", + led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? + "red" : led_color1 == 0x04 ? + "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : + led_color1 == 0x01 ? "magenta" : "white", + led_color2 == 0x07 ? "off" : led_color2 == 0x06 ? "green" : led_color2 == 0x05 ? + "red" : led_color2 == 0x04 ? + "yellow" : led_color2 == 0x03 ? "blue" : led_color2 == 0x02 ? "cyan" : + led_color2 == 0x01 ? "magenta" : "white"); +} + +static ssize_t port_led_color_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int status; + uint8_t led_color; + struct switch_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client1 = data->client; + struct i2c_client *client2 = data->client2; + + if (sysfs_streq(buf, "off")) + led_color = 0x07; + else if (sysfs_streq(buf, "green")) + led_color = 0x06; + else if (sysfs_streq(buf, "red")) + led_color = 0x05; + else if (sysfs_streq(buf, "yellow")) + led_color = 0x04; + else if (sysfs_streq(buf, "blue")) + led_color = 0x03; + else if (sysfs_streq(buf, "cyan")) + led_color = 0x02; + else if (sysfs_streq(buf, "magenta")) + led_color = 0x01; + else if (sysfs_streq(buf, "white")) + led_color = 0x00; + else + return -EINVAL; + + status = i2c_smbus_write_byte_data(client1, LED_TEST, led_color); + if (status != 0) { + return status; + } + + status = i2c_smbus_write_byte_data(client2, LED_TEST, led_color); + if (status != 0) { + return status; + } + + return size; +} + +DEVICE_ATTR_RW(port_led_mode); +DEVICE_ATTR_RW(port_led_color); + +static struct attribute *sff_led_attrs[] = { + &dev_attr_port_led_mode.attr, + &dev_attr_port_led_color.attr, + NULL, +}; + +static struct attribute_group sff_led_groups = { + .attrs = sff_led_attrs, +}; + +static int switch_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + struct switch_cpld_data *drvdata1, *drvdata2; + struct device *hwmon_dev1, *hwmon_dev2; + struct i2c_client *client2; + + if (client->addr != CPLD1_ADDR) { + dev_err(&client->dev, "probe, bad i2c addr: 0x%x\n", + client->addr); + err = -EINVAL; + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EPFNOSUPPORT; + + /* CPLD1 */ + drvdata1 = devm_kzalloc(&client->dev, + sizeof(struct switch_cpld_data), GFP_KERNEL); + + if (!drvdata1) { + err = -ENOMEM; + goto exit; + } + + mutex_init(&drvdata1->lock); + drvdata1->client = client; + drvdata1->read_addr = 0x00; + i2c_set_clientdata(client, drvdata1); + hwmon_dev1 = devm_hwmon_device_register_with_groups(&client->dev, + "CPLD1", + drvdata1, + switch_cpld_groups); + + if (IS_ERR(hwmon_dev1)) { + err = PTR_ERR(hwmon_dev1); + goto exit; + } + + err = sysfs_create_link(&client->dev.kobj, &hwmon_dev1->kobj, "CPLD1"); + if (err) { + goto exit; + } + + /* CPLD2 */ + drvdata2 = devm_kzalloc(&client->dev, + sizeof(struct switch_cpld_data), GFP_KERNEL); + + if (!drvdata2) { + err = -ENOMEM; + goto err_link; + } + + client2 = i2c_new_dummy_device(client->adapter, CPLD2_ADDR); + if (!client2) { + dev_err(&client->dev, "address 0x%02x unavailable\n", + CPLD2_ADDR); + err = -EADDRINUSE; + goto err_link; + } + + mutex_init(&drvdata2->lock); + drvdata2->read_addr = 0x00; + drvdata2->client = client2; + i2c_set_clientdata(client2, drvdata2); + + /* attach client2 to be client2 of CPLD1 + for later use on port led sysfs */ + drvdata1->client2 = client2; + + hwmon_dev2 = devm_hwmon_device_register_with_groups(&client2->dev, + "CPLD2", + drvdata2, + switch_cpld_groups); + + if (IS_ERR(hwmon_dev2)) { + err = PTR_ERR(hwmon_dev2); + goto err_client2; + } + + err = sysfs_create_link(&client2->dev.kobj, &hwmon_dev2->kobj, "CPLD2"); + if (err) { + goto err_client2; + } + + //port led + err = sysfs_create_group(&client->dev.kobj, &sff_led_groups); + if (err) { + dev_err(&client->dev, + "failed to create sysfs attribute group.\n"); + goto err_link2; + } + + return 0; + +err_link2: + sysfs_remove_link(&client2->dev.kobj, "CPLD2"); + +err_client2: + if (client2) + i2c_unregister_device(client2); + +err_link: + sysfs_remove_link(&client->dev.kobj, "CPLD1"); + +exit: + dev_err(&client->dev, "probe error %d\n", err); + return err; +} + +static void switch_cpld_remove(struct i2c_client *client) +{ + struct switch_cpld_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &sff_led_groups); + sysfs_remove_link(&data->client2->dev.kobj, "CPLD2"); + sysfs_remove_link(&client->dev.kobj, "CPLD1"); + i2c_unregister_device(data->client2); +} + +static const struct i2c_device_id switch_cpld_ids[] = { + { "switch_cpld", 0x30 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, switch_cpld_ids); + +static struct i2c_driver switch_cpld_driver = { + .driver = { + .name = "switch_cpld", + .owner = THIS_MODULE, + }, + .probe = switch_cpld_probe, + .remove = switch_cpld_remove, + .id_table = switch_cpld_ids, +}; + +module_i2c_driver(switch_cpld_driver); + +MODULE_AUTHOR("Budsakol Sirirattanasakul"); +MODULE_DESCRIPTION("Celestica Silverstone Switchboard CPLD driver"); +MODULE_VERSION("1.0.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.c new file mode 100644 index 000000000000..10fda963b9b3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.c @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * xcvr-cls.c - front panel port control. + * + * Pradchaya Phucharoen + * Copyright (C) 2019 Celestica Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "xcvr-cls.h" + +/* FPGA front panel */ +#define PORT_CTRL 0 +#define PORT_STATUS 0x4 +#define PORT_INT_STATUS 0x8 +#define PORT_INT_MASK 0xC + +/* + * Port control degister + * LPMOD : active high, RW + * RST : active low, RW + * TXDIS : active high, RW +*/ +#define CTRL_LPMOD BIT(6) +#define CTRL_RST_L BIT(4) +#define CTRL_TXDIS BIT(0) + +/* + * Port status register + * IRQ : active low, RO + * PRESENT : active low, RO, for QSFP + * TXFAULT : active high, RO + * RXLOS : active high, RO + * MODABS : active high, RO, for SFP +*/ +#define STAT_IRQ_L BIT(5) +#define STAT_PRESENT_L BIT(4) +#define STAT_TXFAULT BIT(2) +#define STAT_RXLOS BIT(1) +#define STAT_MODABS BIT(0) + +/* + * NOTE: Interrupt and mask must be expose as bitfeild. + * Because the registers of interrupt flags are read-clear. + * + * Port interrupt flag resgister + * INT_N : interrupt flag, set when INT_N is assert. + * PRESENT : interrupt flag, set when QSFP module plugin/plugout. + * RXLOS : interrupt flag, set when rxlos is assert. + * MODABS : interrupt flag, set when SFP module plugin/plugout. +*/ +#define INTR_INT_N BIT(5) +#define INTR_PRESENT BIT(4) +#define INTR_TXFAULT BIT(2) +#define INTR_RXLOS BIT(1) +#define INTR_MODABS BIT(0) + +/* + * Port interrupt mask register + * INT_N : active low + * PRESENT : active low + * RXLOS_INT : active low + * MODABS : active low +*/ +#define MASK_INT_N_L BIT(5) +#define MASK_PRESENT_L BIT(4) +#define MASK_TXFAULT_L BIT(2) +#define MASK_RXLOS_L BIT(1) +#define MASK_MODABS_L BIT(0) + + +/* + * port_data - optical port data + * @xcvr: xcvr memory accessor + * @name: port name + * @index: front panel port index starting from 1 + */ +struct port_data { + struct xcvr_priv *xcvr; + const char *name; + unsigned int index; +}; + +/* + * xcvr_priv - port xcvr private data + * @dev: device for reference + * @base: virtual base address + * @num_ports: number of front panel ports + * @fp_devs: list of front panel port devices + */ +struct xcvr_priv { + struct device* dev; + void __iomem *base; + int port_reg_size; + int num_ports; + struct device **fp_devs; +}; + +static inline void port_setreg(struct xcvr_priv *xcvr, int reg, int index, u8 value) +{ + return iowrite8(value, xcvr->base + reg + (index - 1) * xcvr->port_reg_size); +} + +static inline u8 port_getreg(struct xcvr_priv *xcvr, int reg, int index) +{ + return ioread8(xcvr->base + reg + (index - 1) * xcvr->port_reg_size); +} + +static ssize_t qsfp_modprsL_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_STATUS, index); + return sprintf(buf, "%d\n", (data & STAT_PRESENT_L)?1:0); +} + +static ssize_t qsfp_irqL_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_STATUS, index); + return sprintf(buf, "%d\n", (data & STAT_IRQ_L)?1:0); +} + +static ssize_t qsfp_lpmode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_CTRL, index); + return sprintf(buf, "%d\n", (data & CTRL_LPMOD)?1:0); +} + +static ssize_t qsfp_lpmode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + long value; + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + status = kstrtol(buf, 0, &value); + if (status == 0) { + data = port_getreg(port_data->xcvr, PORT_CTRL, index); + if (value == 0) + data &= ~CTRL_LPMOD; + else + data |= CTRL_LPMOD; + port_setreg(port_data->xcvr, PORT_CTRL, index, data); + status = size; + } + return status; +} + +static ssize_t qsfp_resetL_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_CTRL, index); + return sprintf(buf, "%d\n", (data & CTRL_RST_L)?1:0); +} + +static ssize_t qsfp_resetL_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + long value; + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + status = kstrtol(buf, 0, &value); + if (status == 0) { + data = port_getreg(port_data->xcvr, PORT_CTRL, index); + if (value == 0) + data &= ~CTRL_RST_L; + else + data |= CTRL_RST_L; + port_setreg(port_data->xcvr, PORT_CTRL, index, data); + status = size; + } + return status; +} + +static ssize_t sfp_modabs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_STATUS, index); + return sprintf(buf, "%d\n", (data & STAT_MODABS)?1:0); +} + +static ssize_t sfp_txfault_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_STATUS, index); + return sprintf(buf, "%d\n", (data & STAT_TXFAULT)?1:0); +} + +static ssize_t sfp_rxlos_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_STATUS, index); + return sprintf(buf, "%d\n", (data & STAT_RXLOS)?1:0); +} + +static ssize_t sfp_txdisable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_CTRL, index); + return sprintf(buf, "%d\n", (data & CTRL_TXDIS)?1:0); +} + +static ssize_t sfp_txdisable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + long value; + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + status = kstrtol(buf, 0, &value); + if (status == 0) { + data = port_getreg(port_data->xcvr, PORT_CTRL, index); + if (value == 0) + data &= ~CTRL_TXDIS; + else + data |= CTRL_TXDIS; + port_setreg(port_data->xcvr, PORT_CTRL, index, data); + status = size; + } + return status; +} + +static ssize_t interrupt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_INT_STATUS, index); + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t interrupt_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + long value; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + status = kstrtoul(buf, 0, &value); + if (status == 0) { + port_setreg(port_data->xcvr, PORT_INT_STATUS, index, value); + status = size; + } + return status; +} + +static ssize_t interrupt_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + data = port_getreg(port_data->xcvr, PORT_INT_MASK, index); + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t interrupt_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + long value; + struct port_data *port_data = dev_get_drvdata(dev); + unsigned int index = port_data->index; + + status = kstrtoul(buf, 0, &value); + if (status == 0) { + port_setreg(port_data->xcvr, PORT_INT_MASK, index, value); + status = size; + } + return status; +} + +DEVICE_ATTR_RO(qsfp_modprsL); +DEVICE_ATTR_RO(qsfp_irqL); +DEVICE_ATTR_RW(qsfp_lpmode); +DEVICE_ATTR_RW(qsfp_resetL); + +DEVICE_ATTR_RO(sfp_modabs); +DEVICE_ATTR_RO(sfp_txfault); +DEVICE_ATTR_RO(sfp_rxlos); +DEVICE_ATTR_RW(sfp_txdisable); + +DEVICE_ATTR_RW(interrupt); +DEVICE_ATTR_RW(interrupt_mask); + +/* qsfp_attrs */ +static struct attribute *qsfp_attrs[] = { + &dev_attr_qsfp_modprsL.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_resetL.attr, + &dev_attr_interrupt.attr, + &dev_attr_interrupt_mask.attr, + NULL +}; + +/* sfp_attrs */ +static struct attribute *sfp_attrs[] = { + &dev_attr_sfp_modabs.attr, + &dev_attr_sfp_txfault.attr, + &dev_attr_sfp_rxlos.attr, + &dev_attr_sfp_txdisable.attr, + &dev_attr_interrupt.attr, + &dev_attr_interrupt_mask.attr, + NULL +}; + +ATTRIBUTE_GROUPS(qsfp); +ATTRIBUTE_GROUPS(sfp); + +/* A single port device init */ +static struct device* init_port(struct device *dev, + struct xcvr_priv *xcvr, + struct port_info info, + const struct attribute_group **groups) +{ + struct port_data *new_data; + + new_data = devm_kzalloc(dev, sizeof(struct port_data), GFP_KERNEL); + if (!new_data) + return ERR_PTR(-ENOMEM); + + new_data->index = info.index; + new_data->name = info.name; + new_data->xcvr = xcvr; + + return devm_hwmon_device_register_with_groups(dev, + info.name, + new_data, + groups); +} + +static void xcvr_cleanup(struct xcvr_priv *xcvr) +{ + struct device *dev; + struct port_data *data; + int i; + + for (i = 0; i < xcvr->num_ports; i++){ + dev = xcvr->fp_devs[i]; + if (dev == NULL) + continue; + data = dev_get_drvdata(dev); + sysfs_remove_link(&xcvr->dev->kobj, data->name); + } +} + +static int cls_xcvr_probe(struct platform_device *pdev) +{ + + struct xcvr_priv *xcvr; + struct cls_xcvr_platform_data *pdata; + struct resource *res; + int ret; + int i; + + struct device **port_devs; + + xcvr = devm_kzalloc(&pdev->dev, sizeof(struct xcvr_priv), GFP_KERNEL); + if (!xcvr){ + ret = -ENOMEM; + goto err_exit; + } + + dev_set_drvdata(&pdev->dev, xcvr); + + /* mmap resource */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + xcvr->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(xcvr->base)){ + ret = PTR_ERR(xcvr->base); + goto err_exit; + } + } + + pdata = dev_get_platdata(&pdev->dev); + xcvr->dev = &pdev->dev; + + if (pdata) { + /* assign pdata */ + xcvr->num_ports = pdata->num_ports; + xcvr->port_reg_size = pdata->port_reg_size; + } + + /* alloc front panel device list */ + port_devs = devm_kzalloc(&pdev->dev, + xcvr->num_ports * sizeof(struct device*), + GFP_KERNEL); + if (!port_devs){ + ret = -ENOMEM; + goto err_exit; + } + + + if (pdata) { + /* create each device attrs group determined by type */ + for (i = 0; i < pdata->num_ports; i++) { + struct device *fp_dev; + + if (pdata->devices[i].type == SFP){ + fp_dev = init_port(&pdev->dev, + xcvr, + pdata->devices[i], + sfp_groups); + }else{ + fp_dev = init_port(&pdev->dev, + xcvr, + pdata->devices[i], + qsfp_groups); + } + if (IS_ERR(fp_dev)) { + dev_err(&pdev->dev, + "Failed to init port %s\n", + pdata->devices[i].name); + ret = PTR_ERR(fp_dev); + goto dev_clean_up; + } + + dev_info(&pdev->dev, + "Register port %s\n", + pdata->devices[i].name); + + WARN(sysfs_create_link(&pdev->dev.kobj, + &fp_dev->kobj, + pdata->devices[i].name), + "can't create symlink to %s\n", pdata->devices[i].name); + port_devs[i] = fp_dev; + fp_dev = NULL; + } + xcvr->fp_devs = port_devs; + } + + return 0; + +dev_clean_up: + xcvr_cleanup(xcvr); +err_exit: + return ret; + +} + + +static int cls_xcvr_remove(struct platform_device *pdev) +{ + struct xcvr_priv *xcvr = dev_get_drvdata(&pdev->dev); + xcvr_cleanup(xcvr); + return 0; +} + + +static struct platform_driver cls_xcvr_driver = { + .probe = cls_xcvr_probe, + .remove = cls_xcvr_remove, + .driver = { + .name = "cls-xcvr", + }, +}; + +module_platform_driver(cls_xcvr_driver); + +MODULE_AUTHOR("Pradchaya Phucharoen"); +MODULE_DESCRIPTION("Celestica xcvr control driver"); +MODULE_VERSION("0.0.1-3"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:cls-xcvr"); diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.h b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.h new file mode 100644 index 000000000000..7659a7c0e9cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/xcvr-cls.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * xcvr-cls.h + * + * Pradchaya Phucharoen + * Copyright (C) 2019 Celestica Corp. + */ + +#ifndef _LINUX_I2C_CLS_H +#define _LINUX_I2C_CLS_H + +enum PORT_TYPE { + NONE = 0, + SFP, + QSFP +}; + +/* + * port_info - optical port info + * @index: front panel port index starting from 1 + * @typr: port type, see *PORT_TYPE* + */ +struct port_info { + const char *name; + unsigned int index; + enum PORT_TYPE type; +}; + +/* + * cls_xcvr_platform_data - port xcvr private data + * @port_reg_size: register range of each port + * @num_ports: number of front panel ports + * @devices: list of front panel port info + */ +struct cls_xcvr_platform_data { + unsigned int port_reg_size; + int num_ports; + struct port_info *devices; +}; + +#endif /* _LINUX_I2C_CLS_H */ \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/platform_sensors.py index 1aa1c0719825..0d4691b60005 100755 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/platform_sensors.py +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/platform_sensors.py @@ -6,28 +6,39 @@ # The following data is support: # 1. Temperature sensors # 2. PSUs -# 3. Fan trays +# 3. Fan Drawers import sys import logging import subprocess -IPMI_SDR_CMD = ["ipmitool", "sdr", "elist"] +IPMI_SDR_CMD = ['/usr/bin/ipmitool', 'sdr', 'elist'] MAX_NUM_FANS = 7 MAX_NUM_PSUS = 2 +SENSOR_NAME = 0 +SENSOR_VAL = 4 + +sensor_dict = {} def ipmi_sensor_dump(cmd): ''' Execute ipmitool command return dump output exit if any error occur. ''' + global sensor_dict sensor_dump = '' + try: - sensor_dump = subprocess.check_output(cmd) + sensor_dump = subprocess.check_output(cmd, universal_newlines=True) except subprocess.CalledProcessError as e: logging.error('Error! Failed to execute: {}'.format(cmd)) sys.exit(1) - return sensor_dump + + for line in sensor_dump.splitlines(): + sensor_info = line.split('|') + sensor_dict[sensor_info[SENSOR_NAME].strip()] = sensor_info[SENSOR_VAL].strip() + + return True def get_reading_by_name(sensor_name, sdr_elist_dump): ''' @@ -49,7 +60,8 @@ def get_reading_by_name(sensor_name, sdr_elist_dump): ''' found = '' - for line in sdr_elist_dump.split("\n"): + for line in sdr_elist_dump.splitlines(): + line = line.decode() if sensor_name in line: found = line.strip() break @@ -67,19 +79,18 @@ def get_reading_by_name(sensor_name, sdr_elist_dump): return found -def read_temperature_sensors(ipmi_sdr_elist): - - sensor_list = [ - ('TEMP_FAN_U52', 'Fan Tray Middle Temp'), - ('TEMP_FAN_U17', 'Fan Tray Right Temp'), - ('TEMP_SW_U52', 'Switchboard Left Inlet Temp'), - ('TEMP_SW_U16', 'Switchboard Right Inlet Temp'), - ('TEMP_BB_U3', 'Baseboard Temp'), - ('TEMP_CPU', 'CPU Internal Temp'), - ('TEMP_SW_Internal', 'ASIC Internal Temp'), - ('SW_U04_Temp', 'IR3595 Chip Left Temp'), - ('SW_U14_Temp', 'IR3595 Chip Right Temp'), - ('SW_U4403_Temp', 'IR3584 Chip Temp'), +def read_temperature_sensors(): + sensor_list = [\ + ('TEMP_FAN_U52', 'Fanboard Center Temp'),\ + ('TEMP_FAN_U17', 'Fanboard Right Temp'),\ + ('TEMP_SW_U52', 'Switchboard Left Temp'),\ + ('TEMP_SW_U16', 'Switchboard Right Temp'),\ + ('TEMP_BB_U3', 'Baseboard Temp'),\ + ('TEMP_CPU', 'CPU Internal Temp'),\ + ('TEMP_SW_Internal', 'ASIC Internal Temp'),\ + ('SW_U04_Temp', 'IR35215 Chip Left Temp'),\ + ('SW_U14_Temp', 'IR35215 Chip Right Temp'),\ + ('SW_U4403_Temp', 'IR3584 Chip Temp'),\ ] output = '' @@ -90,20 +101,18 @@ def read_temperature_sensors(ipmi_sdr_elist): output += "Temperature Sensors\n" output += "Adapter: IPMI adapter\n" for sensor in sensor_list: - reading = get_reading_by_name(sensor[0],ipmi_sdr_elist) - output += sensor_format.format('{}:'.format(sensor[1]), - reading, + output += sensor_format.format('{}:'.format(sensor[1]),\ + sensor_dict[sensor[0]],\ width=str(max_name_width+1)) output += '\n' return output +def read_fan_sensors(num_fans): -def read_fan_sensors(num_fans, ipmi_sdr_elist): - - sensor_list = [ - ('Fan{}_Status', 'Status'), - ('Fan{}_Front', 'Fan {} front'), - ('Fan{}_Rear', 'Fan {} rear'), + sensor_list = [\ + ('Fan{}_Status', 'Fan Drawer {} Status'),\ + ('Fan{}_Front', 'Fan {} front'),\ + ('Fan{}_Rear', 'Fan {} rear'),\ ] output = '' @@ -111,33 +120,31 @@ def read_fan_sensors(num_fans, ipmi_sdr_elist): # Find max length of sensor calling name max_name_width = max(len(sensor[1]) for sensor in sensor_list) - output += "Fan Trays\n" + output += "Fan Drawers\n" output += "Adapter: IPMI adapter\n" for fan_num in range(1, num_fans+1): for sensor in sensor_list: ipmi_sensor_name = sensor[0].format(fan_num) display_sensor_name = sensor[1].format(fan_num) - reading = get_reading_by_name(ipmi_sensor_name, ipmi_sdr_elist) - output += sensor_format.format('{}:'.format(display_sensor_name), - reading, + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ width=str(max_name_width+1)) output += '\n' return output - -def read_psu_sensors(num_psus, ipmi_sdr_elist): - - sensor_list = [ - ('PSU{}_Status', 'PSU {} Status'), - ('PSU{}_Fan', 'PSU {} Fan'), - ('PSU{}_VIn', 'PSU {} Input Voltag'), - ('PSU{}_CIn', 'PSU {} Input Current'), - ('PSU{}_PIn', 'PSU {} Input Power'), - ('PSU{}_Temp1', 'PSU {} Temp1'), - ('PSU{}_Temp2', 'PSU {} Temp2'), - ('PSU{}_VOut', 'PSU {} Output Voltag'), - ('PSU{}_COut', 'PSU {} Output Current'), - ('PSU{}_POut', 'PSU {} Output Power'), +def read_psu_sensors(num_psus): + + sensor_list = [\ + ('PSU{}_Status', 'PSU {} Status'),\ + ('PSU{}_Fan', 'PSU {} Fan 1'),\ + ('PSU{}_VIn', 'PSU {} Input Voltage'),\ + ('PSU{}_CIn', 'PSU {} Input Current'),\ + ('PSU{}_PIn', 'PSU {} Input Power'),\ + ('PSU{}_Temp1', 'PSU {} Ambient Temp'),\ + ('PSU{}_Temp2', 'PSU {} Hotspot Temp'),\ + ('PSU{}_VOut', 'PSU {} Output Voltage'),\ + ('PSU{}_COut', 'PSU {} Output Current'),\ + ('PSU{}_POut', 'PSU {} Output Power'),\ ] output = '' @@ -151,22 +158,21 @@ def read_psu_sensors(num_psus, ipmi_sdr_elist): for sensor in sensor_list: ipmi_sensor_name = sensor[0].format(psu_num) display_sensor_name = sensor[1].format(psu_num) - reading = get_reading_by_name(ipmi_sensor_name, ipmi_sdr_elist) - output += sensor_format.format('{}:'.format(display_sensor_name), - reading, + output += sensor_format.format('{}:'.format(display_sensor_name),\ + sensor_dict[ipmi_sensor_name],\ width=str(max_name_width+1)) output += '\n' return output - def main(): output_string = '' - ipmi_sdr_elist = ipmi_sensor_dump(IPMI_SDR_CMD) - output_string += read_temperature_sensors(ipmi_sdr_elist) - output_string += read_psu_sensors(MAX_NUM_PSUS, ipmi_sdr_elist) - output_string += read_fan_sensors(MAX_NUM_FANS, ipmi_sdr_elist) - print(output_string) + if ipmi_sensor_dump(IPMI_SDR_CMD): + output_string += read_temperature_sensors() + output_string += read_psu_sensors(MAX_NUM_PSUS) + output_string += read_fan_sensors(MAX_NUM_FANS) + + print(output_string) if __name__ == '__main__': diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/sensors index 405d92c2b3cc..5d740a9eb7d7 100755 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/sensors +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/sensors @@ -8,4 +8,4 @@ if [ -t 1 ] ; then fi docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" -docker exec -$DOCKER_EXEC_FLAGS pmon platform_sensors.py "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon python3 /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/silverstone_platform_shutdown.sh b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/silverstone_platform_shutdown.sh new file mode 100755 index 000000000000..973c90378dca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/silverstone_platform_shutdown.sh @@ -0,0 +1,26 @@ +#!/bin/bash +REBOOT_CAUSE_DIR="/host/reboot-cause" +HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +REBOOT_TIME=$(date) + +if [ $# -ne 1 ]; then + echo "Require reboot type" + exit 1 +fi + +if [ ! -d "$REBOOT_CAUSE_DIR" ]; then + mkdir $REBOOT_CAUSE_DIR +fi + +echo "Reason:$1,Time:${REBOOT_TIME}" > ${HW_REBOOT_CAUSE_FILE} + +# Best effort to write buffered data onto the disk +sync ; sync ; sync ; sleep 3 + +# BMC cold power-cyle +ipmitool chassis power cycle &> /dev/null + +# System should reboot by now and avoid the script returning to caller +sleep 10 + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/setup.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/setup.py index 20a2b6d1063a..7da0814059d9 100644 --- a/platform/broadcom/sonic-platform-modules-cel/silverstone/setup.py +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/setup.py @@ -1,8 +1,5 @@ from setuptools import setup -DEVICE_NAME = 'celestica' -HW_SKU = 'x86_64-cel_silverstone-r0' - setup( name='sonic-platform', version='1.0', @@ -17,7 +14,7 @@ 'sonic_platform', ], package_dir={ - 'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)}, + 'sonic_platform': 'sonic_platform'}, classifiers=[ 'Development Status :: 3 - Alpha', 'Environment :: Plugins', diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/__init__.py new file mode 100644 index 000000000000..d3c24cb008dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import platform diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/chassis.py new file mode 100644 index 000000000000..da898c9a147e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/chassis.py @@ -0,0 +1,452 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_py_common import device_info + from sonic_platform_base.sfp_base import SfpBase + from .helper import APIHelper + import time + import os + import re + import shutil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 7 +NUM_FAN = 2 +NUM_PSU = 2 +NUM_THERMAL = 14 +NUM_SFP = 32 +NUM_COMPONENT = 10 + +IPMI_OEM_NETFN = "0x3A" +IPMI_GET_REBOOT_CAUSE = "0x03 0x00 0x01 0x06" + +IPMI_SET_SYS_LED_CMD = "0x07 0x00 {}" +IPMI_GET_SYS_LED_CMD = "0x08 0x00" + +LPC_GETREG_PATH = "/sys/bus/platform/devices/baseboard-lpc/getreg" +LPC_SETREG_PATH = "/sys/bus/platform/devices/baseboard-lpc/setreg" +LPC_STATUS_LED_REG = "0xA162" + +ORG_HW_REBOOT_CAUSE_FILE="/host/reboot-cause/hw-reboot-cause.txt" +TMP_HW_REBOOT_CAUSE_FILE="/tmp/hw-reboot-cause.txt" + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + #led color status + SYSLED_COLOR_VAL_MAP = { + 'off': '0xff', + 'green': '0xdc', + 'amber': '0xec', + 'green_blink_1hz': '0xdd', + 'green_blink_4hz': '0xde', + 'amber_blink_1hz': '0xed', + 'amber_blink_4hz': '0xee', + 'green_amber_1hz': '0xcd', + 'green_amber_4hz': '0xce' + } + + SYSLED_VAL_COLOR_DESC_MAP = { + "0xff": "off", + "0xdc": "green", + "0xec": "amber", + "0xdd": "green blinking 1Hz", + "0xde": "green blinking 4Hz", + "0xed": "amber blinking 1Hz", + "0xee": "amber blinking 4Hz", + "0xcd": "green & amber alternate 1Hz", + "0xce": "green & amber alternate 4Hz" + } + + def __init__(self): + ChassisBase.__init__(self) + self._api_helper = APIHelper() + self.sfp_module_initialized = False + self._sfp_list = [] + self.sfp_status_dict = {} + self._watchdog = None + self._airflow_direction = None + + self.__initialize_eeprom() + self.is_host = self._api_helper.is_host() + + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + self.__initialize_components() + + def __initialize_sfp(self): + sfputil_helper = SfpUtilHelper() + port_config_file_path = device_info.get_path_to_port_config_file() + sfputil_helper.read_porttab_mappings(port_config_file_path, 0) + + #from sonic_platform.sfp import Sfp + from sonic_platform.sfp import Sfp + for index in range(0, NUM_SFP): + #sfp = Sfp(index, sfputil_helper.logical[index]) + sfp = Sfp(index, sfputil_helper.physical_to_logical[index + 1]) + self._sfp_list.append(sfp) + self.sfp_status_dict[sfp.index] = '1' if sfp.get_presence() else '0' + self.sfp_module_initialized = True + + def __initialize_psu(self): + from sonic_platform.psu import Psu + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_fan(self): + from sonic_platform.fan_drawer import FanDrawer + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + # airflow = self.__get_air_flow() + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Eeprom + self._eeprom = Eeprom() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def initizalize_system_led(self): + pass + + 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.get_mac() + + def get_revision(self): + """ + Retrieves the hardware revision for the chassis + Returns: + A string containing the hardware revision for this chassis. + """ + return self._eeprom.get_revision() + + def get_serial(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.get_serial() + + 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.get_eeprom() + + 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. + """ + + status, raw_cause = self._api_helper.ipmi_raw( + IPMI_OEM_NETFN, IPMI_GET_REBOOT_CAUSE) + hx_cause = raw_cause.split()[0] if status and len( + raw_cause.split()) > 0 else 00 + + # This tmp copy is to retain the reboot-cause only for the current boot + if os.path.isfile(ORG_HW_REBOOT_CAUSE_FILE): + shutil.move(ORG_HW_REBOOT_CAUSE_FILE, TMP_HW_REBOOT_CAUSE_FILE) + + if hx_cause == "77" and os.path.isfile(TMP_HW_REBOOT_CAUSE_FILE): + with open(TMP_HW_REBOOT_CAUSE_FILE) as hw_cause_file: + reboot_info = hw_cause_file.readline().rstrip('\n') + match = re.search(r'Reason:(.*),Time:(.*)', reboot_info) + if match is not None: + if match.group(1) == 'system': + return (self.REBOOT_CAUSE_NON_HARDWARE, 'System cold reboot') + + reboot_cause = { + "00": self.REBOOT_CAUSE_HARDWARE_OTHER, + "11": self.REBOOT_CAUSE_POWER_LOSS, + "22": self.REBOOT_CAUSE_NON_HARDWARE, + "33": self.REBOOT_CAUSE_NON_HARDWARE, + "44": self.REBOOT_CAUSE_NON_HARDWARE, + "55": self.REBOOT_CAUSE_HARDWARE_OTHER, + "66": self.REBOOT_CAUSE_WATCHDOG, + "77": self.REBOOT_CAUSE_POWER_LOSS, + "88": self.REBOOT_CAUSE_WATCHDOG + }.get(hx_cause, self.REBOOT_CAUSE_HARDWARE_OTHER) + + description = { + "00": "Hardware Reason", + "11": "Power On Reset", + "22": "Soft-Set CPU Warm Reset", + "33": "Soft-Set CPU Cold Reset", + "44": "CPU Warm Reset", + "55": "CPU Cold Reset", + "66": "GPIO Watchdog Reset", + "77": "Power Cycle Reset", + "88": "Hardware Watchdog Reset" + }.get(hx_cause, "Unknown reason") + + return (reboot_cause, description) + + 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. + """ + # SFP event + if not self.sfp_module_initialized: + self.__initialize_sfp() + + sfp_dict = {} + + SFP_REMOVED = '0' + SFP_INSERTED = '1' + + SFP_PRESENT = True + SFP_ABSENT = False + + start_time = time.time() + time_period = timeout/float(1000) #Convert msecs to secs + + while time.time() < (start_time + time_period) or timeout == 0: + for sfp in self._sfp_list: + port_idx = sfp.index + if self.sfp_status_dict[port_idx] == SFP_REMOVED and \ + sfp.get_presence() == SFP_PRESENT: + sfp_dict[port_idx] = SFP_INSERTED + self.sfp_status_dict[port_idx] = SFP_INSERTED + elif self.sfp_status_dict[port_idx] == SFP_INSERTED and \ + sfp.get_presence() == SFP_ABSENT: + sfp_dict[port_idx] = SFP_REMOVED + self.sfp_status_dict[port_idx] = SFP_REMOVED + + if sfp_dict: + return True, {'sfp':sfp_dict} + + time.sleep(0.5) + + return True, {'sfp':{}} # Timeout + + ############################################################## + ######################## SFP methods ######################### + ############################################################## + + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + Returns: + An integer, the number of sfps available on this chassis + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return len(self._sfp_list) + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return self._sfp_list + + def get_sfp(self, index): + """ + Retrieves sfp represented by (1-based) index + Args: + index: An integer, the index (1-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 1. + For example, 1 for Ethernet0, 2 for Ethernet4 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + return super(Chassis, self).get_sfp(index-1) + + ############################################################## + ####################### Other methods ######################## + ############################################################## + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + if self._watchdog is None: + from sonic_platform.watchdog import Watchdog + self._watchdog = Watchdog() + + return self._watchdog + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._api_helper.hwsku + + 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 device + Returns: + string: Model/part number of device + """ + return self._eeprom.get_pn() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + 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 + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + """ + color_val = self.SYSLED_COLOR_VAL_MAP.get(color) + if color_val == None: + return False + + status = self._api_helper.lpc_setreg(LPC_SETREG_PATH, LPC_STATUS_LED_REG, color_val) + return status + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + color_val = self._api_helper.lpc_getreg(LPC_GETREG_PATH, LPC_STATUS_LED_REG) + color = self.SYSLED_VAL_COLOR_DESC_MAP.get(color_val, "N/A") + return color + + def get_airflow_direction(self): + if self._airflow_direction == None: + try: + vendor_extn = self._eeprom.get_vendor_extn() + airflow_type = vendor_extn.split()[2][2:4] # Either 0xFB or 0xBF + if airflow_type == 'FB': + direction = 'exhaust' + elif airflow_type == 'BF': + direction = 'intake' + else: + direction = 'N/A' + except (AttributeError, IndexError): + direction = 'N/A' + + self._airflow_direction = direction + + return self._airflow_direction + + def get_port_or_cage_type(self, index): + """ + Retrieves sfp port or cage type corresponding to physical port + + Args: + index: An integer (>=0), the index of the sfp to retrieve. + + Returns: + The masks of all types of port or cage that can be supported on the port + Types are defined in sfp_base.py + """ + if index in range(1, 32+1): + return (SfpBase.SFP_PORT_TYPE_BIT_QSFP28 | SfpBase.SFP_PORT_TYPE_BIT_SFP28 | \ + SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_QSFPDD | SfpBase.SFP_PORT_TYPE_BIT_QSFP) + else: + raise NotImplementedError + + diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/component.py new file mode 100644 index 000000000000..8748404d9931 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/component.py @@ -0,0 +1,181 @@ +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import os.path +import subprocess +import re + +try: + from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NAME_IDX = 0 +DESC_IDX = 1 +VER_API_IDX = 2 + +BASE_CPLD_VER_CMD = "0x03 0x00 0x01 0x00" +FAN_CPLD_VER_CMD = "0x03 0x01 0x01 0x00" +BIOS_VER_PATH = "/sys/class/dmi/id/bios_version" +BMC_VER_CMD1 = ["ipmitool", "mc", "info"] +BMC_VER_CMD2 = ["grep", "Firmware Revision"] +ONIE_VER_CMD = ["cat", "/host/machine.conf"] +SSD_VER_CMD = ["smartctl", " -i", "/dev/sda"] +BASE_GETREG_PATH = "/sys/devices/platform/baseboard-lpc/getreg" +MEM_PCI_RESOURCE = "/sys/bus/pci/devices/0000:09:00.0/resource0" +FPGA_VER_MEM_OFFSET = 0 +NETFN = "0x3A" +COME_CPLD_VER_REG = "0xA1E0" + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + COMPONENT_LIST = [ + ("BIOS", "Basic Input/Output System", self.__get_bios_ver), + ("ONIE", "Open Network Install Environment", self.__get_onie_ver), + ("BMC", "Baseboard Management Controller", self.__get_bmc_ver), + ("FPGA", "FPGA for transceiver EEPROM access and other component I2C access", self.__get_fpga_ver), + ("CPLD COMe", "COMe board CPLD", self.__get_come_cpld_ver), + ("CPLD BASE", "CPLD for board functions and watchdog", self.__get_cpld_ver_from_bmc), + ("CPLD SW1", "CPLD for port control QSFP(1-16)", self.__get_sw_cpld1_ver), + ("CPLD SW2", "CPLD for port control QSFP(17-32) SFP(33-34)", self.__get_sw_cpld2_ver), + ("CPLD FAN", "CPLD for fan control and status", self.__get_cpld_ver_from_bmc), + ("SSD", "Solid State Drive - {}", self.__get_ssd_ver) + ] + self.index = component_index + self.name = COMPONENT_LIST[self.index][NAME_IDX] + self.description = COMPONENT_LIST[self.index][DESC_IDX] + self.__get_version = COMPONENT_LIST[self.index][VER_API_IDX] + self._api_helper = APIHelper() + + def __i2c_get(self, bus, i2caddr, offset): + try: + return int(subprocess.check_output(['/usr/sbin/i2cget', '-y', '-f', str(bus), str(i2caddr), str(offset)]), 16) + except (FileNotFoundError, subprocess.CalledProcessError): + return -1 + + def __get_bios_ver(self): + return self._api_helper.read_txt_file(BIOS_VER_PATH) + + def __get_onie_ver(self): + onie_ver = "N/A" + status, raw_onie_data = self._api_helper.run_command(ONIE_VER_CMD) + if status: + ret = re.search(r"(?<=onie_version=).+[^\n]", raw_onie_data) + if ret != None: + onie_ver = ret.group(0) + return onie_ver + + def __get_bmc_ver(self): + bmc_ver = "Unknown" + status, raw_bmc_data = self._api_helper.run_command(BMC_VER_CMD1, BMC_VER_CMD2) + if status: + bmc_ver_data = raw_bmc_data.split(":") + bmc_ver = bmc_ver_data[-1].strip() if len( + bmc_ver_data) > 1 else bmc_ver + return bmc_ver + + def __get_fpga_ver(self): + fpga_ver = "Unknown" + status, reg_val = self._api_helper.pci_get_value( + MEM_PCI_RESOURCE, FPGA_VER_MEM_OFFSET) + if status: + major = reg_val[0] >> 16 + minor = int(bin(reg_val[0])[16:32], 2) + fpga_ver = '{}.{}'.format(major, minor) + return fpga_ver + + def __get_come_cpld_ver(self): + cpld_ver_str = self._api_helper.lpc_getreg(BASE_GETREG_PATH, COME_CPLD_VER_REG) + if not cpld_ver_str: + return "N/A" + + cpld_ver = int(cpld_ver_str, 16) + return "{:x}.{:x}".format((cpld_ver >> 4) & 0xF, cpld_ver & 0xF) + + def __get_cpld_ver_from_bmc(self): + cpld_ver = "N/A" + cmd = BASE_CPLD_VER_CMD + + if self.name == "CPLD FAN": + cmd = FAN_CPLD_VER_CMD + + (rc, op) = self._api_helper.ipmi_raw(NETFN, cmd) + if rc and len(op) == 2: + cpld_ver = op[0] + '.' + op[1] + + return cpld_ver + + def __get_sw_cpld1_ver(self): + val = self.__i2c_get(4, 0x30, 0) + if val != -1: + return '{:x}.{:x}'.format((val >> 4) & 0xf, val & 0xf) + else: + return 'N/A' + + def __get_sw_cpld2_ver(self): + val = self.__i2c_get(4, 0x31, 0) + if val != -1: + return '{:x}.{:x}'.format((val >> 4) & 0xf, val & 0xf) + else: + return 'N/A' + + def __get_ssd_ver(self): + ssd_ver = "N/A" + status, raw_ssd_data = self._api_helper.run_command(SSD_VER_CMD) + if status: + ret = re.search(r"Firmware Version: +(.*)[^\\]", raw_ssd_data) + if ret != None: + ssd_ver = ret.group(1) + return ssd_ver + + def __get_ssd_model(self): + model = "N/A" + + status, raw_ssd_data = self._api_helper.run_command(SSD_VER_CMD) + if status: + ret = re.search(r"Device Model: +(.*)[^\\]", raw_ssd_data) + if ret != None: + try: + model = ret.group(1) + except (IndexError): + pass + + return model + + 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 + """ + # For SSD get the model name from device + if self.get_name() == "SSD": + return self.description.format(self.__get_ssd_model()) + + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + return self.__get_version() diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/eeprom.py new file mode 100644 index 000000000000..ed5891f4f5d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/eeprom.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os + import sys + import re + import json + import fcntl + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +NULL = 'N/A' +EEPROM_TMP_FILE = '/tmp/eeprom_dump.json' + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(Eeprom, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + try: + match = re.search('(0x[0-9a-fA-F]{2})\s+\d+\s+(.+)', line) + if match is not None: + idx = match.group(1) + value = match.group(2).rstrip('\0') + + _eeprom_info_dict[idx] = value + except Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + eeprom_dict = {} + + if os.path.exists(EEPROM_TMP_FILE): + with open(EEPROM_TMP_FILE, 'r') as fd: + eeprom_dict = json.load(fd) + + return eeprom_dict + + original_stdout = sys.stdout + sys.stdout = StringIO() + rv = -1 + try: + rv = self.read_eeprom_db() + except BaseException: + pass + + if rv == 0: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + eeprom_dict = self.__parse_output(decode_output) + else: + e = self.read_eeprom() + if e is None: + sys.stdout = original_stdout + return {} + + self.decode_eeprom(e) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(e) + if not is_valid: + return {} + + eeprom_dict = self.__parse_output(decode_output) + + if len(eeprom_dict) != 0: + with open(EEPROM_TMP_FILE, 'w') as fd: + fcntl.flock(fd, fcntl.LOCK_EX) + json.dump(eeprom_dict, fd) + fcntl.flock(fd, fcntl.LOCK_UN) + + return eeprom_dict + + def get_eeprom(self): + return self._eeprom + + def get_product(self): + return self._eeprom.get('0x21', NULL) + + def get_pn(self): + return self._eeprom.get('0x22', NULL) + + def get_serial(self): + return self._eeprom.get('0x23', NULL) + + def get_mac(self): + return self._eeprom.get('0x24', NULL) + + def get_revision(self): + return self._eeprom.get('0x26', NULL) + + def get_vendor_extn(self): + return self._eeprom.get('0xFD', NULL) diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan.py similarity index 51% rename from device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py rename to platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan.py index 1a18eed9c8d5..30ef3d934bc1 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan.py @@ -17,37 +17,36 @@ raise ImportError(str(e) + "- required module not found") -FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", "FAN-3F", "FAN-3R", - "FAN-4F", "FAN-4R", "FAN-5F", "FAN-5R", "FAN-6F", "FAN-6R", "FAN-7F", "FAN-7R"] - IPMI_OEM_NETFN = "0x3A" IPMI_SENSOR_NETFN = "0x04" IPMI_FAN_SPEED_CMD = "0x2D {}" IPMI_AIR_FLOW_CMD = "0x0A {}" IPMI_FAN_PRESENT_CMD = "0x06 0x03 {}" +IPMI_FAN_SPEED_CPLD_CMD = "0x03 0x01 0x01 {}" IPMI_SET_FAN_LED_CMD = "0x07 {} {}" IPMI_GET_FAN_LED_CMD = "0x08 {}" -IPMI_SET_PWM = "0x03 0x01 0x02 {} {}" - -IPMI_FRU_MODEL_KEY = "Board Part Number" -IPMI_FRU_SERIAL_KEY = "Board Serial" - -MAX_OUTLET = 24700 -MAX_INLET = 29700 -SPEED_TOLERANCE = 10 -FAN1_FRONT_SS_ID = "0x0D" -FAN1_REAR_SS_ID = "0x45" +FAN_NAME_TEMPLATE = "{}Fan{}{}" + +FAN_FRONT_MAX_SPEED = 24700 +FAN_REAR_MAX_SPEED = 29700 +FAN_PSU_MAX_SPEED = 26500 +FAN_SPEED_TOLERANCE = 25 + +CPLD_REG_FANTRAY_BASE = 0x22 +FAN_FRONT_SID_BASE = 0x0D # IPMI Sensor ID +FAN_REAR_SID_BASE = 0x45 # IPMI Sensor ID +FAN_FRU_ID_BASE = 6 +PSU_FRU_ID_BASE = 3 +PSU_FAN_SID_BASE = {\ + 0: 0x33,\ + 1: 0x3D\ +} FAN_LED_OFF_CMD = "0x00" FAN_LED_GREEN_CMD = "0x01" FAN_LED_RED_CMD = "0x02" FAN1_LED_CMD = "0x04" -FAN_PWM_REGISTER_START = 0x22 -FAN_PWM_REGISTER_STEP = 0x10 -FAN1_FRU_ID = 6 - -NUM_OF_FAN_TRAY = 7 -PSU_FAN1_FRONT_SS_ID = "0x33" +NUM_FAN_TRAY = 7 class Fan(FanBase): @@ -58,10 +57,24 @@ def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): self.fan_index = fan_index self.fan_tray_index = fan_tray_index self.is_psu_fan = is_psu_fan + self.name = None if self.is_psu_fan: self.psu_index = psu_index + self.index = NUM_FAN_TRAY * 2 + self.psu_index + self.max_speed = FAN_PSU_MAX_SPEED + self.sid_offset = PSU_FAN_SID_BASE[self.psu_index] + else: + self.index = self.fan_tray_index * 2 + self.fan_index + if fan_index % 2 == 0: + self.is_front = True + self.sid_offset = FAN_FRONT_SID_BASE + self.fan_tray_index + self.max_speed = FAN_FRONT_MAX_SPEED + else: + self.is_front = False + self.sid_offset = FAN_REAR_SID_BASE + self.fan_tray_index + self.max_speed = FAN_REAR_MAX_SPEED + self._api_helper = APIHelper() - self.index = self.fan_tray_index * 2 + self.fan_index def get_direction(self): """ @@ -70,13 +83,30 @@ def get_direction(self): A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST depending on fan direction """ - direction = self.FAN_DIRECTION_EXHAUST - fan_direction_key = hex(self.fan_tray_index) if not self.is_psu_fan else hex( - self.psu_index + NUM_OF_FAN_TRAY) - status, raw_flow = self._api_helper.ipmi_raw( - IPMI_OEM_NETFN, IPMI_AIR_FLOW_CMD.format(fan_direction_key)) - if status and raw_flow == "01": - direction = self.FAN_DIRECTION_INTAKE + direction = self.FAN_DIRECTION_NOT_APPLICABLE + + if not self.is_psu_fan: + offset = hex(self.fan_tray_index) + else: + offset = hex(NUM_FAN_TRAY + self.psu_index) + + status, output = self._api_helper.ipmi_raw(IPMI_OEM_NETFN,\ + IPMI_AIR_FLOW_CMD.format(offset)) + if status: + if output == "00": + direction = self.FAN_DIRECTION_EXHAUST + elif output == "01": + direction = self.FAN_DIRECTION_INTAKE + elif self.is_psu_fan: + # Trying to deduce from PSU model + status, output = self._api_helper.ipmi_fru_id(PSU_FRU_ID_BASE + self.fan_tray_index, + "Board Part Number") + if status and output: + model = output.split(':')[-1].strip() + if model == "TDPS1500AB7C": + direction = self.FAN_DIRECTION_INTAKE + elif model == "TDPS1500AB6E": + direction = self.FAN_DIRECTION_EXHAUST return direction @@ -86,24 +116,20 @@ def get_speed(self): Returns: An integer, the percentage of full fan speed, in the range 0 (off) to 100 (full speed) - - Note: - M = 150 - Max F2B = 24700 RPM - Max B2F = 29700 RPM """ + speed = 0 - max_rpm = MAX_OUTLET if self.fan_index % 2 == 0 else MAX_INLET - fan1_ss_start = FAN1_FRONT_SS_ID if self.fan_index % 2 == 0 else FAN1_REAR_SS_ID - - ss_id = hex(int(fan1_ss_start, 16) + self.fan_tray_index) if not self.psu_index else hex( - int(PSU_FAN1_FRONT_SS_ID, 16) + self.fan_tray_index) - status, raw_ss_read = self._api_helper.ipmi_raw( - IPMI_SENSOR_NETFN, IPMI_FAN_SPEED_CMD.format(ss_id)) + if not self.is_psu_fan: + multiplier = 150.0 + else: + multiplier = 200.0 - ss_read = raw_ss_read.split()[0] - rpm_speed = int(ss_read, 16)*150 - speed = int(float(rpm_speed)/max_rpm * 100) + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_FAN_SPEED_CMD.format(self.sid_offset)) + if status: + raw_speed = output.split()[0] + rpm_speed = int(raw_speed, 16) * multiplier + speed = int((rpm_speed/self.max_speed) * 100) return speed @@ -120,8 +146,18 @@ def get_target_speed(self): 0 : when PWM mode is use pwm : when pwm mode is not use """ - target = 0 - return target + if self.is_psu_fan: + # Ignored for tolerance check + return self.get_speed() + + offset = hex(CPLD_REG_FANTRAY_BASE + (16 * self.fan_tray_index)) + status, output = self._api_helper.ipmi_raw(IPMI_OEM_NETFN,\ + IPMI_FAN_SPEED_CPLD_CMD.format(offset)) + if status: + fan_pwm = int(output, 16) + target_speed = int(fan_pwm / 255 * 100) + + return target_speed def get_speed_tolerance(self): """ @@ -130,7 +166,8 @@ def get_speed_tolerance(self): An integer, the percentage of variance from target speed which is considered tolerable """ - return SPEED_TOLERANCE + + return FAN_SPEED_TOLERANCE def set_speed(self, speed): """ @@ -140,29 +177,10 @@ def set_speed(self, speed): in the range 0 (off) to 100 (full speed) Returns: A boolean, True if speed is set successfully, False if not - Notes: - pwm setting mode must set as Manual - manual: ipmitool raw 0x3a 0x06 0x01 0x0 - auto: ipmitool raw 0x3a 0x06 0x01 0x1 """ - # ipmitool raw 0x3a 0x03 0x01 0x02 {register} {pwm_speed} - # register = 22 32 42 52 62 72 82 - - if self.is_psu_fan: - # TODO - return False - speed_hex = hex(int(float(speed)/100 * 255)) - fan_register_hex = hex(FAN_PWM_REGISTER_START + - (self.fan_tray_index*FAN_PWM_REGISTER_STEP)) - - set_speed_cmd = IPMI_SET_PWM.format(fan_register_hex, speed_hex) - status, set_speed_res = self._api_helper.ipmi_raw( - IPMI_OEM_NETFN, set_speed_cmd) - - set_speed = False if not status else True - - return set_speed + # FAN speed is controlled by BCM always + return False def set_status_led(self, color): """ @@ -180,7 +198,7 @@ def set_status_led(self, color): """ if self.is_psu_fan: - # Not support + # Not supported for PSU return False led_cmd = { @@ -208,9 +226,9 @@ def get_status_led(self): STATUS_LED_COLOR_RED = "red" STATUS_LED_COLOR_OFF = "off" """ - if self.is_psu_fan: - # Not support - return self.STATUS_LED_COLOR_OFF + if not self.get_presence() or self.is_psu_fan: + # Not supported for PSU + return "N/A" fan_selector = hex(int(FAN1_LED_CMD, 16) + self.fan_tray_index) status, hx_color = self._api_helper.ipmi_raw( @@ -224,16 +242,30 @@ def get_status_led(self): return status_led + ############################################################## + ###################### Device methods ######################## + ############################################################## + def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ - fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] if not self.is_psu_fan else "PSU-{} FAN-{}".format( - self.psu_index+1, self.fan_index+1) - return fan_name + if not self.name: + if not self.is_psu_fan: + psu_name = "" + fan_id = " {}".format(self.fan_tray_index + 1) + fan_type = " Front" if self.is_front else " Rear" + else: + psu_name = "PSU {} ".format(self.psu_index + 1) + fan_id = " {}".format(self.fan_tray_index + 1) + fan_type = "" + + self.name = FAN_NAME_TEMPLATE.format(psu_name, fan_id, fan_type) + + return self.name def get_presence(self): """ @@ -241,13 +273,12 @@ def get_presence(self): Returns: bool: True if FAN is present, False if not """ - if self.is_psu_fan: - return True presence = False - status, raw_present = self._api_helper.ipmi_raw( + + status, output = self._api_helper.ipmi_raw( IPMI_OEM_NETFN, IPMI_FAN_PRESENT_CMD.format(hex(self.index))) - if status and raw_present == "00": + if status and output == "00": presence = True return presence @@ -258,17 +289,13 @@ def get_model(self): Returns: string: Model/part number of device """ - if self.is_psu_fan: - return "Unknown" - - model = "Unknown" - ipmi_fru_idx = self.fan_tray_index + FAN1_FRU_ID - status, raw_model = self._api_helper.ipmi_fru_id( - ipmi_fru_idx, IPMI_FRU_MODEL_KEY) + model = "N/A" - fru_pn_list = raw_model.split() - if len(fru_pn_list) > 4: - model = fru_pn_list[4] + if not self.is_psu_fan: + status, output = self._api_helper.ipmi_fru_id(FAN_FRU_ID_BASE + self.fan_tray_index, + "Board Part Number") + if status and output: + model = output.split(':')[-1].strip() return model @@ -278,17 +305,13 @@ def get_serial(self): Returns: string: Serial number of device """ - if self.is_psu_fan: - return "Unknown" - - serial = "Unknown" - ipmi_fru_idx = self.fan_tray_index + FAN1_FRU_ID - status, raw_model = self._api_helper.ipmi_fru_id( - ipmi_fru_idx, IPMI_FRU_SERIAL_KEY) + serial = "N/A" - fru_sr_list = raw_model.split() - if len(fru_sr_list) > 3: - serial = fru_sr_list[3] + if not self.is_psu_fan: + status, output = self._api_helper.ipmi_fru_id(FAN_FRU_ID_BASE + self.fan_tray_index, + "Board Serial") + if status and output: + serial = output.split(':')[-1].strip() return serial @@ -299,3 +322,24 @@ def get_status(self): A boolean value, True if device is operating properly, False if not """ return self.get_presence() and self.get_speed() > 0 + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + + return self.fan_index + 1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True if not self.is_psu_fan else False diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..a7e5f167ad79 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/fan_drawer.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the the Fan-Drawers' information available in the platform +# +############################################################################# + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN = 2 + + +class FanDrawer(FanDrawerBase): + def __init__(self, fantray_index): + FanDrawerBase.__init__(self) + self._index = fantray_index + 1 + self._init_fan(fantray_index) + + def _init_fan(self, fantray_index): + from sonic_platform.fan import Fan + for index in range(NUM_FAN): + fan = Fan(fantray_index, index) + self._fan_list.append(fan) + + 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[0].set_status_led(color) + + def get_status_led(self): + """ + Gets the state of the fan drawer LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._fan_list[0].get_status_led() + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return "Drawer {}".format(self._index) + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return self._fan_list[0].get_presence() + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._fan_list[0].get_model() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._fan_list[0].get_serial() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self._fan_list[0].get_status() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self._index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/helper.py new file mode 100644 index 000000000000..3e2cb798df91 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/helper.py @@ -0,0 +1,190 @@ +import fcntl +import os +import struct +import subprocess +import fcntl + +from mmap import * +from sonic_py_common.general import check_output_pipe +from sonic_py_common.device_info import get_platform_and_hwsku + +from sonic_py_common import device_info + +HOST_CHK_CMD = "docker > /dev/null 2>&1" +EMPTY_STRING = "" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = get_platform_and_hwsku() + + def is_host(self): + ret,data = subprocess.getstatusoutput(HOST_CHK_CMD) + if ret != 0: + return False + return True + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except: + status = False + return status, result + + def run_command(self, cmd1_args, cmd2_args=None): + status = True + result = "" + args = [cmd1_args] + ([cmd2_args] if cmd2_args is not None else []) + try: + result = check_output_pipe(*args) + except subprocess.CalledProcessError: + status = False + return status, result + + def run_interactive_command(self, cmd): + try: + subprocess.call(cmd) + except: + return False + return True + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def read_one_line_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def get_cpld_reg_value(self, getreg_path, register): + cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register) + status, result = self.run_command(cmd) + return result if status else None + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + cmd = "ipmitool raw {} {}".format(netfn, cmd) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data.strip() + + return status, result + + def ipmi_fru_id(self, id, key=None): + status = True + result = "" + cmd1_args = ["ipmitool", "fru", "print", str(id)] + if not key: + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data.strip() + else: + cmd2_args = ["grep", str(key)] + status, result = self.run_command(cmd1_args, cmd2_args) + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + cmd = "ipmitool sensor thresh '{}' {} {}".format( + str(id), str(threshold_key), str(value)) + ret, data = subprocess.getstatusoutput(cmd) + if ret != 0: + status = False + else: + result = data.strip() + + return status, result + + def lpc_getreg(self, getreg_path, reg): + """ + Get the cpld reg through lpc interface + + Args: + getreg_path: getreg sysfs path + reg: 16 bits reg addr in hex str format + + Returns: + A str, register value in hex str format + """ + try: + file = open(getreg_path, 'w+') + # Acquire an exclusive lock on the file + fcntl.flock(file, fcntl.LOCK_SH) + + file.write(reg) + file.flush() + + # Seek to the beginning of the file + file.seek(0) + + # Read the content of the file + result = file.readline().strip() + except (OSError, IOError, FileNotFoundError): + result = None + finally: + # Release the lock and close the file + fcntl.flock(file, fcntl.LOCK_UN) + file.close() + + return result + + def lpc_setreg(self, setreg_path, reg, val): + """ + Set the cpld reg through lpc interface + + Args: + setreg_path: setreg sysfs path + reg: 16 bits reg addr in hex str format + val: 8 bits register value in hex str format + + Returns: + A boolean, True if speed is set successfully, False if not + """ + status = True + try: + file = open(setreg_path, 'w') + # Acquire an exclusive lock on the file + fcntl.flock(file, fcntl.LOCK_EX) + + data = "{} {}".format(reg, val) + file.write(data) + file.flush() + except (OSError, IOError, FileNotFoundError): + status = False + finally: + # Release the lock and close the file + fcntl.flock(file, fcntl.LOCK_UN) + file.close() + + return status diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/pcie.py new file mode 100644 index 000000000000..0f8bc0830384 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/pcie.py @@ -0,0 +1,15 @@ +# +# pcie_base.py +# +# Abstract base class for implementing platform-specific +# PCIE functionality for SONiC +# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +class Pcie(PcieUtil): + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/platform.py similarity index 100% rename from device/celestica/x86_64-cel_silverstone-r0/sonic_platform/platform.py rename to platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/platform.py diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/psu.py new file mode 100644 index 000000000000..ced1022796de --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/psu.py @@ -0,0 +1,338 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from .helper import APIHelper + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +IPMI_SENSOR_NETFN = "0x04" +IPMI_SENSOR_READ_CMD = "0x2D {}" +IPMI_SENSOR_THRESH_CMD = "0x27 {}" +IPMI_FRU_MODEL_KEY = "Board Part Number" +IPMI_FRU_SERIAL_KEY = "Board Serial" + +PSU_LED_OFF_CMD = "0x00" +PSU_LED_GREEN_CMD = "0x01" +PSU_LED_AMBER_CMD = "0x02" + +psu_ipmi_id = {\ + 1: {\ + "TEMP": "0x34",\ + "VOUT": "0x36",\ + "COUT": "0x37",\ + "POUT": "0x38",\ + "STATUS": "0x2f",\ + "FRU": 3,\ + }, + 2: {\ + "TEMP": "0x3E",\ + "VOUT": "0x40",\ + "COUT": "0x41",\ + "POUT": "0x42",\ + "STATUS": "0x39",\ + "FRU": 4,\ + } +} + +ANALOG_READ_OFFSET = 0 +EVENT_0_7_OFFSET = 2 +EVENT_8_14_OFFSET = 3 + +FRU_SERIAL = 3 +FRU_MODEL = 4 + +TH_LNC = 0 # Low Non-critical threshold +TH_LCR = 1 # Low Critical threshold +TH_LNR = 2 # Low Non-recoverable threshold +TH_HNC = 3 # High Non-critical threshold +TH_HCR = 4 # High Critical threshold +TH_HNR = 5 # High Non-recoverable threshold + +PSU_VOUT_SS_ID = ["0x36", "0x40"] +PSU_COUT_SS_ID = ["0x37", "0x41"] +PSU_POUT_SS_ID = ["0x38", "0x42"] +PSU_STATUS_REG = ["0x39", "0x2f"] + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index+1 + # PSU has only one FAN + fan = Fan(0, 0, is_psu_fan=True, psu_index=psu_index) + self._fan_list.append(fan) + self._api_helper = APIHelper() + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = 0.0 + psu_vout_key = psu_ipmi_id[self.index]['VOUT'] + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_READ_CMD.format(psu_vout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx6x10^-2 + psu_voltage = int(value, 16) * 6 / 100.0 + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + psu_current = 0.0 + psu_cout_key = psu_ipmi_id[self.index]['COUT'] + status, output = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_cout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx57x10^-2 + psu_current = int(value, 16) * 57 / 100.0 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + psu_power = 0.0 + psu_pout_key = psu_ipmi_id[self.index]['POUT'] + status, output = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pout_key)) + value = output.split()[ANALOG_READ_OFFSET] + # Formula: Rx68x10^-1 + psu_power = int(value, 16) * 68 / 10.0 + + return psu_power + + 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. + """ + return self.get_status() + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if not self.get_presence(): + return "N/A" + + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + + return self.STATUS_LED_COLOR_OFF + + def __get_sensor_threshold(self, sensor_id, th_offset): + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_THRESH_CMD.format(sensor_id)) + if status: + value = output.split() + if (int(value[0],16) >> th_offset) & 0x01 == 0x01: + return value[th_offset + 1] + + raise NotImplementedError + + 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 + """ + # PSU's ambient temperature sensor is considered as the PSU temperature + psu_temp = 0.0 + psu_temp_id = psu_ipmi_id[self.index]['TEMP'] + status, output = self._api_helper.ipmi_raw(IPMI_SENSOR_NETFN,\ + IPMI_SENSOR_READ_CMD.format(psu_temp_id)) + if status: + value = output.split()[ANALOG_READ_OFFSET] + psu_temp = float(int(value, 16)) + + return psu_temp + + 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 + """ + # Using critical-high as high threshold + + value = self.__get_sensor_threshold(psu_ipmi_id[self.index]['TEMP'], TH_HCR) + psu_temp_high_threshold = float(int(value, 16)) + + return psu_temp_high_threshold + + 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 + """ + # Using critical-high as high threshold + + value = self.__get_sensor_threshold(psu_ipmi_id[self.index]['VOUT'], TH_HCR) + # Formula: Rx6x10^-2 + psu_voltage_high_crit = int(value, 16) * 6 / 100.0 + + return psu_voltage_high_crit + + 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 + """ + # Using critical-low as low threshold + + value = self.__get_sensor_threshold(psu_ipmi_id[self.index]['VOUT'], TH_LCR) + # Formula: Rx6x10^-2 + psu_voltage_low_crit = int(value, 16) * 6 / 100.0 + + return psu_voltage_low_crit + + 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 + """ + # Using critical-high as the maximum available safe power limit + + value = self.__get_sensor_threshold(psu_ipmi_id[self.index]['POUT'], TH_HCR) + # Formula: Rx12x10^0 + psu_power_high_crit = int(value, 16) * 12.0 + + return psu_power_high_crit + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return "PSU {}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + psu_presence = False + psu_pstatus_key = psu_ipmi_id[self.index]['STATUS'] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pstatus_key)) + status_byte = raw_status_read.split()[EVENT_0_7_OFFSET] + + if status: + psu_presence = True if int(status_byte, 16) & 0x01 == 0x01 else False + + return psu_presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model = "Unknown" + if self.get_presence(): + ipmi_fru_idx = psu_ipmi_id[self.index]['FRU'] + status, raw_model = self._api_helper.ipmi_fru_id( + ipmi_fru_idx, IPMI_FRU_MODEL_KEY) + + fru_pn_list = raw_model.split() + if len(fru_pn_list) > FRU_MODEL: + model = fru_pn_list[FRU_MODEL] + else: + model = "N/A" + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + serial = "Unknown" + if self.get_presence(): + ipmi_fru_idx = psu_ipmi_id[self.index]['FRU'] + status, raw_model = self._api_helper.ipmi_fru_id( + ipmi_fru_idx, IPMI_FRU_SERIAL_KEY) + + fru_sr_list = raw_model.split() + if len(fru_sr_list) > FRU_SERIAL: + serial = fru_sr_list[FRU_SERIAL] + else: + model = "N/A" + + return serial + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + psu_status = False + psu_pstatus_key = psu_ipmi_id[self.index]['STATUS'] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SENSOR_READ_CMD.format(psu_pstatus_key)) + status_byte = raw_status_read.split()[EVENT_0_7_OFFSET] + + if status: + failure_detected = True if int(status_byte, 16) & 0x02 == 0x02 else False + input_lost = True if int(status_byte, 16) & 0x08 == 0x08 else False + psu_status = False if (input_lost or failure_detected) else True + + return psu_status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/sfp.py new file mode 100644 index 000000000000..204ee659f91d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/sfp.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the sfp status which are available in the platform +# +############################################################################# + +import time + +try: + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +SFP_I2C_START = 10 +I2C_EEPROM_PATH = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' +RESET_PATH = '/sys/devices/platform/cls-xcvr/hwmon/hwmon{0}/qsfp_resetL' +LP_PATH = '/sys/devices/platform/cls-xcvr/hwmon/hwmon{0}/qsfp_lpmode' +PRS_PATH = '/sys/devices/platform/cls-xcvr/hwmon/hwmon{0}/qsfp_modprsL' + + +class Sfp(SfpOptoeBase): + """Platform-specific SfpOptoe class""" + + def __init__(self, sfp_index=0, sfp_name=None): + SfpOptoeBase.__init__(self) + + self.index = sfp_index + 1 + self._api_helper = APIHelper() + self._name = sfp_name + self._sfp_type = None + + def _detect_sfp_type(self): + sfp_type = 'N/A' + info = self.get_transceiver_info() + if info: + sfp_type = info.get("type_abbrv_name") + # XXX: Need this hack until xcvrd is refactored + if sfp_type in ["OSFP-8X", "QSFP-DD"]: + sfp_type = "QSFP_DD" + return sfp_type + + @property + def sfp_type(self): + if self._sfp_type is None: + self._sfp_type = self._detect_sfp_type() + return self._sfp_type + + def get_eeprom_path(self): + port_to_i2c_mapping = SFP_I2C_START + self.index - 1 + port_eeprom_path = I2C_EEPROM_PATH.format(port_to_i2c_mapping) + return port_eeprom_path + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._name + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.get_presence(): + return False + reset = self.get_reset_status() + if reset: + status = False + else: + status = True + return status + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_status_raw = self._api_helper.read_txt_file( + RESET_PATH.format((self.index))).rstrip() + if not reset_status_raw: + return False + + reg_value = int(reset_status_raw, 16) + bin_format = bin(reg_value)[2:].zfill(32) + return bin_format[::-1][self.index - 1] == '0' + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + presence_status_raw = self._api_helper.read_txt_file( + PRS_PATH.format((self.index))).rstrip() + + if not presence_status_raw: + return False + + content = presence_status_raw.rstrip() + reg_value = int(content, 16) + + + # Mask absent + absence_mask = 0x1 + + # ModPrsL is active low + if reg_value & absence_mask == 0: + return True + + return False + + 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 + """ + try: + with open(LP_PATH.format((self.index))) as reg_file: + content = reg_file.readline().rstrip() + lpmode = int(content, 16) + except (ValueError, IOError) as e: + return False + + # check LPMode is active low + if lpmode == 0: + return False + + return True + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + # Check for invalid port_num + + try: + reg_file = open(RESET_PATH.format((self.index)), "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the + # register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + bit_index = self.index - 1 + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + reg_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + # Flip the bit back high and write back to the register + # to take port out of reset + try: + reg_file = open(RESET_PATH.format((self.index)), "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + reg_file.close() + + return True + + def 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 + """ + try: + with open(LP_PATH.format((self.index)), "r+") as reg_file: + reg_file.seek(0) + content = hex(lpmode) + reg_file.write(content) + except IOError as e: + return False + + return True + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + Returns: + String that represents the current error descriptions of + vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + if self.sfp_type == "QSFP_DD": + return super().get_error_description() + + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + return self.SFP_STATUS_OK + + def get_position_in_parent(self): + return self.index + + def is_replaceable(self): + return True diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/thermal.py new file mode 100644 index 000000000000..9f0c9e17adfa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/thermal.py @@ -0,0 +1,205 @@ +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import re +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +IPMI_SENSOR_NETFN = "0x04" +IPMI_SS_READ_CMD = "0x2D {}" +IPMI_SS_THRESHOLD_CMD = "0x27 {}" +HIGH_TRESHOLD_SET_KEY = "unc" +DEFAULT_VAL = 'N/A' + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self._api_helper = APIHelper() + self.index = thermal_index + thermal_list = [\ + ('TEMP_FAN_U52', '0x00', 'Fanboard Center Temp'),\ + ('TEMP_FAN_U17', '0x01', 'Fanboard Right Temp'),\ + ('TEMP_SW_U52', '0x02', 'Switchboard Left Temp'),\ + ('TEMP_SW_U16', '0x03', 'Switchboard Right Temp'),\ + ('TEMP_BB_U3', '0x04', 'Baseboard Temp'),\ + ('TEMP_CPU', '0x05', 'CPU Internal Temp'),\ + ('TEMP_SW_Internal', '0x61', 'ASIC Internal Temp'),\ + ('SW_U04_Temp', '0x4F', 'IR35215 Chip Left Temp'),\ + ('SW_U14_Temp', '0x56', 'IR35215 Chip Right Temp'),\ + ('SW_U4403_Temp', '0x5D', 'IR3584 Chip Temp'),\ + ('PSU1_Temp1', '0x34', 'PSU 1 Ambient Temp'),\ + ('PSU1_Temp2', '0x35', 'PSU 1 Hotspot Temp'),\ + ('PSU2_Temp1', '0x3E', 'PSU 2 Ambient Temp'),\ + ('PSU2_Temp2', '0x3F', 'PSU 2 Hotspot Temp'),\ + ] + self.sensor_id = thermal_list[self.index][0] + self.sensor_reading_addr = thermal_list[self.index][1] + self.sensor_name = thermal_list[self.index][2] + + temp = self.get_temperature(True) + self.minimum_thermal = temp + self.maximum_thermal = temp + + def get_temperature(self, skip_record=False): + """ + 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 + """ + temperature = 0.0 + status, raw_ss_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(self.sensor_reading_addr)) + if status and len(raw_ss_read.split()) > 0: + ss_read = raw_ss_read.split()[0] + temperature = float(int(ss_read, 16)) + + if temperature != 0.0: + if not skip_record: + # Record maximum + if temperature > self.maximum_thermal: + self.maximum_thermal = temperature + + # Record minimum + if temperature < self.minimum_thermal: + self.minimum_thermal = temperature + + return temperature + else: + return DEFAULT_VAL + + 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 + """ + high_threshold = 0.0 + status, raw_up_thres_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr)) + if status and len(raw_up_thres_read.split()) > 6: + ss_read = raw_up_thres_read.split()[4] + high_threshold = float(int(ss_read, 16)) + if high_threshold != 0.0: + return high_threshold + else: + return DEFAULT_VAL + + 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 + """ + return DEFAULT_VAL + + 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 + """ + status, ret_txt = self._api_helper.ipmi_set_ss_thres( + self.sensor_id, HIGH_TRESHOLD_SET_KEY, temperature) + return status + + 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 + """ + 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 + """ + high_critical_threshold = 0.0 + status, raw_up_thres_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr)) + if status and len(raw_up_thres_read.split()) > 6: + ss_read = raw_up_thres_read.split()[5] + high_critical_threshold = float(int(ss_read, 16)) + if high_critical_threshold != 0.0: + return high_critical_threshold + else: + return DEFAULT_VAL + + 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 + """ + return 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 + """ + return self.maximum_thermal + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.sensor_name + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True if self.get_temperature() > 0 else False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() + + def is_replaceable(self): + """ + Retrieves whether thermal module is replaceable + Returns: + A boolean value, True if replaceable, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/watchdog.py new file mode 100644 index 000000000000..011759b0f457 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/sonic_platform/watchdog.py @@ -0,0 +1,247 @@ +############################################################################# +# Celestica Silverstone +# +# Watchdog contains an implementation of SONiC Platform Base API +# +############################################################################# +import os +import time +import ctypes +import fcntl +import subprocess +import array +import syslog + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +PLATFORM_CPLD_PATH = '/sys/devices/platform/baseboard-lpc/' +WDT_TIMER_REG = '0xA181' +WDT_ENABLE_REG = '0xA182' +WDT_FEED_REG = '0xA183' +WDT_REMAINTIME_REG1 = '0xA185' +WDT_REMAINTIME_REG2 = '0xA186' +ENABLE_CMD = 0x1 +DISABLE_CMD = 0x0 +WDT_COMMON_ERROR = -1 + + +class Watchdog(WatchdogBase): + + timeout = 0 + + def __init__(self): + WatchdogBase.__init__(self) + + # Set default value + #self._disable() + #self.timeout = self._gettimeout() + self.keepalive = int(1) + + def _get_lpc_reg(self, reg): + file_path = os.path.join(PLATFORM_CPLD_PATH, 'getreg') + status = True + value = None + + try: + with open(file_path, "r+") as fd: + fd.seek(0) + fd.write(reg) + except IOError as e: + syslog.syslog(syslog.LOG_ERR, "Unable to access file: {}".format(e)) + return False, None + try: + with open(file_path) as fd: + value = fd.readline().rstrip() + except IOError as e: + syslog.syslog(syslog.LOG_ERR, "Unable to access file: {}".format(e)) + return False, None + return True, value + + def _set_lpc_reg(self, reg, val): + file_path = os.path.join(PLATFORM_CPLD_PATH, 'setreg') + value = '{} {}'.format(reg, hex(val)) + + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def _enable(self): + """ + Turn on the watchdog timer + """ + # echo 0xA182 0x1 > /sys/devices/platform/baseboard-lpc/setreg + status = self._set_lpc_reg(WDT_ENABLE_REG, ENABLE_CMD) + + if not status: + return False + + return True + + def _disable(self): + """ + Trun off the watchdog timer + """ + # echo 0xA182 0x0 > /sys/devices/platform/baseboard-lpc/setreg + status = self._set_lpc_reg(WDT_ENABLE_REG, DISABLE_CMD) + if not status: + return False + + return True + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + if bool(self.keepalive % 2): + status = self._set_lpc_reg(WDT_FEED_REG, ENABLE_CMD) + else: + status = self._set_lpc_reg(WDT_FEED_REG, DISABLE_CMD) + + if not status: + syslog.syslog(syslog.LOG_ERR, "Feed Watchdog failed") + + self.keepalive = self.keepalive+1 + if (self.keepalive >= 11): + self.keepalive = 1 + + def _settimeout(self, seconds): + """ + set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + second_int = { + 30: 1, + 60: 2, + 180: 3, + 240: 4, + 300: 5, + 420: 6, + 600: 7, + }.get(seconds) + + status = self._set_lpc_reg(WDT_TIMER_REG, second_int) + if not status: + syslog.syslog(syslog.LOG_ERR, "Set timeout failed") + return self._gettimeout() + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + status, data = self._get_lpc_reg(WDT_TIMER_REG) + if status: + pass + + bin_val = bin(int(data, 16))[2:].zfill(3) + + return { + '001': 30, + '010': 60, + '011': 180, + '100': 240, + '101': 300, + '110': 420, + '111': 600, + }.get(bin_val) + + 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. + """ + avaliable_second = [30, 60, 180, 240, 300, 420, 600] + ret = WDT_COMMON_ERROR + + if seconds < 0 or seconds not in avaliable_second: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + + if self.is_armed(): + self._keepalive() + else: + status = self._enable() + if not status: + syslog.syslog(syslog.LOG_ERR, "Enable watchdog failed") + return ret + + ret = self.timeout + except IOError as e: + syslog.syslog(syslog.LOG_ERR, "{}".format(e)) + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + status = self._disable() + if status: + disarmed = True + except IOError: + syslog.syslog(syslog.LOG_ERR, "{}".format(e)) + + return disarmed + + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + status, data = self._get_lpc_reg(WDT_ENABLE_REG) + if status: + pass + + armed = int(data, 16) & 0x1 + + return bool(armed) + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + Retruns: + An integer specifying the number of seconds remaining on the + watchdog timer. If the watchdog is not armed, returns -1 + """ + retime = 0 + + status, data1 = self._get_lpc_reg(WDT_REMAINTIME_REG1) + if status: + pass + + status, data2 = self._get_lpc_reg(WDT_REMAINTIME_REG2) + if status: + pass + + retime = (int(data2,16) & 0xff) + ((int(data1,16) & 0x3f) * 256) + + if retime <= 0: + return WDT_COMMON_ERROR + else: + return int(retime/10)