From c5665ce5063eacd14b551c70dcd23697b19e3ff7 Mon Sep 17 00:00:00 2001 From: roy_lee Date: Thu, 1 Aug 2019 11:19:33 +0800 Subject: [PATCH 1/6] 1st commit for as7315-27xb, before verfied. Signed-off-by: roy_lee --- .../Accton-AS7315-27XB/port_config.ini | 55 + .../qax-as7315-20x10G+4x25G+3x100G.config.bcm | 519 +++++++++ .../Accton-AS7315-27XB/sai.profile | 1 + .../x86_64-accton_as7315_27xb-r0/default_sku | 1 + .../installer.conf | 2 + .../led_proc_init.soc | 79 ++ .../plugins/eeprom.py | 21 + .../plugins/psuutil.py | 61 + .../plugins/sfputil.py | 245 ++++ .../as7315-27xb/classes/__init__.py | 0 .../as7315-27xb/classes/fanutil.py | 244 ++++ .../as7315-27xb/classes/thermalutil.py | 128 +++ .../as7315-27xb/modules/Makefile | 2 + .../modules/accton_as7315_27xb_fan.c | 673 +++++++++++ .../as7315-27xb/modules/at24_as7315_27xb.c | 695 ++++++++++++ .../modules/x86-64-accton-as7315-27xb-cpld.c | 1008 +++++++++++++++++ .../modules/x86-64-accton-as7315-27xb-led.c | 408 +++++++ .../modules/x86-64-accton-as7315-27xb-psu.c | 454 ++++++++ .../as7315-27xb/modules/ym2651y.c | 1 + .../service/as7315-platform-init.service | 13 + .../as7315-27xb/setup.py | 16 + .../as7315-27xb/utils/README | 60 + .../utils/accton_as7315_monitor.py | 163 +++ .../as7315-27xb/utils/accton_as7315_util.py | 525 +++++++++ 24 files changed, 5374 insertions(+) create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/default_sku create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/installer.conf create mode 100755 device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py create mode 100644 device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c create mode 120000 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini new file mode 100644 index 00000000000..93160688d74 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed +Ethernet0 41 twentyfiveGigE1 1 25000 +Ethernet1 42 twentyfiveGigE2 2 25000 +Ethernet2 43 twentyfiveGigE3 3 25000 +Ethernet3 44 twentyfiveGigE4 4 25000 +Ethernet4 49 twentyfiveGigE5 5 25000 +Ethernet5 50 twentyfiveGigE6 6 25000 +Ethernet6 51 twentyfiveGigE7 7 25000 +Ethernet7 52 twentyfiveGigE8 8 25000 +Ethernet8 53 twentyfiveGigE9 9 25000 +Ethernet9 54 twentyfiveGigE10 10 25000 +Ethernet10 55 twentyfiveGigE11 11 25000 +Ethernet11 56 twentyfiveGigE12 12 25000 +Ethernet12 65 twentyfiveGigE13 13 25000 +Ethernet13 66 twentyfiveGigE14 14 25000 +Ethernet14 67 twentyfiveGigE15 15 25000 +Ethernet15 68 twentyfiveGigE16 16 25000 +Ethernet16 33 twentyfiveGigE17 17 25000 +Ethernet17 34 twentyfiveGigE18 18 25000 +Ethernet18 35 twentyfiveGigE19 19 25000 +Ethernet19 36 twentyfiveGigE20 20 25000 +Ethernet20 37 twentyfiveGigE21 21 25000 +Ethernet21 38 twentyfiveGigE22 22 25000 +Ethernet22 39 twentyfiveGigE23 23 25000 +Ethernet23 40 twentyfiveGigE24 24 25000 +Ethernet24 69 twentyfiveGigE25 25 25000 +Ethernet25 70 twentyfiveGigE26 26 25000 +Ethernet26 71 twentyfiveGigE27 27 25000 +Ethernet27 72 twentyfiveGigE28 28 25000 +Ethernet28 81 twentyfiveGigE29 29 25000 +Ethernet29 82 twentyfiveGigE30 30 25000 +Ethernet30 83 twentyfiveGigE31 31 25000 +Ethernet31 84 twentyfiveGigE32 32 25000 +Ethernet32 85 twentyfiveGigE33 33 25000 +Ethernet33 86 twentyfiveGigE34 34 25000 +Ethernet34 87 twentyfiveGigE35 35 25000 +Ethernet35 88 twentyfiveGigE36 36 25000 +Ethernet36 97 twentyfiveGigE37 37 25000 +Ethernet37 98 twentyfiveGigE38 38 25000 +Ethernet38 99 twentyfiveGigE39 39 25000 +Ethernet39 100 twentyfiveGigE40 40 25000 +Ethernet40 101 twentyfiveGigE41 41 25000 +Ethernet41 102 twentyfiveGigE42 42 25000 +Ethernet42 103 twentyfiveGigE43 43 25000 +Ethernet43 104 twentyfiveGigE44 44 25000 +Ethernet44 105 twentyfiveGigE45 45 25000 +Ethernet45 106 twentyfiveGigE46 46 25000 +Ethernet46 107 twentyfiveGigE47 47 25000 +Ethernet47 108 twentyfiveGigE48 48 25000 +Ethernet48 5,6,7,8 hundredGigE49 49 100000 +Ethernet52 1,2,3,4 hundredGigE50 50 100000 +Ethernet56 109,110,111,112 hundredGigE51 51 100000 +Ethernet60 21,22,23,24 hundredGigE52 52 100000 +Ethernet64 9,10,11,12 hundredGigE53 53 100000 +Ethernet68 117,118,119,120 hundredGigE54 54 100000 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm new file mode 100644 index 00000000000..eef4d987e8e --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm @@ -0,0 +1,519 @@ +# accton_as7312_54x 48x25G+6x100G SDK config +os=unix +schan_intr_enable=0 + +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x0407ffc00ff00ff003fc3ffc00200222 +pbmp_xport_xe=0x0407ffd00ff00ff403fc3ffc00200222 + +## FC10 ## +dport_map_port_42=1 +dport_map_port_43=2 +dport_map_port_44=3 +dport_map_port_45=4 + +## FC12 ## +dport_map_port_50=5 +dport_map_port_51=6 +dport_map_port_52=7 +dport_map_port_53=8 + +## FC13 ## +dport_map_port_54=9 +dport_map_port_55=10 +dport_map_port_56=11 +dport_map_port_57=12 + +## FC16 ## +dport_map_port_68=13 +dport_map_port_69=14 +dport_map_port_70=15 +dport_map_port_71=16 + +## FC8 ## +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +## FC9 ## +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +## FC17 ## +dport_map_port_72=25 +dport_map_port_73=26 +dport_map_port_74=27 +dport_map_port_75=28 + +## FC20 ## +dport_map_port_84=29 +dport_map_port_85=30 +dport_map_port_86=31 +dport_map_port_87=32 + +## FC21 ## +dport_map_port_88=33 +dport_map_port_89=34 +dport_map_port_90=35 +dport_map_port_91=36 + +## FC24 ## +dport_map_port_102=37 +dport_map_port_103=38 +dport_map_port_104=39 +dport_map_port_105=40 + +## FC25 ## +dport_map_port_106=41 +dport_map_port_107=42 +dport_map_port_108=43 +dport_map_port_109=44 + +## FC26 ## +dport_map_port_110=45 +dport_map_port_111=46 +dport_map_port_112=47 +dport_map_port_113=48 + +## FC1 ## +dport_map_port_5=49 + +## FC0 ## +dport_map_port_1=50 + +## FC27 ## +dport_map_port_114=51 + +## FC5 ## +dport_map_port_21=52 + +## FC2 ## +dport_map_port_9=53 + +## FC29 ## +dport_map_port_122=54 + +#for KR +#dport_map_port_66=55 +#dport_map_port_100=56 + +/* Port Map */ +## FC10 ## +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +## FC12 ## +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + + +## FC13 ## +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +## FC16 ## +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + + +## FC8 ## +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +## FC9 ## +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +## FC17 ## +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +## FC20 ## +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + + +## FC21 ## +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +## FC24 ## +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +## FC25 ## +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +## FC26 ## +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +## FC1 ## +portmap_5=5:100 + +## FC0 ## +portmap_1=1:100 + +## FC27 ## +portmap_114=109:100 + +## FC5 ## +portmap_21=21:100 + +## FC2 ## +portmap_9=9:100 + +## FC29 ## +portmap_122=117:100 + +# CPU to MAC +# TSC-E management port 1 +#portmap_66=129:10 +# TSC-E management port 2 +#portmap_100=131:10 + +xgxs_rx_lane_map_42=0x2310 +xgxs_rx_lane_map_43=0x2310 +xgxs_rx_lane_map_44=0x2310 +xgxs_rx_lane_map_45=0x2310 +xgxs_rx_lane_map_50=0x3210 +xgxs_rx_lane_map_51=0x3210 +xgxs_rx_lane_map_52=0x3210 +xgxs_rx_lane_map_53=0x3210 +xgxs_rx_lane_map_54=0x3210 +xgxs_rx_lane_map_55=0x3210 +xgxs_rx_lane_map_56=0x3210 +xgxs_rx_lane_map_57=0x3210 +xgxs_rx_lane_map_68=0x0123 +xgxs_rx_lane_map_69=0x0123 +xgxs_rx_lane_map_70=0x0123 +xgxs_rx_lane_map_71=0x0123 +xgxs_rx_lane_map_34=0x0123 +xgxs_rx_lane_map_35=0x0123 +xgxs_rx_lane_map_36=0x0123 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0123 +xgxs_rx_lane_map_39=0x0123 +xgxs_rx_lane_map_40=0x0123 +xgxs_rx_lane_map_41=0x0123 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_84=0x1032 +xgxs_rx_lane_map_85=0x1032 +xgxs_rx_lane_map_86=0x1032 +xgxs_rx_lane_map_87=0x1032 +xgxs_rx_lane_map_88=0x2301 +xgxs_rx_lane_map_89=0x2301 +xgxs_rx_lane_map_90=0x2301 +xgxs_rx_lane_map_91=0x2301 +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_103=0x0123 +xgxs_rx_lane_map_104=0x0123 +xgxs_rx_lane_map_105=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_114=0x0123 +xgxs_rx_lane_map_21=0x0213 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_122=0x1230 + +xgxs_tx_lane_map_42=0x0132 +xgxs_tx_lane_map_43=0x0132 +xgxs_tx_lane_map_44=0x0132 +xgxs_tx_lane_map_45=0x0132 +xgxs_tx_lane_map_50=0x3210 +xgxs_tx_lane_map_51=0x3210 +xgxs_tx_lane_map_52=0x3210 +xgxs_tx_lane_map_53=0x3210 +xgxs_tx_lane_map_54=0x3210 +xgxs_tx_lane_map_55=0x3210 +xgxs_tx_lane_map_56=0x3210 +xgxs_tx_lane_map_57=0x3210 +xgxs_tx_lane_map_68=0x0123 +xgxs_tx_lane_map_69=0x0123 +xgxs_tx_lane_map_70=0x0123 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_34=0x0123 +xgxs_tx_lane_map_35=0x0123 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_39=0x0123 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_73=0x0123 +xgxs_tx_lane_map_74=0x0123 +xgxs_tx_lane_map_75=0x0123 +xgxs_tx_lane_map_84=0x0123 +xgxs_tx_lane_map_85=0x0123 +xgxs_tx_lane_map_86=0x0123 +xgxs_tx_lane_map_87=0x0123 +xgxs_tx_lane_map_88=0x2301 +xgxs_tx_lane_map_89=0x2301 +xgxs_tx_lane_map_90=0x2301 +xgxs_tx_lane_map_91=0x2301 +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_103=0x0123 +xgxs_tx_lane_map_104=0x0123 +xgxs_tx_lane_map_105=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_107=0x3210 +xgxs_tx_lane_map_108=0x3210 +xgxs_tx_lane_map_109=0x3210 +xgxs_tx_lane_map_110=0x1032 +xgxs_tx_lane_map_111=0x1032 +xgxs_tx_lane_map_112=0x1032 +xgxs_tx_lane_map_113=0x1032 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_114=0x0123 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_122=0x3210 + +#Polarity RX +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_rx_polarity_flip_37=0x1 +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_rx_polarity_flip_84=0x1 +phy_xaui_rx_polarity_flip_85=0x0 +phy_xaui_rx_polarity_flip_86=0x1 +phy_xaui_rx_polarity_flip_87=0x0 +phy_xaui_rx_polarity_flip_88=0x1 +phy_xaui_rx_polarity_flip_89=0x0 +phy_xaui_rx_polarity_flip_90=0x1 +phy_xaui_rx_polarity_flip_91=0x1 +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x0 +phy_xaui_rx_polarity_flip_104=0x1 +phy_xaui_rx_polarity_flip_105=0x0 +phy_xaui_rx_polarity_flip_122=0xf +#Polarity TX +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x1 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_72=0x1 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x1 +phy_xaui_tx_polarity_flip_75=0x1 +phy_xaui_tx_polarity_flip_84=0x1 +phy_xaui_tx_polarity_flip_85=0x1 +phy_xaui_tx_polarity_flip_86=0x1 +phy_xaui_tx_polarity_flip_87=0x1 +phy_xaui_tx_polarity_flip_88=0x1 +phy_xaui_tx_polarity_flip_89=0x1 +phy_xaui_tx_polarity_flip_90=0x1 +phy_xaui_tx_polarity_flip_91=0x1 +phy_xaui_tx_polarity_flip_102=0x1 +phy_xaui_tx_polarity_flip_103=0x1 +phy_xaui_tx_polarity_flip_104=0x1 +phy_xaui_tx_polarity_flip_105=0x1 +phy_xaui_tx_polarity_flip_122=0xb + +#Driver Current +serdes_driver_current_42=0x8 +serdes_driver_current_43=0x8 +serdes_driver_current_44=0x8 +serdes_driver_current_45=0x8 +serdes_driver_current_50=0x8 +serdes_driver_current_51=0x8 +serdes_driver_current_52=0x8 +serdes_driver_current_53=0x8 +serdes_driver_current_54=0x8 +serdes_driver_current_55=0x8 +serdes_driver_current_56=0x8 +serdes_driver_current_57=0x8 +serdes_driver_current_68=0x8 +serdes_driver_current_69=0x8 +serdes_driver_current_70=0x8 +serdes_driver_current_71=0x8 +serdes_driver_current_34=0x8 +serdes_driver_current_35=0x8 +serdes_driver_current_36=0x8 +serdes_driver_current_37=0x8 +serdes_driver_current_38=0x8 +serdes_driver_current_39=0x8 +serdes_driver_current_40=0x8 +serdes_driver_current_41=0x8 +serdes_driver_current_72=0x8 +serdes_driver_current_73=0x8 +serdes_driver_current_74=0x8 +serdes_driver_current_75=0x8 +serdes_driver_current_84=0x8 +serdes_driver_current_85=0x8 +serdes_driver_current_86=0x8 +serdes_driver_current_87=0x8 +serdes_driver_current_88=0x8 +serdes_driver_current_89=0x8 +serdes_driver_current_90=0x8 +serdes_driver_current_91=0x8 +serdes_driver_current_102=0x8 +serdes_driver_current_103=0x8 +serdes_driver_current_104=0x8 +serdes_driver_current_105=0x8 +serdes_driver_current_106=0x8 +serdes_driver_current_107=0x8 +serdes_driver_current_108=0x8 +serdes_driver_current_109=0x8 +serdes_driver_current_110=0x8 +serdes_driver_current_111=0x8 +serdes_driver_current_112=0x8 +serdes_driver_current_113=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 + +#Preemphasis +serdes_preemphasis_42=0x264006 +serdes_preemphasis_43=0x264006 +serdes_preemphasis_44=0x254106 +serdes_preemphasis_45=0x254106 +serdes_preemphasis_50=0x254106 +serdes_preemphasis_51=0x254106 +serdes_preemphasis_52=0x254106 +serdes_preemphasis_53=0x254106 +serdes_preemphasis_54=0x254106 +serdes_preemphasis_55=0x254106 +serdes_preemphasis_56=0x254106 +serdes_preemphasis_57=0x234306 +serdes_preemphasis_68=0x234306 +serdes_preemphasis_69=0x204606 +serdes_preemphasis_70=0x204606 +serdes_preemphasis_71=0x204606 +serdes_preemphasis_34=0x234306 +serdes_preemphasis_35=0x234306 +serdes_preemphasis_36=0x234306 +serdes_preemphasis_37=0x234306 +serdes_preemphasis_38=0x234306 +serdes_preemphasis_39=0x234306 +serdes_preemphasis_40=0x234306 +serdes_preemphasis_41=0x234306 +serdes_preemphasis_72=0x1e4806 +serdes_preemphasis_73=0x1e4806 +serdes_preemphasis_74=0x1e4806 +serdes_preemphasis_75=0x1e4806 +serdes_preemphasis_84=0x1e4806 +serdes_preemphasis_85=0x1a4c06 +serdes_preemphasis_86=0x1a4c06 +serdes_preemphasis_87=0x1b4b06 +serdes_preemphasis_88=0x1b4b06 +serdes_preemphasis_89=0x1e4806 +serdes_preemphasis_90=0x1e4806 +serdes_preemphasis_91=0x1e4806 +serdes_preemphasis_102=0x1e4806 +serdes_preemphasis_103=0x1e4806 +serdes_preemphasis_104=0x1e4806 +serdes_preemphasis_105=0x1e4806 +serdes_preemphasis_106=0x1e4806 +serdes_preemphasis_107=0x1e4806 +serdes_preemphasis_108=0x1e4806 +serdes_preemphasis_109=0x1e4806 +serdes_preemphasis_110=0x1e4806 +serdes_preemphasis_111=0x1d4906 +serdes_preemphasis_112=0x234306 +serdes_preemphasis_113=0x1f4706 +serdes_preemphasis_lane0_5=0x294106 +serdes_preemphasis_lane1_5=0x294106 +serdes_preemphasis_lane2_5=0x294106 +serdes_preemphasis_lane3_5=0x294106 +serdes_preemphasis_lane0_1=0x294106 +serdes_preemphasis_lane1_1=0x294106 +serdes_preemphasis_lane2_1=0x294106 +serdes_preemphasis_lane3_1=0x294106 +serdes_preemphasis_lane0_114=0x2a4006 +serdes_preemphasis_lane1_114=0x2a4006 +serdes_preemphasis_lane2_114=0x2a4006 +serdes_preemphasis_lane3_114=0x2a4006 +serdes_preemphasis_lane0_21=0x2c3c08 +serdes_preemphasis_lane1_21=0x2a4006 +serdes_preemphasis_lane2_21=0x2a4006 +serdes_preemphasis_lane3_21=0x2a4006 +serdes_preemphasis_lane0_9=0x284206 +serdes_preemphasis_lane1_9=0x284206 +serdes_preemphasis_lane2_9=0x284206 +serdes_preemphasis_lane3_9=0x284206 +serdes_preemphasis_lane0_122=0x283e06 +serdes_preemphasis_lane1_122=0x283e06 +serdes_preemphasis_lane2_122=0x283e06 +serdes_preemphasis_lane3_122=0x294601 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile new file mode 100644 index 00000000000..191b27dac2f --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/qax-as7315-20x10G+4x25G+3x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/default_sku b/device/accton/x86_64-accton_as7315_27xb-r0/default_sku new file mode 100644 index 00000000000..ef2d9d4c044 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7335-27XB t1 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/installer.conf b/device/accton/x86_64-accton_as7315_27xb-r0/installer.conf new file mode 100644 index 00000000000..9fa12f88854 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc new file mode 100755 index 00000000000..3074649497e --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc @@ -0,0 +1,79 @@ +# accton_as7312_54x 48x25G+6x100G SDK port LED macro init SOC +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start +led auto on diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py new file mode 100644 index 00000000000..171593068ae --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/4-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py new file mode 100644 index 00000000000..6df014abb52 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +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/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "13-0053", + 1: "12-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py new file mode 100644 index 00000000000..a1785fde553 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py @@ -0,0 +1,245 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 49 + QSFP_PORT_END = 54 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 0: "4-0060", + 1: "5-0062", + 2: "6-0064", + } + _port_to_i2c_mapping = { + 1: 18, + 2: 19, + 3: 20, + 4: 21, + 5: 22, + 6: 23, + 7: 24, + 8: 25, + 9: 26, + 10: 27, + 11: 28, + 12: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 21: 38, + 22: 39, + 23: 40, + 24: 41, + 25: 42, + 26: 43, + 27: 44, + 28: 45, + 29: 46, + 30: 47, + 31: 48, + 32: 49, + 33: 50, + 34: 51, + 35: 52, + 36: 53, + 37: 54, + 38: 55, + 39: 56, + 40: 57, + 41: 58, + 42: 59, + 43: 60, + 44: 61, + 45: 62, + 46: 63, + 47: 64, + 48: 65, + 49: 66, #QSFP49 + 50: 67, + 51: 68, + 52: 69, + 53: 70, + 54: 71, #QSFP54 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + def get_cpld_num(self, port_num): + cpld_i = 1 + if (port_num > 24 and port_num < self.qsfp_port_start): + cpld_i = 2 + + if (port_num > 52): + cpld_i = 2 + + return cpld_i + + 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 + + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, port_num) + + try: + val_file = open(port_ps) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + return False # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, port_num) + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = '0' + + reg_file.write(reg_value) + reg_file.close() + + return True + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/__init__.py new file mode 100755 index 00000000000..e69de29bb2d diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py new file mode 100644 index 00000000000..42ccb17eaa0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 4 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/17-0068/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0068/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py new file mode 100644 index 00000000000..65e872c6beb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 6 + THERMAL_NUM_1_IDX = 1 + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = [ + ['18', '48'], + ['18', '49'], + ['18', '4a'], + ['18', '4b'], + ['17', '4d'], + ['17', '4e'], + ] + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + self._thermal_to_device_path_mapping[x+1] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_temp(self): + sum = 0 + o = [] + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + sum += self._get_thermal_node_val(x+1) + avg = sum/self.THERMAL_NUM_ON_MAIN_BROAD + avg = (avg/1000)*1000 #round down for hysteresis. + return avg + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile new file mode 100644 index 00000000000..a1bf8335378 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:= accton_as7315_27xb_fan.o x86-64-accton-as7315-27xb-cpld.o x86-64-accton-as7315-27xb-psu.o \ + at24_as7315_27xb.o x86-64-accton-as7315-27xb-led.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c new file mode 100644 index 00000000000..e08522718c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c @@ -0,0 +1,673 @@ +/* + * A hwmon driver for the Accton as5710 54x fan contrl + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "as5812_54x_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_TACH_TO_RPM_STEP 750 +#define FAN_SPEED_PWM_STEPS 31 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ +#define NAME_SIZE 24 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + + +struct fan_sensor { + struct fan_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_fan_sensor(_attr) \ + container_of(_attr, struct fan_sensor, attribute) + + +struct model_attrs { + struct attrs **cmn; + struct attrs **indiv; +}; + + +struct fan_data_t { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + struct fan_sensor *sensors; + int attr_index; + struct model_attrs *attrs; + + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + + u8 fan_num; + + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_byte(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_rpm(struct device *dev, + struct device_attribute *devattr, char *buf); + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + int mask; + bool invert; + struct base_attrs *base; +}; + +enum common_attrs { + BRD_VERSION, + PLD_VERSION, + PLD_SVERSION, + NUM_COMMON_ATTR +}; + +struct base_attrs common_base_attrs[NUM_COMMON_ATTR] = +{ + [BRD_VERSION] = {"borad_ver", S_IRUGO, show_byte, NULL}, + [PLD_VERSION] = {"cpld_ver", S_IRUGO, show_byte, NULL}, + [PLD_SVERSION] = {"cpld_subver", S_IRUGO, show_byte, NULL}, +}; + +struct attrs common_attrs[] = { + [BRD_VERSION] = {0x00, -1, false, &common_base_attrs[BRD_VERSION]}, + [PLD_VERSION] = {0x01, -1, false, &common_base_attrs[PLD_VERSION]}, + [PLD_SVERSION] = {0x02, -1, false, &common_base_attrs[PLD_SVERSION]}, +}; + +struct attrs *as7315_cmn_list[] = { + &common_attrs[BRD_VERSION], + &common_attrs[PLD_VERSION], + &common_attrs[PLD_SVERSION], + NULL +}; + +enum fan_attrs { + _ENABLE, + _PRESENT, + _FAULT, + _SPEED_RPM, + _PWM, + _DIRECTION, + NUM_FAN_ATTRS +}; + +struct base_attrs tray_base_attrs[NUM_FAN_ATTRS] = +{ + {"enable", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + {"present", S_IRUGO, show_bit, NULL}, + {"fault", S_IRUGO, show_bit, NULL}, + {"input", S_IRUGO, show_rpm, NULL}, + {"pwm", S_IRUGO|S_IWUSR, show_pwm, set_pwm}, + {"dir", S_IRUGO, show_bit, NULL}, +}; + +struct attrs as7315_module[NUM_FAN_ATTRS] = { + {0x10, -1, false, &tray_base_attrs[_ENABLE]}, + {0x22, 0, true, &tray_base_attrs[_PRESENT]}, + {0x22, 1, false, &tray_base_attrs[_FAULT]}, + {0x20, 0, false, &tray_base_attrs[_SPEED_RPM]}, + {0x21, 0, false, &tray_base_attrs[_PWM]}, + {-1, -1, false, &tray_base_attrs[_DIRECTION]}, +}; + +struct attrs *as7315_mod_list[] = { + &as7315_module[_ENABLE], + &as7315_module[_PRESENT], + &as7315_module[_FAULT], + &as7315_module[_SPEED_RPM], + &as7315_module[_PWM], + NULL +}; + +struct model_attrs models_attr = { + .cmn = as7315_cmn_list, + .indiv = as7315_mod_list, +}; + + +static const struct i2c_device_id as7315_fan_id[] = { + { "as7315_fan", 0}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, as7315_fan_id); + + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *data = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + if (unlikely(value < 0)) { + mutex_unlock(&data->update_lock); + return value; + } + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", !!value); +} + +static ssize_t _read_1byte(struct device *dev, + struct device_attribute *devattr, u8 *data) +{ + int rv; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *fdata = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + + mutex_lock(&fdata->update_lock); + rv = cpld_read_internal(client, sensor->reg); + if (unlikely(rv < 0)) { + mutex_unlock(&fdata->update_lock); + return rv; + } + mutex_unlock(&fdata->update_lock); + *data = rv; + return 0; +} + +static ssize_t show_byte(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u8 data; + int rv; + + rv =_read_1byte(dev, devattr, &data); + if (unlikely(rv < 0)) { + return rv; + } + return snprintf(buf, PAGE_SIZE, "0x%x\n", data); +} + + +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return ((u32)(reg_val+1) * 312 + 88)/ 100; +} +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 311) - 1; +} + +static ssize_t show_pwm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u8 data; + int rv; + + rv =_read_1byte(dev, devattr, &data); + if (unlikely(rv < 0)) { + return rv; + } + data = reg_val_to_duty_cycle(data); + data = (data > FAN_DUTY_CYCLE_MAX)? FAN_DUTY_CYCLE_MAX: data; + return snprintf(buf, PAGE_SIZE, "%d\n", data); +} + +static ssize_t show_rpm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u8 data; + int rv; + + rv =_read_1byte(dev, devattr, &data); + if (unlikely(rv < 0)) { + return rv; + } + rv = data * FAN_SPEED_TACH_TO_RPM_STEP; + return snprintf(buf, PAGE_SIZE, "%d\n", rv); +} +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *data = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long value; + int status; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *data = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + u8 reg; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + value = (value > FAN_DUTY_CYCLE_MAX )? FAN_DUTY_CYCLE_MAX: value; + value = duty_cycle_to_reg_val(value); + reg = sensor->reg; + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + mutex_unlock(&data->update_lock); + return status; + } + mutex_unlock(&data->update_lock); + return count; +} + + + +static int _add_attribute(struct fan_data_t *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + + if (!new_attrs) + return -ENOMEM; + + data->group.attrs = new_attrs; + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct fan_sensor * _add_sensor(struct fan_data_t *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct fan_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int _add_attributes_cmn(struct fan_data_t *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + reg = a->reg; + invert = a->invert; + + + + b = a->base; + if (NULL == b) + break; + + + if (_add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int _add_attributes_indiv(struct fan_data_t *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j, mask; + u8 reg, invert, reg_start, jump; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -EFAULT; + + jump = 0x10; + for (i = 0; pa[i]; i++) { + a = pa[i]; + reg_start = a->reg; + + if (reg < 0) + break; + + b = a->base; + if (b == NULL) + break; + invert = a->invert; + for (j = 0; j < data->fan_num; j++) + { + + snprintf(name, NAME_SIZE, "fan%d_%s", j+1, b->name); + /*If mask < 0, mask is as index*/ + if (a->mask < 0) { + mask = 1 << (j%8); + reg = reg_start; + } else { /*If mask >= 0, means to get full byte and reg need to shift*/ + mask = 1 << (a->mask); + reg = reg_start + ((j%8)*jump); + } + if (_add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + + + return 0; +} + +static int _add_attributes(struct i2c_client *client, + struct fan_data_t *data) +{ + struct model_attrs *m = data->attrs; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + _add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + _add_attributes_indiv(data, m->indiv); + + return 0; +} + +static int fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct fan_data_t *data = NULL; + struct device *dev = &client->dev; + + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->attrs = &models_attr; + data->fan_num = FAN_MAX_NUMBER; + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + + status = _add_attributes(client, data); + if (status) { + return status; + } + + if (!data->num_attributes) { + dev_err(&client->dev, "No attributes found\n"); + return -ENODEV; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + goto out_kfree; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, + client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_rm_sys; + } + + i2c_set_clientdata(client, data); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->dev), client->name); + + return 0; + +exit_rm_sys: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; +} + + +static int fan_remove(struct i2c_client *client) +{ + struct fan_data_t *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->group.attrs); + return 0; +} + + +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver as7315_i2c_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRV_NAME, + }, + .probe = fan_probe, + .remove = fan_remove, + .id_table = as7315_fan_id, + .address_list = normal_i2c, +}; + +static int __init accton_as7315_27xb_fan_init(void) +{ + return i2c_add_driver(&as7315_i2c_fan_driver); +} + +static void __exit accton_as7315_27xb_fan_exit(void) +{ + i2c_del_driver(&as7315_i2c_fan_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7315_27xb_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as7315_27xb_fan_init); +module_exit(accton_as7315_27xb_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c new file mode 100755 index 00000000000..8d8c7601a71 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c @@ -0,0 +1,695 @@ +/* + * at24_as7315_27xb.c - handle most I2C EEPROMs for ethernet switch, as7315_27xb. + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * Copyright (C) 2019 Roy Lee, EdgeCore network. + * Revised to support specially I2C transactions, pure READ and WRITE. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + int use_smbus_write; + + ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t); + ssize_t (*write_func)(struct at24_data *, + const char *, unsigned int, size_t); + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + struct nvmem_config nvmem_config; + struct nvmem_device *nvmem; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +/* + * Both reads and writes fail if the previous write didn't complete yet. This + * macro loops a few times waiting at least long enough for one entire page + * write to work while making sure that at least one iteration is run before + * checking the break condition. + * + * It takes two parameters: a variable in which the future timeout in jiffies + * will be stored and a temporary variable holding the time of the last + * iteration of processing the request. Both should be unsigned integers + * holding at least 32 bits. + */ +#define loop_until_timeout(tout, op_time) \ + for (tout = jiffies + msecs_to_jiffies(write_timeout), op_time = 0; \ + op_time ? time_before(op_time, tout) : true; \ + usleep_range(1000, 1500), op_time = jiffies) + +static const struct i2c_device_id at24_ids[] = { + { "24cxb04", AT24_DEVICE_MAGIC(4096 / 8, AT24_FLAG_ADDR16) }, + { "24cxb08", AT24_DEVICE_MAGIC(8192 / 8, AT24_FLAG_ADDR16) }, + { "24cxb16", AT24_DEVICE_MAGIC(16384 / 8, AT24_FLAG_ADDR16) }, + { "24cxb32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, + { "24cxb64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, + { "at24", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ids); + +static const struct acpi_device_id at24_acpi_ids[] = { + { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) }, + { } +}; +MODULE_DEVICE_TABLE(acpi, at24_acpi_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + * + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + * + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned int *offset) +{ + unsigned i; + + /*Always AT24_FLAG_ADDR16*/ + i = *offset >> 16; + *offset &= 0xffff; + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + int status; + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + loop_until_timeout(timeout, read_time) { +/* + status = i2c_smbus_read_i2c_block_data_or_emulated(client, + offset, + count, buf); + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); +*/ + int i=0; + + /*Write 2-byte offset*/ + unsigned char bb = offset&0xff; + status = i2c_smbus_write_i2c_block_data(client, offset>>8, 1, &bb); + if (status < 0) { + return status; + } + + while (i < count) { + status = i2c_smbus_read_byte(client); + if (status < 0) { + return status; + } + buf[i] = status; + i++; + } + + + if (i == count) + return count; + } + + return -ETIMEDOUT; +} + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. These routines + * write at most one page. + */ + +static size_t at24_adjust_write_count(struct at24_data *at24, + unsigned int offset, size_t count) +{ + unsigned next_page; + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + return count; +} + +static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24, + const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + ssize_t status = 0; + + client = at24_translate_offset(at24, &offset); + count = at24_adjust_write_count(at24, offset, count); + + loop_until_timeout(timeout, write_time) { + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24, + const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + ssize_t status = 0; + + client = at24_translate_offset(at24, &offset); + + loop_until_timeout(timeout, write_time) { + status = i2c_smbus_write_byte_data(client, offset, buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + struct i2c_msg msg; + ssize_t status = 0; + int i = 0; + + client = at24_translate_offset(at24, &offset); + count = at24_adjust_write_count(at24, offset, count); + + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = at24->writebuf; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msg.buf[i++] = offset >> 8; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + loop_until_timeout(timeout, write_time) { + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static int at24_read(void *priv, unsigned int off, void *val, size_t count) +{ + struct at24_data *at24 = priv; + char *buf = val; + + + + if (unlikely(!count)) + return count; + + if (off + count > at24->chip.byte_len) + return -EINVAL; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + int status; + + status = at24->read_func(at24, buf, off, count); + if (status < 0) { + mutex_unlock(&at24->lock); + return status; + } + buf += status; + off += status; + count -= status; + } + + mutex_unlock(&at24->lock); + + return 0; +} + +static int at24_write(void *priv, unsigned int off, void *val, size_t count) +{ + struct at24_data *at24 = priv; + char *buf = val; + + if (unlikely(!count)) + return -EINVAL; + + if (off + count > at24->chip.byte_len) + return -EINVAL; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + int status; + + status = at24->write_func(at24, buf, off, count); + if (status < 0) { + mutex_unlock(&at24->lock); + return status; + } + buf += status; + off += status; + count -= status; + } + + mutex_unlock(&at24->lock); + + return 0; +} + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + kernel_ulong_t magic = 0; + bool writable; + int use_smbus = 0; + int use_smbus_write = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (id) { + magic = id->driver_data; + } else { + const struct acpi_device_id *aid; + + aid = acpi_match_device(at24_acpi_ids, &client->dev); + if (aid) + magic = aid->driver_data; + } + if (!magic) + return -ENODEV; + + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* + * REVISIT: the size of the EUI-48 byte array is 6 in at24mac402, while + * the call to ilog2() in AT24_DEVICE_MAGIC() rounds it down to 4. + * + * Eventually we'll get rid of the magic values altoghether in favor of + * real structs, but for now just manually set the right size. + */ + if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4) + chip.byte_len = 6; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /*if (chip.flags & AT24_FLAG_ADDR16){ + return -EPFNOSUPPORT; + }*/ + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + use_smbus_write = I2C_SMBUS_BYTE_DATA; + chip.page_size = 1; + } + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, + (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->use_smbus_write = use_smbus_write; + at24->chip = chip; + at24->num_addresses = num_addresses; + + if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) { + dev_err(&client->dev, + "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC."); + return -EINVAL; + } + at24->read_func = at24_eeprom_read_smbus; + + if (at24->use_smbus) { + if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA) + at24->write_func = at24_eeprom_write_smbus_block; + else + at24->write_func = at24_eeprom_write_smbus_byte; + } else { + at24->write_func = at24_eeprom_write_i2c; + } + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || use_smbus_write) { + + unsigned write_max = chip.page_size; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, + write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, + client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", + client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + i2c_set_clientdata(client, at24); + at24->nvmem_config.name = dev_name(&client->dev); + at24->nvmem_config.dev = &client->dev; + at24->nvmem_config.read_only = !writable; + at24->nvmem_config.root_only = true; + at24->nvmem_config.owner = THIS_MODULE; + at24->nvmem_config.compat = true; + at24->nvmem_config.base_dev = &client->dev; + at24->nvmem_config.reg_read = at24_read; + at24->nvmem_config.reg_write = at24_write; + at24->nvmem_config.priv = at24; + at24->nvmem_config.stride = 1; + at24->nvmem_config.word_size = 1; + at24->nvmem_config.size = chip.byte_len; + + at24->nvmem = nvmem_register(&at24->nvmem_config); + + if (IS_ERR(at24->nvmem)) { + err = PTR_ERR(at24->nvmem); + goto err_clients; + } + + dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n", + chip.byte_len, client->name, + writable ? "writable" : "read-only", at24->write_max); + if (use_smbus == I2C_SMBUS_WORD_DATA || + use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } + + /* export data to kernel code */ + if (chip.setup) + chip.setup(at24->nvmem, chip.context); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + + nvmem_unregister(at24->nvmem); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_driver at24_as7315_27xb_driver = { + .driver = { + .name = "at24_as7315_27xb", + .acpi_match_table = ACPI_PTR(at24_acpi_ids), + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ids, +}; + +static int __init at24_as7315_27xb_init(void) +{ + if (!io_limit) { + pr_err("at24_as7315_27xb: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + return i2c_add_driver(&at24_as7315_27xb_driver); +} +module_init(at24_as7315_27xb_init); + +static void __exit at24_as7315_27xb_exit(void) +{ + i2c_del_driver(&at24_as7315_27xb_driver); +} +module_exit(at24_as7315_27xb_exit); + +MODULE_DESCRIPTION("Driver for I2C EEPROMs on accton switch, as7315_27xb"); +MODULE_AUTHOR("Roy Lee"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c new file mode 100755 index 00000000000..dcd604f1f61 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c @@ -0,0 +1,1008 @@ +/* + * A hwmon driver for the as7315_i2c_cpld + * + * Copyright (C) 2019 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "as7315_i2c_cpld" +#define NUM_SFP 24 +#define NUM_QSFP 3 +#define NUM_ALL_PORTS 27 + +#define SFP_1ST_PRST_REG 0x10 +#define QSFP_1ST_PRST_REG 0x18 + +#define SFP_1ST_RXLOS_REG 0x13 +#define MUX_CHANNEL_SELECT_REG 0x80 + + +enum models { + MDL_CPLD_SFP, + MDL_CPLD_QSFP, + PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/ + NUM_MODEL +}; + + +#define MAX_PORT_NUM 64 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ + +#define NAME_SIZE 24 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +enum port_type { + PT_SFP, + PT_QSFP, +}; + +enum common_attrs { + CMN_VERSION, + CMN_ACCESS, + CMN_PRESENT_ALL, + CMN_RXLOS_ALL, + NUM_COMMON_ATTR +}; + +enum sfp_sb_attrs { + SFP_PRESENT, + SFP_RESET, + SFP_TX_DIS, + SFP_TX_FAULT, + SFP_RX_LOS, + QSFP_PRESENT, + QSFP_LP_MODE, + NUM_SFP_SB_ATTR +}; + +struct cpld_sensor { + struct cpld_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_cpld_sensor(_attr) \ + container_of(_attr, struct cpld_sensor, attribute) + +struct cpld_data { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + + enum models model; + struct cpld_sensor *sensors; + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + int attr_index; + u16 sfp_num; + u8 sfp_types; + struct model_attrs *attrs; + + /*For mux function*/ + struct i2c_mux_core *muxc; +}; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + bool invert; + struct base_attrs *base; +}; + +struct model_attrs { + struct attrs **cmn; + struct attrs **portly; +}; + + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_rxlos_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg); +int accton_i2c_cpld_write(u8 cpld_addr, u8 reg, u8 value); + + +struct base_attrs common_base_attrs[NUM_COMMON_ATTR] = +{ + [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL}, + [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte}, + [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL}, + [CMN_RXLOS_ALL] = {"rx_los_all", S_IRUGO, show_rxlos_all, NULL}, +}; + +struct attrs common_attrs[] = { + [CMN_VERSION] = {0x01, false, &common_base_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {-1, false, &common_base_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {-1, false, &common_base_attrs[CMN_PRESENT_ALL]}, + [CMN_RXLOS_ALL] = {-1, false, &common_base_attrs[CMN_RXLOS_ALL]}, +}; +struct attrs plain_common[] = { + [CMN_VERSION] = {0x01, false, &common_base_attrs[CMN_VERSION]}, +}; + +struct base_attrs portly_attrs[] = +{ + [SFP_PRESENT] = {"present", S_IRUGO, show_bit, NULL}, + [SFP_RESET] = {0}, + [SFP_TX_DIS] = {"tx_disable", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + [SFP_TX_FAULT] = {"tx_fault", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + [SFP_RX_LOS] = {"rx_los", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + [QSFP_PRESENT] = {"present", S_IRUGO, show_bit, NULL}, + [QSFP_LP_MODE] = {"low_power_mode", S_IRUGO|S_IWUSR, show_bit, set_1bit}, +}; + +struct attrs as7315_port[NUM_SFP_SB_ATTR] = { + {SFP_1ST_PRST_REG, true, &portly_attrs[SFP_PRESENT]}, + {0}, + {0x12, false, &portly_attrs[SFP_TX_DIS]}, + {0x11, false, &portly_attrs[SFP_TX_FAULT]}, + {SFP_1ST_RXLOS_REG, false, &portly_attrs[SFP_RX_LOS]}, + {QSFP_1ST_PRST_REG, true, &portly_attrs[QSFP_PRESENT]}, + {0x19, false, &portly_attrs[QSFP_LP_MODE]}, +}; + +struct attrs *as7315_cmn_list[] = { + &common_attrs[CMN_VERSION], + &common_attrs[CMN_ACCESS], + &common_attrs[CMN_PRESENT_ALL], + &common_attrs[CMN_RXLOS_ALL], + NULL +}; + +struct attrs *plain_cmn_list[] = { + &plain_common[CMN_VERSION], + NULL +}; + +struct attrs *as7315_qsfp_list[] = { + &as7315_port[QSFP_PRESENT], + &as7315_port[QSFP_LP_MODE], + NULL +}; + +struct attrs *as7315_sfp_list[] = { + &as7315_port[SFP_PRESENT], + &as7315_port[SFP_TX_DIS], + &as7315_port[SFP_TX_FAULT], + &as7315_port[SFP_RX_LOS], + NULL +}; + +struct model_attrs models_attr[NUM_MODEL] = { + {.cmn = as7315_cmn_list, .portly=as7315_sfp_list}, + {.cmn = as7315_cmn_list, .portly=as7315_qsfp_list}, + {.cmn = plain_cmn_list, .portly=NULL}, +}; + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for as7315_i2c_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [MDL_CPLD_SFP] = {0}, + [MDL_CPLD_QSFP] = { + .nchans = 4, /*Fan + 3*LM75*/ + .deselectChan = 0, + }, +}; + +static const struct i2c_device_id as7315_cpld_id[] = { + { "as7315_cpld1", MDL_CPLD_SFP}, + { "as7315_cpld2", MDL_CPLD_QSFP}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, as7315_cpld_id); + + + + +static int get_sfp_spec(int model, u16 *num, u8 *types) +{ + switch (model) { + case MDL_CPLD_SFP: + *num = NUM_SFP; + *types = PT_SFP; + break; + case MDL_CPLD_QSFP: + *num = NUM_QSFP; + *types = PT_QSFP; + break; + default: + *types = 0; + *num = 0; + break; + } + + return 0; +} + +/*num: how many bits can be applied for this read.*/ +static int get_present_reg(int model, u8 port, u8 *reg, u8 *num) +{ + + switch (model) { + case MDL_CPLD_SFP: + if (port < NUM_SFP) { + *reg = SFP_1ST_PRST_REG + (port/8)*4; + *num = (NUM_SFP > 8)? 8 : NUM_SFP; + return 0; + } + break; + case MDL_CPLD_QSFP: + if (port < NUM_QSFP) { + *reg = QSFP_1ST_PRST_REG + (port/8); + *num = (NUM_QSFP > 8)? 8 : NUM_QSFP; + return 0; + } + break; + default: + return -EINVAL; + } + return -EINVAL; +} + +static int get_rxlos_reg(int model, u8 port, u8 *reg, u8 *num) +{ + + switch (model) { + case MDL_CPLD_SFP: + if (port < NUM_SFP) { + *reg = SFP_1ST_RXLOS_REG + (port/8)*4; + *num = (NUM_SFP > 8)? 8 : NUM_SFP; + return 0; + } + break; + default: + return -EINVAL; + } + return -EINVAL; +} + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg, num; + u64 values; + + i = num = reg =0; + values = 0; + mutex_lock(&data->update_lock); + while (i < data->sfp_num) + { + /*No rxlos for QSFP*/ + if (data->model == MDL_CPLD_QSFP) { + values = 0; + break; + } + get_rxlos_reg(data->model, i, ®, &num); + if (!(num > 0)) + { + value = -EINVAL; + goto exit; + } + value = cpld_read_internal(client, reg); + if (unlikely(value < 0)) { + goto exit; + } + values |= (value &((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + values = cpu_to_le64(values); + return snprintf(buf, sizeof(values)+1, "%llx\n", values); +exit: + mutex_unlock(&data->update_lock); + return value; +} + + +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg, num; + u64 values; + + i = num = reg =0; + values = 0; + mutex_lock(&data->update_lock); + while (i < data->sfp_num) + { + get_present_reg(data->model, i, ®, &num); + if (!(num > 0)) + { + value = -EINVAL; + goto exit; + } + value = cpld_read_internal(client, reg); + if (unlikely(value < 0)) { + goto exit; + } + values |= (~value&((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + values = cpu_to_le64(values); + return snprintf(buf, sizeof(values)+1, "%llx\n", values); +exit: + mutex_unlock(&data->update_lock); + return value; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", !!value); +} + +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return access(dev, da, buf, count); +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = + kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", + client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct cpld_sensor * add_sensor(struct cpld_data *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct cpld_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (cpld_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + + reg = a->reg; + invert = a->invert; + + b = a->base; + if (NULL == b) + break; + + if (add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int add_attributes_portly(struct cpld_data *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j; + u8 reg, mask, invert, reg_start, jump; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -EFAULT; + + jump = 0; + if (data->sfp_types == PT_SFP) { + jump = 4; /*SFP sideband registers in set of 4 bytes.*/ + } else if (data->sfp_types == PT_QSFP) { + jump = 1; + } + + for (i = 0; pa[i]; i++) { + a = pa[i]; + reg_start = a->reg; + invert = a->invert; + b = a->base; + if (b == NULL) + break; + + for (j = 0; j < data->sfp_num; j++) + { + snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1); + reg = reg_start + ((j/8)*jump); + mask = 1 << ((j)%8); + if (add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + + + return 0; +} + +static int add_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + struct model_attrs *m = data->attrs; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + add_attributes_portly(data, m->portly); + + return 0; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int _cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= ~(I2C_M_TEN | I2C_CLIENT_PEC); + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, MUX_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + + +static int _mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + u8 regval; + struct i2c_client *client = i2c_mux_priv(muxc); + int ret = 0; + + regval = (chan+1) << 5; + ret = _cpld_mux_reg_write(muxc->parent, client, regval); + if (unlikely(ret < 0)) { + return ret; + } + return ret; +} + + +static int _prealloc_attrs(struct cpld_data *data) +{ + void *new_attrs = krealloc(data->group.attrs, + ATTR_ALLOC_SIZE * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + + return 0; +} + +static int _add_sysfs_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + int status; + + status = add_attributes(client, data); + if (status) { + return status; + } + + /*If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(&client->dev, "No attributes found\n"); + return -ENODEV; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + return status; + } + + return 0; +} + + +static int _add_mux_channels(struct i2c_client *client, + const struct i2c_device_id *id, struct cpld_data *data) +{ + int num, force, class; + int status; + struct i2c_mux_core *muxc; + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int model = id->driver_data; + + data->muxc = i2c_mux_alloc(adap, &client->dev, + chips[model].nchans, + sizeof(client), 0, + _mux_select_chan, NULL); + + if (!data->muxc) { + return ENOMEM; + } + muxc = data->muxc; + muxc->priv = client; + for (num = 0; num < chips[model].nchans; num++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + status = i2c_mux_add_adapter(muxc, force, num, class); + if (status) + return status ; + } + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + num, client->name); + + return 0; +} + +static int as7315_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int status; + struct cpld_data *data = NULL; + struct device *dev = &client->dev; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + data->model = dev_id->driver_data; + data->attrs = &models_attr[data->model]; + get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types); + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + + status = _prealloc_attrs(data); + if (status) + return -ENOMEM; + + status = _add_sysfs_attributes(client, data); + if (status) + goto out_kfree; + + status = _add_mux_channels(client, dev_id, data); + if (status) + goto exit_rm_sys; + + i2c_set_clientdata(client, data); + accton_i2c_cpld_add_client(client); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->dev), client->name); + + return 0; + +exit_rm_sys: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; +} + + +static int as7315_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + struct i2c_mux_core *muxc = data->muxc; + + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->group.attrs); + if(muxc) { + i2c_mux_del_adapters(muxc); + } + accton_i2c_cpld_remove_client(client); + return 0; +} + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(u8 cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + + +static struct i2c_driver as7315_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRV_NAME, + }, + .probe = as7315_i2c_cpld_probe, + .remove = as7315_i2c_cpld_remove, + .id_table = as7315_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init as7315_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7315_i2c_cpld_driver); +} + +static void __exit as7315_i2c_cpld_exit(void) +{ + i2c_del_driver(&as7315_i2c_cpld_driver); +} + +module_init(as7315_i2c_cpld_init); +module_exit(as7315_i2c_cpld_exit); + +MODULE_AUTHOR("Roy Lee "); +MODULE_DESCRIPTION("as7315_i2c_cpld driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c new file mode 100755 index 00000000000..fefb44fad33 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c @@ -0,0 +1,408 @@ +/* + * A LED driver for the accton_as7315_27xb_led + * + * Copyright (C) 2019 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7315_27xb_led" +#define CPLD_I2C_ADDR 0x64 + +enum led_type { + TYPE_DIAG, + TYPE_LOC, + TYPE_MAX +}; + +struct led_list_s { + enum led_type type; + char name[64]; + u8 reg_addr; + u8 slave_addr; +} led_list[TYPE_MAX] = { + {TYPE_DIAG, "as7315_27xb_diag", 0x41, CPLD_I2C_ADDR}, + {TYPE_LOC, "as7315_27xb_loc", 0x40, CPLD_I2C_ADDR} +}; + +struct accton_as7315_27xb_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 slave_addr[TYPE_MAX]; /* For LOC and DIAG.*/ + u8 reg_addr[TYPE_MAX]; /* For LOC and DIAG.*/ + u8 reg_val[TYPE_MAX]; /* Register value, 0 = LOC + 1 = DIAG */ +}; +static struct accton_as7315_27xb_led_data *ledctl = NULL; + +/* LED related data + */ +#define TYPE_DIAG_REG_MASK 0x30 +#define MODE_DIAG_GREEN_MASK 0x10 +#define MODE_DIAG_AMBER_MASK 0x20 +#define MODE_DIAG_GBLINK_MASK 0x00 +#define MODE_DIAG_OFF_MASK 0x30 + +#define TYPE_LOC_REG_MASK 0x40 +#define MODE_LOC_OFF_MASK 0x40 +#define MODE_LOC_BLINK_MASK 0x00 + + +typedef enum onlp_led_mode_e { + ONLP_LED_MODE_OFF, + ONLP_LED_MODE_ON, + ONLP_LED_MODE_BLINKING, + ONLP_LED_MODE_RED = 10, + ONLP_LED_MODE_RED_BLINKING = 11, + ONLP_LED_MODE_ORANGE = 12, + ONLP_LED_MODE_ORANGE_BLINKING = 13, + ONLP_LED_MODE_YELLOW = 14, + ONLP_LED_MODE_YELLOW_BLINKING = 15, + ONLP_LED_MODE_GREEN = 16, + ONLP_LED_MODE_GREEN_BLINKING = 17, + ONLP_LED_MODE_BLUE = 18, + ONLP_LED_MODE_BLUE_BLINKING = 19, + ONLP_LED_MODE_PURPLE = 20, + ONLP_LED_MODE_PURPLE_BLINKING = 21, + ONLP_LED_MODE_AUTO = 22, + ONLP_LED_MODE_AUTO_BLINKING = 23, +} onlp_led_mode_t; + + +struct led_type_mode { + enum led_type type; + int type_mask; + enum onlp_led_mode_e mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_GREEN_BLINKING, MODE_DIAG_GBLINK_MASK}, + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_GREEN, MODE_DIAG_GREEN_MASK}, + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_ORANGE, MODE_DIAG_AMBER_MASK}, + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_OFF, MODE_DIAG_OFF_MASK}, + {TYPE_LOC, TYPE_LOC_REG_MASK, ONLP_LED_MODE_BLUE_BLINKING, MODE_LOC_BLINK_MASK}, + {TYPE_LOC, TYPE_LOC_REG_MASK, ONLP_LED_MODE_OFF, MODE_LOC_OFF_MASK}, +}; + +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(u8 cpld_addr, u8 reg, u8 value); + + +static int pdata_init(struct accton_as7315_27xb_led_data *data) { + int i; + + for (i=0; ireg_addr[i] = led_list[i].reg_addr; + data->slave_addr[i] = led_list[i].slave_addr; + } + + return 0; +} + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum onlp_led_mode_e mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as7315_27xb_led_read_value(u8 slave, u8 reg) +{ + return accton_i2c_cpld_read(slave, reg); +} + +static int accton_as7315_27xb_led_write_value(u8 slave, u8 reg, u8 value) +{ + return accton_i2c_cpld_write(slave, reg, value); +} + +static void accton_as7315_27xb_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7315_27xb_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status; + u8 addr, offset; + addr = ledctl->slave_addr[i]; + offset = ledctl->reg_addr[i]; + status = accton_as7315_27xb_led_read_value(addr, offset); + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", ledctl->reg_addr[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7315_27xb_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 addr, offset; + + if (type >= ARRAY_SIZE(led_list)) { + dev_dbg(&ledctl->pdev->dev, "Illegal type:%d\n", type); + return; + } + mutex_lock(&ledctl->update_lock); + addr = ledctl->slave_addr[type], + offset = ledctl->reg_addr[type], + reg_val = accton_as7315_27xb_led_read_value(addr, offset); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", offset, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7315_27xb_led_write_value(addr, offset, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static enum led_type get_led_type(struct led_classdev *cdev) +{ + int i; + + for (i=0; iname)) + return i; + } + return -EINVAL; +} + +static void led_mode_set(struct led_classdev *cdev, + enum led_brightness led_light_mode) +{ + enum led_type type; + + type = get_led_type(cdev); + if (type < 0) { + dev_dbg(&ledctl->pdev->dev, "Found no corresponding type:%d\n", type); + return ; + } + accton_as7315_27xb_led_set(cdev, led_light_mode, type); +} + +static enum led_brightness led_mode_get(struct led_classdev *cdev) +{ + enum led_type type; + + type = get_led_type(cdev); + if (type < 0) + return type; + + accton_as7315_27xb_led_update(); + return led_reg_val_to_light_mode(type, ledctl->reg_val[type]); +} + +static struct led_classdev accton_as7315_27xb_leds[TYPE_MAX] = { + [TYPE_DIAG] = { + .name = led_list[TYPE_DIAG].name, + .default_trigger = "unused", + .brightness_set = led_mode_set, + .brightness_get = led_mode_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = ONLP_LED_MODE_AUTO, + }, + [TYPE_LOC] = { + .name = led_list[TYPE_LOC].name, + .default_trigger = "unused", + .brightness_set = led_mode_set, + .brightness_get = led_mode_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = ONLP_LED_MODE_AUTO, + }, +}; + +static int accton_as7315_27xb_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + led_classdev_suspend(&accton_as7315_27xb_leds[i]); + } + + return 0; +} + +static int accton_as7315_27xb_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + led_classdev_resume(&accton_as7315_27xb_leds[i]); + } + + return 0; +} + +static int accton_as7315_27xb_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7315_27xb_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7315_27xb_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7315_27xb_leds[i]); + } + } + + return ret; +} + +static int accton_as7315_27xb_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + led_classdev_unregister(&accton_as7315_27xb_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7315_27xb_led_driver = { + .probe = accton_as7315_27xb_led_probe, + .remove = accton_as7315_27xb_led_remove, + .suspend = accton_as7315_27xb_led_suspend, + .resume = accton_as7315_27xb_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7315_27xb_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7315_27xb_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7315_27xb_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7315_27xb_led_driver); + goto exit; + } + + pdata_init(ledctl); + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7315_27xb_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7315_27xb_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7315_27xb_led_driver); + kfree(ledctl); +} + +module_init(accton_as7315_27xb_led_init); +module_exit(accton_as7315_27xb_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7315_27xb_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c new file mode 100644 index 00000000000..1cf6313eab0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c @@ -0,0 +1,454 @@ +/* + * An hwmon driver for accton as7315_27xb Power Module + * + * Copyright (C) 2019 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "as7315_27xb_psu" +#define PSU_STATUS_I2C_ADDR 0x64 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 +#define USE_BYTE_ACCESS 0 /*Somehow i2c block access is failed on this platform.*/ +#define UPDATE_PERIOD (HZ*2) +#define MAX_OUTPUT_LENGTH 32 +#define BASIC_EEPROM_SIZE 32 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id + 2))) +#define IS_PRESENT(id, value) (!(value & BIT(id))) + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7315_27xb_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char eeprom[BASIC_EEPROM_SIZE*2]; /* EEPROM*/ +}; + + +enum as7315_27xb_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +enum psu_type { + PSU_YM_1401_A, /* AC110V - B2F */ + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_YM_2401_TCR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G, /* DC48V - B2F */ + PSU_BEL_TOT120, /* DC48V - N/A */ + PSU_TYPE_MAX +}; + +struct model_info { + enum psu_type type; + u8 offset; + char* model_name; + u8 serial_offset; +}; + +struct model_info models[] = { + {PSU_YM_1401_A, 0x20, "YM-1401ACR",0x35}, + {PSU_YM_2401_JCR, 0x20, "YM-2401JCR",0x35}, + {PSU_YM_2401_JDR, 0x20, "YM-2401JDR",0x35}, + {PSU_YM_2401_TCR, 0x20, "YM-2401TCR",0x35}, + {PSU_CPR_4011_4M11, 0x26, "CPR-4011-4M11",0x47}, + {PSU_CPR_4011_4M21, 0x26, "CPR-4011-4M21",0x47}, + {PSU_CPR_6011_2M11, 0x26, "CPR-6011-2M11",0x46}, + {PSU_CPR_6011_2M21, 0x26, "CPR-6011-2M21",0x46}, + {PSU_UM400D_01G, 0x50, "um400d01G",0x50}, + {PSU_UM400D01_01G, 0x50, "um400d01-01G",0x50}, + {PSU_BEL_TOT120, 0x0A, "CRXT-T0T120",0x18}, +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_serial_number(struct device *dev, struct device_attribute *da,char *buf); +static int as7315_27xb_psu_block_read(struct i2c_client *client, u8 command, u8 *data,int data_len); +static int as7315_27xb_psu_model_name_get( + struct device *dev, char *buf); +static int as7315_27xb_psu_serial_number_get( + struct device *dev, enum psu_type type, char *out); +static struct as7315_27xb_psu_data *as7315_27xb_psu_update_device(struct device *dev); +extern int accton_i2c_cpld_read(u8 cpld_addr, u8 reg); + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_serial, S_IRUGO, show_serial_number, NULL, PSU_SERIAL_NUMBER); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7315_27xb_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_serial.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7315_27xb_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_serial_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i; + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + i = as7315_27xb_psu_model_name_get(dev, buf); + if ( i < 0) { + return -ENXIO; + } + + if (as7315_27xb_psu_serial_number_get(dev, i, buf) < 0) { + return -ENXIO; + } + return sprintf(buf, "%s\n", buf); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as7315_27xb_psu_model_name_get(dev, buf) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", buf); +} + +static const struct attribute_group as7315_27xb_psu_group = { + .attrs = as7315_27xb_psu_attributes, +}; + +static int as7315_27xb_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7315_27xb_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7315_27xb_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7315_27xb_psu_group); + if (status) { + goto exit_free; + } + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, + client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7315_27xb_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7315_27xb_psu_remove(struct i2c_client *client) +{ + struct as7315_27xb_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7315_27xb_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7315_27xb_psu1, + as7315_27xb_psu2 +}; + +static const struct i2c_device_id as7315_27xb_psu_id[] = { + { "as7315_27xb_psu1", as7315_27xb_psu1 }, + { "as7315_27xb_psu2", as7315_27xb_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7315_27xb_psu_id); + +static struct i2c_driver as7315_27xb_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRV_NAME, + }, + .probe = as7315_27xb_psu_probe, + .remove = as7315_27xb_psu_remove, + .id_table = as7315_27xb_psu_id, + .address_list = normal_i2c, +}; + +static int as7315_27xb_psu_block_read(struct i2c_client *client, + u8 command, u8 *data, int max_len) +{ + int result; + + u8 i, offset; + + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = 0; i < max_len; i += 32) { + offset = i + command ; + result = i2c_smbus_read_i2c_block_data(client, offset, + 32, data + i); + + if (result != 32) { + result = -EIO; + goto abort; + } + } + + } else { + for (i = 0; i < max_len; i += 2) { + int word; + offset = i + command ; + word = i2c_smbus_read_word_data(client, offset); + if (word < 0) { + result = -EIO; + goto abort; + } + data[i] = word & 0xff; + data[i + 1] = word >> 8; + } + } + result = 0; +abort: + return result; +} + +static int as7315_27xb_psu_serial_number_get( + struct device *dev, enum psu_type type, char *out) +{ + char *serial; + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (type >= PSU_TYPE_MAX) { + return -EINVAL; + } + + if (!data->valid) { + out[0] = '\0'; + return 0; + } + + serial = data->eeprom + models[type].serial_offset; + strncpy(out, serial, MAX_OUTPUT_LENGTH); + return 0; +} + +static int find_model_name_from_eeprom( char *eeprom) +{ + int i; + char *name; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + name = eeprom + models[i].offset; + if (strncmp(name, models[i].model_name, + strlen(models[i].model_name)) == 0) { + break; + } + } + + return (i == ARRAY_SIZE(models))? -EINVAL: i; +} +static int as7315_27xb_psu_model_name_get( + struct device *dev, char *buf) +{ + int i; + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + /* Determine if the model name is known, if not, read next index + */ + i = find_model_name_from_eeprom(data->eeprom); + if (i < 0) { + return -ENODATA; + } + + mutex_lock(&data->update_lock); + strncpy(buf, models[i].model_name, MAX_OUTPUT_LENGTH); + /*Work-around for some special models*/ + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR || + i == PSU_YM_1401_A || i == PSU_YM_2401_TCR) { + /* Skip the meaningless data byte 8*/ + buf[8] = buf[9]; + buf[9] = buf[10]; + buf = '\0'; + } + + mutex_unlock(&data->update_lock); + return i; +} + +static struct as7315_27xb_psu_data *as7315_27xb_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7315_27xb_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + UPDATE_PERIOD) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as7315_27xb update\n"); + data->valid = 0; + + /* Read psu status */ + status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + if (status < 0) { + dev_dbg(&client->dev, + "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + /*Read the eeprom of psu*/ + memset(data->eeprom, 0, sizeof(data->eeprom)); + status = as7315_27xb_psu_block_read(client, 0, + data->eeprom, sizeof(data->eeprom)); + + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from (0x%x)\n", + client->addr); + goto exit; + } + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +module_i2c_driver(as7315_27xb_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7315_27xb_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c new file mode 120000 index 00000000000..f4d67640ccc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service new file mode 100755 index 00000000000..cdaf437166b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7315-27XB Platform initialization service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7315_util.py install +ExecStart=/usr/local/bin/accton_as7315_monitor.py +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py new file mode 100755 index 00000000000..09187900c7e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7315_27xb', + version='1.0', + description='Module to initialize Accton AS7315-27XB platforms', + + packages=['as7315_27xb'], + package_dir={'as7315_27xb': 'as7315-27xb/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README new file mode 100755 index 00000000000..0b9fc163399 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py new file mode 100755 index 00000000000..3d9f6fc3ce5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + import signal + from tabulate import tabulate + from as7816_64x.fanutil import FanUtil + from as7816_64x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7816_monitor' +DUTY_MAX = 100 +DUTY_DEF = 40 + +global log_file +global log_level + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7816_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + max_duty = DUTY_MAX + fan_policy = { + 0: [52, 0, 43000], + 1: [63, 43000, 46000], + 2: [75, 46000, 52000], + 3: [88, 52000, 57000], + 4: [max_duty, 57000, sys.maxsize], + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + new_duty_cycle = DUTY_DEF + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle = fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as7816_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py new file mode 100755 index 00000000000..f06fd2891f4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py @@ -0,0 +1,525 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7315_27xb' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':5,'thermal':3, 'psu':2, 'sfp':27} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-64 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-64 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe ym2651y', +'modprobe accton_as7315_27xb_fan', +'modprobe at24_as7315_27xb', +'modprobe x86-64-accton-as7315_27xb-cpld', +'modprobe x86-64-accton-as7315_27xb-led', +'modprobe x86-64-accton-as7315_27xb-psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['50-0066'] , + 'thermal': ['51-0049','52-004a', '53-004c'] , + 'psu': ['13-0053','12-0050'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present', 'psu_power_good'] , + 'sfp': ['module_present']} + +sfp_map = [25,26,27,28,37,38,39,40,42,41,44,43,33,34,35,36,45,46,47,48,49, + 21, 22, 23] + +mknod =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', + +'echo as7315_cpld1 0x63 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo as7315_cpld2 0x64 > /sys/bus/i2c/devices/i2c-7/new_device', + +'echo 24cxb04 0x57 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo as7315_27xb_psu2 0x50 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as7315_27xb_psu1 0x53 > /sys/bus/i2c/devices/i2c-13/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-13/new_device', +'echo as7315_fan 0x66 > /sys/bus/i2c/devices/i2c-50/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-51/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-52/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-53/new_device', +'] + +def i2c_order_check(): + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" + status, output =log_os_system("echo optoe1 0x50 > " + path, 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + fmt = i2c_prefix+"19-0060/{0}_{1}" + path = fmt.format(nodes[j], k+1) + + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + i = int(index)-1 + node = i2c_prefix+ str(sfp_map[i])+ i2c_bus['sfp'][0]+"/"+ 'eeprom' + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system(hex_cmd +" -C "+node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() From f346eac300e4a3f6022f7e14b7060bc24922a04f Mon Sep 17 00:00:00 2001 From: roy_lee Date: Thu, 1 Aug 2019 11:26:38 +0800 Subject: [PATCH 2/6] Add files. Signed-off-by: roy_lee --- .../Accton-AS7315-27XB/port_config.ini | 81 ++++++---------- .../x86_64-accton_as7315_27xb-r0/default_sku | 2 +- .../led_proc_init.soc | 93 ++++--------------- platform/broadcom/one-image.mk | 1 + platform/broadcom/platform-modules-accton.mk | 6 ++ .../as7315-27xb/utils/README | 30 +++--- .../utils/accton_as7315_monitor.py | 4 +- .../debian/control | 4 + .../debian/rules | 2 +- 9 files changed, 76 insertions(+), 147 deletions(-) diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini index 93160688d74..26d49cdde58 100644 --- a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini @@ -1,55 +1,28 @@ # name lanes alias index speed -Ethernet0 41 twentyfiveGigE1 1 25000 -Ethernet1 42 twentyfiveGigE2 2 25000 -Ethernet2 43 twentyfiveGigE3 3 25000 -Ethernet3 44 twentyfiveGigE4 4 25000 -Ethernet4 49 twentyfiveGigE5 5 25000 -Ethernet5 50 twentyfiveGigE6 6 25000 -Ethernet6 51 twentyfiveGigE7 7 25000 -Ethernet7 52 twentyfiveGigE8 8 25000 -Ethernet8 53 twentyfiveGigE9 9 25000 -Ethernet9 54 twentyfiveGigE10 10 25000 -Ethernet10 55 twentyfiveGigE11 11 25000 -Ethernet11 56 twentyfiveGigE12 12 25000 -Ethernet12 65 twentyfiveGigE13 13 25000 -Ethernet13 66 twentyfiveGigE14 14 25000 -Ethernet14 67 twentyfiveGigE15 15 25000 -Ethernet15 68 twentyfiveGigE16 16 25000 -Ethernet16 33 twentyfiveGigE17 17 25000 -Ethernet17 34 twentyfiveGigE18 18 25000 -Ethernet18 35 twentyfiveGigE19 19 25000 -Ethernet19 36 twentyfiveGigE20 20 25000 -Ethernet20 37 twentyfiveGigE21 21 25000 -Ethernet21 38 twentyfiveGigE22 22 25000 -Ethernet22 39 twentyfiveGigE23 23 25000 -Ethernet23 40 twentyfiveGigE24 24 25000 -Ethernet24 69 twentyfiveGigE25 25 25000 -Ethernet25 70 twentyfiveGigE26 26 25000 -Ethernet26 71 twentyfiveGigE27 27 25000 -Ethernet27 72 twentyfiveGigE28 28 25000 -Ethernet28 81 twentyfiveGigE29 29 25000 -Ethernet29 82 twentyfiveGigE30 30 25000 -Ethernet30 83 twentyfiveGigE31 31 25000 -Ethernet31 84 twentyfiveGigE32 32 25000 -Ethernet32 85 twentyfiveGigE33 33 25000 -Ethernet33 86 twentyfiveGigE34 34 25000 -Ethernet34 87 twentyfiveGigE35 35 25000 -Ethernet35 88 twentyfiveGigE36 36 25000 -Ethernet36 97 twentyfiveGigE37 37 25000 -Ethernet37 98 twentyfiveGigE38 38 25000 -Ethernet38 99 twentyfiveGigE39 39 25000 -Ethernet39 100 twentyfiveGigE40 40 25000 -Ethernet40 101 twentyfiveGigE41 41 25000 -Ethernet41 102 twentyfiveGigE42 42 25000 -Ethernet42 103 twentyfiveGigE43 43 25000 -Ethernet43 104 twentyfiveGigE44 44 25000 -Ethernet44 105 twentyfiveGigE45 45 25000 -Ethernet45 106 twentyfiveGigE46 46 25000 -Ethernet46 107 twentyfiveGigE47 47 25000 -Ethernet47 108 twentyfiveGigE48 48 25000 -Ethernet48 5,6,7,8 hundredGigE49 49 100000 -Ethernet52 1,2,3,4 hundredGigE50 50 100000 -Ethernet56 109,110,111,112 hundredGigE51 51 100000 -Ethernet60 21,22,23,24 hundredGigE52 52 100000 -Ethernet64 9,10,11,12 hundredGigE53 53 100000 -Ethernet68 117,118,119,120 hundredGigE54 54 100000 +Ethernet0 28 twentyfiveGigE1 1 25000 +Ethernet1 29 twentyfiveGigE2 2 25000 +Ethernet2 30 twentyfiveGigE3 3 25000 +Ethernet3 31 twentyfiveGigE4 4 25000 +Ethernet4 24 twentyfiveGigE5 5 10000 +Ethernet5 25 twentyfiveGigE6 6 10000 +Ethernet6 26 twentyfiveGigE7 7 10000 +Ethernet7 27 twentyfiveGigE8 8 10000 +Ethernet8 20 twentyfiveGigE9 9 10000 +Ethernet9 21 twentyfiveGigE10 10 10000 +Ethernet10 22 twentyfiveGigE11 11 10000 +Ethernet11 23 twentyfiveGigE12 12 10000 +Ethernet12 16 twentyfiveGigE13 13 10000 +Ethernet13 17 twentyfiveGigE14 14 10000 +Ethernet14 18 twentyfiveGigE15 15 10000 +Ethernet15 19 twentyfiveGigE16 16 10000 +Ethernet16 4 twentyfiveGigE17 17 10000 +Ethernet17 5 twentyfiveGigE18 18 10000 +Ethernet18 6 twentyfiveGigE19 19 10000 +Ethernet19 7 twentyfiveGigE20 20 10000 +Ethernet20 0 twentyfiveGigE21 21 10000 +Ethernet21 1 twentyfiveGigE22 22 10000 +Ethernet22 2 twentyfiveGigE23 23 10000 +Ethernet23 3 twentyfiveGigE24 24 10000 +Ethernet24 67,68,69,70 twentyfiveGigE25 25 100000 +Ethernet25 71,72,73,74 twentyfiveGigE26 26 100000 +Ethernet26 75,76,77,78 twentyfiveGigE27 27 100000 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/default_sku b/device/accton/x86_64-accton_as7315_27xb-r0/default_sku index ef2d9d4c044..5c1bb0b4a47 100644 --- a/device/accton/x86_64-accton_as7315_27xb-r0/default_sku +++ b/device/accton/x86_64-accton_as7315_27xb-r0/default_sku @@ -1 +1 @@ -Accton-AS7335-27XB t1 +Accton-AS7315-27XB t1 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc index 3074649497e..790ab9cfc93 100755 --- a/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc +++ b/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc @@ -1,79 +1,24 @@ -# accton_as7312_54x 48x25G+6x100G SDK port LED macro init SOC -s CMIC_LEDUP0_DATA_RAM 0 -s CMIC_LEDUP1_DATA_RAM 0 - -m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 -m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 -m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 -m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 -m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 -m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 -m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 -m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 -m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 -m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 - -m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 -m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 -m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 -m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 -m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 -m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 -m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 -m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 -m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 -m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 -m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 -m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 -m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 -m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 -m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 -m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 - +# accton_as7315_27xb LED macro init SOC +######################################### +## LED program for BCM88470 Qumran-AX +######################################### led 0 stop led 0 prog \ - 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ - 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ - 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ - 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ - 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ - 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ - 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ - F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ - 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ - 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ - 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ - 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ - 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ - 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ - 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 02 FC 42 03 02 F9 42 00 02 00 67 26 67 2D 86 F9 \ + 67 2D 86 F9 67 2D 86 F9 67 2D 86 F9 06 F9 D2 24 \ + 74 0A 86 FB 3A 7E 67 59 67 41 67 69 57 67 59 67 \ + 41 67 72 1A 00 75 7B 1A 01 75 3D 77 50 67 59 77 \ + 46 12 A0 F8 15 57 80 28 32 00 32 01 B7 97 75 7F \ + 16 FB 06 FC C8 70 7F 77 7B 06 F9 C2 FC 98 98 12 \ + E0 F8 05 16 F9 CA 03 F1 57 1A 07 27 87 1A 06 27 \ + 87 57 1A 05 27 87 1A 04 27 87 57 32 0E 87 57 32 \ + 0F 87 57 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 led 0 start led auto on - -led 1 stop -led 1 prog \ - 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ - 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ - 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ - 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ - 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ - 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ - 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ - F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ - 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ - 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ - 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ - 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ - 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ - 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ - 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -led 1 start -led auto on diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index b87c6dc1470..985bfabae1f 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -30,6 +30,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ $(ACCTON_AS5835_54T_PLATFORM_MODULE) \ $(ACCTON_AS7312_54XS_PLATFORM_MODULE) \ + $(ACCTON_AS7315_27XB_PLATFORM_MODULE) \ $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk index 6745bb59236..6ef4224e7c3 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -16,6 +16,7 @@ ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS7312_54XS_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION = 1.1 export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION @@ -33,6 +34,7 @@ export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION export ACCTON_AS7312_54XS_PLATFORM_MODULE_VERSION +export ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton @@ -100,4 +102,8 @@ ACCTON_AS5835_54T_PLATFORM_MODULE = sonic-platform-accton-as5835-54t_$(ACCTON_AS $(ACCTON_AS5835_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54t-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54T_PLATFORM_MODULE))) +ACCTON_AS7315_27XB_PLATFORM_MODULE = sonic-platform-accton-as7312-27xb_$(ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7315_27XB_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7315_27xb-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7315_27XB_PLATFORM_MODULE))) + SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README index 0b9fc163399..0561fe7a277 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README @@ -1,4 +1,4 @@ -Copyright (C) 2016 Accton Networks, Inc. +Copyright (C) 2019 Accton Networks, Inc. This program is free software: you can redistribute it and/or modify It under the terms of the GNU General Public License as published by @@ -13,17 +13,17 @@ See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -To initialize the system, run "accton_as7712_util.py install". -To clean up the drivers & devices, run "accton_as7712_util.py clean". -To dump information of sensors, run "accton_as7712_util.py show". -To dump SFP EEPROM, run "accton_as7712_util.py sff". -To set fan speed, run "accton_as7712_util.py set fan". -To enable/disable SFP emission, run "accton_as7712_util.py set sfp". -To set system LEDs' color, run "accton_as7712_util.py set led" -For more information, run "accton_as7712_util.py --help". +To initialize the system, run "accton_as7315_util.py install". +To clean up the drivers & devices, run "accton_as7315_util.py clean". +To dump information of sensors, run "accton_as7315_util.py show". +To dump SFP EEPROM, run "accton_as7315_util.py sff". +To set fan speed, run "accton_as7315_util.py set fan". +To enable/disable SFP emission, run "accton_as7315_util.py set sfp". +To set system LEDs' color, run "accton_as7315_util.py set led" +For more information, run "accton_as7315_util.py --help". ==================================================================== -Besides applying accton_as7712_util.py to access peripherals, you can +Besides applying accton_as7315_util.py to access peripherals, you can access peripherals by sysfs nodes directly after the installation is run. LED controls can be found under /sys/class/leds. The sysfs interface @@ -41,7 +41,7 @@ The loc led has only 1 color, blue. The diag one has 3 colors: red, amber, and green. Fan controls can be found in /sys/bus/i2c/devices/2-0066. -There are 12 fans inside 6 fan modules. +There are 10 fans inside 5 fan modules. All fans share 1 duty setting, ranged from 0~100. Three temperature sensors are controlled by the lm75 kernel modules. @@ -51,10 +51,10 @@ Two power supplies are controlled by the CPLD. Here provide their status under /sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. -There are 32 QSFP+ modules are equipped. -Apply "accton_as7712_util.py show" to get their status. -Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. -Apply "accton_as7712_util.py sff" to dump EEPROM information. +There are QSFP/SFP modules are equipped. +Apply "accton_as7315_util.py show" to get their status. +Apply "accton_as7315_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7315_util.py sff" to dump EEPROM information. Before operating on that QSFP+, please make sure it is well plugged. Otherwise, operation is going to fail. diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py index 3d9f6fc3ce5..41a867aab18 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (C) 2017 Accton Technology Corporation +# Copyright (C) 2019 Accton Technology Corporation # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ # mm/dd/yyyy (A.D.) # 11/13/2017: Polly Hsu, Create # 1/10/2018: Jostar modify for as7716_32 -# 5/02/2019: Roy Lee modify for as7816_64x +# 8/02/2019: Roy Lee modify for as7315_27x # ------------------------------------------------------------------ try: diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control index cb78e152fff..e8bedd9081a 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -68,3 +68,7 @@ Description: kernel modules for platform devices such as fan, led, sfp Package: sonic-platform-accton-as7312-54xs Architecture: amd64 Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7315-27xb +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules index e2c6a4df8f3..11e5b10ae42 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -21,7 +21,7 @@ KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) MODULE_DIRS := as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x MODULE_DIRS += as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x -MODULE_DIRS += as5835-54x as9716-32d as5835-54t as7312-54xs +MODULE_DIRS += as5835-54x as9716-32d as5835-54t as7312-54xs as7315-27xb MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service From 174b4a3c5b5361eb258bc26b8dbb5cef9474762e Mon Sep 17 00:00:00 2001 From: roy_lee Date: Fri, 2 Aug 2019 16:32:05 +0800 Subject: [PATCH 3/6] Correct the typo. Signed-off-by: roy_lee --- platform/broadcom/platform-modules-accton.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk index 6ef4224e7c3..37ef2669fbb 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -102,7 +102,7 @@ ACCTON_AS5835_54T_PLATFORM_MODULE = sonic-platform-accton-as5835-54t_$(ACCTON_AS $(ACCTON_AS5835_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54t-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54T_PLATFORM_MODULE))) -ACCTON_AS7315_27XB_PLATFORM_MODULE = sonic-platform-accton-as7312-27xb_$(ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION)_amd64.deb +ACCTON_AS7315_27XB_PLATFORM_MODULE = sonic-platform-accton-as7315-27xb_$(ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS7315_27XB_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7315_27xb-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7315_27XB_PLATFORM_MODULE))) From 532b7548a3a79fdfaf8648458b20b6d3f4417092 Mon Sep 17 00:00:00 2001 From: roy_lee Date: Mon, 5 Aug 2019 17:05:09 +0800 Subject: [PATCH 4/6] Update verified utils. But control policy is not finalized. Signed-off-by: roy_lee --- .../plugins/psuutil.py | 4 +- .../plugins/sfputil.py | 203 +++++++++--------- .../as7315-27xb/classes/fanutil.py | 148 +++++-------- .../as7315-27xb/classes/thermalutil.py | 28 +-- .../utils/accton_as7315_monitor.py | 84 ++++---- .../as7315-27xb/utils/accton_as7315_util.py | 40 ++-- 6 files changed, 251 insertions(+), 256 deletions(-) diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py index 6df014abb52..7ec16640e5a 100644 --- a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py @@ -25,8 +25,8 @@ def __init__(self): self.psu_presence = "/psu_present" self.psu_oper_status = "/psu_power_good" self.psu_mapping = { - 2: "13-0053", - 1: "12-0050", + 1: "13-0053", + 2: "12-0050", } def get_num_psus(self): diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py index a1785fde553..1d777d25aee 100644 --- a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py @@ -6,20 +6,24 @@ try: import time import string + import pprint from ctypes import create_string_buffer from sonic_sfp.sfputilbase import SfpUtilBase except ImportError as e: raise ImportError("%s - required module not found" % str(e)) +#from xcvrd +SFP_STATUS_REMOVED = '0' +SFP_STATUS_INSERTED = '1' class SfpUtil(SfpUtilBase): """Platform-specific SfpUtil class""" PORT_START = 1 - PORT_END = 54 - PORTS_IN_BLOCK = 54 - QSFP_PORT_START = 49 - QSFP_PORT_END = 54 + PORT_END = 27 + PORTS_IN_BLOCK = 27 + QSFP_PORT_START = 25 + QSFP_PORT_END = 27 BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" @@ -27,66 +31,36 @@ class SfpUtil(SfpUtilBase): _port_to_lp_mode = {} _port_to_eeprom_mapping = {} - _cpld_mapping = { - 0: "4-0060", - 1: "5-0062", - 2: "6-0064", - } + _cpld_mapping = [ "8-0063", "7-0064"] + _port_to_i2c_mapping = { - 1: 18, - 2: 19, - 3: 20, - 4: 21, - 5: 22, - 6: 23, - 7: 24, - 8: 25, - 9: 26, - 10: 27, - 11: 28, - 12: 29, - 13: 30, - 14: 31, - 15: 32, - 16: 33, - 17: 34, - 18: 35, - 19: 36, - 20: 37, - 21: 38, - 22: 39, - 23: 40, - 24: 41, - 25: 42, - 26: 43, - 27: 44, - 28: 45, - 29: 46, - 30: 47, - 31: 48, - 32: 49, - 33: 50, - 34: 51, - 35: 52, - 36: 53, - 37: 54, - 38: 55, - 39: 56, - 40: 57, - 41: 58, - 42: 59, - 43: 60, - 44: 61, - 45: 62, - 46: 63, - 47: 64, - 48: 65, - 49: 66, #QSFP49 - 50: 67, - 51: 68, - 52: 69, - 53: 70, - 54: 71, #QSFP54 + 1: 26, + 2: 27, + 3: 28, + 4: 29, + 5: 30, + 6: 31, + 7: 32, + 8: 33, + 9: 34, + 10: 35, + 11: 36, + 12: 37, + 13: 38, + 14: 39, + 15: 40, + 16: 41, + 17: 42, + 18: 43, + 19: 44, + 20: 45, + 21: 46, + 22: 47, + 23: 48, + 24: 49, + 25: 21, #QSFP + 26: 22, + 27: 23, } @property @@ -119,15 +93,13 @@ def __init__(self): self.port_to_eeprom_mapping[x] = eeprom_path.format( self._port_to_i2c_mapping[x]) + self.get_transceiver_change_event() SfpUtilBase.__init__(self) def get_cpld_num(self, port_num): - cpld_i = 1 - if (port_num > 24 and port_num < self.qsfp_port_start): - cpld_i = 2 - - if (port_num > 52): - cpld_i = 2 + cpld_i = 0 + if (port_num >= self.qsfp_port_start): + cpld_i = 1 return cpld_i @@ -137,10 +109,10 @@ def get_presence(self, port_num): return False cpld_i = self.get_cpld_num(port_num) - cpld_ps = self._cpld_mapping[cpld_i] - path = "/sys/bus/i2c/devices/{0}/module_present_{1}" - port_ps = path.format(cpld_ps, port_num) + path = "/sys/bus/i2c/devices/{0}/present_{1}" + index = ((port_num-1)%24) +1 + port_ps = path.format(cpld_ps, index) try: val_file = open(port_ps) @@ -216,30 +188,67 @@ def set_low_power_mode(self, port_num, lpmode): time.sleep(0.01) def reset(self, port_num): - if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: - return False - - cpld_i = self.get_cpld_num(port_num) - cpld_ps = self._cpld_mapping[cpld_i] - path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" - port_ps = path.format(cpld_ps, port_num) - try: - reg_file = open(port_ps, 'w') - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False + raise NotImplementedError + + @property + def _get_present_bitmap(self): + nodes = [] + port_num = [24,3] + + path = "/sys/bus/i2c/devices/{0}/" + cpld_path = path.format(self._cpld_mapping[0]) + nodes.append((cpld_path + "module_present_all", port_num[0])) + cpld_path = path.format(self._cpld_mapping[1]) + nodes.append((cpld_path + "module_present_all", port_num[1])) + + bitmap = [] + for node in nodes: + try: + reg_file = open(node[0]) + + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + cpld_bm = reg_file.readline().rstrip().zfill(node[1]/4) + bitmap.append(cpld_bm) + reg_file.close() + + rev = "".join(bitmap[::-1]) + return int(rev,16) + + data = {'valid':0, 'last':0, 'present':0} + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_present_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range (self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + pprint.pprint(port_dict) + return True, port_dict + else: + return True, {} + return False, {} - reg_value = '0' - reg_file.write(reg_value) - reg_file.close() - - return True - - def get_transceiver_change_event(self): - """ - TODO: This function need to be implemented - when decide to support monitoring SFP(Xcvrd) - on this platform. - """ - raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py index 42ccb17eaa0..0e7b06bbd28 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py @@ -34,59 +34,39 @@ class FanUtil(object): """Platform-specific FanUtil class""" - FAN_NUM_ON_MAIN_BROAD = 4 + FAN_TOTAL_NUM = 5 FAN_NUM_1_IDX = 1 - FAN_NUM_2_IDX = 2 - FAN_NUM_3_IDX = 3 - FAN_NUM_4_IDX = 4 - - FAN_NODE_NUM_OF_MAP = 2 - FAN_NODE_FAULT_IDX_OF_MAP = 1 - #FAN_NODE_SPEED_IDX_OF_MAP = 2 - FAN_NODE_DIR_IDX_OF_MAP = 2 + + FAN_NODE_NUM = 2 + FAN_FAULT_IDX = 1 + #FAN_SPEED_IDX = 2 + FAN_DIR_IDX = 2 #FAN_NODE_DUTY_IDX_OF_MAP = 4 #FANR_NODE_FAULT_IDX_OF_MAP = 5 - BASE_VAL_PATH = '/sys/bus/i2c/devices/17-0068/{0}' - FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0068/fan_duty_cycle_percentage' + BASE_VAL_PATH = '/sys/bus/i2c/devices/50-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/50-0066/fan{0}_pwm' #logfile = '' - #loglevel = logging.INFO + #loglevel = self.logger.INFO """ Dictionary where key1 = fan id index (integer) starting from 1 key2 = fan node index (interger) starting from 1 value = path to fan device file (string) """ - _fan_to_device_path_mapping = {} + dev_paths = {} -#fan1_direction -#fan1_fault -#fan1_present - - #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', - _fan_to_device_node_mapping = { - (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', - (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', - (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', - (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', - - (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', - (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', - - (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', - (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', - } - + node_postfix = ["fault", "direction"] def _get_fan_to_device_node(self, fan_num, node_num): - return self._fan_to_device_node_mapping[(fan_num, node_num)] + return "fan{0}_{1}".format(fan_num, self.node_postfix[node_num-1]) def _get_fan_node_val(self, fan_num, node_num): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num:%d', fan_num) + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_TOTAL_NUM: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) return None - if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: - logging.debug('GET. Parameter error. node_num:%d', node_num) + if node_num < self.FAN_FAULT_IDX or node_num > self.FAN_NODE_NUM: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) return None device_path = self.get_fan_to_device_path(fan_num, node_num) @@ -94,42 +74,42 @@ def _get_fan_node_val(self, fan_num, node_num): try: val_file = open(device_path, 'r') except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) + self.logger.error('GET. unable to open file: %s', str(e)) return None content = val_file.readline().rstrip() if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) + self.logger.debug('GET. content is NULL. device_path:%s', device_path) return None try: val_file.close() except: - logging.debug('GET. unable to close file. device_path:%s', device_path) + self.logger.debug('GET. unable to close file. device_path:%s', device_path) return None return int(content) def _set_fan_node_val(self, fan_num, node_num, val): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num:%d', fan_num) + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_TOTAL_NUM: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) return None - if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: - logging.debug('GET. Parameter error. node_num:%d', node_num) + if node_num < self.FAN_FAULT_IDX or node_num > self.FAN_NODE_NUM: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) return None content = str(val) if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) + self.logger.debug('GET. content is NULL. device_path:%s', device_path) return None device_path = self.get_fan_to_device_path(fan_num, node_num) try: val_file = open(device_path, 'w') except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) + self.logger.error('GET. unable to open file: %s', str(e)) return None val_file.write(content) @@ -137,96 +117,86 @@ def _set_fan_node_val(self, fan_num, node_num, val): try: val_file.close() except: - logging.debug('GET. unable to close file. device_path:%s', device_path) + self.logger.debug('GET. unable to close file. device_path:%s', device_path) return None return True - def __init__(self): - fan_path = self.BASE_VAL_PATH + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) - for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): - for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): - self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( - self._fan_to_device_node_mapping[(fan_num, node_num)]) + fan_path = self.BASE_VAL_PATH + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_TOTAL_NUM+1): + for node_num in range(1, self.FAN_NODE_NUM+1): + node = self._get_fan_to_device_node(fan_num, node_num) + self.dev_paths[(fan_num, node_num)] = fan_path.format(node) def get_num_fans(self): - return self.FAN_NUM_ON_MAIN_BROAD + return self.FAN_TOTAL_NUM def get_idx_fan_start(self): return self.FAN_NUM_1_IDX def get_num_nodes(self): - return self.FAN_NODE_NUM_OF_MAP + return self.FAN_NODE_NUM def get_idx_node_start(self): - return self.FAN_NODE_FAULT_IDX_OF_MAP + return self.FAN_FAULT_IDX def get_size_node_map(self): - return len(self._fan_to_device_node_mapping) + return len(self.dev_paths) def get_size_path_map(self): - return len(self._fan_to_device_path_mapping) + return len(self.dev_paths) def get_fan_to_device_path(self, fan_num, node_num): - return self._fan_to_device_path_mapping[(fan_num, node_num)] + return self.dev_paths[(fan_num, node_num)] def get_fan_fault(self, fan_num): - return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + return self._get_fan_node_val(fan_num, self.FAN_FAULT_IDX) #def get_fan_speed(self, fan_num): - # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + # return self._get_fan_node_val(fan_num, self.FAN_SPEED_IDX) def get_fan_dir(self, fan_num): - return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + return self._get_fan_node_val(fan_num, self.FAN_DIR_IDX) def get_fan_duty_cycle(self): - #duty_path = self.FAN_DUTY_PATH try: - val_file = open(self.FAN_DUTY_PATH) + val_file = open(self.FAN_DUTY_PATH.format(1)) except IOError as e: print "Error: unable to open file: %s" % str(e) return False content = val_file.readline().rstrip() val_file.close() - return int(content) - #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) -#static u32 reg_val_to_duty_cycle(u8 reg_val) -#{ -# reg_val &= FAN_DUTY_CYCLE_REG_MASK; -# return ((u32)(reg_val+1) * 625 + 75)/ 100; -#} -# + def set_fan_duty_cycle(self, val): - - try: - fan_file = open(self.FAN_DUTY_PATH, 'r+') - except IOError as e: - print "Error: unable to open file: %s" % str(e) - return False - fan_file.write(str(val)) - fan_file.close() + for fan_num in range(1, self.FAN_TOTAL_NUM+1): + try: + fan_file = open(self.FAN_DUTY_PATH.format(fan_num), 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() return True - #def get_fanr_fault(self, fan_num): - # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) - - def get_fanr_speed(self, fan_num): - return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) - def get_fan_status(self, fan_num): - if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. fan_num, %d', fan_num) + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_TOTAL_NUM: + self.logger.debug('GET. Parameter error. fan_num, %d', fan_num) return None if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: - logging.debug('GET. FAN fault. fan_num, %d', fan_num) + self.logger.debug('GET. FAN fault. fan_num, %d', fan_num) return False #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: - # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # self.logger.debug('GET. FANR fault. fan_num, %d', fan_num) # return False return True diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py index 65e872c6beb..47dba67f2c1 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py @@ -35,7 +35,7 @@ class ThermalUtil(object): """Platform-specific ThermalUtil class""" - THERMAL_NUM_ON_MAIN_BROAD = 6 + THERMAL_NUM_ON_MAIN_BROAD = 3 THERMAL_NUM_1_IDX = 1 BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' @@ -45,17 +45,17 @@ class ThermalUtil(object): _thermal_to_device_path_mapping = {} _thermal_to_device_node_mapping = [ - ['18', '48'], - ['18', '49'], - ['18', '4a'], - ['18', '4b'], - ['17', '4d'], - ['17', '4e'], + ['51', '49'], + ['52', '4a'], + ['53', '4c'], ] + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) - def __init__(self): thermal_path = self.BASE_VAL_PATH - for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): self._thermal_to_device_path_mapping[x+1] = thermal_path.format( self._thermal_to_device_node_mapping[x][0], @@ -63,7 +63,7 @@ def __init__(self): def _get_thermal_node_val(self, thermal_num): if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: - logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + self.logger.debug('GET. Parameter error. thermal_num, %d', thermal_num) return None device_path = self.get_thermal_to_device_path(thermal_num) @@ -71,19 +71,19 @@ def _get_thermal_node_val(self, thermal_num): try: val_file = open(filename, 'r') except IOError as e: - logging.error('GET. unable to open file: %s', str(e)) + self.logger.error('GET. unable to open file: %s', str(e)) return None content = val_file.readline().rstrip() if content == '': - logging.debug('GET. content is NULL. device_path:%s', device_path) + self.logger.debug('GET. content is NULL. device_path:%s', device_path) return None try: - val_file.close() + val_file.close() except: - logging.debug('GET. unable to close file. device_path:%s', device_path) + self.logger.debug('GET. unable to close file. device_path:%s', device_path) return None return int(content) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py index 41a867aab18..be27ce8b191 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py @@ -36,48 +36,53 @@ import traceback import signal from tabulate import tabulate - from as7816_64x.fanutil import FanUtil - from as7816_64x.thermalutil import ThermalUtil + from as7315_27xb.fanutil import FanUtil + from as7315_27xb.thermalutil import ThermalUtil except ImportError as e: raise ImportError('%s - required module not found' % str(e)) # Deafults VERSION = '1.0' -FUNCTION_NAME = 'accton_as7816_monitor' +FUNCTION_NAME = 'accton_as7315_monitor' DUTY_MAX = 100 DUTY_DEF = 40 global log_file -global log_level +global log_console # Make a class we can use to capture stdout and sterr in the log -class accton_as7816_monitor(object): +class accton_as7315_monitor(object): # static temp var _ori_temp = 0 _new_perc = 0 _ori_perc = 0 - def __init__(self, log_file, log_level): + llog = logging.getLogger("["+FUNCTION_NAME+"]") + def __init__(self, log_console, log_file): """Needs a logger and a logger level.""" - # set up logging to file - logging.basicConfig( - filename=log_file, - filemode='w', - level=log_level, - format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', - datefmt='%H:%M:%S' - ) + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + sys_handler.setLevel(logging.WARNING) #only fatal for syslog + self.llog.addHandler(sys_handler) + self.llog.setLevel(logging.DEBUG) + + if log_file: + fh = logging.FileHandler(log_file) + fh.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + fh.setFormatter(formatter) + self.llog.addHandler(fh) # set up logging to console - if log_level == logging.DEBUG: + if log_console: console = logging.StreamHandler() - console.setLevel(log_level) - formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setLevel(logging.DEBUG) #For debugging + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') console.setFormatter(formatter) - logging.getLogger('').addHandler(console) - - logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + self.llog.addHandler(console) def manage_fans(self): max_duty = DUTY_MAX @@ -94,13 +99,13 @@ def manage_fans(self): for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): fan_status = fan.get_fan_status(x) if fan_status is None: - logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + self.llog.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) return False if fan_status is False: - logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + self.llog.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) fan.set_fan_duty_cycle(max_duty) return True - #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + #self.llog.debug('INFO. fan_status is True (fan_num:%d)', x) #Find if current duty matched any of define duty. #If not, set it to highest one. @@ -119,40 +124,41 @@ def manage_fans(self): y = len(fan_policy) - x -1 #checked from highest if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : new_duty_cycle = fan_policy[y][0] - logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + self.llog.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) - logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + self.llog.debug('INFO. Final duty_cycle=%d', new_duty_cycle) if(new_duty_cycle != cur_duty_cycle): fan.set_fan_duty_cycle(new_duty_cycle) return True -def handler(signum, frame): +def sig_handler(signum, frame): fan = FanUtil() - logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + self.llog.debug('INFO:Cause signal %d, set fan speed max.', signum) fan.set_fan_duty_cycle(DUTY_MAX) sys.exit(0) def main(argv): log_file = '%s.log' % FUNCTION_NAME - log_level = logging.INFO + log_console = 0 + log_file = "" if len(sys.argv) != 1: try: - opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + opts, args = getopt.getopt(argv,'hdl') except getopt.GetoptError: - print 'Usage: %s [-d] [-l ]' % sys.argv[0] + print 'Usage: %s [-d] [-l]' % sys.argv[0] return 0 for opt, arg in opts: if opt == '-h': - print 'Usage: %s [-d] [-l ]' % sys.argv[0] + print 'Usage: %s [-d] [-l]' % sys.argv[0] return 0 - elif opt in ('-d', '--debug'): - log_level = logging.DEBUG - elif opt in ('-l', '--lfile'): - log_file = arg - - signal.signal(signal.SIGINT, handler) - signal.signal(signal.SIGTERM, handler) - monitor = accton_as7816_monitor(log_file, log_level) + elif opt in ('-d'): + log_console = 1 + elif opt in ('-l'): + log_file = '%s.log' % sys.argv[0] + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + monitor = accton_as7315_monitor(log_console, log_file) # Loop forever, doing something useful hopefully: while True: diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py index f06fd2891f4..ea856e4ff56 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py @@ -47,11 +47,13 @@ DEBUG = False args = [] ALL_DEVICE = {} -DEVICE_NO = {'led':5, 'fan':5,'thermal':3, 'psu':2, 'sfp':27} +DEVICE_NO = {'led':2, 'fan':5,'thermal':3, 'psu':2, 'sfp':27} FORCE = 0 #logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) #logging.basicConfig(level=logging.INFO) +qsfp_start_index = 24 + if DEBUG == True: print sys.argv[0] @@ -119,14 +121,14 @@ def show_help(): def show_set_help(): cmd = sys.argv[0].split("/")[-1]+ " " + args[0] print cmd +" [led|sfp|fan]" - print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " led 0-1 \" to set led color" print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" - print " use \""+ cmd + " sfp 1-64 {0|1}\" to set sfp# tx_disable" + print " use \""+ cmd + " sfp 1-27 {0|1}\" to set sfp# tx_disable" sys.exit(0) def show_eeprom_help(): cmd = sys.argv[0].split("/")[-1]+ " " + args[0] - print " use \""+ cmd + " 1-64 \" to dump sfp# eeprom" + print " use \""+ cmd + " 1-27 \" to dump sfp# eeprom" sys.exit(0) def my_log(txt): @@ -194,8 +196,8 @@ def driver_uninstall(): return status return 0 -led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' -hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_' +hwmon_types = {'led': ['diag','loc']} hwmon_nodes = {'led': ['brightness'] } hwmon_prefix ={'led': led_prefix} @@ -204,18 +206,20 @@ def driver_uninstall(): 'thermal': ['51-0049','52-004a', '53-004c'] , 'psu': ['13-0053','12-0050'], 'sfp': ['-0050']} -i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , +i2c_nodes = {'fan': ['present', 'input'] , 'thermal': ['hwmon/hwmon*/temp1_input'] , 'psu': ['psu_present', 'psu_power_good'] , - 'sfp': ['module_present']} + 'sfp': ['present']} -sfp_map = [25,26,27,28,37,38,39,40,42,41,44,43,33,34,35,36,45,46,47,48,49, +sfp_map = [26,27,28,29,30,31,32,33, + 34,35,36,37,38,39,40,41, + 42,43,44,45,46,47,48,49, 21, 22, 23] mknod =[ -'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-3/new_device', -'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-18/new_device', 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-19/new_device', 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', @@ -232,7 +236,7 @@ def driver_uninstall(): 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-51/new_device', 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-52/new_device', 'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-53/new_device', -'] +] def i2c_order_check(): return 0 @@ -253,7 +257,10 @@ def device_install(): for i in range(0,len(sfp_map)): path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" - status, output =log_os_system("echo optoe1 0x50 > " + path, 1) + if 1 >= qsfp_start_index: + status, output =log_os_system("echo optoe1 0x50 > " + path, 1) + else: + status, output =log_os_system("echo optoe2 0x50 > " + path, 1) if status: print output if FORCE == 0: @@ -361,8 +368,11 @@ def devices_info(): elif 'sfp' == key: for k in range(0,DEVICE_NO[key]): node = key+str(k+1) - fmt = i2c_prefix+"19-0060/{0}_{1}" - path = fmt.format(nodes[j], k+1) + if k > qsfp_start_index: + fmt = i2c_prefix+"7-0064/{0}_{1}" + else: + fmt = i2c_prefix+"8-0063/{0}_{1}" + path = fmt.format(nodes[j], (k%qsfp_start_index)+1) my_log(node+": "+ path) ALL_DEVICE[key][node].append(path) From b4ef8c56c4ede7b21a514417ac4dc865389122bf Mon Sep 17 00:00:00 2001 From: roy_lee Date: Tue, 6 Aug 2019 14:54:58 +0800 Subject: [PATCH 5/6] Use root logger for signal caught. Signed-off-by: roy_lee --- .../as7315-27xb/utils/accton_as7315_monitor.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py index be27ce8b191..5d821350ac8 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py @@ -99,13 +99,12 @@ def manage_fans(self): for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): fan_status = fan.get_fan_status(x) if fan_status is None: - self.llog.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + self.llog.debug('SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) return False if fan_status is False: - self.llog.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + self.llog.debug('SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) fan.set_fan_duty_cycle(max_duty) return True - #self.llog.debug('INFO. fan_status is True (fan_num:%d)', x) #Find if current duty matched any of define duty. #If not, set it to highest one. @@ -124,16 +123,16 @@ def manage_fans(self): y = len(fan_policy) - x -1 #checked from highest if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : new_duty_cycle = fan_policy[y][0] - self.llog.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + self.llog.debug('Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) - self.llog.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + self.llog.debug('Final duty_cycle=%d', new_duty_cycle) if(new_duty_cycle != cur_duty_cycle): fan.set_fan_duty_cycle(new_duty_cycle) return True def sig_handler(signum, frame): fan = FanUtil() - self.llog.debug('INFO:Cause signal %d, set fan speed max.', signum) + logging.critical('Cause signal %d, set fan speed max.', signum) fan.set_fan_duty_cycle(DUTY_MAX) sys.exit(0) From 294a81d5d40ab6c1b599136c52d67263453076a1 Mon Sep 17 00:00:00 2001 From: roy_lee Date: Tue, 6 Aug 2019 17:13:39 +0800 Subject: [PATCH 6/6] Updated fan speed for new cpld firmware. Signed-off-by: roy_lee --- .../as7315-27xb/modules/accton_as7315_27xb_fan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c index e08522718c6..adf8fc69ea3 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c @@ -39,7 +39,7 @@ #define DRV_NAME "as5812_54x_fan" #define FAN_MAX_NUMBER 5 -#define FAN_SPEED_TACH_TO_RPM_STEP 750 +#define FAN_SPEED_TACH_TO_RPM_STEP 175 #define FAN_SPEED_PWM_STEPS 31 #define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ #define FAN_DUTY_CYCLE_MAX 100 /* 100% */ @@ -300,11 +300,11 @@ static ssize_t show_byte(struct device *dev, static u32 reg_val_to_duty_cycle(u8 reg_val) { - return ((u32)(reg_val+1) * 312 + 88)/ 100; + return ((u32)(reg_val+1) * 156 + 88) / 100; } static u8 duty_cycle_to_reg_val(u8 duty_cycle) { - return ((u32)duty_cycle * 100 / 311) - 1; + return ((u32)duty_cycle * 100 / 155) - 1; } static ssize_t show_pwm(struct device *dev,