From be4cf09b5ddac134b0f76456f6d46ff29d4b6f12 Mon Sep 17 00:00:00 2001 From: guxianghong Date: Sun, 2 May 2021 01:37:07 +0800 Subject: [PATCH] [Centec][arm64] support new board E530-48s4x and E530-24x2q (#7189) 1. support new board E530-48s4x E530-24x2q 2. optimize platform driver for Centec TsingMa board Co-authored-by: shi lei --- .../E530-24x2c/port_config.ini | 54 +- .../arm64-centec_e530_24x2c-r0/fancontrol | 11 + .../platform_components.json | 8 + .../platform_reboot | 11 + .../plugins/eeprom.py | 4 +- .../plugins/led_control.py | 123 +- .../plugins/psuutil.py | 5 +- .../plugins/sfputil.py | 221 +-- .../pmon_daemon_control.json | 3 + .../E530-24x2q/buffers.json.j2 | 70 + .../E530-24x2q/pg_profile_lookup.ini | 21 + .../E530-24x2q/port_config.ini | 27 + .../E530-24x2q/qos.json.j2 | 1 + .../E530-24x2q/sai.profile | 2 + .../arm64-centec_e530_24x2q-r0/default_sku | 1 + .../arm64-centec_e530_24x2q-r0/fancontrol | 12 + .../arm64-centec_e530_24x2q-r0/installer.conf | 0 .../platform_components.json | 8 + .../platform_reboot | 11 + .../plugins/eeprom.py | 22 + .../plugins/led_control.py | 165 +++ .../plugins/psuutil.py | 72 + .../plugins/sfputil.py | 200 +++ .../pmon_daemon_control.json | 3 + .../E530-48s4x/buffers.json.j2 | 70 + .../E530-48s4x/pg_profile_lookup.ini | 21 + .../E530-48s4x/port_config.ini | 53 + .../E530-48s4x/qos.json.j2 | 1 + .../E530-48s4x/sai.profile | 2 + .../arm64-centec_e530_48s4x-r0/default_sku | 1 + .../arm64-centec_e530_48s4x-r0/fancontrol | 12 + .../arm64-centec_e530_48s4x-r0/installer.conf | 0 .../platform_components.json | 8 + .../platform_reboot | 12 + .../plugins/eeprom.py | 22 + .../plugins/led_control.py | 98 ++ .../plugins/psuutil.py | 72 + .../plugins/sfputil.py | 161 +++ .../pmon_daemon_control.json | 3 + .../E530-48t4x-p/port_config.ini | 106 +- .../arm64-centec_e530_48t4x_p-r0/fancontrol | 11 + .../platform_components.json | 8 + .../platform_reboot | 11 + .../plugins/eeprom.py | 4 +- .../plugins/led_control.py | 9 +- .../plugins/psuutil.py | 5 +- .../plugins/sfputil.py | 78 +- .../pmon_daemon_control.json | 3 + .../plugins/sfputil.py | 2 +- platform/centec-arm64/one-image.mk | 2 + .../platform-modules-centec-e530.mk | 14 +- platform/centec-arm64/platform.conf | 56 +- platform/centec-arm64/sai.mk | 2 +- .../24x2c/setup.py | 8 +- .../24x2c/sonic_platform/__init__.py | 3 + .../24x2c/sonic_platform/chassis.py | 203 +++ .../24x2c/sonic_platform/eeprom.py | 111 ++ .../24x2c/sonic_platform/fan.py | 186 +++ .../24x2c/sonic_platform/fan_drawer.py | 36 + .../24x2c/sonic_platform/platform.py | 21 + .../24x2c/sonic_platform/psu.py | 45 + .../24x2c/sonic_platform/sfp.py | 102 ++ .../24x2c/sonic_platform/thermal.py | 118 ++ .../24x2q/modules/Makefile | 1 + .../modules/centec_e530_24x2q_platform.c | 1111 ++++++++++++++++ .../24x2q/service/24x2q_platform.service | 13 + .../24x2q/setup.py | 15 + .../24x2q/sonic_platform/__init__.py | 3 + .../24x2q/sonic_platform/chassis.py | 203 +++ .../24x2q/sonic_platform/eeprom.py | 111 ++ .../24x2q/sonic_platform/fan.py | 186 +++ .../24x2q/sonic_platform/fan_drawer.py | 36 + .../24x2q/sonic_platform/platform.py | 21 + .../24x2q/sonic_platform/psu.py | 45 + .../24x2q/sonic_platform/sfp.py | 102 ++ .../24x2q/sonic_platform/thermal.py | 118 ++ .../48s4x/modules/Makefile | 1 + .../modules/centec_e530_48s4x_platform.c | 1184 +++++++++++++++++ .../48s4x/service/48s4x_platform.service | 13 + .../48s4x/setup.py | 15 + .../48s4x/sonic_platform/__init__.py | 3 + .../48s4x/sonic_platform/chassis.py | 173 +++ .../48s4x/sonic_platform/eeprom.py | 111 ++ .../48s4x/sonic_platform/fan.py | 186 +++ .../48s4x/sonic_platform/fan_drawer.py | 36 + .../48s4x/sonic_platform/platform.py | 21 + .../48s4x/sonic_platform/psu.py | 45 + .../48s4x/sonic_platform/sfp.py | 102 ++ .../48s4x/sonic_platform/thermal.py | 118 ++ .../{48t4x_p => 48t4x-p}/modules/Makefile | 0 .../modules/centec_e530_48t4x_p_platform.c | 83 +- .../service/48t4x_p_platform.service | 0 .../{48t4x_p => 48t4x-p}/setup.py | 8 +- .../48t4x-p/sonic_platform/__init__.py | 3 + .../48t4x-p/sonic_platform/chassis.py | 173 +++ .../48t4x-p/sonic_platform/eeprom.py | 111 ++ .../48t4x-p/sonic_platform/fan.py | 186 +++ .../48t4x-p/sonic_platform/fan_drawer.py | 36 + .../48t4x-p/sonic_platform/platform.py | 21 + .../48t4x-p/sonic_platform/psu.py | 45 + .../48t4x-p/sonic_platform/sfp.py | 102 ++ .../48t4x-p/sonic_platform/thermal.py | 118 ++ .../debian/changelog | 12 + .../debian/control | 10 + .../debian/platform-modules-e530-24x2c.init | 21 + .../platform-modules-e530-24x2c.install | 5 +- .../debian/platform-modules-e530-24x2q.init | 82 ++ .../platform-modules-e530-24x2q.install | 2 + .../platform-modules-e530-24x2q.postinst | 2 + .../debian/platform-modules-e530-48s4x.init | 82 ++ .../platform-modules-e530-48s4x.install | 2 + .../platform-modules-e530-48s4x.postinst | 2 + .../debian/platform-modules-e530-48t4x-p.init | 21 + .../platform-modules-e530-48t4x-p.install | 5 +- .../sonic-platform-modules-e530/debian/rules | 23 +- .../sonic-platform-modules-e530/fan/Makefile | 1 + .../fan/fan-ctc5236.c | 268 ++++ platform/centec/centec-dal/dal_common.h | 66 +- platform/centec/centec-dal/dal_kernel.c | 481 ++++--- platform/centec/centec-dal/dal_kernel.h | 20 +- platform/centec/centec-dal/dal_mpool.c | 31 +- 121 files changed, 8259 insertions(+), 471 deletions(-) create mode 100644 device/centec/arm64-centec_e530_24x2c-r0/platform_components.json create mode 100755 device/centec/arm64-centec_e530_24x2c-r0/platform_reboot create mode 100644 device/centec/arm64-centec_e530_24x2c-r0/pmon_daemon_control.json create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/buffers.json.j2 create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/pg_profile_lookup.ini create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/port_config.ini create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/qos.json.j2 create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/sai.profile create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/default_sku create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/fancontrol rename platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py => device/centec/arm64-centec_e530_24x2q-r0/installer.conf (100%) create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/platform_components.json create mode 100755 device/centec/arm64-centec_e530_24x2q-r0/platform_reboot create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/plugins/eeprom.py create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/plugins/led_control.py create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/plugins/psuutil.py create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/plugins/sfputil.py create mode 100644 device/centec/arm64-centec_e530_24x2q-r0/pmon_daemon_control.json create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/buffers.json.j2 create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/pg_profile_lookup.ini create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/port_config.ini create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/qos.json.j2 create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/sai.profile create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/default_sku create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/fancontrol rename platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py => device/centec/arm64-centec_e530_48s4x-r0/installer.conf (100%) create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/platform_components.json create mode 100755 device/centec/arm64-centec_e530_48s4x-r0/platform_reboot create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/plugins/eeprom.py create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/plugins/led_control.py create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/plugins/psuutil.py create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/plugins/sfputil.py create mode 100644 device/centec/arm64-centec_e530_48s4x-r0/pmon_daemon_control.json create mode 100644 device/centec/arm64-centec_e530_48t4x_p-r0/platform_components.json create mode 100755 device/centec/arm64-centec_e530_48t4x_p-r0/platform_reboot create mode 100644 device/centec/arm64-centec_e530_48t4x_p-r0/pmon_daemon_control.json create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/chassis.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/eeprom.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan_drawer.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/platform.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/psu.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/sfp.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/thermal.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/centec_e530_24x2q_platform.c create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/service/24x2q_platform.service create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/setup.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/chassis.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/eeprom.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan_drawer.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/platform.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/psu.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/sfp.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/thermal.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/centec_e530_48s4x_platform.c create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/service/48s4x_platform.service create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/setup.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/chassis.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/eeprom.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan_drawer.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/platform.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/psu.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/sfp.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/thermal.py rename platform/centec-arm64/sonic-platform-modules-e530/{48t4x_p => 48t4x-p}/modules/Makefile (100%) rename platform/centec-arm64/sonic-platform-modules-e530/{48t4x_p => 48t4x-p}/modules/centec_e530_48t4x_p_platform.c (93%) rename platform/centec-arm64/sonic-platform-modules-e530/{48t4x_p => 48t4x-p}/service/48t4x_p_platform.service (100%) rename platform/centec-arm64/sonic-platform-modules-e530/{48t4x_p => 48t4x-p}/setup.py (54%) create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/__init__.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/chassis.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/eeprom.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan_drawer.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/platform.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/psu.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/sfp.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/thermal.py create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.init create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.install create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.postinst create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.init create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.install create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.postinst create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/fan/Makefile create mode 100644 platform/centec-arm64/sonic-platform-modules-e530/fan/fan-ctc5236.c diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini index 27d43a0ab..454440e10 100644 --- a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini @@ -1,27 +1,27 @@ -# name lanes alias speed -Ethernet1 0 eth-0-1 10000 -Ethernet2 1 eth-0-2 10000 -Ethernet3 2 eth-0-3 10000 -Ethernet4 3 eth-0-4 10000 -Ethernet5 8 eth-0-5 10000 -Ethernet6 9 eth-0-6 10000 -Ethernet7 10 eth-0-7 10000 -Ethernet8 11 eth-0-8 10000 -Ethernet9 20 eth-0-9 10000 -Ethernet10 21 eth-0-10 10000 -Ethernet11 22 eth-0-11 10000 -Ethernet12 23 eth-0-12 10000 -Ethernet13 12 eth-0-13 10000 -Ethernet14 13 eth-0-14 10000 -Ethernet15 14 eth-0-15 10000 -Ethernet16 15 eth-0-16 10000 -Ethernet17 24 eth-0-17 10000 -Ethernet18 25 eth-0-18 10000 -Ethernet19 26 eth-0-19 10000 -Ethernet20 27 eth-0-20 10000 -Ethernet21 28 eth-0-21 10000 -Ethernet22 29 eth-0-22 10000 -Ethernet23 30 eth-0-23 10000 -Ethernet24 31 eth-0-24 10000 -Ethernet25 61,60,63,62 eth-0-25 100000 -Ethernet26 45,44,47,46 eth-0-26 100000 +# name lanes alias index speed fec +Ethernet0 0 eth-0-1 0 10000 none +Ethernet1 1 eth-0-2 1 10000 none +Ethernet2 2 eth-0-3 2 10000 none +Ethernet3 3 eth-0-4 3 10000 none +Ethernet4 8 eth-0-5 4 10000 none +Ethernet5 9 eth-0-6 5 10000 none +Ethernet6 10 eth-0-7 6 10000 none +Ethernet7 11 eth-0-8 7 10000 none +Ethernet8 20 eth-0-9 8 10000 none +Ethernet9 21 eth-0-10 9 10000 none +Ethernet10 22 eth-0-11 10 10000 none +Ethernet11 23 eth-0-12 11 10000 none +Ethernet12 12 eth-0-13 12 10000 none +Ethernet13 13 eth-0-14 13 10000 none +Ethernet14 14 eth-0-15 14 10000 none +Ethernet15 15 eth-0-16 15 10000 none +Ethernet16 24 eth-0-17 16 10000 none +Ethernet17 25 eth-0-18 17 10000 none +Ethernet18 26 eth-0-19 18 10000 none +Ethernet19 27 eth-0-20 19 10000 none +Ethernet20 28 eth-0-21 20 10000 none +Ethernet21 29 eth-0-22 21 10000 none +Ethernet22 30 eth-0-23 22 10000 none +Ethernet23 31 eth-0-24 23 10000 none +Ethernet24 61,60,63,62 eth-0-25 24 100000 none +Ethernet25 45,44,47,46 eth-0-26 25 100000 none diff --git a/device/centec/arm64-centec_e530_24x2c-r0/fancontrol b/device/centec/arm64-centec_e530_24x2c-r0/fancontrol index e37752971..4fbc9cba3 100644 --- a/device/centec/arm64-centec_e530_24x2c-r0/fancontrol +++ b/device/centec/arm64-centec_e530_24x2c-r0/fancontrol @@ -1 +1,12 @@ # Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236 +DEVNAME=hwmon1=ctc5236fan +FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input +MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30 +MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90 +MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12 +MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 +MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 +MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/platform_components.json b/device/centec/arm64-centec_e530_24x2c-r0/platform_components.json new file mode 100644 index 000000000..1e1e968f6 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "E530-24x2c": { + "component": { + } + } + } +} diff --git a/device/centec/arm64-centec_e530_24x2c-r0/platform_reboot b/device/centec/arm64-centec_e530_24x2c-r0/platform_reboot new file mode 100755 index 000000000..f22723f98 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/platform_reboot @@ -0,0 +1,11 @@ +#!/usr/bin/python +import os + +def main(): + # reboot the system + os.system('echo 502 > /sys/class/gpio/export') + os.system('echo out > /sys/class/gpio/gpio502/direction') + os.system('echo 1 > /sys/class/gpio/gpio502/value') + +if __name__ == "__main__": + main() diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py index afea818be..4a7613c40 100644 --- a/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + ############################################################################# # Centec E550-24X8Y2C # @@ -10,7 +12,7 @@ try: from sonic_eeprom import eeprom_tlvinfo except ImportError as e: - raise ImportError(str(e) + "- required module not found") + raise ImportError (str(e) + "- required module not found") class board(eeprom_tlvinfo.TlvInfoDecoder): diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py index 627cf03dd..13ec67e97 100644 --- a/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # # led_control.py # @@ -5,37 +6,110 @@ # try: - from sonic_led.led_control_base import LedControlBase + import os + import re import syslog - from socket import * - from select import * + import collections + from sonic_led.led_control_base import LedControlBase + from sonic_py_common import device_info except ImportError as e: raise ImportError(str(e) + " - required module not found") +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" def DBG_PRINT(str): syslog.openlog("centec-led") syslog.syslog(syslog.LOG_INFO, str) syslog.closelog() - class LedControl(LedControlBase): """Platform specific LED control class""" + # Constructor + def __init__(self): + + self.mac_to_led = { + 0: 1, + 1: 2, + 2: 3, + 3: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 8, + 20: 9, + 21:10, + 22:11, + 23:12, + 12:13, + 13:14, + 14:15, + 15:16, + 24:17, + 25:18, + 26:19, + 27:20, + 28:21, + 29:22, + 30:23, + 31:24, + 61:-1, + 60:25, + 63:-1, + 62:-1, + 45:-1, + 44:26, + 47:-1, + 46:-1, + } + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + self.LED_MODE_UP = [11, 11] + self.LED_MODE_DOWN = [7, 7] + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() + # Helper method to map SONiC port name to index def _port_name_to_index(self, port_name): - # Strip "Ethernet" off port name - if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): - return -1 - - port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) - return port_idx + for port_cfg in self._port_cfgs: + if port_name == port_cfg.name: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + return None + return led + return None def _port_state_to_mode(self, port_idx, state): if state == "up": - return self.LED_MODE_UP[0] if (port_idx < 25) else self.LED_MODE_UP[1] + return self.LED_MODE_UP[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_UP[0] else: - return self.LED_MODE_DOWN[0] if (port_idx < 25) else self.LED_MODE_DOWN[1] + return self.LED_MODE_DOWN[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_DOWN[0] def _port_led_mode_update(self, port_idx, ledMode): with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: @@ -57,11 +131,15 @@ class LedControl(LedControlBase): shouldInit = (int(led_file.read()) == 0) if shouldInit == True: - for idx in range(1, 27): - defmode = self._port_state_to_mode(idx, "down") - with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + for port_cfg in self._port_cfgs: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + continue + defmode = self._port_state_to_mode(led, "down") + with open(self.f_led.format("port{}".format(led)), 'w') as led_file: led_file.write(str(defmode)) - DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + DBG_PRINT("init port{} led to mode={}".format(led, defmode)) def _initDefaultConfig(self): DBG_PRINT("start init led") @@ -72,9 +150,10 @@ class LedControl(LedControlBase): DBG_PRINT("init led done") # Concrete implementation of port_link_state_change() method - def port_link_state_change(self, portname, state): port_idx = self._port_name_to_index(portname) + if port_idx is None: + return ledMode = self._port_state_to_mode(port_idx, state) with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: saveMode = int(led_file.read()) @@ -84,13 +163,3 @@ class LedControl(LedControlBase): self._port_led_mode_update(port_idx, ledMode) DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) - - # Constructor - - def __init__(self): - self.SONIC_PORT_NAME_PREFIX = "Ethernet" - self.LED_MODE_UP = [11, 11] - self.LED_MODE_DOWN = [7, 7] - - self.f_led = "/sys/class/leds/{}/brightness" - self._initDefaultConfig() diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py index 3a83f406d..1e83c12c1 100644 --- a/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + ############################################################################# # Centec # @@ -9,8 +11,7 @@ try: from sonic_psu.psu_base import PsuBase except ImportError as e: - raise ImportError(str(e) + "- required module not found") - + raise ImportError (str(e) + "- required module not found") class PsuUtil(PsuBase): """Platform-specific PSUutil class""" diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py index c5c0dc8e1..3ae79108c 100644 --- a/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py @@ -1,28 +1,117 @@ +#!/usr/bin/env python + # sfputil.py # # Platform-specific SFP transceiver interface for SONiC # try: + import os + import re import time - from socket import * - from select import * + import collections from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_py_common import device_info except ImportError as e: raise ImportError("%s - required module not found" % str(e)) - -def DBG_PRINT(str): - print(str + "\n") - - SFP_STATUS_INSERTED = '1' SFP_STATUS_REMOVED = '0' - +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" class SfpUtil(SfpUtilBase): """Platform-specific SfpUtil class""" + def __init__(self): + self.mac_to_sfp = { + 0: 1, + 1: 2, + 2: 3, + 3: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 8, + 20: 9, + 21:10, + 22:11, + 23:12, + 12:13, + 13:14, + 14:15, + 15:16, + 24:17, + 25:18, + 26:19, + 27:20, + 28:21, + 29:22, + 30:23, + 31:24, + 61:25, + 60:25, + 63:25, + 62:25, + 45:26, + 44:26, + 47:26, + 46:26, + } + self.logical = [] + self.physical_to_logical = {} + self.logical_to_physical = {} + self.logical_to_asic = {} + self.data = {'valid':0, 'last':0} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + self.PORT_START = 256 + self.PORT_END = 0 + for port_cfg in self._port_cfgs: + if int(port_cfg.index) <= self.PORT_START: + self.PORT_START = int(port_cfg.index) + elif int(port_cfg.index) >= self.PORT_END: + self.PORT_END = int(port_cfg.index) + + self.eeprom_mapping = {} + self.presence = {} + for port_cfg in self._port_cfgs: + sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])] + if sfp_idx > 0: + self.eeprom_mapping[int(port_cfg.index)] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(sfp_idx) + self.logical.append(port_cfg.name) + else: + self.eeprom_mapping[int(port_cfg.index)] = None + self.presence[int(port_cfg.index)] = False + + SfpUtilBase.__init__(self) + @property def port_start(self): return self.PORT_START @@ -33,11 +122,20 @@ class SfpUtil(SfpUtilBase): @property def sfp_base(self): - return self.SFP_BASE + return self.PORT_START @property def qsfp_ports(self): - return list(range(25, self.PORTS_IN_BLOCK + 1)) + start = 256 + end = 0 + for port_cfg in self._port_cfgs: + sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])] + if sfp_idx == 25 or sfp_idx == 26: + if int(port_cfg.index) <= start: + start = int(port_cfg.index) + elif int(port_cfg.index) >= end: + end = int(port_cfg.index) + return range(start, end + 1) @property def port_to_eeprom_mapping(self): @@ -46,93 +144,32 @@ class SfpUtil(SfpUtilBase): def is_logical_port(self, port_name): return True - def get_eeprom_data(self, port): - ret = None - port_num = self.get_logical_to_physical(port)[0] - if port_num < self.port_start or port_num > self.port_end: - return ret - if port_num < self.sfp_base: - return ret - try: - with open(self.eeprom_mapping[port_num], 'r') as eeprom_file: - ret = eeprom_file.read() - except IOError as e: - DBG_PRINT(str(e)) - - return ret - - # todo - # def _get_port_eeprom_path(self, port_num, devid): - # pass - - def __init__(self): - self.SONIC_PORT_NAME_PREFIX = "Ethernet" - self.PORT_START = 1 - self.PORT_END = 26 - self.SFP_BASE = 1 - self.PORTS_IN_BLOCK = 26 - self.logical = [] - self.physical_to_logical = {} - self.logical_to_physical = {} - - self.eeprom_mapping = {} - self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" - self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" - for x in range(self.port_start, self.sfp_base): - self.eeprom_mapping[x] = None - for x in range(self.sfp_base, self.port_end + 1): - self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format( - x - self.sfp_base + 1) - self.presence = {} - for x in range(self.sfp_base, self.port_end + 1): - self.presence[x] = False - - SfpUtilBase.__init__(self) - - for x in range(self.sfp_base, self.port_end + 1): - self.logical.append('Ethernet' + str(x)) - def get_presence(self, port_num): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - if port_num < self.sfp_base: - return False - try: - with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: - return 1 == int(sfp_file.read()) - except IOError as e: - DBG_PRINT(str(e)) - + for port_cfg in self._port_cfgs: + if int(port_cfg.index) == port_num: + sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])] + if sfp_idx >= 0: + try: + with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) return False def get_low_power_mode(self, port_num): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - return False def set_low_power_mode(self, port_num, lpmode): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - return False def reset(self, port_num): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - return False - def read_porttab_mappings(self, porttabfile): - for x in range(self.sfp_base, self.port_end + 1): - self.logical_to_physical['Ethernet' + str(x)] = [x] - self.physical_to_logical[x] = ['Ethernet' + str(x)] - - data = {'valid': 0, 'last': 0} + def read_porttab_mappings(self, porttabfile, asic_inst = 0): + for port_cfg in self._port_cfgs: + self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)] + self.logical_to_asic[port_cfg.name] = 0 + self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name] def get_transceiver_change_event(self, timeout=2000): now = time.time() @@ -140,19 +177,19 @@ class SfpUtil(SfpUtilBase): if timeout < 1000: timeout = 1000 - timeout = (timeout) / float(1000) # Convert to secs + timeout = (timeout) / float(1000) # Convert to secs if now < (self.data['last'] + timeout) and self.data['valid']: return True, {} - for x in range(self.sfp_base, self.port_end + 1): - presence = self.get_presence(x) - if presence != self.presence[x]: - self.presence[x] = presence + for port_cfg in self._port_cfgs: + presence = self.get_presence(int(port_cfg.index)) + if presence != self.presence[int(port_cfg.index)]: + self.presence[int(port_cfg.index)] = presence if presence: - port_dict[x] = SFP_STATUS_INSERTED + port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED else: - port_dict[x] = SFP_STATUS_REMOVED + port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED if bool(port_dict): self.data['last'] = now diff --git a/device/centec/arm64-centec_e530_24x2c-r0/pmon_daemon_control.json b/device/centec/arm64-centec_e530_24x2c-r0/pmon_daemon_control.json new file mode 100644 index 000000000..0db3279e4 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/buffers.json.j2 b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/buffers.json.j2 new file mode 100644 index 000000000..08e21e428 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/pg_profile_lookup.ini b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/pg_profile_lookup.ini new file mode 100644 index 000000000..a65244e69 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/port_config.ini b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/port_config.ini new file mode 100644 index 000000000..19847734e --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/port_config.ini @@ -0,0 +1,27 @@ +# name lanes alias index speed fec +Ethernet0 0 eth-0-1 0 10000 none +Ethernet1 1 eth-0-2 1 10000 none +Ethernet2 2 eth-0-3 2 10000 none +Ethernet3 3 eth-0-4 3 10000 none +Ethernet4 8 eth-0-5 4 10000 none +Ethernet5 9 eth-0-6 5 10000 none +Ethernet6 10 eth-0-7 6 10000 none +Ethernet7 11 eth-0-8 7 10000 none +Ethernet8 20 eth-0-9 8 10000 none +Ethernet9 21 eth-0-10 9 10000 none +Ethernet10 22 eth-0-11 10 10000 none +Ethernet11 23 eth-0-12 11 10000 none +Ethernet12 12 eth-0-13 12 10000 none +Ethernet13 13 eth-0-14 13 10000 none +Ethernet14 14 eth-0-15 14 10000 none +Ethernet15 15 eth-0-16 15 10000 none +Ethernet16 24 eth-0-17 16 10000 none +Ethernet17 25 eth-0-18 17 10000 none +Ethernet18 26 eth-0-19 18 10000 none +Ethernet19 27 eth-0-20 19 10000 none +Ethernet20 28 eth-0-21 20 10000 none +Ethernet21 29 eth-0-22 21 10000 none +Ethernet22 30 eth-0-23 22 10000 none +Ethernet23 31 eth-0-24 23 10000 none +Ethernet24 61,60,63,62 eth-0-25 24 40000 none +Ethernet25 45,44,47,46 eth-0-26 25 40000 none diff --git a/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/qos.json.j2 b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/qos.json.j2 new file mode 100644 index 000000000..3e548325e --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/sai.profile b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/sai.profile new file mode 100644 index 000000000..7dc47bf34 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/E530-24x2q/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E530-24x2q-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-24x2q-datapath-cfg.txt diff --git a/device/centec/arm64-centec_e530_24x2q-r0/default_sku b/device/centec/arm64-centec_e530_24x2q-r0/default_sku new file mode 100644 index 000000000..bbf54fb95 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/default_sku @@ -0,0 +1 @@ +E530-24x2q l2 diff --git a/device/centec/arm64-centec_e530_24x2q-r0/fancontrol b/device/centec/arm64-centec_e530_24x2q-r0/fancontrol new file mode 100644 index 000000000..4fbc9cba3 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236 +DEVNAME=hwmon1=ctc5236fan +FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input +MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30 +MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90 +MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12 +MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 +MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 +MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py b/device/centec/arm64-centec_e530_24x2q-r0/installer.conf similarity index 100% rename from platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py rename to device/centec/arm64-centec_e530_24x2q-r0/installer.conf diff --git a/device/centec/arm64-centec_e530_24x2q-r0/platform_components.json b/device/centec/arm64-centec_e530_24x2q-r0/platform_components.json new file mode 100644 index 000000000..a9fe4fd4e --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "E530-24x2q": { + "component": { + } + } + } +} diff --git a/device/centec/arm64-centec_e530_24x2q-r0/platform_reboot b/device/centec/arm64-centec_e530_24x2q-r0/platform_reboot new file mode 100755 index 000000000..f22723f98 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/platform_reboot @@ -0,0 +1,11 @@ +#!/usr/bin/python +import os + +def main(): + # reboot the system + os.system('echo 502 > /sys/class/gpio/export') + os.system('echo out > /sys/class/gpio/gpio502/direction') + os.system('echo 1 > /sys/class/gpio/gpio502/value') + +if __name__ == "__main__": + main() diff --git a/device/centec/arm64-centec_e530_24x2q-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_24x2q-r0/plugins/eeprom.py new file mode 100644 index 000000000..4a7613c40 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Centec E550-24X8Y2C +# +# 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 = "/dev/mtd3" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/arm64-centec_e530_24x2q-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_24x2q-r0/plugins/led_control.py new file mode 100644 index 000000000..e1ea93952 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/plugins/led_control.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + import os + import re + import syslog + import collections + from sonic_led.led_control_base import LedControlBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + # Constructor + def __init__(self): + + self.mac_to_led = { + 0: 1, + 1: 2, + 2: 3, + 3: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 8, + 20: 9, + 21:10, + 22:11, + 23:12, + 12:13, + 13:14, + 14:15, + 15:16, + 24:17, + 25:18, + 26:19, + 27:20, + 28:21, + 29:22, + 30:23, + 31:24, + 61:-1, + 60:25, + 63:-1, + 62:-1, + 45:-1, + 44:26, + 47:-1, + 46:-1, + } + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + self.LED_MODE_UP = [11, 11] + self.LED_MODE_DOWN = [7, 7] + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + for port_cfg in self._port_cfgs: + if port_name == port_cfg.name: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + return None + return led + return None + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_UP[0] + else: + return self.LED_MODE_DOWN[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_DOWN[0] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for port_cfg in self._port_cfgs: + macs = [int(x) for x in (port_cfg.lanes.split(','))] + led = self.mac_to_led[min(macs)] + if led < 0: + continue + defmode = self._port_state_to_mode(led, "down") + with open(self.f_led.format("port{}".format(led)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(led, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + if port_idx is None: + return + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) diff --git a/device/centec/arm64-centec_e530_24x2q-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_24x2q-r0/plugins/psuutil.py new file mode 100644 index 000000000..1e83c12c1 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/plugins/psuutil.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + 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 + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + 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 + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/centec/arm64-centec_e530_24x2q-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_24x2q-r0/plugins/sfputil.py new file mode 100644 index 000000000..ac5a937e7 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/plugins/sfputil.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import os + import re + import time + import collections + from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + def __init__(self): + self.mac_to_sfp = { + 0: 1, + 1: 2, + 2: 3, + 3: 4, + 8: 5, + 9: 6, + 10: 7, + 11: 8, + 20: 9, + 21:10, + 22:11, + 23:12, + 12:13, + 13:14, + 14:15, + 15:16, + 24:17, + 25:18, + 26:19, + 27:20, + 28:21, + 29:22, + 30:23, + 31:24, + 61:25, + 60:25, + 63:25, + 62:25, + 45:26, + 44:26, + 47:26, + 46:26, + } + self.logical = [] + self.physical_to_logical = {} + self.logical_to_physical = {} + self.logical_to_asic = {} + self.data = {'valid':0, 'last':0} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + self._port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + self.PORT_START = 256 + self.PORT_END = 0 + for port_cfg in self._port_cfgs: + if int(port_cfg.index) <= self.PORT_START: + self.PORT_START = int(port_cfg.index) + elif int(port_cfg.index) >= self.PORT_END: + self.PORT_END = int(port_cfg.index) + + self.eeprom_mapping = {} + self.presence = {} + for port_cfg in self._port_cfgs: + sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])] + if sfp_idx > 0: + self.eeprom_mapping[int(port_cfg.index)] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(sfp_idx) + self.logical.append(port_cfg.name) + else: + self.eeprom_mapping[int(port_cfg.index)] = None + self.presence[int(port_cfg.index)] = False + + SfpUtilBase.__init__(self) + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_base(self): + return self.PORT_START + + @property + def qsfp_ports(self): + start = 256 + end = 0 + for port_cfg in self._port_cfgs: + sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])] + if sfp_idx == 25 or sfp_idx == 26: + if int(port_cfg.index) <= start: + start = int(port_cfg.index) + elif int(port_cfg.index) >= end: + end = int(port_cfg.index) + return range(start, end + 1) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_presence(self, port_num): + for port_cfg in self._port_cfgs: + if int(port_cfg.index) == port_num: + sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])] + if sfp_idx >= 0: + try: + with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + return False + + def get_low_power_mode(self, port_num): + return False + + def set_low_power_mode(self, port_num, lpmode): + return False + + def reset(self, port_num): + return False + + def read_porttab_mappings(self, porttabfile, asic_inst = 0): + for port_cfg in self._port_cfgs: + self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)] + self.logical_to_asic[port_cfg.name] = 0 + self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name] + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + for port_cfg in self._port_cfgs: + presence = self.get_presence(int(port_cfg.index)) + if presence != self.presence[int(port_cfg.index)]: + self.presence[int(port_cfg.index)] = presence + if presence: + port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED + else: + port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED + + if bool(port_dict): + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + time.sleep(0.5) + return True, {} diff --git a/device/centec/arm64-centec_e530_24x2q-r0/pmon_daemon_control.json b/device/centec/arm64-centec_e530_24x2q-r0/pmon_daemon_control.json new file mode 100644 index 000000000..0db3279e4 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2q-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/buffers.json.j2 b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/buffers.json.j2 new file mode 100644 index 000000000..08e21e428 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/pg_profile_lookup.ini b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/pg_profile_lookup.ini new file mode 100644 index 000000000..a65244e69 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/port_config.ini b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/port_config.ini new file mode 100644 index 000000000..d83d20e81 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias index speed fec +Ethernet0 0 eth-0-1 0 1000 none +Ethernet1 1 eth-0-2 1 1000 none +Ethernet2 2 eth-0-3 2 1000 none +Ethernet3 3 eth-0-4 3 1000 none +Ethernet4 4 eth-0-5 4 1000 none +Ethernet5 5 eth-0-6 5 1000 none +Ethernet6 6 eth-0-7 6 1000 none +Ethernet7 7 eth-0-8 7 1000 none +Ethernet8 16 eth-0-9 8 1000 none +Ethernet9 17 eth-0-10 9 1000 none +Ethernet10 18 eth-0-11 10 1000 none +Ethernet11 19 eth-0-12 11 1000 none +Ethernet12 20 eth-0-13 12 1000 none +Ethernet13 21 eth-0-14 13 1000 none +Ethernet14 22 eth-0-15 14 1000 none +Ethernet15 23 eth-0-16 15 1000 none +Ethernet16 8 eth-0-17 16 1000 none +Ethernet17 9 eth-0-18 17 1000 none +Ethernet18 10 eth-0-19 18 1000 none +Ethernet19 11 eth-0-20 19 1000 none +Ethernet20 32 eth-0-21 20 1000 none +Ethernet21 33 eth-0-22 21 1000 none +Ethernet22 34 eth-0-23 22 1000 none +Ethernet23 35 eth-0-24 23 1000 none +Ethernet24 36 eth-0-25 24 1000 none +Ethernet25 37 eth-0-26 25 1000 none +Ethernet26 38 eth-0-27 26 1000 none +Ethernet27 39 eth-0-28 27 1000 none +Ethernet28 40 eth-0-29 28 1000 none +Ethernet29 41 eth-0-30 29 1000 none +Ethernet30 42 eth-0-31 30 1000 none +Ethernet31 43 eth-0-32 31 1000 none +Ethernet32 25 eth-0-33 32 1000 none +Ethernet33 24 eth-0-34 33 1000 none +Ethernet34 27 eth-0-35 34 1000 none +Ethernet35 26 eth-0-36 35 1000 none +Ethernet36 13 eth-0-37 36 1000 none +Ethernet37 12 eth-0-38 37 1000 none +Ethernet38 15 eth-0-39 38 1000 none +Ethernet39 14 eth-0-40 39 1000 none +Ethernet40 29 eth-0-41 40 1000 none +Ethernet41 28 eth-0-42 41 1000 none +Ethernet42 31 eth-0-43 42 1000 none +Ethernet43 30 eth-0-44 43 1000 none +Ethernet44 61 eth-0-45 44 1000 none +Ethernet45 60 eth-0-46 45 1000 none +Ethernet46 63 eth-0-47 46 1000 none +Ethernet47 62 eth-0-48 47 1000 none +Ethernet48 44 eth-0-49 48 10000 none +Ethernet49 45 eth-0-50 49 10000 none +Ethernet50 47 eth-0-51 50 10000 none +Ethernet51 46 eth-0-52 51 10000 none diff --git a/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/qos.json.j2 b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/qos.json.j2 new file mode 100644 index 000000000..3e548325e --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/sai.profile b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/sai.profile new file mode 100644 index 000000000..306e071e5 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/E530-48s4x/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E530-48s4x-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-48s4x-datapath.txt diff --git a/device/centec/arm64-centec_e530_48s4x-r0/default_sku b/device/centec/arm64-centec_e530_48s4x-r0/default_sku new file mode 100644 index 000000000..08098071d --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/default_sku @@ -0,0 +1 @@ +E530-48s4x l2 diff --git a/device/centec/arm64-centec_e530_48s4x-r0/fancontrol b/device/centec/arm64-centec_e530_48s4x-r0/fancontrol new file mode 100644 index 000000000..cf8acbdec --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236 +DEVNAME=hwmon1=ctc5236fan +FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input hwmon1/pwm4=hwmon1/temp1_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm4=hwmon1/fan4_input +MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30 hwmon1/pwm4=30 +MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90 hwmon1/pwm4=90 +MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12 hwmon1/pwm4=12 +MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 hwmon1/pwm4=6 +MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 hwmon1/pwm4=6 +MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18 hwmon1/pwm4=18 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py b/device/centec/arm64-centec_e530_48s4x-r0/installer.conf similarity index 100% rename from platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py rename to device/centec/arm64-centec_e530_48s4x-r0/installer.conf diff --git a/device/centec/arm64-centec_e530_48s4x-r0/platform_components.json b/device/centec/arm64-centec_e530_48s4x-r0/platform_components.json new file mode 100644 index 000000000..3649f3c14 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "E530-48s4x": { + "component": { + } + } + } +} diff --git a/device/centec/arm64-centec_e530_48s4x-r0/platform_reboot b/device/centec/arm64-centec_e530_48s4x-r0/platform_reboot new file mode 100755 index 000000000..98f62ca16 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/platform_reboot @@ -0,0 +1,12 @@ +#!/usr/bin/python +import os + +def main(): + # reboot the system + os.system('modprobe i2c-dev') + os.system('i2cset -y 0 0x36 0x23 0x0') + os.system('sleep 1') + os.system('i2cset -y 0 0x36 0x23 0x3') + +if __name__ == "__main__": + main() diff --git a/device/centec/arm64-centec_e530_48s4x-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_48s4x-r0/plugins/eeprom.py new file mode 100644 index 000000000..173c34ed5 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Centec E530-48S4X +# +# 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 = "/dev/mtd3" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/arm64-centec_e530_48s4x-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_48s4x-r0/plugins/led_control.py new file mode 100644 index 000000000..2820df84d --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/plugins/led_control.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import syslog + from socket import * + from select import * +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + 1 + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("3") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for idx in range(1, 53): + defmode = self._port_state_to_mode(idx, "down") + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + + # Constructor + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.LED_MODE_UP = [5, 6] + self.LED_MODE_DOWN = [7, 7] + + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() diff --git a/device/centec/arm64-centec_e530_48s4x-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_48s4x-r0/plugins/psuutil.py new file mode 100644 index 000000000..1e83c12c1 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/plugins/psuutil.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + 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 + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + 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 + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/centec/arm64-centec_e530_48s4x-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_48s4x-r0/plugins/sfputil.py new file mode 100644 index 000000000..9e44afb8f --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/plugins/sfputil.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python + +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print(str + "\n") + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_base(self): + return self.SFP_BASE + + @property + def qsfp_ports(self): + return () + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_eeprom_data(self, port): + ret = None + port_num = self.get_logical_to_physical(port)[0] + 1 + if port_num < self.port_start or port_num > self.port_end: + return ret + if port_num < self.sfp_base: + return ret + try: + with open(self.eeprom_mapping[port_num], 'r') as eeprom_file: + ret = eeprom_file.read() + except IOError as e: + DBG_PRINT(str(e)) + + return ret + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.PORT_START = 0 + self.PORT_END = 51 + self.SFP_BASE = 0 + self.PORTS_IN_BLOCK = 52 + self.logical = [] + self.physical_to_logical = {} + self.logical_to_physical = {} + self.logical_to_asic = {} + self.data = {'valid':0, 'last':0} + + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + for x in range(self.port_start, self.sfp_base): + self.eeprom_mapping[x] = None + for x in range(self.sfp_base, self.port_end + 1): + self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1) + self.presence = {} + for x in range(self.sfp_base, self.port_end + 1): + self.presence[x] = False; + + SfpUtilBase.__init__(self) + + for x in range(self.sfp_base, self.port_end + 1): + self.logical.append('Ethernet' + str(x)) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.sfp_base: + return False + try: + with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + + def read_porttab_mappings(self, porttabfile, asic_inst = 0): + for x in range(self.sfp_base, self.port_end + 1): + self.logical_to_physical['Ethernet' + str(x)] = [x] + self.logical_to_asic['Ethernet' + str(x)] = 0 + self.physical_to_logical[x] = ['Ethernet' + str(x)] + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + for x in range(self.sfp_base, self.port_end + 1): + presence = self.get_presence(x) + if presence != self.presence[x]: + self.presence[x] = presence + # index in port_config.ini + if presence: + port_dict[x] = SFP_STATUS_INSERTED + else: + port_dict[x] = SFP_STATUS_REMOVED + + if bool(port_dict): + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + time.sleep(0.5) + return True, {} diff --git a/device/centec/arm64-centec_e530_48s4x-r0/pmon_daemon_control.json b/device/centec/arm64-centec_e530_48s4x-r0/pmon_daemon_control.json new file mode 100644 index 000000000..0db3279e4 --- /dev/null +++ b/device/centec/arm64-centec_e530_48s4x-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini index c904ece72..928267bee 100644 --- a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini @@ -1,53 +1,53 @@ -# name lanes alias speed -Ethernet1 1 eth-0-1 1000 -Ethernet2 0 eth-0-2 1000 -Ethernet3 3 eth-0-3 1000 -Ethernet4 2 eth-0-4 1000 -Ethernet5 5 eth-0-5 1000 -Ethernet6 4 eth-0-6 1000 -Ethernet7 7 eth-0-7 1000 -Ethernet8 6 eth-0-8 1000 -Ethernet9 17 eth-0-9 1000 -Ethernet10 16 eth-0-10 1000 -Ethernet11 19 eth-0-11 1000 -Ethernet12 18 eth-0-12 1000 -Ethernet13 21 eth-0-13 1000 -Ethernet14 20 eth-0-14 1000 -Ethernet15 23 eth-0-15 1000 -Ethernet16 22 eth-0-16 1000 -Ethernet17 9 eth-0-17 1000 -Ethernet18 8 eth-0-18 1000 -Ethernet19 11 eth-0-19 1000 -Ethernet20 10 eth-0-20 1000 -Ethernet21 33 eth-0-21 1000 -Ethernet22 32 eth-0-22 1000 -Ethernet23 35 eth-0-23 1000 -Ethernet24 34 eth-0-24 1000 -Ethernet25 37 eth-0-25 1000 -Ethernet26 36 eth-0-26 1000 -Ethernet27 39 eth-0-27 1000 -Ethernet28 38 eth-0-28 1000 -Ethernet29 41 eth-0-29 1000 -Ethernet30 40 eth-0-30 1000 -Ethernet31 43 eth-0-31 1000 -Ethernet32 42 eth-0-32 1000 -Ethernet33 25 eth-0-33 1000 -Ethernet34 24 eth-0-34 1000 -Ethernet35 27 eth-0-35 1000 -Ethernet36 26 eth-0-36 1000 -Ethernet37 49 eth-0-37 1000 -Ethernet38 48 eth-0-38 1000 -Ethernet39 51 eth-0-39 1000 -Ethernet40 50 eth-0-40 1000 -Ethernet41 53 eth-0-41 1000 -Ethernet42 52 eth-0-42 1000 -Ethernet43 55 eth-0-43 1000 -Ethernet44 54 eth-0-44 1000 -Ethernet45 57 eth-0-45 1000 -Ethernet46 56 eth-0-46 1000 -Ethernet47 59 eth-0-47 1000 -Ethernet48 58 eth-0-48 1000 -Ethernet49 13 eth-0-49 10000 -Ethernet50 12 eth-0-50 10000 -Ethernet51 15 eth-0-51 10000 -Ethernet52 14 eth-0-52 10000 +# name lanes alias index speed fec +Ethernet0 1 eth-0-1 0 1000 none +Ethernet1 0 eth-0-2 1 1000 none +Ethernet2 3 eth-0-3 2 1000 none +Ethernet3 2 eth-0-4 3 1000 none +Ethernet4 5 eth-0-5 4 1000 none +Ethernet5 4 eth-0-6 5 1000 none +Ethernet6 7 eth-0-7 6 1000 none +Ethernet7 6 eth-0-8 7 1000 none +Ethernet8 17 eth-0-9 8 1000 none +Ethernet9 16 eth-0-10 9 1000 none +Ethernet10 19 eth-0-11 10 1000 none +Ethernet11 18 eth-0-12 11 1000 none +Ethernet12 21 eth-0-13 12 1000 none +Ethernet13 20 eth-0-14 13 1000 none +Ethernet14 23 eth-0-15 14 1000 none +Ethernet15 22 eth-0-16 15 1000 none +Ethernet16 9 eth-0-17 16 1000 none +Ethernet17 8 eth-0-18 17 1000 none +Ethernet18 11 eth-0-19 18 1000 none +Ethernet19 10 eth-0-20 19 1000 none +Ethernet20 33 eth-0-21 20 1000 none +Ethernet21 32 eth-0-22 21 1000 none +Ethernet22 35 eth-0-23 22 1000 none +Ethernet23 34 eth-0-24 23 1000 none +Ethernet24 37 eth-0-25 24 1000 none +Ethernet25 36 eth-0-26 25 1000 none +Ethernet26 39 eth-0-27 26 1000 none +Ethernet27 38 eth-0-28 27 1000 none +Ethernet28 41 eth-0-29 28 1000 none +Ethernet29 40 eth-0-30 29 1000 none +Ethernet30 43 eth-0-31 30 1000 none +Ethernet31 42 eth-0-32 31 1000 none +Ethernet32 25 eth-0-33 32 1000 none +Ethernet33 24 eth-0-34 33 1000 none +Ethernet34 27 eth-0-35 34 1000 none +Ethernet35 26 eth-0-36 35 1000 none +Ethernet36 49 eth-0-37 36 1000 none +Ethernet37 48 eth-0-38 37 1000 none +Ethernet38 51 eth-0-39 38 1000 none +Ethernet39 50 eth-0-40 39 1000 none +Ethernet40 53 eth-0-41 40 1000 none +Ethernet41 52 eth-0-42 41 1000 none +Ethernet42 55 eth-0-43 42 1000 none +Ethernet43 54 eth-0-44 43 1000 none +Ethernet44 57 eth-0-45 44 1000 none +Ethernet45 56 eth-0-46 45 1000 none +Ethernet46 59 eth-0-47 46 1000 none +Ethernet47 58 eth-0-48 47 1000 none +Ethernet48 13 eth-0-49 48 10000 none +Ethernet49 12 eth-0-50 49 10000 none +Ethernet50 15 eth-0-51 50 10000 none +Ethernet51 14 eth-0-52 51 10000 none diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol b/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol index e37752971..4fbc9cba3 100644 --- a/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol @@ -1 +1,12 @@ # Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236 +DEVNAME=hwmon1=ctc5236fan +FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input +MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30 +MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90 +MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12 +MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 +MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 +MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/platform_components.json b/device/centec/arm64-centec_e530_48t4x_p-r0/platform_components.json new file mode 100644 index 000000000..cd0afe73c --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "E530-48t4x-p": { + "component": { + } + } + } +} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/platform_reboot b/device/centec/arm64-centec_e530_48t4x_p-r0/platform_reboot new file mode 100755 index 000000000..f22723f98 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/platform_reboot @@ -0,0 +1,11 @@ +#!/usr/bin/python +import os + +def main(): + # reboot the system + os.system('echo 502 > /sys/class/gpio/export') + os.system('echo out > /sys/class/gpio/gpio502/direction') + os.system('echo 1 > /sys/class/gpio/gpio502/value') + +if __name__ == "__main__": + main() diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py index afea818be..4a7613c40 100644 --- a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + ############################################################################# # Centec E550-24X8Y2C # @@ -10,7 +12,7 @@ try: from sonic_eeprom import eeprom_tlvinfo except ImportError as e: - raise ImportError(str(e) + "- required module not found") + raise ImportError (str(e) + "- required module not found") class board(eeprom_tlvinfo.TlvInfoDecoder): diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py index eb567de89..5b20e882c 100644 --- a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python +# # led_control.py # # Platform-specific LED control functionality for SONiC @@ -21,6 +23,7 @@ def DBG_PRINT(str): class LedControl(LedControlBase): """Platform specific LED control class""" + # Helper method to map SONiC port name to index def _port_name_to_index(self, port_name): # Strip "Ethernet" off port name @@ -28,7 +31,7 @@ class LedControl(LedControlBase): return -1 port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) - return port_idx + return port_idx + 1 def _port_state_to_mode(self, port_idx, state): if state == "up": @@ -70,8 +73,8 @@ class LedControl(LedControlBase): DBG_PRINT("init led done") - # Concrete implementation of port_link_state_change() method + # Concrete implementation of port_link_state_change() method def port_link_state_change(self, portname, state): port_idx = self._port_name_to_index(portname) ledMode = self._port_state_to_mode(port_idx, state) @@ -84,8 +87,8 @@ class LedControl(LedControlBase): self._port_led_mode_update(port_idx, ledMode) DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) - # Constructor + # Constructor def __init__(self): self.SONIC_PORT_NAME_PREFIX = "Ethernet" self.LED_MODE_UP = [2, 11] diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py index 3a83f406d..1e83c12c1 100644 --- a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + ############################################################################# # Centec # @@ -9,8 +11,7 @@ try: from sonic_psu.psu_base import PsuBase except ImportError as e: - raise ImportError(str(e) + "- required module not found") - + raise ImportError (str(e) + "- required module not found") class PsuUtil(PsuBase): """Platform-specific PSUutil class""" diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py index f7094828e..189e469d4 100644 --- a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # sfputil.py # # Platform-specific SFP transceiver interface for SONiC @@ -15,6 +17,8 @@ except ImportError as e: def DBG_PRINT(str): print(str + "\n") +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' class SfpUtil(SfpUtilBase): """Platform-specific SfpUtil class""" @@ -42,17 +46,9 @@ class SfpUtil(SfpUtilBase): def is_logical_port(self, port_name): return True - def get_logical_to_physical(self, port_name): - if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): - return None - - port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) - - return [port_idx] - def get_eeprom_data(self, port): ret = None - port_num = self.get_logical_to_physical(port)[0] + port_num = self.get_logical_to_physical(port)[0] + 1 if port_num < self.port_start or port_num > self.port_end: return ret if port_num < self.sfp_base: @@ -65,16 +61,17 @@ class SfpUtil(SfpUtilBase): return ret - # todo - # def _get_port_eeprom_path(self, port_num, devid): - # pass - def __init__(self): self.SONIC_PORT_NAME_PREFIX = "Ethernet" - self.PORT_START = 1 - self.PORT_END = 52 - self.SFP_BASE = 49 + self.PORT_START = 0 + self.PORT_END = 51 + self.SFP_BASE = 48 self.PORTS_IN_BLOCK = 52 + self.logical = [] + self.physical_to_logical = {} + self.logical_to_physical = {} + self.logical_to_asic = {} + self.data = {'valid':0, 'last':0} self.eeprom_mapping = {} self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" @@ -82,14 +79,16 @@ class SfpUtil(SfpUtilBase): for x in range(self.port_start, self.sfp_base): self.eeprom_mapping[x] = None for x in range(self.sfp_base, self.port_end + 1): - self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format( - x - self.sfp_base + 1) + self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1) self.presence = {} for x in range(self.sfp_base, self.port_end + 1): - self.presence[x] = False + self.presence[x] = False; SfpUtilBase.__init__(self) + for x in range(self.sfp_base, self.port_end + 1): + self.logical.append('Ethernet' + str(x)) + def get_presence(self, port_num): # Check for invalid port_num if port_num < self.port_start or port_num > self.port_end: @@ -125,13 +124,38 @@ class SfpUtil(SfpUtilBase): return False - def get_transceiver_change_event(self, timeout=0): + + def read_porttab_mappings(self, porttabfile, asic_inst = 0): + for x in range(self.sfp_base, self.port_end + 1): + self.logical_to_physical['Ethernet' + str(x)] = [x] + self.logical_to_asic['Ethernet' + str(x)] = 0 + self.physical_to_logical[x] = ['Ethernet' + str(x)] + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() port_dict = {} - while True: - for x in range(self.sfp_base, self.port_end + 1): - presence = self.get_presence(x) - if presence != self.presence[x]: - self.presence[x] = presence - port_dict[x] = presence - return True, port_dict + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + for x in range(self.sfp_base, self.port_end + 1): + presence = self.get_presence(x) + if presence != self.presence[x]: + self.presence[x] = presence + # index in port_config.ini + if presence: + port_dict[x] = SFP_STATUS_INSERTED + else: + port_dict[x] = SFP_STATUS_REMOVED + + if bool(port_dict): + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: time.sleep(0.5) + return True, {} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/pmon_daemon_control.json b/device/centec/arm64-centec_e530_48t4x_p-r0/pmon_daemon_control.json new file mode 100644 index 000000000..0db3279e4 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py index 103b3cd56..2aced9201 100644 --- a/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py @@ -82,7 +82,7 @@ class SfpUtil(SfpUtilBase): try: reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode") except IOError as e: - print "Error: unable to open file: %s" % str(e) + print("Error: unable to open file: %s" % str(e)) content = reg_file.readline().rstrip() diff --git a/platform/centec-arm64/one-image.mk b/platform/centec-arm64/one-image.mk index e8f0cf369..87fd7627b 100755 --- a/platform/centec-arm64/one-image.mk +++ b/platform/centec-arm64/one-image.mk @@ -8,6 +8,8 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_INSTALLS += $(TSINGMA_BSP_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48S4X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2Q_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) diff --git a/platform/centec-arm64/platform-modules-centec-e530.mk b/platform/centec-arm64/platform-modules-centec-e530.mk index 3058e77a5..a5237e679 100644 --- a/platform/centec-arm64/platform-modules-centec-e530.mk +++ b/platform/centec-arm64/platform-modules-centec-e530.mk @@ -1,8 +1,10 @@ # Centec E530-48T4X-P Platform modules -CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.1 -CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.1 +CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.3 +CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.3 +CENTEC_E530_48S4X_PLATFORM_MODULE_VERSION =1.3 +CENTEC_E530_24X2Q_PLATFORM_MODULE_VERSION =1.3 export CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION @@ -16,3 +18,11 @@ SONIC_DPKG_DEBS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) CENTEC_E530_24X2C_PLATFORM_MODULE = platform-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb $(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0 $(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2C_PLATFORM_MODULE))) + +CENTEC_E530_48S4X_PLATFORM_MODULE = platform-modules-e530-48s4x_$(CENTEC_E530_48S4X_PLATFORM_MODULE_VERSION)_arm64.deb +$(CENTEC_E530_48S4X_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_48s4x-r0 +$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_48S4X_PLATFORM_MODULE))) + +CENTEC_E530_24X2Q_PLATFORM_MODULE = platform-modules-e530-24x2q_$(CENTEC_E530_24X2Q_PLATFORM_MODULE_VERSION)_arm64.deb +$(CENTEC_E530_24X2Q_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2q-r0 +$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2Q_PLATFORM_MODULE))) diff --git a/platform/centec-arm64/platform.conf b/platform/centec-arm64/platform.conf index 2577f64ea..39dc4b702 100755 --- a/platform/centec-arm64/platform.conf +++ b/platform/centec-arm64/platform.conf @@ -4,43 +4,45 @@ echo "Preparing for installation ... " -demo_mnt=/mnt - -hw_load() { - echo "ext4load mmc 0:2 \$loadaddr onie_uimage" -} - create_partition() { echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1 } mount_partition() { - echo "mount flash" + echo "mount flash partition" + demo_mnt=/mnt mount -t ext4 /dev/mmcblk0p1 $demo_mnt } bootloader_menu_config() { - mkdir -p $demo_mnt/boot - mount -t ext4 /dev/mmcblk0p2 $demo_mnt/boot - - rm $demo_mnt/boot/centec-e530.itb -rf - cp $demo_mnt/$image_dir/boot/sonic_arm64.fit $demo_mnt/boot/centec-e530.itb - cd $demo_mnt/boot - rm onie_uimage -rf - ln -s centec-e530.itb onie_uimage - cd - - sync - umount -l $demo_mnt/boot + if [ "$install_env" = "onie" ]; then + fw_setenv -f nos_bootcmd "test -n \$boot_once && setenv do_boot_once \$boot_once && setenv boot_once && saveenv && run do_boot_once; run boot_next" - hw_load_str="$(hw_load)" + fw_setenv -f sonic_image_1 "ext4load mmc 0:1 \$loadaddr \$sonic_dir_1/boot/sonic_arm64.fit && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=\$sonic_dir_1/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr" + fw_setenv -f sonic_image_2 "NONE" + fw_setenv -f sonic_dir_1 $image_dir + fw_setenv -f sonic_dir_2 "NONE" + fw_setenv -f sonic_version_1 `echo $image_dir | sed "s/^image-/SONiC-OS-/g"` + fw_setenv -f sonic_version_2 "NONE" - (cat < /tmp/env.txt + fw_setenv -f boot_next "run sonic_image_1" + else + running_sonic_revision=`cat /etc/sonic/sonic_version.yml | grep build_version | awk -F \' '{print $2}'` + SONIC_IMAGE_MAX=2 + idx=0 + for i in $(seq 1 $SONIC_IMAGE_MAX); do + if [ "`fw_printenv sonic_version_$i 2>/dev/null | awk -F = '{print $2}'`" != "SONiC-OS-$running_sonic_revision" ]; then + idx=$i + break + fi + done - fw_setenv -f -s /tmp/env.txt - fw_setenv -f image_dir $image_dir + fw_setenv nos_bootcmd "test -n \$boot_once && setenv do_boot_once \$boot_once && setenv boot_once && saveenv && run do_boot_once; run boot_next" + + fw_setenv sonic_image_$idx "ext4load mmc 0:1 \$loadaddr \$sonic_dir_$idx/boot/sonic_arm64.fit && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=\$sonic_dir_$idx/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr" + fw_setenv sonic_dir_$idx $image_dir + fw_setenv sonic_version_$idx `echo $image_dir | sed "s/^image-/SONiC-OS-/g"` + + fw_setenv boot_next "run sonic_image_$idx" + fi } diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk index 2b902b494..cef055447 100755 --- a/platform/centec-arm64/sai.mk +++ b/platform/centec-arm64/sai.mk @@ -1,6 +1,6 @@ # Centec SAI -export CENTEC_SAI_VERSION = 1.6.3-1 +export CENTEC_SAI_VERSION = 1.7.1-1 export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb $(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py index 17f8b8f01..d41f195d6 100755 --- a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py @@ -5,11 +5,11 @@ from setuptools import setup os.listdir setup( - name='24x2c', - version='1.1', + name='sonic_platform', + version='1.0', description='Module to initialize centec e530-24x2c platforms', - packages=['24x2c'], - package_dir={'24x2c': '24x2c/classes'}, + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, ) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/__init__.py new file mode 100644 index 000000000..d4a9e746e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"] +from . import platform + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/chassis.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/chassis.py new file mode 100644 index 000000000..1dfb0e6d8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/chassis.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import re + import collections + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from .fan_drawer import FanDrawer + from .thermal import Thermal + from .sfp import Sfp + from .psu import Psu + from sonic_py_common import device_info +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 1 +NUM_THERMAL = 1 +NUM_PSU = 2 +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + _port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + # Initialize EEPROM + self._eeprom = Eeprom() + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # Initialize SFP + for port_cfg in _port_cfgs: + sfp = Sfp(int(port_cfg.index)) + self._sfp_list.append(sfp) + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index + 1) + self._psu_list.append(psu) + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_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.serial_number_str() + + 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. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + return (None, None) + + def get_change_event(self, timeout=2000): + """ + 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. + """ + ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout) + ret_dict = {"sfp": port_dict} + return ret, ret_dict + + def get_num_psus(self): + return len(self._psu_list) + + def get_psu(self, psu_index): + return self._psu_list[psu_index] diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/eeprom.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/eeprom.py new file mode 100644 index 000000000..77e3e82df --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/eeprom.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/dev/mtd3" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.open_eeprom() + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += str(tlv[6:6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan.py new file mode 100644 index 000000000..a26163226 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan.py @@ -0,0 +1,186 @@ +#!/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 +# +############################################################################# + +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/class/hwmon/hwmon1/" +FAN_MAX_PWM = 255 +FAN_FAN_PWM = "pwm{}" +FAN_FAN_INPUT = "fan{}_input" +FAN_MAX_RPM = 9000 +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + + FanBase.__init__(self) + + 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 "" + + 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 __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + 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 = self.FAN_DIRECTION_EXHAUST + 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) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return int(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 = 0 + # fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + # fan_target_sysfs_path = self.__search_file_by_name( + # FAN_PATH, fan_target_sysfs_name) + # fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0 + # target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM) + + # return target + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return 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 10 + + 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 + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + fan_target_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_target_sysfs_name) + return self.__write_txt_file(fan_target_sysfs_path, int(pwm)) + + 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: always True + """ + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_index] + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: always True + """ + + return True + + def get_status(self): + """ + Retrieves the status of the FAN + Returns: + bool: always True + """ + return True diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan_drawer.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan_drawer.py new file mode 100644 index 000000000..b2130520f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/fan_drawer.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +######################################################################## +# Centec E530 24x2c +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from .fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CENTEC_FANS_PER_FANTRAY = 3 + + +class FanDrawer(FanDrawerBase): + """Centec E530 24x2c Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + for i in range(CENTEC_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/platform.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/platform.py new file mode 100644 index 000000000..a69d726ee --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs for Centec E530-24X2C +# + + +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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/psu.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/psu.py new file mode 100644 index 000000000..0e133d15c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/psu.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Psu(PsuBase): + """Centec Platform-specific PSU class""" + + def __init__(self, index): + self._index = index + self._fan_list = [] + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "psuutil.py"]) + module = imp.load_source("psuutil", module_file) + psu_util_class = getattr(module, "PsuUtil") + self._psuutil = psu_util_class() + + def _get_psuutil(self): + return self._psuutil + + def get_presence(self): + return self._get_psuutil().get_psu_presence(self._index) + + def get_powergood_status(self): + return self._get_psuutil().get_psu_status(self._index) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/sfp.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/sfp.py new file mode 100644 index 000000000..4a92fecfa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/sfp.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Sfp(SfpBase): + """ + Platform-specific sfp class + + Unimplemented methods: + - get_model + - get_serial + - get_status + - get_transceiver_info + - get_transceiver_bulk_status + - get_transceiver_threshold_info + - get_reset_status + - get_rx_los + - get_tx_fault + - get_tx_disable_channel + - get_power_override + - get_temperature + - get_voltage + - get_tx_bias + - get_rx_power + - get_tx_power + - tx_disable_channel + - set_power_override + """ + + def __init__(self, index): + self._index = index + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "sfputil.py"]) + module = imp.load_source("sfputil", module_file) + sfp_util_class = getattr(module, "SfpUtil") + self._sfputil = sfp_util_class() + + def get_id(self): + return self._index + + def get_name(self): + return "Ethernet{}".format(self._index) + + def get_lpmode(self): + return False + + def set_lpmode(self, lpmode): + return False + + def get_tx_disable(self): + return False + + def tx_disable(self, tx_disable): + return False + + def reset(self): + pass + + def clear_interrupt(self): + return False + + def get_interrupt_file(self): + return None + + def _get_sfputil(self): + return self._sfputil + + def get_presence(self): + return self._get_sfputil().get_presence(self._index) + + def get_transceiver_info(self): + return self._get_sfputil().get_transceiver_info_dict(self._index) + + def get_transceiver_bulk_status(self): + return self._get_sfputil().get_transceiver_dom_info_dict(self._index) + + def get_transceiver_threshold_info(self): + return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index) + + def get_transceiver_change_event(self, timeout): + return self._get_sfputil().get_transceiver_change_event(timeout) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/thermal.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/thermal.py new file mode 100644 index 000000000..ce224f0ed --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/sonic_platform/thermal.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +############################################################################# +# 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 os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1" + + def __init__(self, thermal_index): + self.index = thermal_index + self.high_threshold = float(112) + + # Add thermal name + self.THERMAL_NAME_LIST.append("SENSOR-1") + + # Set hwmon path + self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH + self.ss_key = self.THERMAL_NAME_LIST[self.index - 1] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + 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 + """ + return self.high_threshold + + 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 + """ + self.high_threshold = float(temperature) + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + 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 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/Makefile new file mode 100644 index 000000000..8736ed3a8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e530_24x2q_platform.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/centec_e530_24x2q_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/centec_e530_24x2q_platform.c new file mode 100644 index 000000000..68830775e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/modules/centec_e530_24x2q_platform.c @@ -0,0 +1,1111 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 24 +#define QSFP_NUM 2 +#define PORT_NUM (SFP_NUM + QSFP_NUM) +#endif + +#if SEP("i2c:smbus") +static int e530_24x2q_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e530_24x2q_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-1-cpu */ + +static int e530_24x2q_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e530_24x2q_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e530_24x2q_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 */ +static struct i2c_adapter *i2c_adp_gpio1 = NULL; /* gpio1 */ +static struct i2c_adapter *i2c_adp_gpio2 = NULL; /* gpio2 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x23), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; + +static int e530_24x2q_init_i2c_gpio(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_24x2q_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e530_24x2q gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e530_24x2q board i2c client gpio0 failed\n"); + return -1; + } + + i2c_adp_gpio1 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio1)) + { + i2c_adp_gpio1 = NULL; + printk(KERN_CRIT "get e530_24x2q gpio1 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_gpio1, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e530_24x2q board i2c client gpio1 failed\n"); + return -1; + } + + i2c_adp_gpio2 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio2)) + { + i2c_adp_gpio2 = NULL; + printk(KERN_CRIT "get e530_24x2q gpio2 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_gpio2, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e530_24x2q board i2c client gpio2 failed\n"); + return -1; + } + + /* gpio0 */ + ret = e530_24x2q_smbus_write_reg(i2c_client_gpio0, 0x02, 0x00); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio0, 0x03, 0x00); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio0, 0x06, 0x00); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio0, 0x07, 0x00); + /* gpio1 */ + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio1, 0x02, 0xbf); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio1, 0x03, 0xff); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio1, 0x06, 0x0c); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio1, 0x07, 0xff); + /* gpio2 */ + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio2, 0x02, 0x00); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio2, 0x03, 0xff); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio2, 0x06, 0x00); + ret += e530_24x2q_smbus_write_reg(i2c_client_gpio2, 0x07, 0xff); + + if (ret) + { + printk(KERN_CRIT "init e530_24x2q board i2c gpio config failed\n"); + return -1; + } + + return 0; +} + +static int e530_24x2q_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio1)) + { + i2c_put_adapter(i2c_adp_gpio1); + i2c_adp_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio2)) + { + i2c_put_adapter(i2c_adp_gpio2); + i2c_adp_gpio2 = NULL; + } + + return 0; +} +#endif + + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e530_24x2q_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio1; + present_no = 9; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio1; + present_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_24x2q_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_24x2q_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio1; + workstate_no = 11; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio1; + workstate_no = 15; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_24x2q_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e530_24x2q_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e530_24x2q_psu_read_status, NULL); + +static int e530_24x2q_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e530_24x2q class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e530_24x2q psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e530_24x2q psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e530_24x2q_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e530_24x2q_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_24x2q_led_get(struct led_classdev *led_cdev); +extern void e530_24x2q_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_24x2q_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e530_24x2q_led_set, + .brightness_get = e530_24x2q_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port2", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port3", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port4", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port5", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port6", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port7", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port8", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port9", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port10", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port11", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port12", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port13", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port14", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port15", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port16", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port17", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port18", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port19", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port20", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port21", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port22", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port23", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port24", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port25", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +{ .name = "port26", .brightness_set = e530_24x2q_led_port_set, .brightness_get = e530_24x2q_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e530_24x2q_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio1; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_24x2q_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & (~mask)) | ((set_value << shift) & (mask))); + + ret = e530_24x2q_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: led not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e530_24x2q_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_24x2q_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e530_24x2q_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e530_24x2q_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e530_24x2q_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + presence = sfp_info[portNum].presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + return sprintf(buf, "%d\n", presence); +} + +static ssize_t e530_24x2q_sfp_write_presence(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + int presence = simple_strtol(buf, NULL, 10); + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].presence = presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_24x2q_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + value = 0; + } + + if (portNum <= SFP_NUM) + { + if (portNum >= 1 && portNum <= 16) + { + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + } + else if (portNum > 16 && portNum <= 24) + { + reg_no = portNum - 17; + i2c_sfp_client = i2c_client_gpio2; + } + + input_bank = (reg_no/8) + 0x2; + ret = e530_24x2q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp enable: %s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + } + else + { + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + value = sfp_info[portNum].enable; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_24x2q_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + return size; + } + + if (portNum <= SFP_NUM) + { + if (portNum >= 1 && portNum <= 16) + { + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + } + else if (portNum > 16 && portNum <= 24) + { + reg_no = portNum - 17; + i2c_sfp_client = i2c_client_gpio2; + } + + set_value = ((set_value > 0) ? 0 : 1); + + input_bank = (reg_no/8) + 0x2; + ret = e530_24x2q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s enable failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x2; + ret = e530_24x2q_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s enable failed\n", name); + return size; + } + } + else + { + set_value = ((set_value > 0) ? 1 : 0); + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].enable = set_value; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + } + + return size; +} + +static ssize_t e530_24x2q_sfp_read_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + size_t size = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read eeprom, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(buf, sfp_info[portNum].eeprom[0], sfp_info[portNum].data_len[0]); + size = sfp_info[portNum].data_len[0]; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_24x2q_sfp_write_eeprom(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp write eeprom, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(sfp_info[portNum].eeprom[0], buf, size); + sfp_info[portNum].data_len[0] = size; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO|S_IWUSR, e530_24x2q_sfp_read_presence, e530_24x2q_sfp_write_presence); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e530_24x2q_sfp_read_enable, e530_24x2q_sfp_write_enable); +static DEVICE_ATTR(sfp_eeprom, S_IRUGO|S_IWUSR, e530_24x2q_sfp_read_eeprom, e530_24x2q_sfp_write_eeprom); + +static int e530_24x2q_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e530_24x2q class sfp failed\n"); + return -1; + } + + for (i=1; i<=SFP_NUM+QSFP_NUM; i++) + { + memset(&(sfp_info[i].eeprom), 0, sizeof(sfp_info[i].eeprom)); + memset(&(sfp_info[i].data_len), 0, sizeof(sfp_info[i].data_len)); + spin_lock_init(&(sfp_info[i].lock)); + + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e530_24x2q sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q sfp[%d] device attr:enable failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_eeprom); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2q sfp[%d] device attr:eeprom failed\n", i); + continue; + } + } + + return ret; +} + +static int e530_24x2q_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=SFP_NUM+QSFP_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_remove_file(sfp_dev[i], &dev_attr_sfp_eeprom); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e530_24x2q_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e530_24x2q board dirver...\n"); + + ret = e530_24x2q_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2q_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2q_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2q_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2q_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e530_24x2q board driver failed\n"); + else + printk(KERN_ALERT "install e530_24x2q board dirver...ok\n"); + + return 0; +} + +static void e530_24x2q_exit(void) +{ + printk(KERN_INFO "uninstall e530_24x2q board dirver...\n"); + + e530_24x2q_exit_sfp(); + e530_24x2q_exit_led(); + e530_24x2q_exit_psu(); + e530_24x2q_exit_i2c_gpio(); + e530_24x2q_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("e530-24x2q board driver"); +module_init(e530_24x2q_init); +module_exit(e530_24x2q_exit); diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/service/24x2q_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/service/24x2q_platform.service new file mode 100644 index 000000000..272fe2d70 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/service/24x2q_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e530-24x2q start +ExecStop=-/etc/init.d/platform-modules-e530-24x2q stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/setup.py new file mode 100644 index 000000000..c068fb446 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize centec e530-24x2q platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/__init__.py new file mode 100644 index 000000000..d4a9e746e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"] +from . import platform + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/chassis.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/chassis.py new file mode 100644 index 000000000..ab58df284 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/chassis.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import re + import collections + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from .fan_drawer import FanDrawer + from .thermal import Thermal + from .sfp import Sfp + from .psu import Psu + from sonic_py_common import device_info +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 1 +NUM_THERMAL = 1 +NUM_PSU = 2 +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + raise + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"]) + try: + f = open(port_config_file) + except: + raise + for line in f: + line.strip() + if re.search('^#', line) is not None: + Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:]) + break + f.close() + f = open(port_config_file) + _port_cfgs = [Port_cfg(*tuple((line.strip().split()))) + for line in f if re.search('^#', line) is None] + f.close() + + # Initialize EEPROM + self._eeprom = Eeprom() + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # Initialize SFP + for port_cfg in _port_cfgs: + sfp = Sfp(int(port_cfg.index)) + self._sfp_list.append(sfp) + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index + 1) + self._psu_list.append(psu) + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_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.serial_number_str() + + 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. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + return (None, None) + + def get_change_event(self, timeout=2000): + """ + 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. + """ + ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout) + ret_dict = {"sfp": port_dict} + return ret, ret_dict + + def get_num_psus(self): + return len(self._psu_list) + + def get_psu(self, psu_index): + return self._psu_list[psu_index] diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/eeprom.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/eeprom.py new file mode 100644 index 000000000..77e3e82df --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/eeprom.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/dev/mtd3" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.open_eeprom() + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += str(tlv[6:6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan.py new file mode 100644 index 000000000..a26163226 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan.py @@ -0,0 +1,186 @@ +#!/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 +# +############################################################################# + +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/class/hwmon/hwmon1/" +FAN_MAX_PWM = 255 +FAN_FAN_PWM = "pwm{}" +FAN_FAN_INPUT = "fan{}_input" +FAN_MAX_RPM = 9000 +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + + FanBase.__init__(self) + + 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 "" + + 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 __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + 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 = self.FAN_DIRECTION_EXHAUST + 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) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return int(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 = 0 + # fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + # fan_target_sysfs_path = self.__search_file_by_name( + # FAN_PATH, fan_target_sysfs_name) + # fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0 + # target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM) + + # return target + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return 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 10 + + 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 + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + fan_target_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_target_sysfs_name) + return self.__write_txt_file(fan_target_sysfs_path, int(pwm)) + + 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: always True + """ + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_index] + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: always True + """ + + return True + + def get_status(self): + """ + Retrieves the status of the FAN + Returns: + bool: always True + """ + return True diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan_drawer.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan_drawer.py new file mode 100644 index 000000000..500846129 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/fan_drawer.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +######################################################################## +# Centec E530 24x2q +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from .fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CENTEC_FANS_PER_FANTRAY = 3 + + +class FanDrawer(FanDrawerBase): + """Centec E530 24x2q Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + for i in range(CENTEC_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/platform.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/platform.py new file mode 100644 index 000000000..612055de0 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs for Centec E530-24X2Q +# + + +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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/psu.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/psu.py new file mode 100644 index 000000000..0e133d15c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/psu.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Psu(PsuBase): + """Centec Platform-specific PSU class""" + + def __init__(self, index): + self._index = index + self._fan_list = [] + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "psuutil.py"]) + module = imp.load_source("psuutil", module_file) + psu_util_class = getattr(module, "PsuUtil") + self._psuutil = psu_util_class() + + def _get_psuutil(self): + return self._psuutil + + def get_presence(self): + return self._get_psuutil().get_psu_presence(self._index) + + def get_powergood_status(self): + return self._get_psuutil().get_psu_status(self._index) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/sfp.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/sfp.py new file mode 100644 index 000000000..4a92fecfa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/sfp.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Sfp(SfpBase): + """ + Platform-specific sfp class + + Unimplemented methods: + - get_model + - get_serial + - get_status + - get_transceiver_info + - get_transceiver_bulk_status + - get_transceiver_threshold_info + - get_reset_status + - get_rx_los + - get_tx_fault + - get_tx_disable_channel + - get_power_override + - get_temperature + - get_voltage + - get_tx_bias + - get_rx_power + - get_tx_power + - tx_disable_channel + - set_power_override + """ + + def __init__(self, index): + self._index = index + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "sfputil.py"]) + module = imp.load_source("sfputil", module_file) + sfp_util_class = getattr(module, "SfpUtil") + self._sfputil = sfp_util_class() + + def get_id(self): + return self._index + + def get_name(self): + return "Ethernet{}".format(self._index) + + def get_lpmode(self): + return False + + def set_lpmode(self, lpmode): + return False + + def get_tx_disable(self): + return False + + def tx_disable(self, tx_disable): + return False + + def reset(self): + pass + + def clear_interrupt(self): + return False + + def get_interrupt_file(self): + return None + + def _get_sfputil(self): + return self._sfputil + + def get_presence(self): + return self._get_sfputil().get_presence(self._index) + + def get_transceiver_info(self): + return self._get_sfputil().get_transceiver_info_dict(self._index) + + def get_transceiver_bulk_status(self): + return self._get_sfputil().get_transceiver_dom_info_dict(self._index) + + def get_transceiver_threshold_info(self): + return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index) + + def get_transceiver_change_event(self, timeout): + return self._get_sfputil().get_transceiver_change_event(timeout) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/thermal.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/thermal.py new file mode 100644 index 000000000..ce224f0ed --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2q/sonic_platform/thermal.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +############################################################################# +# 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 os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1" + + def __init__(self, thermal_index): + self.index = thermal_index + self.high_threshold = float(112) + + # Add thermal name + self.THERMAL_NAME_LIST.append("SENSOR-1") + + # Set hwmon path + self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH + self.ss_key = self.THERMAL_NAME_LIST[self.index - 1] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + 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 + """ + return self.high_threshold + + 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 + """ + self.high_threshold = float(temperature) + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + 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 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/Makefile new file mode 100644 index 000000000..b3a639cc4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e530_48s4x_platform.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/centec_e530_48s4x_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/centec_e530_48s4x_platform.c new file mode 100644 index 000000000..179db7873 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/modules/centec_e530_48s4x_platform.c @@ -0,0 +1,1184 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 + +#if SEP("defines") + +#define CTC_GPIO_BASE 496 +int xirq_gpio_0 = 0; +int xirq_gpio_1 = 0; +int xirq_gpio_15 = 0; +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) +#define SFP_NUM 52 +#define PORT_NUM (SFP_NUM) +#endif + +#if SEP("ctc:pinctl") +u8 ctc_gpio_set(u8 gpio_pin, u8 val) +{ + gpio_set_value_cansleep(gpio_pin + CTC_GPIO_BASE, val); + return 0; +} + +u8 ctc_gpio_get(u8 gpio_pin) +{ + return gpio_get_value_cansleep(gpio_pin + CTC_GPIO_BASE); +} + +u8 ctc_gpio_direction_config(u8 gpio_pin, u8 dir,u8 default_out) +{ + return dir ? gpio_direction_input(gpio_pin + CTC_GPIO_BASE) + : gpio_direction_output(gpio_pin + CTC_GPIO_BASE,default_out); +} + +static void ctc_pincrtl_init(void) +{ + /* configure phy interrupt pin input */ + ctc_gpio_direction_config(0, 1, 0); + + /* aura clock (not use), + * set output for disable phy interrupt, + * tmp code for phy in sdk bug. + */ + ctc_gpio_direction_config(1, 0, 0); + + return; +} + +static void ctc_irq_init(void) +{ + struct device_node *xnp; + for_each_node_by_type(xnp, "ctc-irq") + { + if (of_device_is_compatible(xnp, "centec,ctc-irq")) + { + xirq_gpio_0 = irq_of_parse_and_map(xnp, 0); + printk(KERN_INFO "ctc-irq GPIO0 IRQ is %d\n", xirq_gpio_0); + xirq_gpio_1 = irq_of_parse_and_map(xnp, 1); + printk(KERN_INFO "ctc-irq GPIO1 IRQ is %d\n", xirq_gpio_1); + xirq_gpio_15 = irq_of_parse_and_map(xnp, 2); + printk(KERN_INFO "ctc-irq GPIO15 IRQ is %d\n", xirq_gpio_15); + } + } + return; +} +#endif + +#if SEP("i2c:smbus") +static int e530_48s4x_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e530_48s4x_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-1-cpu */ + +static int e530_48s4x_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e530_48s4x_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e530_48s4x_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x21), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; + +static struct i2c_adapter *i2c_adp_gpio1 = NULL; /* gpio1 */ +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x22), +}; +static struct i2c_client *i2c_client_gpio1 = NULL; + +static int e530_48s4x_init_i2c_gpio(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_48s4x_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e530_48s4x gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e530_48s4x board i2c client gpio0 failed\n"); + return -1; + } + + i2c_adp_gpio1 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio1)) + { + i2c_adp_gpio1 = NULL; + printk(KERN_CRIT "get e530_48s4x gpio1 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_gpio1, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e530_48s4x board i2c client gpio1 failed\n"); + return -1; + } + + if (ret) + { + printk(KERN_CRIT "init e530_48s4x board i2c gpio config failed\n"); + return -1; + } + + return 0; +} + +static int e530_48s4x_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio1)) + { + i2c_put_adapter(i2c_adp_gpio1); + i2c_adp_gpio1 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:epld") +static struct i2c_board_info i2c_dev_epld = { + I2C_BOARD_INFO("i2c-epld", 0x36), +}; +static struct i2c_client *i2c_client_epld = NULL; + +static int e530_48s4x_init_i2c_epld(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_48s4x_init_i2c_epld can't find i2c-core bus\n"); + return -1; + } + + i2c_client_epld = i2c_new_device(i2c_adp_master, &i2c_dev_epld); + if(IS_INVALID_PTR(i2c_client_epld)) + { + i2c_client_epld = NULL; + printk(KERN_CRIT "create e530_48s4x board i2c client epld failed\n"); + return -1; + } + + /* release asic i2c bridge */ + ret = e530_48s4x_smbus_write_reg(i2c_client_epld, 0x05, 0xff); + /* release phy */ + ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x07, 0xff); + /* unmask phy interrupt */ + ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x0b, 0x00); + + /* set sfp tx enable */ + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x0e, 0x00); + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x0f, 0x00); + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x10, 0x00); + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x11, 0x00); + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x12, 0x00); + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x13, 0x00); + //ret += e530_48s4x_smbus_write_reg(i2c_client_epld, 0x14, 0x00); + + return ret; +} + +static int e530_48s4x_exit_i2c_epld(void) +{ + if(IS_VALID_PTR(i2c_client_epld)) { + i2c_unregister_device(i2c_client_epld); + i2c_client_epld = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e530_48s4x_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_epld; + present_no = 0x1e * 8 + 2; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_epld; + present_no = 0x1e * 8 + 3; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_48s4x_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_48s4x_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_epld; + workstate_no = 0x1e * 8 + 4; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_epld; + workstate_no = 0x1e * 8 + 5; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_48s4x_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e530_48s4x_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e530_48s4x_psu_read_status, NULL); + +static int e530_48s4x_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e530_48s4x class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e530_48s4x psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e530_48s4x psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e530_48s4x_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e530_48s4x_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_48s4x_led_get(struct led_classdev *led_cdev); +extern void e530_48s4x_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_48s4x_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e530_48s4x_led_set, + .brightness_get = e530_48s4x_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port2", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port3", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port4", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port5", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port6", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port7", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port8", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port9", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port10", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port11", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port12", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port13", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port14", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port15", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port16", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port17", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port18", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port19", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port20", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port21", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port22", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port23", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port24", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port25", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port26", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port27", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port28", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port29", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port30", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port31", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port32", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port33", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port34", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port35", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port36", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port37", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port38", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port39", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port40", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port41", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port42", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port43", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port44", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port45", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port46", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port47", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port48", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port49", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port50", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port51", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +{ .name = "port52", .brightness_set = e530_48s4x_led_port_set, .brightness_get = e530_48s4x_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e530_48s4x_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x0f; + shift = 0; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0x01; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_48s4x_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & (~mask)) | ((set_value << shift) & (mask))); + + ret = e530_48s4x_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: led not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e530_48s4x_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x0f; + shift = 0; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0x01; + shift = 1; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_48s4x_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e530_48s4x_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e530_48s4x_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e530_48s4x_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i SFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + presence = sfp_info[portNum].presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + return sprintf(buf, "%d\n", presence); +} + +static ssize_t e530_48s4x_sfp_write_presence(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + int presence = simple_strtol(buf, NULL, 10); + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].presence = presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_48s4x_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + value = 0; + } + + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_epld; + + input_bank = (reg_no/8) + 0xe; + ret = e530_48s4x_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp enable: %s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_48s4x_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + return size; + } + + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_epld; + + set_value = ((set_value > 0) ? 0 : 1); + + input_bank = (reg_no/8) + 0xe; + ret = e530_48s4x_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s enable failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0xe; + ret = e530_48s4x_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s enable failed\n", name); + return size; + } + + return size; +} + +static ssize_t e530_48s4x_sfp_read_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + size_t size = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read eeprom, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(buf, sfp_info[portNum].data, sfp_info[portNum].data_len); + size = sfp_info[portNum].data_len; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_48s4x_sfp_write_eeprom(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp write eeprom, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(sfp_info[portNum].data, buf, size); + sfp_info[portNum].data_len = size; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO|S_IWUSR, e530_48s4x_sfp_read_presence, e530_48s4x_sfp_write_presence); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e530_48s4x_sfp_read_enable, e530_48s4x_sfp_write_enable); +static DEVICE_ATTR(sfp_eeprom, S_IRUGO|S_IWUSR, e530_48s4x_sfp_read_eeprom, e530_48s4x_sfp_write_eeprom); +static int e530_48s4x_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e530_48s4x class sfp failed\n"); + return -1; + } + + for (i=1; i<=SFP_NUM; i++) + { + memset(&(sfp_info[i].data), 0, MAX_SFP_EEPROM_DATA_LEN+1); + sfp_info[i].data_len = 0; + spin_lock_init(&(sfp_info[i].lock)); + + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e530_48s4x sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x sfp[%d] device attr:enable failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_eeprom); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48s4x sfp[%d] device attr:eeprom failed\n", i); + continue; + } + } + + return ret; +} + +static int e530_48s4x_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=SFP_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_remove_file(sfp_dev[i], &dev_attr_sfp_eeprom); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e530_48s4x_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e530_48s4x board dirver...\n"); + + ctc_irq_init(); + ctc_pincrtl_init(); + + ret = e530_48s4x_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48s4x_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48s4x_init_i2c_epld(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48s4x_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48s4x_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48s4x_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e530_48s4x board driver failed\n"); + else + printk(KERN_ALERT "install e530_48s4x board dirver...ok\n"); + + return 0; +} + +static void e530_48s4x_exit(void) +{ + printk(KERN_INFO "uninstall e530_48s4x board dirver...\n"); + + e530_48s4x_exit_sfp(); + e530_48s4x_exit_led(); + e530_48s4x_exit_psu(); + e530_48s4x_exit_i2c_epld(); + e530_48s4x_exit_i2c_gpio(); + e530_48s4x_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("e530-48s4x board driver"); +module_init(e530_48s4x_init); +module_exit(e530_48s4x_exit); diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/service/48s4x_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/service/48s4x_platform.service new file mode 100644 index 000000000..b98ed2153 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/service/48s4x_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e530-48s4x start +ExecStop=-/etc/init.d/platform-modules-e530-48s4x stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/setup.py new file mode 100644 index 000000000..d1fe198d2 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize centec e530-48s4x platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/__init__.py new file mode 100644 index 000000000..d4a9e746e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"] +from . import platform + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/chassis.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/chassis.py new file mode 100644 index 000000000..318351778 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/chassis.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from .fan_drawer import FanDrawer + from .thermal import Thermal + from .sfp import Sfp + from .psu import Psu + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 1 +NUM_THERMAL = 1 +NUM_PORT = 52 +NUM_PSU = 2 + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + # Initialize EEPROM + self._eeprom = Eeprom() + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # Initialize SFP + for index in range(0, NUM_PORT): + sfp = Sfp(index) + self._sfp_list.append(sfp) + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index + 1) + self._psu_list.append(psu) + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_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.serial_number_str() + + 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. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + return (None, None) + + def get_change_event(self, timeout=2000): + """ + 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. + """ + ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout) + ret_dict = {"sfp": port_dict} + return ret, ret_dict + + def get_num_psus(self): + return len(self._psu_list) + + def get_psu(self, psu_index): + return self._psu_list[psu_index] diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/eeprom.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/eeprom.py new file mode 100644 index 000000000..77e3e82df --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/eeprom.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/dev/mtd3" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.open_eeprom() + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += str(tlv[6:6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan.py new file mode 100644 index 000000000..a26163226 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan.py @@ -0,0 +1,186 @@ +#!/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 +# +############################################################################# + +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/class/hwmon/hwmon1/" +FAN_MAX_PWM = 255 +FAN_FAN_PWM = "pwm{}" +FAN_FAN_INPUT = "fan{}_input" +FAN_MAX_RPM = 9000 +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + + FanBase.__init__(self) + + 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 "" + + 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 __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + 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 = self.FAN_DIRECTION_EXHAUST + 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) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return int(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 = 0 + # fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + # fan_target_sysfs_path = self.__search_file_by_name( + # FAN_PATH, fan_target_sysfs_name) + # fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0 + # target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM) + + # return target + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return 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 10 + + 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 + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + fan_target_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_target_sysfs_name) + return self.__write_txt_file(fan_target_sysfs_path, int(pwm)) + + 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: always True + """ + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_index] + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: always True + """ + + return True + + def get_status(self): + """ + Retrieves the status of the FAN + Returns: + bool: always True + """ + return True diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan_drawer.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan_drawer.py new file mode 100644 index 000000000..cd6a726d3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/fan_drawer.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +######################################################################## +# Centec E530 48s4x +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from .fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CENTEC_FANS_PER_FANTRAY = 4 + + +class FanDrawer(FanDrawerBase): + """Centec E530 48s4x Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + for i in range(CENTEC_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/platform.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/platform.py new file mode 100644 index 000000000..3faee64ec --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs for Centec E530-48S4X +# + + +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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/psu.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/psu.py new file mode 100644 index 000000000..0e133d15c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/psu.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Psu(PsuBase): + """Centec Platform-specific PSU class""" + + def __init__(self, index): + self._index = index + self._fan_list = [] + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "psuutil.py"]) + module = imp.load_source("psuutil", module_file) + psu_util_class = getattr(module, "PsuUtil") + self._psuutil = psu_util_class() + + def _get_psuutil(self): + return self._psuutil + + def get_presence(self): + return self._get_psuutil().get_psu_presence(self._index) + + def get_powergood_status(self): + return self._get_psuutil().get_psu_status(self._index) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/sfp.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/sfp.py new file mode 100644 index 000000000..4a92fecfa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/sfp.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Sfp(SfpBase): + """ + Platform-specific sfp class + + Unimplemented methods: + - get_model + - get_serial + - get_status + - get_transceiver_info + - get_transceiver_bulk_status + - get_transceiver_threshold_info + - get_reset_status + - get_rx_los + - get_tx_fault + - get_tx_disable_channel + - get_power_override + - get_temperature + - get_voltage + - get_tx_bias + - get_rx_power + - get_tx_power + - tx_disable_channel + - set_power_override + """ + + def __init__(self, index): + self._index = index + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "sfputil.py"]) + module = imp.load_source("sfputil", module_file) + sfp_util_class = getattr(module, "SfpUtil") + self._sfputil = sfp_util_class() + + def get_id(self): + return self._index + + def get_name(self): + return "Ethernet{}".format(self._index) + + def get_lpmode(self): + return False + + def set_lpmode(self, lpmode): + return False + + def get_tx_disable(self): + return False + + def tx_disable(self, tx_disable): + return False + + def reset(self): + pass + + def clear_interrupt(self): + return False + + def get_interrupt_file(self): + return None + + def _get_sfputil(self): + return self._sfputil + + def get_presence(self): + return self._get_sfputil().get_presence(self._index) + + def get_transceiver_info(self): + return self._get_sfputil().get_transceiver_info_dict(self._index) + + def get_transceiver_bulk_status(self): + return self._get_sfputil().get_transceiver_dom_info_dict(self._index) + + def get_transceiver_threshold_info(self): + return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index) + + def get_transceiver_change_event(self, timeout): + return self._get_sfputil().get_transceiver_change_event(timeout) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/thermal.py b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/thermal.py new file mode 100644 index 000000000..ce224f0ed --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48s4x/sonic_platform/thermal.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +############################################################################# +# 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 os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1" + + def __init__(self, thermal_index): + self.index = thermal_index + self.high_threshold = float(112) + + # Add thermal name + self.THERMAL_NAME_LIST.append("SENSOR-1") + + # Set hwmon path + self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH + self.ss_key = self.THERMAL_NAME_LIST[self.index - 1] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + 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 + """ + return self.high_threshold + + 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 + """ + self.high_threshold = float(temperature) + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + 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 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/modules/Makefile similarity index 100% rename from platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile rename to platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/modules/Makefile diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/modules/centec_e530_48t4x_p_platform.c similarity index 93% rename from platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c rename to platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/modules/centec_e530_48t4x_p_platform.c index aedbe6601..7f5584279 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/modules/centec_e530_48t4x_p_platform.c @@ -8,16 +8,92 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define SEP(XXX) 1 -#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) -#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) #if SEP("defines") + +#define CTC_GPIO_BASE 496 +int xirq_gpio_0 = 0; +int xirq_gpio_1 = 0; +int xirq_gpio_6 = 0; /* add for E530_48S4X EPLD INT0*/ +int xirq_gpio_7 = 0; /* add for E530_48S4X EPLD INT1*/ +int xirq_gpio_15 = 0; +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) #define SFP_NUM 4 #define PORT_NUM (48+SFP_NUM) #endif +#if SEP("ctc:pinctl") +u8 ctc_gpio_set(u8 gpio_pin, u8 val) +{ + gpio_set_value_cansleep(gpio_pin + CTC_GPIO_BASE, val); + return 0; +} + +u8 ctc_gpio_get(u8 gpio_pin) +{ + return gpio_get_value_cansleep(gpio_pin + CTC_GPIO_BASE); +} + +u8 ctc_gpio_direction_config(u8 gpio_pin, u8 dir,u8 default_out) +{ + return dir ? gpio_direction_input(gpio_pin + CTC_GPIO_BASE) + : gpio_direction_output(gpio_pin + CTC_GPIO_BASE,default_out); +} + +static void ctc_pincrtl_init(void) +{ + /* configure mgmt-phy reset-pin output on product, mgmt-phy release must before this */ + ctc_gpio_direction_config(4, 0, 1); + /* configure power-up pin output on product */ + ctc_gpio_direction_config(6, 0, 0); + /* configure phy interrupt pin input */ + ctc_gpio_direction_config(0, 1, 0); + ctc_gpio_direction_config(1, 1, 0); + /* configure phy reset-pin output, for release phy */ + ctc_gpio_direction_config(5, 0, 1); + + return; +} + +static void ctc_irq_init(void) +{ + struct device_node *xnp; + for_each_node_by_type(xnp, "ctc-irq") + { + if (of_device_is_compatible(xnp, "centec,ctc-irq")) + { + xirq_gpio_0 = irq_of_parse_and_map(xnp, 0); + printk(KERN_INFO "ctc-irq GPIO0 IRQ is %d\n", xirq_gpio_0); + xirq_gpio_1 = irq_of_parse_and_map(xnp, 1); + printk(KERN_INFO "ctc-irq GPIO1 IRQ is %d\n", xirq_gpio_1); + xirq_gpio_15 = irq_of_parse_and_map(xnp, 2); + printk(KERN_INFO "ctc-irq GPIO15 IRQ is %d\n", xirq_gpio_15); + } + } + return; +} +#endif + #if SEP("i2c:smbus") static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) { @@ -966,6 +1042,9 @@ static int e530_48t4x_p_init(void) int failed = 0; printk(KERN_ALERT "install e530_48t4x_p board dirver...\n"); + + ctc_irq_init(); + ctc_pincrtl_init(); ret = e530_48t4x_p_init_i2c_master(); if (ret != 0) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/service/48t4x_p_platform.service similarity index 100% rename from platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service rename to platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/service/48t4x_p_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/setup.py similarity index 54% rename from platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py rename to platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/setup.py index eee1cd2a8..129bcdc26 100755 --- a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/setup.py @@ -5,11 +5,11 @@ from setuptools import setup os.listdir setup( - name='48t4x_p', - version='1.1', + name='sonic_platform', + version='1.0', description='Module to initialize centec e530-48t4x-p platforms', - packages=['48t4x_p'], - package_dir={'48t4x_p': '48t4x_p/classes'}, + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, ) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/__init__.py new file mode 100644 index 000000000..d4a9e746e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"] +from . import platform + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/chassis.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/chassis.py new file mode 100644 index 000000000..318351778 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/chassis.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from .fan_drawer import FanDrawer + from .thermal import Thermal + from .sfp import Sfp + from .psu import Psu + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 1 +NUM_THERMAL = 1 +NUM_PORT = 52 +NUM_PSU = 2 + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + # Initialize EEPROM + self._eeprom = Eeprom() + # Initialize FAN + for i in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + # Initialize THERMAL + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # Initialize SFP + for index in range(0, NUM_PORT): + sfp = Sfp(index) + self._sfp_list.append(sfp) + # Initialize PSU + for index in range(0, NUM_PSU): + psu = Psu(index + 1) + self._psu_list.append(psu) + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_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.serial_number_str() + + 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. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + return (None, None) + + def get_change_event(self, timeout=2000): + """ + 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. + """ + ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout) + ret_dict = {"sfp": port_dict} + return ret, ret_dict + + def get_num_psus(self): + return len(self._psu_list) + + def get_psu(self, psu_index): + return self._psu_list[psu_index] diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/eeprom.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/eeprom.py new file mode 100644 index 000000000..77e3e82df --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/eeprom.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/dev/mtd3" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.open_eeprom() + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += str(tlv[6:6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan.py new file mode 100644 index 000000000..a26163226 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan.py @@ -0,0 +1,186 @@ +#!/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 +# +############################################################################# + +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/class/hwmon/hwmon1/" +FAN_MAX_PWM = 255 +FAN_FAN_PWM = "pwm{}" +FAN_FAN_INPUT = "fan{}_input" +FAN_MAX_RPM = 9000 +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"] + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + + FanBase.__init__(self) + + 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 "" + + 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 __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + 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 = self.FAN_DIRECTION_EXHAUST + 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) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return int(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 = 0 + # fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + # fan_target_sysfs_path = self.__search_file_by_name( + # FAN_PATH, fan_target_sysfs_name) + # fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0 + # target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM) + + # return target + speed = 0 + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM) + + return 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 10 + + 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 + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + fan_target_sysfs_name = "pwm{}".format(self.fan_index+1) + fan_target_sysfs_path = self.__search_file_by_name( + FAN_PATH, fan_target_sysfs_name) + return self.__write_txt_file(fan_target_sysfs_path, int(pwm)) + + 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: always True + """ + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_index] + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: always True + """ + + return True + + def get_status(self): + """ + Retrieves the status of the FAN + Returns: + bool: always True + """ + return True diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan_drawer.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan_drawer.py new file mode 100644 index 000000000..410e9abcf --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/fan_drawer.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +######################################################################## +# Centec E530 48t4x-p +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from .fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CENTEC_FANS_PER_FANTRAY = 3 + + +class FanDrawer(FanDrawerBase): + """Centec E530 48t4x-p Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + self.fantrayindex = fantray_index + for i in range(CENTEC_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/platform.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/platform.py new file mode 100644 index 000000000..644cca8a4 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs for Centec E530-48T4X-P +# + + +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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/psu.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/psu.py new file mode 100644 index 000000000..0e133d15c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/psu.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Psu(PsuBase): + """Centec Platform-specific PSU class""" + + def __init__(self, index): + self._index = index + self._fan_list = [] + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "psuutil.py"]) + module = imp.load_source("psuutil", module_file) + psu_util_class = getattr(module, "PsuUtil") + self._psuutil = psu_util_class() + + def _get_psuutil(self): + return self._psuutil + + def get_presence(self): + return self._get_psuutil().get_psu_presence(self._index) + + def get_powergood_status(self): + return self._get_psuutil().get_psu_status(self._index) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/sfp.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/sfp.py new file mode 100644 index 000000000..4a92fecfa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/sfp.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import imp +import os + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +USR_SHARE_SONIC_PATH = "/usr/share/sonic" +HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device" +CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform" + +class Sfp(SfpBase): + """ + Platform-specific sfp class + + Unimplemented methods: + - get_model + - get_serial + - get_status + - get_transceiver_info + - get_transceiver_bulk_status + - get_transceiver_threshold_info + - get_reset_status + - get_rx_los + - get_tx_fault + - get_tx_disable_channel + - get_power_override + - get_temperature + - get_voltage + - get_tx_bias + - get_rx_power + - get_tx_power + - tx_disable_channel + - set_power_override + """ + + def __init__(self, index): + self._index = index + + if os.path.isdir(CONTAINER_PLATFORM_PATH): + platform_path = CONTAINER_PLATFORM_PATH + else: + platform = device_info.get_platform() + if platform is None: + return + platform_path = os.path.join(HOST_DEVICE_PATH, platform) + + module_file = "/".join([platform_path, "plugins", "sfputil.py"]) + module = imp.load_source("sfputil", module_file) + sfp_util_class = getattr(module, "SfpUtil") + self._sfputil = sfp_util_class() + + def get_id(self): + return self._index + + def get_name(self): + return "Ethernet{}".format(self._index) + + def get_lpmode(self): + return False + + def set_lpmode(self, lpmode): + return False + + def get_tx_disable(self): + return False + + def tx_disable(self, tx_disable): + return False + + def reset(self): + pass + + def clear_interrupt(self): + return False + + def get_interrupt_file(self): + return None + + def _get_sfputil(self): + return self._sfputil + + def get_presence(self): + return self._get_sfputil().get_presence(self._index) + + def get_transceiver_info(self): + return self._get_sfputil().get_transceiver_info_dict(self._index) + + def get_transceiver_bulk_status(self): + return self._get_sfputil().get_transceiver_dom_info_dict(self._index) + + def get_transceiver_threshold_info(self): + return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index) + + def get_transceiver_change_event(self, timeout): + return self._get_sfputil().get_transceiver_change_event(timeout) diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/thermal.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/thermal.py new file mode 100644 index 000000000..ce224f0ed --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x-p/sonic_platform/thermal.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +############################################################################# +# 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 os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1" + + def __init__(self, thermal_index): + self.index = thermal_index + self.high_threshold = float(112) + + # Add thermal name + self.THERMAL_NAME_LIST.append("SENSOR-1") + + # Set hwmon path + self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH + self.ss_key = self.THERMAL_NAME_LIST[self.index - 1] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + 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 + """ + return self.high_threshold + + 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 + """ + self.high_threshold = float(temperature) + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + 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 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog b/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog index 6ac3ca482..0a6dc44af 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog @@ -1,3 +1,15 @@ +sonic-centec-platform-modules (1.3) unstable; urgency=low + + * Add support for centec e530-24x2q + + -- shil Mon, 21 Sep 2020 13:34:33 +0800 + +sonic-centec-platform-modules (1.2) unstable; urgency=low + + * Add support for centec e530-48t4x-p and e530-24x2c and e530-48s4x + + -- shil Mon, 18 May 2020 13:21:57 +0800 + sonic-centec-platform-modules (1.1) unstable; urgency=low * Add support for centec e530-48t4x-p and e530-24x2c diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/control b/platform/centec-arm64/sonic-platform-modules-e530/debian/control index 2a1bc972a..31abd51cd 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/control +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/control @@ -14,3 +14,13 @@ Package: platform-modules-e530-24x2c Architecture: arm64 Depends: linux-image-4.19.0-12-2-arm64-unsigned Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-e530-48s4x +Architecture: arm64 +Depends: linux-image-4.19.0-12-2-arm64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-e530-24x2q +Architecture: arm64 +Depends: linux-image-4.19.0-12-2-arm64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init index e0349914b..e508d5205 100755 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init @@ -12,11 +12,30 @@ # Short-Description: Load Centec kernel modules ### END INIT INFO +function install_python_api_package() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip2 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip2 install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + fi + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} function load_kernel_modules() { + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi depmod -a modprobe centec_e530_24x2c_platform + modprobe fan-ctc5236 modprobe dal modprobe tun modprobe tap @@ -27,6 +46,7 @@ function remove_kernel_modules() modprobe -r tap modprobe -r tun modprobe -r dal + modprobe -r fan-ctc5236 modprobe -r centec_e530_24x2c_platform } @@ -35,6 +55,7 @@ start) echo -n "Load Centec kernel modules... " load_kernel_modules + install_python_api_package echo "done." ;; diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install index b74a968fe..567afa923 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install @@ -1,3 +1,2 @@ -../../centec/centec-dal/dal.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra -24x2c/modules/centec_e530_24x2c_platform.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra -24x2c/service/24x2c_platform.service /lib/systemd/system +24x2c/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/arm64-centec_e530_24x2c-r0 +24x2c/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-centec_e530_24x2c-r0 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.init new file mode 100644 index 000000000..60b3b69a1 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.init @@ -0,0 +1,82 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-e530-24x2q +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + +function install_python_api_package() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip2 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip2 install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + fi + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} + +function load_kernel_modules() +{ + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi + depmod -a + modprobe centec_e530_24x2q_platform + modprobe fan-ctc5236 + modprobe dal + modprobe tun + modprobe tap +} + +function remove_kernel_modules() +{ + modprobe -r tap + modprobe -r tun + modprobe -r dal + modprobe -r fan-ctc5236 + modprobe -r centec_e530_24x2q_platform +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + install_python_api_package + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-e530-24x2q {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.install new file mode 100644 index 000000000..d57210888 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.install @@ -0,0 +1,2 @@ +24x2q/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/arm64-centec_e530_24x2q-r0 +24x2q/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-centec_e530_24x2q-r0 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.postinst b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.postinst new file mode 100644 index 000000000..129711dfd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2q.postinst @@ -0,0 +1,2 @@ +systemctl enable 24x2q_platform.service +systemctl start 24x2q_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.init new file mode 100644 index 000000000..1fa1970f6 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.init @@ -0,0 +1,82 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-e530-48s4x +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + +function install_python_api_package() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip2 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip2 install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + fi + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} + +function load_kernel_modules() +{ + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi + depmod -a + modprobe centec_e530_48s4x_platform + modprobe fan-ctc5236 + modprobe dal + modprobe tun + modprobe tap +} + +function remove_kernel_modules() +{ + modprobe -r tap + modprobe -r tun + modprobe -r dal + modprobe -r fan-ctc5236 + modprobe -r centec_e530_48s4x_platform +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + install_python_api_package + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-e530-48s4x {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.install new file mode 100644 index 000000000..d319f3f65 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.install @@ -0,0 +1,2 @@ +48s4x/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/arm64-centec_e530_48s4x-r0 +48s4x/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-centec_e530_48s4x-r0 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.postinst b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.postinst new file mode 100644 index 000000000..085c874aa --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48s4x.postinst @@ -0,0 +1,2 @@ +systemctl enable 48s4x_platform.service +systemctl start 48s4x_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init index b9a6d555b..cefacf666 100755 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init @@ -12,11 +12,30 @@ # Short-Description: Load Centec kernel modules ### END INIT INFO +function install_python_api_package() +{ + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip2 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip2 install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + fi + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -ne 0 ]; then + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) + fi +} function load_kernel_modules() { + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi depmod -a modprobe centec_e530_48t4x_p_platform + modprobe fan-ctc5236 modprobe dal modprobe tun modprobe tap @@ -27,6 +46,7 @@ function remove_kernel_modules() modprobe -r tap modprobe -r tun modprobe -r dal + modprobe -r fan-ctc5236 modprobe -r centec_e530_48t4x_p_platform } @@ -35,6 +55,7 @@ start) echo -n "Load Centec kernel modules... " load_kernel_modules + install_python_api_package echo "done." ;; diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install index 7d1c00eeb..634e57f36 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install @@ -1,3 +1,2 @@ -../../centec/centec-dal/dal.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra -48t4x_p/modules/centec_e530_48t4x_p_platform.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra -48t4x_p/service/48t4x_p_platform.service /lib/systemd/system +48t4x-p/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/arm64-centec_e530_48t4x_p-r0 +48t4x-p/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-centec_e530_48t4x_p-r0 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/rules b/platform/centec-arm64/sonic-platform-modules-e530/debian/rules index 69ab667c0..0fb2c85a8 100755 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/rules +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/rules @@ -13,22 +13,20 @@ include /usr/share/dpkg/pkg-info.mk export INSTALL_MOD_DIR:=extra -PYTHON ?= python2 - -PACKAGE_PRE_NAME := sonic-platform-modules-e530 +PACKAGE_PRE_NAME := platform-modules-e530 KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= 48t4x_p 24x2c +MODULE_DIRS:= 48t4x-p 24x2c 48s4x 24x2q MODULE_DIR := modules -UTILS_DIR := utils SERVICE_DIR := service CLASSES_DIR := classes CONF_DIR := conf KDAL_DIR := ../../centec/centec-dal/ +FAN_DIR := fan %: - dh $@ --with systemd,python2,python3 --buildsystem=pybuild + dh $@ clean: dh_testdir @@ -40,9 +38,15 @@ build: (for mod in $(KDAL_DIR); do \ make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/; \ done) + (for mod in $(FAN_DIR); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/; \ + done) (for mod in $(MODULE_DIRS); do \ make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ - $(PYTHON) $${mod}/setup.py build; \ + cd $${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd -; \ done) binary: binary-arch binary-indep @@ -64,13 +68,12 @@ binary-indep: # Custom package commands (for mod in $(MODULE_DIRS); do \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc; \ cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ cp $(MOD_SRC_DIR)/$(KDAL_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ - cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$(FAN_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ - $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ done) # Resuming debhelper scripts dh_testroot diff --git a/platform/centec-arm64/sonic-platform-modules-e530/fan/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/fan/Makefile new file mode 100644 index 000000000..07a8237dd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/fan/Makefile @@ -0,0 +1 @@ +obj-m := fan-ctc5236.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/fan/fan-ctc5236.c b/platform/centec-arm64/sonic-platform-modules-e530/fan/fan-ctc5236.c new file mode 100644 index 000000000..96448c7db --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/fan/fan-ctc5236.c @@ -0,0 +1,268 @@ +/* + * Centec FAN driver + * + * based by pwm-fan.c + * Author: shil + * Copyright 2005-2018, Centec Networks (Suzhou) Co., Ltd. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CTC_MAX_PWM 255 +#define CTC_MAX_FAN 4 +char *pwmnames[CTC_MAX_FAN] = { "pwm1", "pwm2", "pwm3", "pwm4" }; + +struct fan_ctc5236_data { + struct mutex lock; + struct pwm_device *pwm[CTC_MAX_FAN]; + unsigned int pwm_value[CTC_MAX_FAN]; + long temp; +}; + +static int __ctc_set_pwm(struct fan_ctc5236_data *data, int index, unsigned long pwm) +{ + struct pwm_args pargs; + unsigned long duty; + int ret = 0; + + pwm_get_args(data->pwm[index], &pargs); + + mutex_lock(&data->lock); + if (data->pwm_value[index] == pwm) + goto exit_set_pwm_err; + + duty = DIV_ROUND_UP(pwm * (pargs.period - 1), CTC_MAX_PWM); + ret = pwm_config(data->pwm[index], duty, pargs.period); + if (ret) + goto exit_set_pwm_err; + + if (pwm == 0) + pwm_disable(data->pwm[index]); + + if (data->pwm_value[index] == 0) { + ret = pwm_enable(data->pwm[index]); + if (ret) + goto exit_set_pwm_err; + } + + data->pwm_value[index] = pwm; +exit_set_pwm_err: + mutex_unlock(&data->lock); + return ret; +} + +static ssize_t ctc_set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct fan_ctc5236_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + unsigned long pwm; + int ret; + + if (kstrtoul(buf, 10, &pwm) || pwm > CTC_MAX_PWM) + return -EINVAL; + + ret = __ctc_set_pwm(data, attr->index, pwm); + if (ret) + return ret; + + return count; +} + +static ssize_t ctc_show_pwm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct fan_ctc5236_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + + return sprintf(buf, "%u\n", data->pwm_value[attr->index]); +} + +static ssize_t ctc_show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct fan_ctc5236_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct pwm_capture result; + int ret = 0; + int ratio = 0; + + mutex_lock(&data->lock); + + ret = pwm_capture(data->pwm[attr->index], &result, jiffies_to_msecs(HZ)); + if (ret) + goto exit_show_fan_err; + + if (result.period == 0 || result.duty_cycle == 0) + goto exit_show_fan_err; + + ratio = result.period * 10 / result.duty_cycle; + if (ratio >= 19 && ratio <= 21) + { + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", (int)(30000000000ll / result.period)); + } + +exit_show_fan_err: + mutex_unlock(&data->lock); + return sprintf(buf, "0\n"); +} + +static ssize_t ctc_show_temp(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct fan_ctc5236_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%ld\n", data->temp); +} + +static ssize_t ctc_set_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct fan_ctc5236_data *data = dev_get_drvdata(dev); + + if (kstrtol(buf, 10, &(data->temp))) + return -EINVAL; + + return count; +} + + +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, ctc_show_pwm, ctc_set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, ctc_show_pwm, ctc_set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, ctc_show_pwm, ctc_set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, ctc_show_pwm, ctc_set_pwm, 3); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, ctc_show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, ctc_show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, ctc_show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, ctc_show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO | S_IWUSR, ctc_show_temp, ctc_set_temp, 0); + +static struct attribute *fan_ctc5236_attrs[] = { + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(fan_ctc5236); + +static int fan_ctc5236_probe(struct platform_device *pdev) +{ + struct fan_ctc5236_data *data; + struct pwm_args pargs; + struct device *hwmon; + int duty_cycle; + int ret; + int idx; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + data->temp = 35000; + + for (idx = 0; idx < CTC_MAX_FAN; idx++) + { + data->pwm[idx] = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, pwmnames[idx]); + if (IS_ERR(data->pwm[idx])) { + dev_err(&pdev->dev, "Could not get PWM\n"); + return PTR_ERR(data->pwm[idx]); + } + } + + platform_set_drvdata(pdev, data); + + for (idx = 0; idx < CTC_MAX_FAN; idx++) + { + /* + * FIXME: pwm_apply_args() should be removed when switching to the + * atomic PWM API. + */ + pwm_apply_args(data->pwm[idx]); + + /* Set duty cycle to maximum allowed */ + pwm_get_args(data->pwm[idx], &pargs); + + duty_cycle = pargs.period - 1; + data->pwm_value[idx] = CTC_MAX_PWM; + + ret = pwm_config(data->pwm[idx], duty_cycle, pargs.period); + if (ret) { + dev_err(&pdev->dev, "Failed to configure PWM\n"); + return ret; + } + + /* Enbale PWM output */ + ret = pwm_enable(data->pwm[idx]); + if (ret) { + dev_err(&pdev->dev, "Failed to enable PWM\n"); + return ret; + } + } + + hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "ctc5236fan", + data, fan_ctc5236_groups); + + if (IS_ERR(hwmon)) { + dev_err(&pdev->dev, "Failed to register hwmon device\n"); + for (idx = 0; idx < CTC_MAX_FAN; idx++) + { + pwm_disable(data->pwm[idx]); + } + return PTR_ERR(hwmon); + } + + return 0; +} + +static int fan_ctc5236_remove(struct platform_device *pdev) +{ + struct fan_ctc5236_data *data = platform_get_drvdata(pdev); + int idx; + + for (idx = 0; idx < CTC_MAX_FAN; idx++) + { + if (data->pwm_value[idx]) + pwm_disable(data->pwm[idx]); + } + return 0; +} + +static const struct of_device_id of_fan_ctc5236_match[] = { + { .compatible = "fan-ctc5236", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_fan_ctc5236_match); + +static struct platform_driver fan_ctc5236_driver = { + .probe = fan_ctc5236_probe, + .remove = fan_ctc5236_remove, + .driver = { + .name = "fan-ctc5236", + .of_match_table = of_fan_ctc5236_match, + }, +}; + +module_platform_driver(fan_ctc5236_driver); + +MODULE_AUTHOR("Shi Lei "); +MODULE_ALIAS("platform:fan-ctc5236"); +MODULE_DESCRIPTION("CTC5236 FAN driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec/centec-dal/dal_common.h b/platform/centec/centec-dal/dal_common.h index d8d4d6a67..d9f410e55 100644 --- a/platform/centec/centec-dal/dal_common.h +++ b/platform/centec/centec-dal/dal_common.h @@ -14,7 +14,7 @@ extern "C" { #endif -#define DAL_MAX_CHIP_NUM 8 /* DAL support max chip num is 8 */ +#define DAL_MAX_CHIP_NUM 4 /* DAL support max chip num is 4 */ #define DAL_MAX_INTR_NUM 8 #define DAL_NETIF_T_PORT 0 @@ -23,6 +23,10 @@ extern "C" { #define DAL_MAX_KNET_NETIF 64 #define DAL_MAX_KNET_NAME_LEN 32 +#define DAL_PCI_CMD_STATUS 0x0 +#define DAL_PCI_ADDR 0x4 +#define DAL_PCI_DATA_BUF 0x8 + enum dal_operate_code_e { DAL_OP_CREATE, @@ -44,7 +48,7 @@ struct dal_dma_info_s }; typedef struct dal_dma_info_s dal_dma_info_t; -struct dal_dma_chan_s +struct dal_dma_chan_s { unsigned char lchip; unsigned char channel_id; @@ -111,6 +115,64 @@ struct dal_pci_dev_s }; typedef struct dal_pci_dev_s dal_pci_dev_t; +#ifndef HOST_IS_LE +#define HOST_IS_LE 1 +#endif + +#if (HOST_IS_LE == 0) + +/* pci cmd struct define */ +typedef struct pci_cmd_status_s +{ + unsigned int pcieReqOverlap : 1; + unsigned int wrReqState : 3; + unsigned int pciePoison : 1; + unsigned int rcvregInProc : 1; + unsigned int regInProc : 1; + unsigned int reqProcAckCnt : 5; + unsigned int reqProcAckError : 1; + unsigned int reqProcTimeout : 1; + unsigned int reqProcError : 1; + unsigned int reqProcDone : 1; + unsigned int pcieDataError : 1; + unsigned int pcieReqError : 1; + unsigned int reserved : 1; + unsigned int cmdDataLen : 5; + unsigned int cmdEntryWords : 4; + unsigned int pcieReqCmdChk : 3; + unsigned int cmdReadType : 1; +} pci_cmd_status_t; + +#else + +typedef struct pci_cmd_status_s +{ + unsigned int cmdReadType : 1; /* bit0 */ + unsigned int pcieReqCmdChk : 3; /* bit1~3 */ + unsigned int cmdEntryWords : 4; /* bit4~7 */ + unsigned int cmdDataLen : 5; /* bit8~12 */ + unsigned int reserved : 1; /* bit13 */ + unsigned int pcieReqError : 1; + unsigned int pcieDataError : 1; + unsigned int reqProcDone : 1; + unsigned int reqProcError : 1; + unsigned int reqProcTimeout : 1; + unsigned int reqProcAckError : 1; + unsigned int reqProcAckCnt : 5; + unsigned int regInProc : 1; + unsigned int rcvregInProc : 1; + unsigned int pciePoison : 1; + unsigned int wrReqState : 3; + unsigned int pcieReqOverlap : 1; +} pci_cmd_status_t; +#endif + +typedef union pci_cmd_status_u_e +{ + pci_cmd_status_t cmd_status; + unsigned int val; +} pci_cmd_status_u_t; + #ifdef __cplusplus } #endif diff --git a/platform/centec/centec-dal/dal_kernel.c b/platform/centec/centec-dal/dal_kernel.c index 23fc6e736..1651e803f 100644 --- a/platform/centec/centec-dal/dal_kernel.c +++ b/platform/centec/centec-dal/dal_kernel.c @@ -20,6 +20,9 @@ #include #include #include +#if defined(SOC_ACTIVE) +#include +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) #include #endif @@ -27,9 +30,6 @@ #include "dal_common.h" #include "dal_mpool.h" #include -#if defined(SOC_ACTIVE) -#include -#endif MODULE_AUTHOR("Centec Networks Inc."); MODULE_DESCRIPTION("DAL kernel module"); MODULE_LICENSE("GPL"); @@ -55,12 +55,12 @@ MODULE_PARM_DESC(dma_pool_size, #define CTC_PCIE_VENDOR_ID 0xcb10 #define CTC_DUET2_DEVICE_ID 0x7148 #define CTC_TSINGMA_DEVICE_ID 0x5236 +#define CTC_TSINGMA_MX_DEVICE_ID 0x8180 #define MEM_MAP_RESERVE SetPageReserved #define MEM_MAP_UNRESERVE ClearPageReserved #define CTC_GREATBELT_DEVICE_ID 0x03e8 /* TBD */ -#define DAL_MAX_CHIP_NUM 8 #define VIRT_TO_PAGE(p) virt_to_page((p)) #define DAL_UNTAG_BLOCK 0 #define DAL_DISCARD_BLOCK 1 @@ -99,8 +99,14 @@ typedef struct dal_kernel_local_dev_s /* PCI I/O mapped base address */ void __iomem * logic_address; + /* Dma ctl I/O mapped base address */ + void __iomem * dma_logic_address; + /* Physical address */ uintptr phys_address; + + /* Dma ctl Physical address*/ + uintptr dma_phys_address; } dal_kern_local_dev_t; #endif @@ -158,8 +164,15 @@ static int dal_intr_num = 0; static int use_high_memory = 0; static unsigned int* dma_virt_base[DAL_MAX_CHIP_NUM]; static unsigned long long dma_phy_base[DAL_MAX_CHIP_NUM]; +#if defined(SOC_ACTIVE) static unsigned int dma_mem_size = 0xc00000; -static unsigned int msi_irq_base[DAL_MAX_CHIP_NUM]; +#else +static unsigned int dma_mem_size = 0x8000000; +#endif +static unsigned int* wb_virt_base[DAL_MAX_CHIP_NUM]; +static unsigned long long wb_phy_base[DAL_MAX_CHIP_NUM]; +static unsigned int wb_mem_size = 0x16000000; +static unsigned int msi_irq_base[DAL_MAX_CHIP_NUM][CTC_MAX_INTR_NUM]; static unsigned int msi_irq_num[DAL_MAX_CHIP_NUM]; static unsigned int msi_used = 0; static unsigned int active_type[DAL_MAX_CHIP_NUM] = {0}; @@ -177,6 +190,7 @@ static struct pci_device_id dal_id_table[] = {PCI_DEVICE((CTC_PCIE_VENDOR_ID+1), (CTC_GOLDENGATE_DEVICE_ID+1))}, {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_DUET2_DEVICE_ID)}, {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_TSINGMA_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_TSINGMA_MX_DEVICE_ID)}, {0, }, }; #if defined(SOC_ACTIVE) @@ -251,25 +265,14 @@ intr0_handler(int irq, void* dev_id) disable_irq_nosync(irq); - if (p_dal_isr) - { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[0] = 1; - wake_up(&poll_intr[0]); - } + /* user mode interrupt handler */ + poll_intr_trigger[0] = 1; + wake_up(&poll_intr[0]); - if (p_dal_isr->isr_knet) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); - } + if (p_dal_isr->isr_knet) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); } return IRQ_HANDLED; @@ -287,19 +290,14 @@ intr1_handler(int irq, void* dev_id) disable_irq_nosync(irq); - if (p_dal_isr) + /* user mode interrupt handler */ + poll_intr_trigger[1] = 1; + wake_up(&poll_intr[1]); + + if (p_dal_isr->isr_knet) { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[1] = 1; - wake_up(&poll_intr[1]); - } + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); } return IRQ_HANDLED; @@ -315,19 +313,14 @@ intr2_handler(int irq, void* dev_id) } disable_irq_nosync(irq); - if (p_dal_isr) + /* user mode interrupt handler */ + poll_intr_trigger[2] = 1; + wake_up(&poll_intr[2]); + + if (p_dal_isr->isr_knet) { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[2] = 1; - wake_up(&poll_intr[2]); - } + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); } return IRQ_HANDLED; @@ -343,19 +336,14 @@ intr3_handler(int irq, void* dev_id) } disable_irq_nosync(irq); - if (p_dal_isr) + /* user mode interrupt handler */ + poll_intr_trigger[3] = 1; + wake_up(&poll_intr[3]); + + if (p_dal_isr->isr_knet) { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[3] = 1; - wake_up(&poll_intr[3]); - } + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); } return IRQ_HANDLED; @@ -371,21 +359,15 @@ intr4_handler(int irq, void* dev_id) } disable_irq_nosync(irq); - if (p_dal_isr) - { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[4] = 1; - wake_up(&poll_intr[4]); - } - } + /* user mode interrupt handler */ + poll_intr_trigger[4] = 1; + wake_up(&poll_intr[4]); + if (p_dal_isr->isr_knet) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); + } return IRQ_HANDLED; } @@ -399,21 +381,15 @@ intr5_handler(int irq, void* dev_id) } disable_irq_nosync(irq); - if (p_dal_isr) - { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[5] = 1; - wake_up(&poll_intr[5]); - } - } + /* user mode interrupt handler */ + poll_intr_trigger[5] = 1; + wake_up(&poll_intr[5]); + if (p_dal_isr->isr_knet) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); + } return IRQ_HANDLED; } @@ -427,21 +403,15 @@ intr6_handler(int irq, void* dev_id) } disable_irq_nosync(irq); - if (p_dal_isr) - { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[6] = 1; - wake_up(&poll_intr[6]); - } - } + /* user mode interrupt handler */ + poll_intr_trigger[6] = 1; + wake_up(&poll_intr[6]); + if (p_dal_isr->isr_knet) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); + } return IRQ_HANDLED; } @@ -455,19 +425,14 @@ intr7_handler(int irq, void* dev_id) } disable_irq_nosync(irq); - if (p_dal_isr) + /* user mode interrupt handler */ + poll_intr_trigger[7] = 1; + wake_up(&poll_intr[7]); + + if (p_dal_isr->isr_knet) { - if (p_dal_isr->isr) - { - /* kernel mode interrupt handler */ - p_dal_isr->isr(p_dal_isr->isr_data); - } - else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) - { - /* user mode interrupt handler */ - poll_intr_trigger[7] = 1; - wake_up(&poll_intr[7]); - } + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); } return IRQ_HANDLED; @@ -660,51 +625,117 @@ dal_interrupt_set_en(unsigned int irq, unsigned int enable) } static int -_dal_set_msi_enabe(unsigned int lchip, unsigned int irq_num) +_dal_set_msi_enabe(unsigned int lchip, unsigned int irq_num, unsigned int msi_type) { int ret = 0; dal_kern_pcie_dev_t* dev = NULL; if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) { + unsigned int index = 0; dev = dal_dev[lchip]; if (NULL == dev) { return -1; } - if (irq_num == 1) - { - ret = pci_enable_msi(dev->pci_dev); - if (ret) - { - printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); - pci_disable_msi(dev->pci_dev); - msi_used = 0; - } - msi_irq_base[lchip] = dev->pci_dev->irq; + if (DAL_MSI_TYPE_MSI == msi_type) + { +#if 0 + if (irq_num == 1) + { + ret = pci_enable_msi(dev->pci_dev); + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dev->pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip][0] = dev->pci_dev->irq; msi_irq_num[lchip] = 1; } else { -#if 0 -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 79)) - ret = pci_enable_msi_exact(dev->pci_dev, irq_num); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) + ret = pci_alloc_irq_vectors(dev->pci_dev, 1, irq_num, PCI_IRQ_ALL_TYPES); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 79)) + ret = pci_enable_msi_exact(dev->pci_dev, irq_num); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 26, 32)) - ret = pci_enable_msi_block(dev->pci_dev, irq_num); + ret = pci_enable_msi_block(dev->pci_dev, irq_num); #else - ret = -1; + ret = -1; #endif - if (ret) + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dev->pci_dev); + msi_used = 0; + } + + msi_irq_num[lchip] = irq_num; + for (index=0; indexpci_dev->irq+index; + } + + } +#endif + ret = -1; + //ret = pci_alloc_irq_vectors(dev->pci_dev, 1, irq_num, PCI_IRQ_ALL_TYPES); + ret = pci_alloc_irq_vectors(dev->pci_dev, 1, irq_num, PCI_IRQ_MSI); + if (ret < 0) { - printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + printk ("msi enable failed!!! lchip = %d, irq_num = %d, ret = %d\n", lchip, irq_num, ret); pci_disable_msi(dev->pci_dev); msi_used = 0; } + else + { + printk ("msi enable success!!! lchip = %d, irq_num = %d, ret = %d\n", lchip, irq_num, ret); + ret = 0; + } - msi_irq_base[lchip] = dev->pci_dev->irq; msi_irq_num[lchip] = irq_num; -#endif + for (index = 0; index < irq_num; index++) + { + msi_irq_base[lchip][index] = dev->pci_dev->irq + index; + } + } + else + { + struct msix_entry entries[CTC_MAX_INTR_NUM]; + unsigned int index = 0; + memset(entries, 0, sizeof(struct msix_entry)*CTC_MAX_INTR_NUM); + for (index = 0; index < CTC_MAX_INTR_NUM; index++) + { + entries[index].entry = index; + } + ret = pci_enable_msix_exact(dev->pci_dev, entries, irq_num); + if (ret > 0) + { + printk ("msix retrying interrupts = %d\n", ret); + ret = pci_enable_msix_exact(dev->pci_dev, entries, ret); + if (ret != 0) + { + printk ("msix enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + return -1; + } + } + else if (ret < 0) + { + printk ("msix enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + return -1; + } + else + { + msi_irq_num[lchip] = irq_num; + for (index=0; indexpci_dev); + if (DAL_MSI_TYPE_MSI == msi_type) + { + pci_disable_msi(dev->pci_dev); + } + else + { + pci_disable_msix(dev->pci_dev); + } - msi_irq_base[lchip] = 0; + memset(&msi_irq_base[0][0], 0, sizeof(unsigned int)*DAL_MAX_CHIP_NUM*CTC_MAX_INTR_NUM); msi_irq_num[lchip] = 0; } @@ -744,7 +782,7 @@ dal_set_msi_cap(unsigned long arg) return -EFAULT; } - printk("####dal_set_msi_cap lchip %d base %d num:%d\n", msi_info.lchip, msi_info.irq_base, msi_info.irq_num); + printk("####dal_set_msi_cap lchip %d base %d num:%d\n", msi_info.lchip, msi_info.irq_base[0], msi_info.irq_num); if (DAL_CPU_MODE_TYPE_PCIE == active_type[msi_info.lchip]) { if (msi_info.irq_num > 0) @@ -752,23 +790,23 @@ dal_set_msi_cap(unsigned long arg) if (0 == msi_used) { msi_used = 1; - ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num, msi_info.msi_type); } else if ((1 == msi_used) && (msi_info.irq_num != msi_irq_num[msi_info.lchip])) { for (index = 0; index < msi_irq_num[msi_info.lchip]; index++) { - dal_interrupt_unregister(msi_irq_base[msi_info.lchip]+index); + dal_interrupt_unregister(msi_irq_base[msi_info.lchip][index]); } - _dal_set_msi_disable(msi_info.lchip); + _dal_set_msi_disable(msi_info.lchip, msi_info.msi_type); msi_used = 1; - ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num, msi_info.msi_type); } } else { msi_used = 0; - ret = _dal_set_msi_disable(msi_info.lchip); + ret = _dal_set_msi_disable(msi_info.lchip, msi_info.msi_type); } } @@ -835,7 +873,6 @@ dal_user_interrupt_set_en(unsigned long arg) * 2: Part of largest contiguous segment * 3: Part of current contiguous segment */ -#ifndef DMA_MEM_MODE_PLATFORM static int _dal_find_largest_segment(dma_segment_t* dseg) { @@ -1068,7 +1105,7 @@ _dal_dma_segment_free(dma_segment_t* dseg) page_addr < dseg->blk_ptr[i] + dseg->blk_size; page_addr += PAGE_SIZE) { - MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + MEM_MAP_UNRESERVE(VIRT_TO_PAGE((void*)page_addr)); } free_pages(dseg->blk_ptr[i], dseg->blk_order); @@ -1128,7 +1165,6 @@ _dal_pgfree(void* ptr) } return -1; } -#endif static void dal_alloc_dma_pool(int lchip, int size) @@ -1203,6 +1239,7 @@ dal_free_dma_pool(int lchip) { dev = &(((dal_kern_local_dev_t*)(dal_dev[lchip]))->pci_dev->dev); } + #endif dma_free_coherent(dev, dma_mem_size, dma_virt_base[lchip], dma_phy_base[lchip]); @@ -1215,6 +1252,14 @@ dal_free_dma_pool(int lchip) } #endif } + if (wb_virt_base[lchip]) + { + ret = _dal_pgfree(wb_virt_base[lchip]); + if(ret<0) + { + printk("free wb memory fail !!!!!! \n"); + } + } } #define _KERNEL_DAL_IO @@ -1434,8 +1479,10 @@ linux_get_device(unsigned long arg) #if defined(SOC_ACTIVE) if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) { - user_dev.phy_base0 = (unsigned int)((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address; - user_dev.phy_base1 = (unsigned int)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address >> 32); + user_dev.phy_base0 = (unsigned int)((dal_kern_local_dev_t*)(dal_dev[lchip]))->phys_address; + user_dev.phy_base1 = (unsigned int)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->phys_address >> 32); + user_dev.dma_phy_base0 = (unsigned int)((dal_kern_local_dev_t*)(dal_dev[lchip]))->dma_phys_address; + user_dev.dma_phy_base1 = (unsigned int)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->dma_phys_address >> 32); user_dev.bus_no = 0; user_dev.dev_no = CTC_TSINGMA_DEVICE_ID; user_dev.fun_no = 0; @@ -1456,7 +1503,7 @@ linux_get_device(unsigned long arg) static int linux_get_dal_version(unsigned long arg) { - int dal_ver = VERSION_1DOT2; /* set dal version */ + int dal_ver = VERSION_1DOT4; /* set dal version */ if (copy_to_user((int*)arg, (void*)&dal_ver, sizeof(dal_ver))) { @@ -1493,11 +1540,44 @@ linux_get_dma_info(unsigned long arg) return 0; } +static int +linux_get_wb_info(unsigned long arg) +{ + dal_dma_info_t dma_para; + + if (copy_from_user(&dma_para, (void*)arg, sizeof(dal_dma_info_t))) + { + return -EFAULT; + } + + if (wb_mem_size && (0 == wb_phy_base[dma_para.lchip])) + { + /* Get wb memory from kernel */ + wb_virt_base[dma_para.lchip] = _dal_pgalloc(wb_mem_size); + wb_phy_base[dma_para.lchip] = virt_to_bus(wb_virt_base[dma_para.lchip]); + printk("wb_phy_base[lchip] 0x%llx wb_virt_base[lchip] %p \n", wb_phy_base[dma_para.lchip], wb_virt_base[dma_para.lchip]); + } + dma_para.phy_base = (unsigned int)wb_phy_base[dma_para.lchip]; + dma_para.phy_base_hi = wb_phy_base[dma_para.lchip] >> 32; + dma_para.virt_base = wb_virt_base[dma_para.lchip]; + dma_para.size = wb_mem_size; + + printk("dal dma phy addr: 0x%llx, virt addr: %p.\n", wb_phy_base[dma_para.lchip], wb_virt_base[dma_para.lchip]); + + if (copy_to_user((dal_dma_info_t*)arg, (void*)&dma_para, sizeof(dal_dma_info_t))) + { + return -EFAULT; + } + + return 0; +} + static int dal_get_msi_info(unsigned long arg) { dal_msi_info_t msi_para; unsigned int lchip = 0; + unsigned int index = 0; /* get lchip form user mode */ if (copy_from_user(&msi_para, (void*)arg, sizeof(dal_msi_info_t))) @@ -1508,14 +1588,20 @@ dal_get_msi_info(unsigned long arg) if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) { - msi_para.irq_base = msi_irq_base[lchip]; msi_para.irq_num = msi_irq_num[lchip]; + for (index=0; indexdma_logic_address + offset); + } +#endif + return 0; +} + +int +dal_dma_direct_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip]) + { + return -1; + } + +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + *(volatile unsigned int*)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->dma_logic_address + offset) = value; + } +#endif + + return 0; +} + #if defined(SOC_ACTIVE) static int linux_dal_local_probe(struct platform_device *pdev) { @@ -1631,6 +1762,7 @@ static int linux_dal_local_probe(struct platform_device *pdev) int i = 0; int irq = 0; struct resource * res = NULL; + struct resource * dma_res = NULL; printk(KERN_WARNING "********found soc dal device*****\n"); @@ -1677,6 +1809,23 @@ static int linux_dal_local_probe(struct platform_device *pdev) return PTR_ERR(dev->logic_address); } + dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (dma_res && dma_res->start) + { + dev->dma_phys_address = dma_res->start; + dev->dma_logic_address = devm_ioremap_resource(&pdev->dev, dma_res); + if (IS_ERR(dev->dma_logic_address)) + { + kfree(dev); + return PTR_ERR(dev->dma_logic_address); + } + } + else + { + dev->dma_phys_address = 0; + dev->dma_logic_address = 0; + } + for (i = 0; i < CTC_MAX_INTR_NUM; i++) { irq = platform_get_irq(pdev, i); @@ -1694,9 +1843,9 @@ static int linux_dal_local_probe(struct platform_device *pdev) _dal_pci_read(lchip, 0x48, &temp); if (((temp >> 8) & 0xffff) == 0x3412) { - printk("Little endian Cpu detected!!! \n"); _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); } + printk("Little endian Cpu detected!!! \n"); /* alloc dma_mem_size for every chip */ if (dma_mem_size) @@ -1725,6 +1874,7 @@ int linux_dal_pcie_probe(struct pci_dev* pdev, const struct pci_device_id* id) unsigned int lchip = 0; int bar = 0; int ret = 0; + int endian_mode = 0; /*unsigned int devid = 0;*/ printk(KERN_WARNING "********found cpu dal device*****\n"); @@ -1763,7 +1913,7 @@ int linux_dal_pcie_probe(struct pci_dev* pdev, const struct pci_device_id* id) dev->pci_dev = pdev; - if (pdev->device == 0x5236) + if ((pdev->device == 0x5236) || (pdev->device == 0x8180)) { printk("use bar2 to config memory space\n"); bar = 2; @@ -1796,15 +1946,25 @@ int linux_dal_pcie_probe(struct pci_dev* pdev, const struct pci_device_id* id) dev->logic_address = (uintptr)ioremap_nocache(dev->phys_address, pci_resource_len(dev->pci_dev, bar)); + /*0: little endian 1: big endian*/ + endian_mode = (CTC_TSINGMA_DEVICE_ID == pdev->device)?0:1; active_type[lchip] = DAL_CPU_MODE_TYPE_PCIE; - _dal_pci_read(lchip, 0x48, &temp); if (((temp >> 8) & 0xffff) == 0x3412) { - printk("Little endian Cpu detected!!! \n"); + endian_mode = (CTC_TSINGMA_DEVICE_ID == pdev->device)?1:0; _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); } + if (endian_mode) + { + printk("Big endian Cpu detected!!! \n"); + } + else + { + printk("Little endian Cpu detected!!! \n"); + } + pci_set_master(pdev); @@ -1848,6 +2008,10 @@ linux_dal_local_remove(struct platform_device *pdev) if (1 == flag) { dal_free_dma_pool(lchip); + if (wb_virt_base[lchip]) + { + _dal_pgfree(wb_virt_base[lchip]); + } dev->pci_dev = NULL; kfree(dev); dal_chip_num--; @@ -1878,6 +2042,10 @@ linux_dal_pcie_remove(struct pci_dev* pdev) if (1 == flag) { dal_free_dma_pool(lchip); + if (wb_virt_base[lchip]) + { + _dal_pgfree(wb_virt_base[lchip]); + } pci_release_regions(pdev); pci_disable_device(pdev); dev->pci_dev = NULL; @@ -1956,6 +2124,9 @@ linux_dal_ioctl(struct inode* inode, struct file* file, case CMD_CACHE_FLUSH: return dal_user_cache_flush(arg); + case CMD_GET_WB_INFO: + return linux_get_wb_info(arg); + default: break; } @@ -2231,4 +2402,6 @@ module_exit(linux_dal_exit); EXPORT_SYMBOL(dal_get_dal_ops); EXPORT_SYMBOL(dal_cache_inval); EXPORT_SYMBOL(dal_cache_flush); +EXPORT_SYMBOL(dal_dma_direct_read); +EXPORT_SYMBOL(dal_dma_direct_write); diff --git a/platform/centec/centec-dal/dal_kernel.h b/platform/centec/centec-dal/dal_kernel.h index 1055dba26..227b2f1ea 100644 --- a/platform/centec/centec-dal/dal_kernel.h +++ b/platform/centec/centec-dal/dal_kernel.h @@ -55,6 +55,7 @@ typedef unsigned int uintptr; #define DAL_DEV_NAME "/dev/" DAL_NAME #define DAL_ONE_KB 1024 #define DAL_ONE_MB (1024*1024) +#define CTC_MAX_INTR_NUM 8 struct dal_chip_parm_s { unsigned int lchip; /*tmp should be uint8*/ @@ -84,6 +85,8 @@ struct dal_user_dev_s unsigned int lchip; /*input: local chip id*/ unsigned int phy_base0; /* low 32bits physical base address */ unsigned int phy_base1; /* high 32bits physical base address */ + unsigned int dma_phy_base0; /* low 32bits physical base address */ + unsigned int dma_phy_base1; /* high 32bits physical base address */ unsigned int bus_no; unsigned int dev_no; unsigned int fun_no; @@ -100,11 +103,20 @@ struct dal_pci_cfg_ioctl_s }; typedef struct dal_pci_cfg_ioctl_s dal_pci_cfg_ioctl_t; +enum dal_msi_type_e +{ + DAL_MSI_TYPE_MSI, + DAL_MSI_TYPE_MSIX, + DAL_MSI_TYPE_MAX +}; +typedef enum dal_msi_type_e dal_msi_type_t; + struct dal_msi_info_s { unsigned int lchip; - unsigned int irq_base; + unsigned int irq_base[CTC_MAX_INTR_NUM]; unsigned int irq_num; + unsigned int msi_type; }; typedef struct dal_msi_info_s dal_msi_info_t; @@ -147,6 +159,7 @@ typedef struct dal_dma_cache_info_s dal_dma_cache_info_t; #define CMD_SET_DMA_INFO _IO(CMD_MAGIC, 21) #define CMD_REG_DMA_CHAN _IO(CMD_MAGIC, 22) #define CMD_HANDLE_NETIF _IO(CMD_MAGIC, 23) +#define CMD_GET_WB_INFO _IO(CMD_MAGIC, 24) enum dal_version_e { @@ -154,6 +167,8 @@ enum dal_version_e VERSION_1DOT0, VERSION_1DOT1, VERSION_1DOT2, + VERSION_1DOT3, + VERSION_1DOT4, VERSION_MAX }; @@ -171,7 +186,8 @@ typedef struct dal_ops_s dal_ops_t; extern int dal_get_dal_ops(dal_ops_t **dal_ops); extern int dal_cache_inval(unsigned long ptr, unsigned int length); extern int dal_cache_flush(unsigned long ptr, unsigned int length); - +extern int dal_dma_direct_read(unsigned char lchip, unsigned int offset, unsigned int* value); +extern int dal_dma_direct_write(unsigned char lchip, unsigned int offset, unsigned int value); #ifdef __cplusplus } #endif diff --git a/platform/centec/centec-dal/dal_mpool.c b/platform/centec/centec-dal/dal_mpool.c index f3b5f85e5..708dcffd9 100644 --- a/platform/centec/centec-dal/dal_mpool.c +++ b/platform/centec/centec-dal/dal_mpool.c @@ -1,9 +1,11 @@ +#ifdef CLANG +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-designator" +#endif -/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ -//#include "sal.h" #include "dal_mpool.h" -#define DAL_MAX_CHIP_NUM 32 -#ifdef __KERNEL__ +#include "dal_common.h" + #include #include @@ -16,20 +18,7 @@ static spinlock_t dal_mpool_lock[DAL_MAX_CHIP_NUM]; #define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&dal_mpool_lock[lchip], flags) #define MPOOL_UNLOCK() spin_unlock_irqrestore(&dal_mpool_lock[lchip], flags) #define DAL_PRINT(fmt,arg...) printk(fmt,##arg) -#else /* !__KERNEL__*/ -#include -#include "sal.h" -#define DAL_MALLOC(x) sal_malloc(x) -#define DAL_FREE(x) sal_free(x) -static sal_mutex_t* dal_mpool_lock[DAL_MAX_CHIP_NUM]; -#define MPOOL_LOCK_INIT() sal_mutex_create(&dal_mpool_lock[lchip]) -#define MPOOL_LOCK_DEINIT() sal_mutex_destroy(dal_mpool_lock[lchip]) -#define MPOOL_LOCK() sal_mutex_lock(dal_mpool_lock[lchip]) -#define MPOOL_UNLOCK() sal_mutex_unlock(dal_mpool_lock[lchip]) -#define DAL_PRINT(fmt,arg...) sal_printf(fmt,##arg) - -#endif /* __KERNEL__ */ dal_mpool_mem_t* g_free_block_ptr = NULL; /* System cache line size */ @@ -40,14 +29,12 @@ dal_mpool_mem_t* g_free_block_ptr = NULL; static dal_mpool_mem_t* p_desc_pool[DAL_MAX_CHIP_NUM] = {0}; static dal_mpool_mem_t* p_data_pool[DAL_MAX_CHIP_NUM] = {0}; -/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ int dal_mpool_init(uint8_t lchip) { MPOOL_LOCK_INIT(); return 0; } -/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ int dal_mpool_deinit(uint8_t lchip) { @@ -320,7 +307,6 @@ dal_mpool_usage(dal_mpool_mem_t* pool, int type) { int usage = 0; dal_mpool_mem_t* ptr; - /*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ uint8_t lchip = 0; MPOOL_LOCK(); @@ -342,7 +328,6 @@ dal_mpool_debug(dal_mpool_mem_t* pool) { dal_mpool_mem_t* ptr; int index = 0; - /*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ uint8_t lchip = 0; MPOOL_LOCK(); @@ -358,3 +343,7 @@ dal_mpool_debug(dal_mpool_mem_t* pool) return 0; } +#ifdef CLANG +#pragma clang diagnostic pop +#endif +