diff --git a/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/hwsku.json b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/hwsku.json new file mode 100644 index 000000000000..ff7e639496b9 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/hwsku.json @@ -0,0 +1,332 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet8": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet16": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet24": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet32": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet40": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet48": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet56": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet64": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet72": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet80": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet88": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet96": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet104": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet112": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet120": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet128": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet136": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet144": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet152": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet160": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet168": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet176": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet184": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet192": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet200": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet208": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet216": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet224": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet232": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet240": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet248": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet256": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet264": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet272": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet280": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet288": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet296": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet304": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet312": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet320": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet328": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet336": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet344": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet352": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet360": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet368": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet376": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet384": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet392": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet400": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet408": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet416": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet424": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet432": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet440": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet448": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet456": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet464": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet472": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet480": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet488": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet496": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet504": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet512": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + + "Ethernet513": { + "default_brkout_mode": "1x25G[10G,1G]" + } + } +} + diff --git a/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/port_config.ini b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/port_config.ini new file mode 100644 index 000000000000..b298efa1aa69 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4,5,6,7,8 Eth1(Port1) 1 800000 +Ethernet8 9,10,11,12,13,14,15,16 Eth2(Port2) 2 800000 +Ethernet16 41,42,43,44,45,46,47,48 Eth3(Port3) 3 800000 +Ethernet24 33,34,35,36,37,38,39,40 Eth4(Port4) 4 800000 +Ethernet32 73,74,75,76,77,78,79,80 Eth5(Port5) 5 800000 +Ethernet40 65,66,67,68,69,70,71,72 Eth6(Port6) 6 800000 +Ethernet48 105,106,107,108,109,110,111,112 Eth7(Port7) 7 800000 +Ethernet56 97,98,99,100,101,102,103,104 Eth8(Port8) 8 800000 +Ethernet64 137,138,139,140,141,142,143,144 Eth9(Port9) 9 800000 +Ethernet72 129,130,131,132,133,134,135,136 Eth10(Port10) 10 800000 +Ethernet80 169,170,171,172,173,174,175,176 Eth11(Port11) 11 800000 +Ethernet88 161,162,163,164,165,166,167,168 Eth12(Port12) 12 800000 +Ethernet96 201,202,203,204,205,206,207,208 Eth13(Port13) 13 800000 +Ethernet104 193,194,195,196,197,198,199,200 Eth14(Port14) 14 800000 +Ethernet112 233,234,235,236,237,238,239,240 Eth15(Port15) 15 800000 +Ethernet120 225,226,227,228,229,230,231,232 Eth16(Port16) 16 800000 +Ethernet128 257,258,259,260,261,262,263,264 Eth17(Port17) 17 800000 +Ethernet136 265,266,267,268,269,270,271,272 Eth18(Port18) 18 800000 +Ethernet144 297,298,299,300,301,302,303,304 Eth19(Port19) 19 800000 +Ethernet152 289,290,291,292,293,294,295,296 Eth20(Port20) 20 800000 +Ethernet160 329,330,331,332,333,334,335,336 Eth21(Port21) 21 800000 +Ethernet168 321,322,323,324,325,326,327,328 Eth22(Port22) 22 800000 +Ethernet176 361,362,363,364,365,366,367,368 Eth23(Port23) 23 800000 +Ethernet184 353,354,355,356,357,358,359,360 Eth24(Port24) 24 800000 +Ethernet192 393,394,395,396,397,398,399,400 Eth25(Port25) 25 800000 +Ethernet200 385,386,387,388,389,390,391,392 Eth26(Port26) 26 800000 +Ethernet208 425,426,427,428,429,430,431,432 Eth27(Port27) 27 800000 +Ethernet216 417,418,419,420,421,422,423,424 Eth28(Port28) 28 800000 +Ethernet224 457,458,459,460,461,462,463,464 Eth29(Port29) 29 800000 +Ethernet232 449,450,451,452,453,454,455,456 Eth30(Port30) 30 800000 +Ethernet240 489,490,491,492,493,494,495,496 Eth31(Port31) 31 800000 +Ethernet248 481,482,483,484,485,486,487,488 Eth32(Port32) 32 800000 +Ethernet256 17,18,19,20,21,22,23,24 Eth33(Port33) 33 800000 +Ethernet264 25,26,27,28,29,30,31,32 Eth34(Port34) 34 800000 +Ethernet272 49,50,51,52,53,54,55,56 Eth35(Port35) 35 800000 +Ethernet280 57,58,59,60,61,62,63,64 Eth36(Port36) 36 800000 +Ethernet288 81,82,83,84,85,86,87,88 Eth37(Port37) 37 800000 +Ethernet296 89,90,91,92,93,94,95,96 Eth38(Port38) 38 800000 +Ethernet304 113,114,115,116,117,118,119,120 Eth39(Port39) 39 800000 +Ethernet312 121,122,123,124,125,126,127,128 Eth40(Port40) 40 800000 +Ethernet320 145,146,147,148,149,150,151,152 Eth41(Port41) 41 800000 +Ethernet328 153,154,155,156,157,158,159,160 Eth42(Port42) 42 800000 +Ethernet336 177,178,179,180,181,182,183,184 Eth43(Port43) 43 800000 +Ethernet344 185,186,187,188,189,190,191,192 Eth44(Port44) 44 800000 +Ethernet352 209,210,211,212,213,214,215,216 Eth45(Port45) 45 800000 +Ethernet360 217,218,219,220,221,222,223,224 Eth46(Port46) 46 800000 +Ethernet368 249,250,251,252,253,254,255,256 Eth47(Port47) 47 800000 +Ethernet376 241,242,243,244,245,246,247,248 Eth48(Port48) 48 800000 +Ethernet384 273,274,275,276,277,278,279,280 Eth49(Port49) 49 800000 +Ethernet392 281,282,283,284,285,286,287,288 Eth50(Port50) 50 800000 +Ethernet400 305,306,307,308,309,310,311,312 Eth51(Port51) 51 800000 +Ethernet408 313,314,315,316,317,318,319,320 Eth52(Port52) 52 800000 +Ethernet416 337,338,339,340,341,342,343,344 Eth53(Port53) 53 800000 +Ethernet424 345,346,347,348,349,350,351,352 Eth54(Port54) 54 800000 +Ethernet432 369,370,371,372,373,374,375,376 Eth55(Port55) 55 800000 +Ethernet440 377,378,379,380,381,382,383,384 Eth56(Port56) 56 800000 +Ethernet448 401,402,403,404,405,406,407,408 Eth57(Port57) 57 800000 +Ethernet456 409,410,411,412,413,414,415,416 Eth58(Port58) 58 800000 +Ethernet464 433,434,435,436,437,438,439,440 Eth59(Port59) 59 800000 +Ethernet472 441,442,443,444,445,446,447,448 Eth60(Port60) 60 800000 +Ethernet480 465,466,467,468,469,470,471,472 Eth61(Port61) 61 800000 +Ethernet488 473,474,475,476,477,478,479,480 Eth62(Port62) 62 800000 +Ethernet496 505,506,507,508,509,510,511,512 Eth63(Port63) 63 800000 +Ethernet504 497,498,499,500,501,502,503,504 Eth64(Port64) 64 800000 +Ethernet512 514 Eth65(Port65) 65 25000 +Ethernet513 513 Eth66(Port66) 66 25000 diff --git a/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/sai.profile b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/sai.profile new file mode 100644 index 000000000000..3a8b8022c348 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th5-as9817-64d-64x800G.config.yml diff --git a/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/th5-as9817-64d-64x800G.config.yml b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/th5-as9817-64d-64x800G.config.yml new file mode 100644 index 000000000000..e98f5228bf1a --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/Accton-AS9817-64D/th5-as9817-64d-64x800G.config.yml @@ -0,0 +1,1139 @@ +--- +bcm_device: + 0: + global: + pktio_mode: 1 + vlan_flooding_l2mc_num_reserved: 0 + ipv6_lpm_128b_enable: 1 + shared_block_mask_section: uc_bc + skip_protocol_default_entries: 1 + # LTSW uses value 1 for ALPM combined mode + l3_alpm_template: 1 + l3_alpm_hit_skip: 1 + sai_feat_tail_timestamp : 1 + sai_field_group_auto_prioritize: 1 + #l3_intf_vlan_split_egress for MTU at L3IF + l3_intf_vlan_split_egress : 1 + pfc_deadlock_seq_control : 1 + sai_tunnel_support: 2 + bcm_tunnel_term_compatible_mode: 1 + l3_ecmp_member_first_lkup_mem_size: 12288 + sai_l3_byte1_udf_disable: 1 + #For PPIU Mode, Set resources for counters in global mode counters like ACL, etc + global_flexctr_ing_action_num_reserved: 20 + global_flexctr_ing_pool_num_reserved: 8 + global_flexctr_ing_op_profile_num_reserved: 20 + global_flexctr_ing_group_num_reserved: 2 + global_flexctr_egr_action_num_reserved: 8 + global_flexctr_egr_pool_num_reserved: 5 + global_flexctr_egr_op_profile_num_reserved: 10 + global_flexctr_egr_group_num_reserved: 1 + flowtracker_enable: 1 + flowtracker_hardware_learn_enable: 2 + flowtracker_flexctr_alloc_enable: 1 + flowtracker_max_flows: 131072 +... +--- +device: + 0: + PC_PM_CORE: + ? + PC_PM_ID: 1 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x37061524 + TX_LANE_MAP: 0x60714253 + RX_POLARITY_FLIP: 0xe0 + TX_POLARITY_FLIP: 0xcc + ? + PC_PM_ID: 2 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06172435 + TX_LANE_MAP: 0x71605342 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0xa5 + ? + PC_PM_ID: 3 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x17063524 + TX_LANE_MAP: 0x71605342 + RX_POLARITY_FLIP: 0x69 + TX_POLARITY_FLIP: 0xcc + ? + PC_PM_ID: 4 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06172435 + TX_LANE_MAP: 0x73625140 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x0f + ? + PC_PM_ID: 5 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60712435 + TX_LANE_MAP: 0x34257160 + RX_POLARITY_FLIP: 0xcd + TX_POLARITY_FLIP: 0x7e + ? + PC_PM_ID: 6 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x12740356 + TX_LANE_MAP: 0x14276053 + RX_POLARITY_FLIP: 0xbb + TX_POLARITY_FLIP: 0x32 + ? + PC_PM_ID: 7 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x26074351 + TX_LANE_MAP: 0x27145360 + RX_POLARITY_FLIP: 0x7b + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 8 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x26074351 + TX_LANE_MAP: 0x45026713 + RX_POLARITY_FLIP: 0x7b + TX_POLARITY_FLIP: 0x8b + ? + PC_PM_ID: 9 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x07265143 + TX_LANE_MAP: 0x14276053 + RX_POLARITY_FLIP: 0xde + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 10 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x12740356 + TX_LANE_MAP: 0x14276053 + RX_POLARITY_FLIP: 0xbb + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 11 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x26074351 + TX_LANE_MAP: 0x27145360 + RX_POLARITY_FLIP: 0x7b + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 12 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x26074351 + TX_LANE_MAP: 0x45026713 + RX_POLARITY_FLIP: 0x7b + TX_POLARITY_FLIP: 0x8b + ? + PC_PM_ID: 13 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x07265143 + TX_LANE_MAP: 0x14276053 + RX_POLARITY_FLIP: 0xde + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 14 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x12740356 + TX_LANE_MAP: 0x14276053 + RX_POLARITY_FLIP: 0xbb + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 15 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x26074351 + TX_LANE_MAP: 0x27145360 + RX_POLARITY_FLIP: 0x7b + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 16 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x26074351 + TX_LANE_MAP: 0x45026713 + RX_POLARITY_FLIP: 0x7b + TX_POLARITY_FLIP: 0x8b + ? + PC_PM_ID: 17 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x71630524 + TX_LANE_MAP: 0x40531627 + RX_POLARITY_FLIP: 0x4b + TX_POLARITY_FLIP: 0x89 + ? + PC_PM_ID: 18 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x56127403 + TX_LANE_MAP: 0x40531627 + RX_POLARITY_FLIP: 0x36 + TX_POLARITY_FLIP: 0x89 + ? + PC_PM_ID: 19 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x63712405 + TX_LANE_MAP: 0x53402716 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0xd9 + ? + PC_PM_ID: 20 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x63712405 + TX_LANE_MAP: 0x02651347 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0xf4 + ? + PC_PM_ID: 21 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x71630524 + TX_LANE_MAP: 0x40531627 + RX_POLARITY_FLIP: 0x4b + TX_POLARITY_FLIP: 0x89 + ? + PC_PM_ID: 22 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x56127403 + TX_LANE_MAP: 0x40531627 + RX_POLARITY_FLIP: 0x36 + TX_POLARITY_FLIP: 0x89 + ? + PC_PM_ID: 23 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x63712405 + TX_LANE_MAP: 0x53402716 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0xd9 + ? + PC_PM_ID: 24 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x63712405 + TX_LANE_MAP: 0x02651347 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0xf4 + ? + PC_PM_ID: 25 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x71630524 + TX_LANE_MAP: 0x40531627 + RX_POLARITY_FLIP: 0x4b + TX_POLARITY_FLIP: 0x89 + ? + PC_PM_ID: 26 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x56127403 + TX_LANE_MAP: 0x40531627 + RX_POLARITY_FLIP: 0x36 + TX_POLARITY_FLIP: 0x89 + ? + PC_PM_ID: 27 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x63712405 + TX_LANE_MAP: 0x53402716 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0xc9 + ? + PC_PM_ID: 28 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06245173 + TX_LANE_MAP: 0x31642075 + RX_POLARITY_FLIP: 0x87 + TX_POLARITY_FLIP: 0x53 + ? + PC_PM_ID: 29 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60714253 + TX_LANE_MAP: 0x17063524 + RX_POLARITY_FLIP: 0x21 + TX_POLARITY_FLIP: 0xa5 + ? + PC_PM_ID: 30 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x51607342 + TX_LANE_MAP: 0x06172435 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0x00 + ? + PC_PM_ID: 31 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60714253 + TX_LANE_MAP: 0x15043726 + RX_POLARITY_FLIP: 0x21 + TX_POLARITY_FLIP: 0x0f + ? + PC_PM_ID: 32 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x71605342 + TX_LANE_MAP: 0x17063524 + RX_POLARITY_FLIP: 0x5a + TX_POLARITY_FLIP: 0xff + ? + PC_PM_ID: 33 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x37061524 + TX_LANE_MAP: 0x60714253 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0xff + ? + PC_PM_ID: 34 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06172435 + TX_LANE_MAP: 0x71605342 + RX_POLARITY_FLIP: 0xed + TX_POLARITY_FLIP: 0xa5 + ? + PC_PM_ID: 35 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x17063524 + TX_LANE_MAP: 0x71605342 + RX_POLARITY_FLIP: 0x5a + TX_POLARITY_FLIP: 0x00 + ? + PC_PM_ID: 36 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06172435 + TX_LANE_MAP: 0x73625140 + RX_POLARITY_FLIP: 0xed + TX_POLARITY_FLIP: 0x0f + ? + PC_PM_ID: 37 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x73512406 + TX_LANE_MAP: 0x26157340 + RX_POLARITY_FLIP: 0x2d + TX_POLARITY_FLIP: 0x3a + ? + PC_PM_ID: 38 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x12560374 + TX_LANE_MAP: 0x16274053 + RX_POLARITY_FLIP: 0x36 + TX_POLARITY_FLIP: 0x63 + ? + PC_PM_ID: 39 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x24056371 + TX_LANE_MAP: 0x27165340 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0x62 + ? + PC_PM_ID: 40 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x24056371 + TX_LANE_MAP: 0x65024713 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0x0e + ? + PC_PM_ID: 41 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x05247163 + TX_LANE_MAP: 0x16274053 + RX_POLARITY_FLIP: 0x4b + TX_POLARITY_FLIP: 0x67 + ? + PC_PM_ID: 42 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x12560374 + TX_LANE_MAP: 0x16274053 + RX_POLARITY_FLIP: 0x36 + TX_POLARITY_FLIP: 0x67 + ? + PC_PM_ID: 43 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x24056371 + TX_LANE_MAP: 0x27165340 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0x62 + ? + PC_PM_ID: 44 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x24056371 + TX_LANE_MAP: 0x65024713 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0x0e + ? + PC_PM_ID: 45 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x05247163 + TX_LANE_MAP: 0x16274053 + RX_POLARITY_FLIP: 0x4b + TX_POLARITY_FLIP: 0x67 + ? + PC_PM_ID: 46 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x12560374 + TX_LANE_MAP: 0x16274053 + RX_POLARITY_FLIP: 0x36 + TX_POLARITY_FLIP: 0x67 + ? + PC_PM_ID: 47 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x24056371 + TX_LANE_MAP: 0x27165340 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0x62 + ? + PC_PM_ID: 48 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x24056371 + TX_LANE_MAP: 0x65024713 + RX_POLARITY_FLIP: 0x1e + TX_POLARITY_FLIP: 0x0e + ? + PC_PM_ID: 49 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x51430726 + TX_LANE_MAP: 0x60531427 + RX_POLARITY_FLIP: 0x12 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 50 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x74125603 + TX_LANE_MAP: 0x60531427 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 51 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x43512607 + TX_LANE_MAP: 0x53602714 + RX_POLARITY_FLIP: 0x48 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 52 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x43512607 + TX_LANE_MAP: 0x02451367 + RX_POLARITY_FLIP: 0x48 + TX_POLARITY_FLIP: 0xd1 + ? + PC_PM_ID: 53 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x51430726 + TX_LANE_MAP: 0x60531427 + RX_POLARITY_FLIP: 0x12 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 54 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x74125603 + TX_LANE_MAP: 0x60531427 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 55 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x43512607 + TX_LANE_MAP: 0x53602714 + RX_POLARITY_FLIP: 0x48 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 56 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x43512607 + TX_LANE_MAP: 0x02451367 + RX_POLARITY_FLIP: 0x48 + TX_POLARITY_FLIP: 0xd1 + ? + PC_PM_ID: 57 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x51430726 + TX_LANE_MAP: 0x60531427 + RX_POLARITY_FLIP: 0x12 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 58 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x74125603 + TX_LANE_MAP: 0x60531427 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 59 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x43512607 + TX_LANE_MAP: 0x53602714 + RX_POLARITY_FLIP: 0x48 + TX_POLARITY_FLIP: 0x8c + ? + PC_PM_ID: 60 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x35247160 + TX_LANE_MAP: 0x12463075 + RX_POLARITY_FLIP: 0x8c + TX_POLARITY_FLIP: 0xf3 + ? + PC_PM_ID: 61 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60714253 + TX_LANE_MAP: 0x17063524 + RX_POLARITY_FLIP: 0xcc + TX_POLARITY_FLIP: 0xa5 + ? + PC_PM_ID: 62 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x51607342 + TX_LANE_MAP: 0x06172435 + RX_POLARITY_FLIP: 0xe1 + TX_POLARITY_FLIP: 0x33 + ? + PC_PM_ID: 63 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60714253 + TX_LANE_MAP: 0x15043726 + RX_POLARITY_FLIP: 0xcc + TX_POLARITY_FLIP: 0x0f + ? + PC_PM_ID: 64 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x71605342 + TX_LANE_MAP: 0x17063524 + RX_POLARITY_FLIP: 0x6b + TX_POLARITY_FLIP: 0x33 +... +--- +device: + 0: + PC_PORT_PHYS_MAP: + ? + PORT_ID: 0 + : + PC_PHYS_PORT_ID: 0 + ? + PORT_ID: 1 + : + PC_PHYS_PORT_ID: 1 + ? + PORT_ID: 2 + : + PC_PHYS_PORT_ID: 9 + ? + PORT_ID: 11 + : + PC_PHYS_PORT_ID: 17 + ? + PORT_ID: 12 + : + PC_PHYS_PORT_ID: 25 + ? + PORT_ID: 22 + : + PC_PHYS_PORT_ID: 33 + ? + PORT_ID: 23 + : + PC_PHYS_PORT_ID: 41 + ? + PORT_ID: 33 + : + PC_PHYS_PORT_ID: 49 + ? + PORT_ID: 34 + : + PC_PHYS_PORT_ID: 57 + ? + PORT_ID: 44 + : + PC_PHYS_PORT_ID: 65 + ? + PORT_ID: 45 + : + PC_PHYS_PORT_ID: 73 + ? + PORT_ID: 55 + : + PC_PHYS_PORT_ID: 81 + ? + PORT_ID: 56 + : + PC_PHYS_PORT_ID: 89 + ? + PORT_ID: 66 + : + PC_PHYS_PORT_ID: 97 + ? + PORT_ID: 67 + : + PC_PHYS_PORT_ID: 105 + ? + PORT_ID: 77 + : + PC_PHYS_PORT_ID: 113 + ? + PORT_ID: 78 + : + PC_PHYS_PORT_ID: 121 + ? + PORT_ID: 88 + : + PC_PHYS_PORT_ID: 129 + ? + PORT_ID: 89 + : + PC_PHYS_PORT_ID: 137 + ? + PORT_ID: 99 + : + PC_PHYS_PORT_ID: 145 + ? + PORT_ID: 100 + : + PC_PHYS_PORT_ID: 153 + ? + PORT_ID: 110 + : + PC_PHYS_PORT_ID: 161 + ? + PORT_ID: 111 + : + PC_PHYS_PORT_ID: 169 + ? + PORT_ID: 121 + : + PC_PHYS_PORT_ID: 177 + ? + PORT_ID: 122 + : + PC_PHYS_PORT_ID: 185 + ? + PORT_ID: 132 + : + PC_PHYS_PORT_ID: 193 + ? + PORT_ID: 133 + : + PC_PHYS_PORT_ID: 201 + ? + PORT_ID: 143 + : + PC_PHYS_PORT_ID: 209 + ? + PORT_ID: 144 + : + PC_PHYS_PORT_ID: 217 + ? + PORT_ID: 154 + : + PC_PHYS_PORT_ID: 225 + ? + PORT_ID: 155 + : + PC_PHYS_PORT_ID: 233 + ? + PORT_ID: 165 + : + PC_PHYS_PORT_ID: 241 + ? + PORT_ID: 166 + : + PC_PHYS_PORT_ID: 249 + ? + PORT_ID: 176 + : + PC_PHYS_PORT_ID: 257 + ? + PORT_ID: 177 + : + PC_PHYS_PORT_ID: 265 + ? + PORT_ID: 187 + : + PC_PHYS_PORT_ID: 273 + ? + PORT_ID: 188 + : + PC_PHYS_PORT_ID: 281 + ? + PORT_ID: 198 + : + PC_PHYS_PORT_ID: 289 + ? + PORT_ID: 199 + : + PC_PHYS_PORT_ID: 297 + ? + PORT_ID: 209 + : + PC_PHYS_PORT_ID: 305 + ? + PORT_ID: 210 + : + PC_PHYS_PORT_ID: 313 + ? + PORT_ID: 220 + : + PC_PHYS_PORT_ID: 321 + ? + PORT_ID: 221 + : + PC_PHYS_PORT_ID: 329 + ? + PORT_ID: 231 + : + PC_PHYS_PORT_ID: 337 + ? + PORT_ID: 232 + : + PC_PHYS_PORT_ID: 345 + ? + PORT_ID: 242 + : + PC_PHYS_PORT_ID: 353 + ? + PORT_ID: 243 + : + PC_PHYS_PORT_ID: 361 + ? + PORT_ID: 253 + : + PC_PHYS_PORT_ID: 369 + ? + PORT_ID: 254 + : + PC_PHYS_PORT_ID: 377 + ? + PORT_ID: 264 + : + PC_PHYS_PORT_ID: 385 + ? + PORT_ID: 265 + : + PC_PHYS_PORT_ID: 393 + ? + PORT_ID: 275 + : + PC_PHYS_PORT_ID: 401 + ? + PORT_ID: 276 + : + PC_PHYS_PORT_ID: 409 + ? + PORT_ID: 286 + : + PC_PHYS_PORT_ID: 417 + ? + PORT_ID: 287 + : + PC_PHYS_PORT_ID: 425 + ? + PORT_ID: 297 + : + PC_PHYS_PORT_ID: 433 + ? + PORT_ID: 298 + : + PC_PHYS_PORT_ID: 441 + ? + PORT_ID: 308 + : + PC_PHYS_PORT_ID: 449 + ? + PORT_ID: 309 + : + PC_PHYS_PORT_ID: 457 + ? + PORT_ID: 319 + : + PC_PHYS_PORT_ID: 465 + ? + PORT_ID: 320 + : + PC_PHYS_PORT_ID: 473 + ? + PORT_ID: 330 + : + PC_PHYS_PORT_ID: 481 + ? + PORT_ID: 331 + : + PC_PHYS_PORT_ID: 489 + ? + PORT_ID: 341 + : + PC_PHYS_PORT_ID: 497 + ? + PORT_ID: 342 + : + PC_PHYS_PORT_ID: 505 + ? + PORT_ID: 76 + : + PC_PHYS_PORT_ID: 513 + ? + PORT_ID: 164 + : + PC_PHYS_PORT_ID: 514 +... +--- +device: + 0: + PC_PORT: + ? + PORT_ID: [[1, 2], [11, 12], [22, 23], [33, 34], [44, 45], [55, 56], [66, 67], [77, 78], [88, 89], [99, 100], [110, 111], [121, 122], [132, 133], [143, 144], [154, 155], [165, 166], [176, 177], [187, 188], [198, 199], [209, 210], [220, 221], [231, 232], [242, 243], [253, 254], [264, 265], [275, 276], [286, 287], [297, 298], [308, 309], [319, 320], [330, 331], [341, 342]] + : + ENABLE: 0 + SPEED: 800000 + NUM_LANES: 8 + FEC_MODE: PC_FEC_RS544_2XN + MAX_FRAME_SIZE: 9416 + ? + PORT_ID: [76, 164] + : + ENABLE: 0 + SPEED: 25000 + NUM_LANES: 1 + FEC_MODE: PC_FEC_NONE + MAX_FRAME_SIZE: 9416 + ? + PORT_ID: 0 + : + ENABLE: 1 + SPEED: 10000 + NUM_LANES: 1 + FEC_MODE: PC_FEC_NONE + + PC_PMD_FIRMWARE: + ? + PORT_ID: [[1, 2], [11, 12], [22, 23], [33, 34], [44, 45], [55, 56], [66, 67], [77, 78], [88, 89], [99, 100], [110, 111], [121, 122], [132, 133], [143, 144], [154, 155], [165, 166], [176, 177], [187, 188], [198, 199], [209, 210], [220, 221], [231, 232], [242, 243], [253, 254], [264, 265], [275, 276], [286, 287], [297, 298], [308, 309], [319, 320], [330, 331], [341, 342]] + : + MEDIUM_TYPE_AUTO: 0 + MEDIUM_TYPE: PC_PHY_MEDIUM_COPPER + NORMAL_REACH_PAM4_AUTO: 1 + NORMAL_REACH_PAM4: 0xff + EXTENDED_REACH_PAM4_AUTO: 1 + EXTENDED_REACH_PAM4: 0xff + LP_TX_PRECODER_ON_AUTO: 1 + LP_TX_PRECODER_ON: 1 +... +--- +device: + 0: + # Per pipe flex counter configuration + CTR_EFLEX_CONFIG: + CTR_ING_EFLEX_OPERMODE_PIPEUNIQUE: 1 + CTR_ING_EFLEX_OPERMODE_PIPE_INSTANCE_UNIQUE: 1 + CTR_EGR_EFLEX_OPERMODE_PIPEUNIQUE: 1 + CTR_EGR_EFLEX_OPERMODE_PIPE_INSTANCE_UNIQUE: 1 + + # IFP mode + FP_CONFIG: + FP_ING_OPERMODE: GLOBAL_PIPE_AWARE + + DEVICE_CONFIG: + AUTOLOAD_BOARD_SETTINGS: 0 +... diff --git a/device/accton/x86_64-accton_as9817_64d-r0/custom_led.bin b/device/accton/x86_64-accton_as9817_64d-r0/custom_led.bin new file mode 100644 index 000000000000..2c2790d0f33d Binary files /dev/null and b/device/accton/x86_64-accton_as9817_64d-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as9817_64d-r0/default_sku b/device/accton/x86_64-accton_as9817_64d-r0/default_sku new file mode 100644 index 000000000000..6e95ff11aaf6 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/default_sku @@ -0,0 +1 @@ +Accton-AS9817-64D t1 diff --git a/device/accton/x86_64-accton_as9817_64d-r0/fast-reboot_plugin b/device/accton/x86_64-accton_as9817_64d-r0/fast-reboot_plugin new file mode 120000 index 000000000000..295bfa58fbf3 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/fast-reboot_plugin @@ -0,0 +1 @@ +warm-reboot_plugin \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/installer.conf b/device/accton/x86_64-accton_as9817_64d-r0/installer.conf new file mode 100644 index 000000000000..f16c4fd21270 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off pcie_aspm=off modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801,ast,ice" diff --git a/device/accton/x86_64-accton_as9817_64d-r0/led_proc_init.soc b/device/accton/x86_64-accton_as9817_64d-r0/led_proc_init.soc new file mode 100644 index 000000000000..ee89b29b479e --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/led_proc_init.soc @@ -0,0 +1,3 @@ +led 0 load /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/accton/x86_64-accton_as9817_64d-r0/pcie.yaml b/device/accton/x86_64-accton_as9817_64d-r0/pcie.yaml new file mode 100644 index 000000000000..dece12c1c957 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/pcie.yaml @@ -0,0 +1,452 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 09a2 + name: 'System peripheral: Intel Corporation Ice Lake Memory Map/VT-d (rev 04)' +- bus: '00' + dev: '00' + fn: '1' + id: 09a4 + name: 'System peripheral: Intel Corporation Ice Lake Mesh 2 PCIe (rev 04)' +- bus: '00' + dev: '00' + fn: '2' + id: 09a3 + name: 'System peripheral: Intel Corporation Ice Lake RAS (rev 04)' +- bus: '00' + dev: '00' + fn: '3' + id: 09a5 + name: 'System peripheral: Intel Corporation Device 09a5 (rev 04)' +- bus: '00' + dev: '00' + fn: '4' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: '00' + dev: '01' + fn: '0' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '1' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '2' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '3' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '4' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '5' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '6' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '7' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '02' + fn: '0' + id: 09a6 + name: 'System peripheral: Intel Corporation Ice Lake MSM' +- bus: '00' + dev: '02' + fn: '1' + id: 09a7 + name: 'System peripheral: Intel Corporation Ice Lake PMON MSM' +- bus: '00' + dev: '02' + fn: '4' + id: '3456' + name: 'Non-Essential Instrumentation [1300]: Intel Corporation Ice Lake NorthPeak + (rev 01)' +- bus: '00' + dev: '06' + fn: '0' + id: 18da + name: 'PCI bridge: Intel Corporation Device 18da (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 18a4 + name: 'PCI bridge: Intel Corporation Device 18a4 (rev 11)' +- bus: '00' + dev: 0b + fn: '0' + id: 18a6 + name: 'PCI bridge: Intel Corporation Device 18a6 (rev 11)' +- bus: '00' + dev: 0e + fn: '0' + id: 18f2 + name: 'SATA controller: Intel Corporation Device 18f2 (rev 11)' +- bus: '00' + dev: 0f + fn: '0' + id: 18ac + name: 'System peripheral: Intel Corporation Device 18ac (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 18a8 + name: 'PCI bridge: Intel Corporation Device 18a8 (rev 11)' +- bus: '00' + dev: '14' + fn: '0' + id: 18ad + name: 'PCI bridge: Intel Corporation Device 18ad (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 18d3 + name: 'Communication controller: Intel Corporation Device 18d3 (rev 11)' +- bus: '00' + dev: '18' + fn: '1' + id: 18d4 + name: 'Communication controller: Intel Corporation Device 18d4 (rev 11)' +- bus: '00' + dev: '18' + fn: '4' + id: 18d6 + name: 'Communication controller: Intel Corporation Device 18d6 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 18d8 + name: 'Serial controller: Intel Corporation Device 18d8 (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 18d8 + name: 'Serial controller: Intel Corporation Device 18d8 (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 18d8 + name: 'Serial controller: Intel Corporation Device 18d8 (rev 11)' +- bus: '00' + dev: 1a + fn: '3' + id: 18d9 + name: 'Unassigned class [ff00]: Intel Corporation Device 18d9 (rev 11)' +- bus: '00' + dev: 1d + fn: '0' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: '00' + dev: 1e + fn: '0' + id: 18d0 + name: 'USB controller: Intel Corporation Device 18d0 (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 18dc + name: 'ISA bridge: Intel Corporation Device 18dc (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 18df + name: 'SMBus: Intel Corporation Device 18df (rev 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 18e0 + name: 'Serial bus controller: Intel Corporation Device 18e0 (rev 11)' +- bus: '00' + dev: 1f + fn: '7' + id: 18e1 + name: 'Non-Essential Instrumentation [1300]: Intel Corporation Device 18e1 (rev + 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 18ee + name: 'Co-processor: Intel Corporation 200xx Series QAT (rev 11)' +- bus: '02' + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: '03' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '04' + dev: '00' + fn: '0' + id: '1150' + name: 'PCI bridge: ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge (rev 06)' +- bus: '05' + dev: '00' + fn: '0' + id: '2000' + name: 'VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family + (rev 52)' +- bus: '06' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '14' + dev: '00' + fn: '0' + id: 09a2 + name: 'System peripheral: Intel Corporation Ice Lake Memory Map/VT-d (rev 04)' +- bus: '14' + dev: '00' + fn: '1' + id: 09a4 + name: 'System peripheral: Intel Corporation Ice Lake Mesh 2 PCIe (rev 04)' +- bus: '14' + dev: '00' + fn: '2' + id: 09a3 + name: 'System peripheral: Intel Corporation Ice Lake RAS (rev 04)' +- bus: '14' + dev: '00' + fn: '3' + id: 09a5 + name: 'System peripheral: Intel Corporation Device 09a5 (rev 04)' +- bus: '14' + dev: '00' + fn: '4' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: '14' + dev: '02' + fn: '0' + id: 347a + name: 'PCI bridge: Intel Corporation Device 347a (rev 06)' +- bus: '14' + dev: '03' + fn: '0' + id: 347b + name: 'PCI bridge: Intel Corporation Device 347b (rev 06)' +- bus: '15' + dev: '00' + fn: '0' + id: f900 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM78900 Switch ASIC + [Tomahawk5] (rev 11)' +- bus: '16' + dev: '00' + fn: '0' + id: '5013' + name: 'Non-Volatile memory controller: Phison Electronics Corporation PS5013 E13 + NVMe Controller (rev 01)' +- bus: f3 + dev: '00' + fn: '0' + id: 09a2 + name: 'System peripheral: Intel Corporation Ice Lake Memory Map/VT-d (rev 04)' +- bus: f3 + dev: '00' + fn: '1' + id: 09a4 + name: 'System peripheral: Intel Corporation Ice Lake Mesh 2 PCIe (rev 04)' +- bus: f3 + dev: '00' + fn: '2' + id: 09a3 + name: 'System peripheral: Intel Corporation Ice Lake RAS (rev 04)' +- bus: f3 + dev: '00' + fn: '3' + id: 09a5 + name: 'System peripheral: Intel Corporation Device 09a5 (rev 04)' +- bus: f3 + dev: '00' + fn: '4' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: f3 + dev: '04' + fn: '0' + id: 18d1 + name: 'PCI bridge: Intel Corporation Device 18d1' +- bus: f4 + dev: '00' + fn: '0' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: f4 + dev: '00' + fn: '1' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: f4 + dev: '00' + fn: '2' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: f4 + dev: '00' + fn: '3' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: fe + dev: '00' + fn: '0' + id: '3450' + name: 'System peripheral: Intel Corporation Device 3450' +- bus: fe + dev: '00' + fn: '1' + id: '3451' + name: 'System peripheral: Intel Corporation Device 3451' +- bus: fe + dev: '00' + fn: '2' + id: '3452' + name: 'System peripheral: Intel Corporation Device 3452' +- bus: fe + dev: '00' + fn: '3' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: fe + dev: '00' + fn: '5' + id: '3455' + name: 'System peripheral: Intel Corporation Device 3455' +- bus: fe + dev: 0b + fn: '0' + id: '3448' + name: 'System peripheral: Intel Corporation Device 3448' +- bus: fe + dev: 0b + fn: '1' + id: '3448' + name: 'System peripheral: Intel Corporation Device 3448' +- bus: fe + dev: 0b + fn: '2' + id: 344b + name: 'System peripheral: Intel Corporation Device 344b' +- bus: fe + dev: 0c + fn: '0' + id: 344a + name: 'Performance counters: Intel Corporation Device 344a' +- bus: fe + dev: 1a + fn: '0' + id: '2880' + name: 'Performance counters: Intel Corporation Device 2880' +- bus: ff + dev: '00' + fn: '0' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: '00' + fn: '1' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: '00' + fn: '2' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: '00' + fn: '3' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: 0a + fn: '0' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 0a + fn: '1' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 0a + fn: '2' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 0a + fn: '3' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 1d + fn: '0' + id: 344f + name: 'System peripheral: Intel Corporation Device 344f' +- bus: ff + dev: 1d + fn: '1' + id: '3457' + name: 'System peripheral: Intel Corporation Device 3457' +- bus: ff + dev: 1e + fn: '0' + id: '3458' + name: 'System peripheral: Intel Corporation Device 3458 (rev 01)' +- bus: ff + dev: 1e + fn: '1' + id: '3459' + name: 'System peripheral: Intel Corporation Device 3459 (rev 01)' +- bus: ff + dev: 1e + fn: '2' + id: 345a + name: 'System peripheral: Intel Corporation Device 345a (rev 01)' +- bus: ff + dev: 1e + fn: '3' + id: 345b + name: 'System peripheral: Intel Corporation Device 345b (rev 01)' +- bus: ff + dev: 1e + fn: '4' + id: 345c + name: 'System peripheral: Intel Corporation Device 345c (rev 01)' +- bus: ff + dev: 1e + fn: '5' + id: 345d + name: 'System peripheral: Intel Corporation Device 345d (rev 01)' +- bus: ff + dev: 1e + fn: '6' + id: 345e + name: 'System peripheral: Intel Corporation Device 345e (rev 01)' +- bus: ff + dev: 1e + fn: '7' + id: 345f + name: 'System peripheral: Intel Corporation Device 345f (rev 01)' diff --git a/device/accton/x86_64-accton_as9817_64d-r0/platform.json b/device/accton/x86_64-accton_as9817_64d-r0/platform.json new file mode 100644 index 000000000000..685b5bfff81c --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/platform.json @@ -0,0 +1,1523 @@ +{ + "chassis": { + "name": "AS9817-64D", + "thermal_manager":false, + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_RED", "STATUS_LED_COLOR_OFF"] + }, + "components": [ + { + "name": "CPLD1" + }, + { + "name": "CPLD2" + }, + { + "name": "CPLD3" + }, + { + "name": "FPGA" + }, + { + "name": "BIOS" + } + ], + "fans": [ + { + "name": "FAN-1F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-1R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-1F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-1R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray2", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-2F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray3", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-3F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray4", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-4F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + } + ], + "psus": [ + { + "name": "PSU-1", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU-1 FAN-1", + "speed": { + "controllable": false + }, + "status_led": { + "controllable": false + } + } + ], + "thermals": [ + { + "name": "PSU-1 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-1 temp sensor 2", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-1 temp sensor 3", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + }, + { + "name": "PSU-2", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU-2 FAN-1", + "speed": { + "controllable": false + }, + "status_led": { + "controllable": false + } + } + ], + "thermals": [ + { + "name": "PSU-2 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-2 temp sensor 2", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-2 temp sensor 3", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + } + ], + "thermals": [ + { + "name": "MB_RearCenter_temp(0x48)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearRight_temp(0x49)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearCenter_temp(0x4A)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearLeft_temp(0x4B)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_FrontLeft_temp(0x4C)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_FrontRight_temp(0x4D)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "FB_temp(0x4D)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "FB_temp(0x4E)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "CPU_Package_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_0_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_1_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_2_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_3_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + } + ], + "sfps": [ + { + "name": "Ethernet0" + }, + { + "name": "Ethernet8" + }, + { + "name": "Ethernet16" + }, + { + "name": "Ethernet24" + }, + { + "name": "Ethernet32" + }, + { + "name": "Ethernet40" + }, + { + "name": "Ethernet48" + }, + { + "name": "Ethernet56" + }, + { + "name": "Ethernet64" + }, + { + "name": "Ethernet72" + }, + { + "name": "Ethernet80" + }, + { + "name": "Ethernet88" + }, + { + "name": "Ethernet96" + }, + { + "name": "Ethernet104" + }, + { + "name": "Ethernet112" + }, + { + "name": "Ethernet120" + }, + { + "name": "Ethernet128" + }, + { + "name": "Ethernet136" + }, + { + "name": "Ethernet144" + }, + { + "name": "Ethernet152" + }, + { + "name": "Ethernet160" + }, + { + "name": "Ethernet168" + }, + { + "name": "Ethernet176" + }, + { + "name": "Ethernet184" + }, + { + "name": "Ethernet192" + }, + { + "name": "Ethernet200" + }, + { + "name": "Ethernet208" + }, + { + "name": "Ethernet216" + }, + { + "name": "Ethernet224" + }, + { + "name": "Ethernet232" + }, + { + "name": "Ethernet240" + }, + { + "name": "Ethernet248" + }, + { + "name": "Ethernet256" + }, + { + "name": "Ethernet264" + }, + { + "name": "Ethernet272" + }, + { + "name": "Ethernet280" + }, + { + "name": "Ethernet288" + }, + { + "name": "Ethernet296" + }, + { + "name": "Ethernet304" + }, + { + "name": "Ethernet312" + }, + { + "name": "Ethernet320" + }, + { + "name": "Ethernet328" + }, + { + "name": "Ethernet336" + }, + { + "name": "Ethernet344" + }, + { + "name": "Ethernet352" + }, + { + "name": "Ethernet360" + }, + { + "name": "Ethernet368" + }, + { + "name": "Ethernet376" + }, + { + "name": "Ethernet384" + }, + { + "name": "Ethernet392" + }, + { + "name": "Ethernet400" + }, + { + "name": "Ethernet408" + }, + { + "name": "Ethernet416" + }, + { + "name": "Ethernet424" + }, + { + "name": "Ethernet432" + }, + { + "name": "Ethernet440" + }, + { + "name": "Ethernet448" + }, + { + "name": "Ethernet456" + }, + { + "name": "Ethernet464" + }, + { + "name": "Ethernet472" + }, + { + "name": "Ethernet480" + }, + { + "name": "Ethernet488" + }, + { + "name": "Ethernet496" + }, + { + "name": "Ethernet504" + }, + { + "name": "Ethernet512" + }, + { + "name": "Ethernet513" + } + ] + }, + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1,1,1,1,1", + "lanes": "1,2,3,4,5,6,7,8", + "breakout_modes": { + "1x800G": ["Eth1(Port1)"], + "1x400G": ["Eth1(Port1)"], + "2x400G[200G]": ["Eth1/1(Port1)", "Eth1/2(Port1)"], + "4x200G[100G]": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"], + "4x100G[50G](4)": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"], + "1x100G(4)": ["Eth1(Port1)"], + "2x50G(4)": ["Eth1/1(Port1)", "Eth1/2(Port1)"] + } + }, + + "Ethernet8": { + "index": "2,2,2,2,2,2,2,2", + "lanes": "9,10,11,12,13,14,15,16", + "breakout_modes": { + "1x800G": ["Eth2(Port2)"], + "1x400G": ["Eth2(Port2)"], + "2x400G[200G]": ["Eth2/1(Port2)", "Eth2/2(Port2)"], + "4x200G[100G]": ["Eth2/1(Port2)", "Eth2/2(Port2)", "Eth2/3(Port2)", "Eth2/4(Port2)"], + "4x100G[50G](4)": ["Eth2/1(Port2)", "Eth2/2(Port2)", "Eth2/3(Port2)", "Eth2/4(Port2)"], + "1x100G(4)": ["Eth2(Port2)"], + "2x50G(4)": ["Eth2/1(Port2)", "Eth2/2(Port2)"] + } + }, + + "Ethernet16": { + "index": "3,3,3,3,3,3,3,3", + "lanes": "41,42,43,44,45,46,47,48", + "breakout_modes": { + "1x800G": ["Eth3(Port3)"], + "1x400G": ["Eth3(Port3)"], + "2x400G[200G]": ["Eth3/1(Port3)", "Eth3/2(Port3)"], + "4x200G[100G]": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"], + "4x100G[50G](4)": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"], + "1x100G(4)": ["Eth3(Port3)"], + "2x50G(4)": ["Eth3/1(Port3)", "Eth3/2(Port3)"] + } + }, + + "Ethernet24": { + "index": "4,4,4,4,4,4,4,4", + "lanes": "33,34,35,36,37,38,39,40", + "breakout_modes": { + "1x800G": ["Eth4(Port4)"], + "1x400G": ["Eth4(Port4)"], + "2x400G[200G]": ["Eth4/1(Port4)", "Eth4/2(Port4)"], + "4x200G[100G]": ["Eth4/1(Port4)", "Eth4/2(Port4)", "Eth4/3(Port4)", "Eth4/4(Port4)"], + "4x100G[50G](4)": ["Eth4/1(Port4)", "Eth4/2(Port4)", "Eth4/3(Port4)", "Eth4/4(Port4)"], + "1x100G(4)": ["Eth4(Port4)"], + "2x50G(4)": ["Eth4/1(Port4)", "Eth4/2(Port4)"] + } + }, + + "Ethernet32": { + "index": "5,5,5,5,5,5,5,5", + "lanes": "73,74,75,76,77,78,79,80", + "breakout_modes": { + "1x800G": ["Eth5(Port5)"], + "1x400G": ["Eth5(Port5)"], + "2x400G[200G]": ["Eth5/1(Port5)", "Eth5/2(Port5)"], + "4x200G[100G]": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"], + "4x100G[50G](4)": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"], + "1x100G(4)": ["Eth5(Port5)"], + "2x50G(4)": ["Eth5/1(Port5)", "Eth5/2(Port5)"] + } + }, + + "Ethernet40": { + "index": "6,6,6,6,6,6,6,6", + "lanes": "65,66,67,68,69,70,71,72", + "breakout_modes": { + "1x800G": ["Eth6(Port6)"], + "1x400G": ["Eth6(Port6)"], + "2x400G[200G]": ["Eth6/1(Port6)", "Eth6/2(Port6)"], + "4x200G[100G]": ["Eth6/1(Port6)", "Eth6/2(Port6)", "Eth6/3(Port6)", "Eth6/4(Port6)"], + "4x100G[50G](4)": ["Eth6/1(Port6)", "Eth6/2(Port6)", "Eth6/3(Port6)", "Eth6/4(Port6)"], + "1x100G(4)": ["Eth6(Port6)"], + "2x50G(4)": ["Eth6/1(Port6)", "Eth6/2(Port6)"] + } + }, + + "Ethernet48": { + "index": "7,7,7,7,7,7,7,7", + "lanes": "105,106,107,108,109,110,111,112", + "breakout_modes": { + "1x800G": ["Eth7(Port7)"], + "1x400G": ["Eth7(Port7)"], + "2x400G[200G]": ["Eth7/1(Port7)", "Eth7/2(Port7)"], + "4x200G[100G]": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"], + "4x100G[50G](4)": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"], + "1x100G(4)": ["Eth7(Port7)"], + "2x50G(4)": ["Eth7/1(Port7)", "Eth7/2(Port7)"] + } + }, + + "Ethernet56": { + "index": "8,8,8,8,8,8,8,8", + "lanes": "97,98,99,100,101,102,103,104", + "breakout_modes": { + "1x800G": ["Eth8(Port8)"], + "1x400G": ["Eth8(Port8)"], + "2x400G[200G]": ["Eth8/1(Port8)", "Eth8/2(Port8)"], + "4x200G[100G]": ["Eth8/1(Port8)", "Eth8/2(Port8)", "Eth8/3(Port8)", "Eth8/4(Port8)"], + "4x100G[50G](4)": ["Eth8/1(Port8)", "Eth8/2(Port8)", "Eth8/3(Port8)", "Eth8/4(Port8)"], + "1x100G(4)": ["Eth8(Port8)"], + "2x50G(4)": ["Eth8/1(Port8)", "Eth8/2(Port8)"] + } + }, + + "Ethernet64": { + "index": "9,9,9,9,9,9,9,9", + "lanes": "137,138,139,140,141,142,143,144", + "breakout_modes": { + "1x800G": ["Eth9(Port9)"], + "1x400G": ["Eth9(Port9)"], + "2x400G[200G]": ["Eth9/1(Port9)", "Eth9/2(Port9)"], + "4x200G[100G]": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"], + "4x100G[50G](4)": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"], + "1x100G(4)": ["Eth9(Port9)"], + "2x50G(4)": ["Eth9/1(Port9)", "Eth9/2(Port9)"] + } + }, + + "Ethernet72": { + "index": "10,10,10,10,10,10,10,10", + "lanes": "129,130,131,132,133,134,135,136", + "breakout_modes": { + "1x800G": ["Eth10(Port10)"], + "1x400G": ["Eth10(Port10)"], + "2x400G[200G]": ["Eth10/1(Port10)", "Eth10/2(Port10)"], + "4x200G[100G]": ["Eth10/1(Port10)", "Eth10/2(Port10)", "Eth10/3(Port10)", "Eth10/4(Port10)"], + "4x100G[50G](4)": ["Eth10/1(Port10)", "Eth10/2(Port10)", "Eth10/3(Port10)", "Eth10/4(Port10)"], + "1x100G(4)": ["Eth10(Port10)"], + "2x50G(4)": ["Eth10/1(Port10)", "Eth10/2(Port10)"] + } + }, + + "Ethernet80": { + "index": "11,11,11,11,11,11,11,11", + "lanes": "169,170,171,172,173,174,175,176", + "breakout_modes": { + "1x800G": ["Eth11(Port11)"], + "1x400G": ["Eth11(Port11)"], + "2x400G[200G]": ["Eth11/1(Port11)", "Eth11/2(Port11)"], + "4x200G[100G]": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"], + "4x100G[50G](4)": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"], + "1x100G(4)": ["Eth11(Port11)"], + "2x50G(4)": ["Eth11/1(Port11)", "Eth11/2(Port11)"] + } + }, + + "Ethernet88": { + "index": "12,12,12,12,12,12,12,12", + "lanes": "161,162,163,164,165,166,167,168", + "breakout_modes": { + "1x800G": ["Eth12(Port12)"], + "1x400G": ["Eth12(Port12)"], + "2x400G[200G]": ["Eth12/1(Port12)", "Eth12/2(Port12)"], + "4x200G[100G]": ["Eth12/1(Port12)", "Eth12/2(Port12)", "Eth12/3(Port12)", "Eth12/4(Port12)"], + "4x100G[50G](4)": ["Eth12/1(Port12)", "Eth12/2(Port12)", "Eth12/3(Port12)", "Eth12/4(Port12)"], + "1x100G(4)": ["Eth12(Port12)"], + "2x50G(4)": ["Eth12/1(Port12)", "Eth12/2(Port12)"] + } + }, + + "Ethernet96": { + "index": "13,13,13,13,13,13,13,13", + "lanes": "201,202,203,204,205,206,207,208", + "breakout_modes": { + "1x800G": ["Eth13(Port13)"], + "1x400G": ["Eth13(Port13)"], + "2x400G[200G]": ["Eth13/1(Port13)", "Eth13/2(Port13)"], + "4x200G[100G]": ["Eth13/1(Port13)", "Eth13/2(Port13)", "Eth13/3(Port13)", "Eth13/4(Port13)"], + "4x100G[50G](4)": ["Eth13/1(Port13)", "Eth13/2(Port13)", "Eth13/3(Port13)", "Eth13/4(Port13)"], + "1x100G(4)": ["Eth13(Port13)"], + "2x50G(4)": ["Eth13/1(Port13)", "Eth13/2(Port13)"] + } + }, + + "Ethernet104": { + "index": "14,14,14,14,14,14,14,14", + "lanes": "193,194,195,196,197,198,199,200", + "breakout_modes": { + "1x800G": ["Eth14(Port14)"], + "1x400G": ["Eth14(Port14)"], + "2x400G[200G]": ["Eth14/1(Port14)", "Eth14/2(Port14)"], + "4x200G[100G]": ["Eth14/1(Port14)", "Eth14/2(Port14)", "Eth14/3(Port14)", "Eth14/4(Port14)"], + "4x100G[50G](4)": ["Eth14/1(Port14)", "Eth14/2(Port14)", "Eth14/3(Port14)", "Eth14/4(Port14)"], + "1x100G(4)": ["Eth14(Port14)"], + "2x50G(4)": ["Eth14/1(Port14)", "Eth14/2(Port14)"] + } + }, + + "Ethernet112": { + "index": "15,15,15,15,15,15,15,15", + "lanes": "233,234,235,236,237,238,239,240", + "breakout_modes": { + "1x800G": ["Eth15(Port15)"], + "1x400G": ["Eth15(Port15)"], + "2x400G[200G]": ["Eth15/1(Port15)", "Eth15/2(Port15)"], + "4x200G[100G]": ["Eth15/1(Port15)", "Eth15/2(Port15)", "Eth15/3(Port15)", "Eth15/4(Port15)"], + "4x100G[50G](4)": ["Eth15/1(Port15)", "Eth15/2(Port15)", "Eth15/3(Port15)", "Eth15/4(Port15)"], + "1x100G(4)": ["Eth15(Port15)"], + "2x50G(4)": ["Eth15/1(Port15)", "Eth15/2(Port15)"] + } + }, + + "Ethernet120": { + "index": "16,16,16,16,16,16,16,16", + "lanes": "225,226,227,228,229,230,231,232", + "breakout_modes": { + "1x800G": ["Eth16(Port16)"], + "1x400G": ["Eth16(Port16)"], + "2x400G[200G]": ["Eth16/1(Port16)", "Eth16/2(Port16)"], + "4x200G[100G]": ["Eth16/1(Port16)", "Eth16/2(Port16)", "Eth16/3(Port16)", "Eth16/4(Port16)"], + "4x100G[50G](4)": ["Eth16/1(Port16)", "Eth16/2(Port16)", "Eth16/3(Port16)", "Eth16/4(Port16)"], + "1x100G(4)": ["Eth16(Port16)"], + "2x50G(4)": ["Eth16/1(Port16)", "Eth16/2(Port16)"] + } + }, + + "Ethernet128": { + "index": "17,17,17,17,17,17,17,17", + "lanes": "257,258,259,260,261,262,263,264", + "breakout_modes": { + "1x800G": ["Eth17(Port17)"], + "1x400G": ["Eth17(Port17)"], + "2x400G[200G]": ["Eth17/1(Port17)", "Eth17/2(Port17)"], + "4x200G[100G]": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"], + "4x100G[50G](4)": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"], + "1x100G(4)": ["Eth17(Port17)"], + "2x50G(4)": ["Eth17/1(Port17)", "Eth17/2(Port17)"] + } + }, + + "Ethernet136": { + "index": "18,18,18,18,18,18,18,18", + "lanes": "265,266,267,268,269,270,271,272", + "breakout_modes": { + "1x800G": ["Eth18(Port18)"], + "1x400G": ["Eth18(Port18)"], + "2x400G[200G]": ["Eth18/1(Port18)", "Eth18/2(Port18)"], + "4x200G[100G]": ["Eth18/1(Port18)", "Eth18/2(Port18)", "Eth18/3(Port18)", "Eth18/4(Port18)"], + "4x100G[50G](4)": ["Eth18/1(Port18)", "Eth18/2(Port18)", "Eth18/3(Port18)", "Eth18/4(Port18)"], + "1x100G(4)": ["Eth18(Port18)"], + "2x50G(4)": ["Eth18/1(Port18)", "Eth18/2(Port18)"] + } + }, + + "Ethernet144": { + "index": "19,19,19,19,19,19,19,19", + "lanes": "297,298,299,300,301,302,303,304", + "breakout_modes": { + "1x800G": ["Eth19(Port19)"], + "1x400G": ["Eth19(Port19)"], + "2x400G[200G]": ["Eth19/1(Port19)", "Eth19/2(Port19)"], + "4x200G[100G]": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"], + "4x100G[50G](4)": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"], + "1x100G(4)": ["Eth19(Port19)"], + "2x50G(4)": ["Eth19/1(Port19)", "Eth19/2(Port19)"] + } + }, + + "Ethernet152": { + "index": "20,20,20,20,20,20,20,20", + "lanes": "289,290,291,292,293,294,295,296", + "breakout_modes": { + "1x800G": ["Eth20(Port20)"], + "1x400G": ["Eth20(Port20)"], + "2x400G[200G]": ["Eth20/1(Port20)", "Eth20/2(Port20)"], + "4x200G[100G]": ["Eth20/1(Port20)", "Eth20/2(Port20)", "Eth20/3(Port20)", "Eth20/4(Port20)"], + "4x100G[50G](4)": ["Eth20/1(Port20)", "Eth20/2(Port20)", "Eth20/3(Port20)", "Eth20/4(Port20)"], + "1x100G(4)": ["Eth20(Port20)"], + "2x50G(4)": ["Eth20/1(Port20)", "Eth20/2(Port20)"] + } + }, + + "Ethernet160": { + "index": "21,21,21,21,21,21,21,21", + "lanes": "329,330,331,332,333,334,335,336", + "breakout_modes": { + "1x800G": ["Eth21(Port21)"], + "1x400G": ["Eth21(Port21)"], + "2x400G[200G]": ["Eth21/1(Port21)", "Eth21/2(Port21)"], + "4x200G[100G]": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"], + "4x100G[50G](4)": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"], + "1x100G(4)": ["Eth21(Port21)"], + "2x50G(4)": ["Eth21/1(Port21)", "Eth21/2(Port21)"] + } + }, + + "Ethernet168": { + "index": "22,22,22,22,22,22,22,22", + "lanes": "321,322,323,324,325,326,327,328", + "breakout_modes": { + "1x800G": ["Eth22(Port22)"], + "1x400G": ["Eth22(Port22)"], + "2x400G[200G]": ["Eth22/1(Port22)", "Eth22/2(Port22)"], + "4x200G[100G]": ["Eth22/1(Port22)", "Eth22/2(Port22)", "Eth22/3(Port22)", "Eth22/4(Port22)"], + "4x100G[50G](4)": ["Eth22/1(Port22)", "Eth22/2(Port22)", "Eth22/3(Port22)", "Eth22/4(Port22)"], + "1x100G(4)": ["Eth22(Port22)"], + "2x50G(4)": ["Eth22/1(Port22)", "Eth22/2(Port22)"] + } + }, + + "Ethernet176": { + "index": "23,23,23,23,23,23,23,23", + "lanes": "361,362,363,364,365,366,367,368", + "breakout_modes": { + "1x800G": ["Eth23(Port23)"], + "1x400G": ["Eth23(Port23)"], + "2x400G[200G]": ["Eth23/1(Port23)", "Eth23/2(Port23)"], + "4x200G[100G]": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"], + "4x100G[50G](4)": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"], + "1x100G(4)": ["Eth23(Port23)"], + "2x50G(4)": ["Eth23/1(Port23)", "Eth23/2(Port23)"] + } + }, + + "Ethernet184": { + "index": "24,24,24,24,24,24,24,24", + "lanes": "353,354,355,356,357,358,359,360", + "breakout_modes": { + "1x800G": ["Eth24(Port24)"], + "1x400G": ["Eth24(Port24)"], + "2x400G[200G]": ["Eth24/1(Port24)", "Eth24/2(Port24)"], + "4x200G[100G]": ["Eth24/1(Port24)", "Eth24/2(Port24)", "Eth24/3(Port24)", "Eth24/4(Port24)"], + "4x100G[50G](4)": ["Eth24/1(Port24)", "Eth24/2(Port24)", "Eth24/3(Port24)", "Eth24/4(Port24)"], + "1x100G(4)": ["Eth24(Port24)"], + "2x50G(4)": ["Eth24/1(Port24)", "Eth24/2(Port24)"] + } + }, + + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "393,394,395,396,397,398,399,400", + "breakout_modes": { + "1x800G": ["Eth25(Port25)"], + "1x400G": ["Eth25(Port25)"], + "2x400G[200G]": ["Eth25/1(Port25)", "Eth25/2(Port25)"], + "4x200G[100G]": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"], + "4x100G[50G](4)": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"], + "1x100G(4)": ["Eth25(Port25)"], + "2x50G(4)": ["Eth25/1(Port25)", "Eth25/2(Port25)"] + } + }, + + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "385,386,387,388,389,390,391,392", + "breakout_modes": { + "1x800G": ["Eth26(Port26)"], + "1x400G": ["Eth26(Port26)"], + "2x400G[200G]": ["Eth26/1(Port26)", "Eth26/2(Port26)"], + "4x200G[100G]": ["Eth26/1(Port26)", "Eth26/2(Port26)", "Eth26/3(Port26)", "Eth26/4(Port26)"], + "4x100G[50G](4)": ["Eth26/1(Port26)", "Eth26/2(Port26)", "Eth26/3(Port26)", "Eth26/4(Port26)"], + "1x100G(4)": ["Eth26(Port26)"], + "2x50G(4)": ["Eth26/1(Port26)", "Eth26/2(Port26)"] + } + }, + + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "425,426,427,428,429,430,431,432", + "breakout_modes": { + "1x800G": ["Eth27(Port27)"], + "1x400G": ["Eth27(Port27)"], + "2x400G[200G]": ["Eth27/1(Port27)", "Eth27/2(Port27)"], + "4x200G[100G]": ["Eth27/1(Port27)", "Eth27/2(Port27)", "Eth27/3(Port27)", "Eth27/4(Port27)"], + "4x100G[50G](4)": ["Eth27/1(Port27)", "Eth27/2(Port27)", "Eth27/3(Port27)", "Eth27/4(Port27)"], + "1x100G(4)": ["Eth27(Port27)"], + "2x50G(4)": ["Eth27/1(Port27)", "Eth27/2(Port27)"] + } + }, + + "Ethernet216": { + "index": "28,28,28,28,28,28,28,28", + "lanes": "417,418,419,420,421,422,423,424", + "breakout_modes": { + "1x800G": ["Eth28(Port28)"], + "1x400G": ["Eth28(Port28)"], + "2x400G[200G]": ["Eth28/1(Port28)", "Eth28/2(Port28)"], + "4x200G[100G]": ["Eth28/1(Port28)", "Eth28/2(Port28)", "Eth28/3(Port28)", "Eth28/4(Port28)"], + "4x100G[50G](4)": ["Eth28/1(Port28)", "Eth28/2(Port28)", "Eth28/3(Port28)", "Eth28/4(Port28)"], + "1x100G(4)": ["Eth28(Port28)"], + "2x50G(4)": ["Eth28/1(Port28)", "Eth28/2(Port28)"] + } + }, + + "Ethernet224": { + "index": "29,29,29,29,29,29,29,29", + "lanes": "457,458,459,460,461,462,463,464", + "breakout_modes": { + "1x800G": ["Eth29(Port29)"], + "1x400G": ["Eth29(Port29)"], + "2x400G[200G]": ["Eth29/1(Port29)", "Eth29/2(Port29)"], + "4x200G[100G]": ["Eth29/1(Port29)", "Eth29/2(Port29)", "Eth29/3(Port29)", "Eth29/4(Port29)"], + "4x100G[50G](4)": ["Eth29/1(Port29)", "Eth29/2(Port29)", "Eth29/3(Port29)", "Eth29/4(Port29)"], + "1x100G(4)": ["Eth29(Port29)"], + "2x50G(4)": ["Eth29/1(Port29)", "Eth29/2(Port29)"] + } + }, + + "Ethernet232": { + "index": "30,30,30,30,30,30,30,30", + "lanes": "449,450,451,452,453,454,455,456", + "breakout_modes": { + "1x800G": ["Eth30(Port30)"], + "1x400G": ["Eth30(Port30)"], + "2x400G[200G]": ["Eth30/1(Port30)", "Eth30/2(Port30)"], + "4x200G[100G]": ["Eth30/1(Port30)", "Eth30/2(Port30)", "Eth30/3(Port30)", "Eth30/4(Port30)"], + "4x100G[50G](4)": ["Eth30/1(Port30)", "Eth30/2(Port30)", "Eth30/3(Port30)", "Eth30/4(Port30)"], + "1x100G(4)": ["Eth30(Port30)"], + "2x50G(4)": ["Eth30/1(Port30)", "Eth30/2(Port30)"] + } + }, + + "Ethernet240": { + "index": "31,31,31,31,31,31,31,31", + "lanes": "489,490,491,492,493,494,495,496", + "breakout_modes": { + "1x800G": ["Eth31(Port31)"], + "1x400G": ["Eth31(Port31)"], + "2x400G[200G]": ["Eth31/1(Port31)", "Eth31/2(Port31)"], + "4x200G[100G]": ["Eth31/1(Port31)", "Eth31/2(Port31)", "Eth31/3(Port31)", "Eth31/4(Port31)"], + "4x100G[50G](4)": ["Eth31/1(Port31)", "Eth31/2(Port31)", "Eth31/3(Port31)", "Eth31/4(Port31)"], + "1x100G(4)": ["Eth31(Port31)"], + "2x50G(4)": ["Eth31/1(Port31)", "Eth31/2(Port31)"] + } + }, + + "Ethernet248": { + "index": "32,32,32,32,32,32,32,32", + "lanes": "481,482,483,484,485,486,487,488", + "breakout_modes": { + "1x800G": ["Eth32(Port32)"], + "1x400G": ["Eth32(Port32)"], + "2x400G[200G]": ["Eth32/1(Port32)", "Eth32/2(Port32)"], + "4x200G[100G]": ["Eth32/1(Port32)", "Eth32/2(Port32)", "Eth32/3(Port32)", "Eth32/4(Port32)"], + "4x100G[50G](4)": ["Eth32/1(Port32)", "Eth32/2(Port32)", "Eth32/3(Port32)", "Eth32/4(Port32)"], + "1x100G(4)": ["Eth32(Port32)"], + "2x50G(4)": ["Eth32/1(Port32)", "Eth32/2(Port32)"] + } + }, + + "Ethernet256": { + "index": "33,33,33,33,33,33,33,33", + "lanes": "17,18,19,20,21,22,23,24", + "breakout_modes": { + "1x800G": ["Eth33(Port33)"], + "1x400G": ["Eth33(Port33)"], + "2x400G[200G]": ["Eth33/1(Port33)", "Eth33/2(Port33)"], + "4x200G[100G]": ["Eth33/1(Port33)", "Eth33/2(Port33)", "Eth33/3(Port33)", "Eth33/4(Port33)"], + "4x100G[50G](4)": ["Eth33/1(Port33)", "Eth33/2(Port33)", "Eth33/3(Port33)", "Eth33/4(Port33)"], + "1x100G(4)": ["Eth33(Port33)"], + "2x50G(4)": ["Eth33/1(Port33)", "Eth33/2(Port33)"] + } + }, + + "Ethernet264": { + "index": "34,34,34,34,34,34,34,34", + "lanes": "25,26,27,28,29,30,31,32", + "breakout_modes": { + "1x800G": ["Eth34(Port34)"], + "1x400G": ["Eth34(Port34)"], + "2x400G[200G]": ["Eth34/1(Port34)", "Eth34/2(Port34)"], + "4x200G[100G]": ["Eth34/1(Port34)", "Eth34/2(Port34)", "Eth34/3(Port34)", "Eth34/4(Port34)"], + "4x100G[50G](4)": ["Eth34/1(Port34)", "Eth34/2(Port34)", "Eth34/3(Port34)", "Eth34/4(Port34)"], + "1x100G(4)": ["Eth34(Port34)"], + "2x50G(4)": ["Eth34/1(Port34)", "Eth34/2(Port34)"] + } + }, + + "Ethernet272": { + "index": "35,35,35,35,35,35,35,35", + "lanes": "49,50,51,52,53,54,55,56", + "breakout_modes": { + "1x800G": ["Eth35(Port35)"], + "1x400G": ["Eth35(Port35)"], + "2x400G[200G]": ["Eth35/1(Port35)", "Eth35/2(Port35)"], + "4x200G[100G]": ["Eth35/1(Port35)", "Eth35/2(Port35)", "Eth35/3(Port35)", "Eth35/4(Port35)"], + "4x100G[50G](4)": ["Eth35/1(Port35)", "Eth35/2(Port35)", "Eth35/3(Port35)", "Eth35/4(Port35)"], + "1x100G(4)": ["Eth35(Port35)"], + "2x50G(4)": ["Eth35/1(Port35)", "Eth35/2(Port35)"] + } + }, + + "Ethernet280": { + "index": "36,36,36,36,36,36,36,36", + "lanes": "57,58,59,60,61,62,63,64", + "breakout_modes": { + "1x800G": ["Eth36(Port36)"], + "1x400G": ["Eth36(Port36)"], + "2x400G[200G]": ["Eth36/1(Port36)", "Eth36/2(Port36)"], + "4x200G[100G]": ["Eth36/1(Port36)", "Eth36/2(Port36)", "Eth36/3(Port36)", "Eth36/4(Port36)"], + "4x100G[50G](4)": ["Eth36/1(Port36)", "Eth36/2(Port36)", "Eth36/3(Port36)", "Eth36/4(Port36)"], + "1x100G(4)": ["Eth36(Port36)"], + "2x50G(4)": ["Eth36/1(Port36)", "Eth36/2(Port36)"] + } + }, + + "Ethernet288": { + "index": "37,37,37,37,37,37,37,37", + "lanes": "81,82,83,84,85,86,87,88", + "breakout_modes": { + "1x800G": ["Eth37(Port37)"], + "1x400G": ["Eth37(Port37)"], + "2x400G[200G]": ["Eth37/1(Port37)", "Eth37/2(Port37)"], + "4x200G[100G]": ["Eth37/1(Port37)", "Eth37/2(Port37)", "Eth37/3(Port37)", "Eth37/4(Port37)"], + "4x100G[50G](4)": ["Eth37/1(Port37)", "Eth37/2(Port37)", "Eth37/3(Port37)", "Eth37/4(Port37)"], + "1x100G(4)": ["Eth37(Port37)"], + "2x50G(4)": ["Eth37/1(Port37)", "Eth37/2(Port37)"] + } + }, + + "Ethernet296": { + "index": "38,38,38,38,38,38,38,38", + "lanes": "89,90,91,92,93,94,95,96", + "breakout_modes": { + "1x800G": ["Eth38(Port38)"], + "1x400G": ["Eth38(Port38)"], + "2x400G[200G]": ["Eth38/1(Port38)", "Eth38/2(Port38)"], + "4x200G[100G]": ["Eth38/1(Port38)", "Eth38/2(Port38)", "Eth38/3(Port38)", "Eth38/4(Port38)"], + "4x100G[50G](4)": ["Eth38/1(Port38)", "Eth38/2(Port38)", "Eth38/3(Port38)", "Eth38/4(Port38)"], + "1x100G(4)": ["Eth38(Port38)"], + "2x50G(4)": ["Eth38/1(Port38)", "Eth38/2(Port38)"] + } + }, + + "Ethernet304": { + "index": "39,39,39,39,39,39,39,39", + "lanes": "113,114,115,116,117,118,119,120", + "breakout_modes": { + "1x800G": ["Eth39(Port39)"], + "1x400G": ["Eth39(Port39)"], + "2x400G[200G]": ["Eth39/1(Port39)", "Eth39/2(Port39)"], + "4x200G[100G]": ["Eth39/1(Port39)", "Eth39/2(Port39)", "Eth39/3(Port39)", "Eth39/4(Port39)"], + "4x100G[50G](4)": ["Eth39/1(Port39)", "Eth39/2(Port39)", "Eth39/3(Port39)", "Eth39/4(Port39)"], + "1x100G(4)": ["Eth39(Port39)"], + "2x50G(4)": ["Eth39/1(Port39)", "Eth39/2(Port39)"] + } + }, + + "Ethernet312": { + "index": "40,40,40,40,40,40,40,40", + "lanes": "121,122,123,124,125,126,127,128", + "breakout_modes": { + "1x800G": ["Eth40(Port40)"], + "1x400G": ["Eth40(Port40)"], + "2x400G[200G]": ["Eth40/1(Port40)", "Eth40/2(Port40)"], + "4x200G[100G]": ["Eth40/1(Port40)", "Eth40/2(Port40)", "Eth40/3(Port40)", "Eth40/4(Port40)"], + "4x100G[50G](4)": ["Eth40/1(Port40)", "Eth40/2(Port40)", "Eth40/3(Port40)", "Eth40/4(Port40)"], + "1x100G(4)": ["Eth40(Port40)"], + "2x50G(4)": ["Eth40/1(Port40)", "Eth40/2(Port40)"] + } + }, + + "Ethernet320": { + "index": "41,41,41,41,41,41,41,41", + "lanes": "145,146,147,148,149,150,151,152", + "breakout_modes": { + "1x800G": ["Eth41(Port41)"], + "1x400G": ["Eth41(Port41)"], + "2x400G[200G]": ["Eth41/1(Port41)", "Eth41/2(Port41)"], + "4x200G[100G]": ["Eth41/1(Port41)", "Eth41/2(Port41)", "Eth41/3(Port41)", "Eth41/4(Port41)"], + "4x100G[50G](4)": ["Eth41/1(Port41)", "Eth41/2(Port41)", "Eth41/3(Port41)", "Eth41/4(Port41)"], + "1x100G(4)": ["Eth41(Port41)"], + "2x50G(4)": ["Eth41/1(Port41)", "Eth41/2(Port41)"] + } + }, + + "Ethernet328": { + "index": "42,42,42,42,42,42,42,42", + "lanes": "153,154,155,156,157,158,159,160", + "breakout_modes": { + "1x800G": ["Eth42(Port42)"], + "1x400G": ["Eth42(Port42)"], + "2x400G[200G]": ["Eth42/1(Port42)", "Eth42/2(Port42)"], + "4x200G[100G]": ["Eth42/1(Port42)", "Eth42/2(Port42)", "Eth42/3(Port42)", "Eth42/4(Port42)"], + "4x100G[50G](4)": ["Eth42/1(Port42)", "Eth42/2(Port42)", "Eth42/3(Port42)", "Eth42/4(Port42)"], + "1x100G(4)": ["Eth42(Port42)"], + "2x50G(4)": ["Eth42/1(Port42)", "Eth42/2(Port42)"] + } + }, + + "Ethernet336": { + "index": "43,43,43,43,43,43,43,43", + "lanes": "177,178,179,180,181,182,183,184", + "breakout_modes": { + "1x800G": ["Eth43(Port43)"], + "1x400G": ["Eth43(Port43)"], + "2x400G[200G]": ["Eth43/1(Port43)", "Eth43/2(Port43)"], + "4x200G[100G]": ["Eth43/1(Port43)", "Eth43/2(Port43)", "Eth43/3(Port43)", "Eth43/4(Port43)"], + "4x100G[50G](4)": ["Eth43/1(Port43)", "Eth43/2(Port43)", "Eth43/3(Port43)", "Eth43/4(Port43)"], + "1x100G(4)": ["Eth43(Port43)"], + "2x50G(4)": ["Eth43/1(Port43)", "Eth43/2(Port43)"] + } + }, + + "Ethernet344": { + "index": "44,44,44,44,44,44,44,44", + "lanes": "185,186,187,188,189,190,191,192", + "breakout_modes": { + "1x800G": ["Eth44(Port44)"], + "1x400G": ["Eth44(Port44)"], + "2x400G[200G]": ["Eth44/1(Port44)", "Eth44/2(Port44)"], + "4x200G[100G]": ["Eth44/1(Port44)", "Eth44/2(Port44)", "Eth44/3(Port44)", "Eth44/4(Port44)"], + "4x100G[50G](4)": ["Eth44/1(Port44)", "Eth44/2(Port44)", "Eth44/3(Port44)", "Eth44/4(Port44)"], + "1x100G(4)": ["Eth44(Port44)"], + "2x50G(4)": ["Eth44/1(Port44)", "Eth44/2(Port44)"] + } + }, + + "Ethernet352": { + "index": "45,45,45,45,45,45,45,45", + "lanes": "209,210,211,212,213,214,215,216", + "breakout_modes": { + "1x800G": ["Eth45(Port45)"], + "1x400G": ["Eth45(Port45)"], + "2x400G[200G]": ["Eth45/1(Port45)", "Eth45/2(Port45)"], + "4x200G[100G]": ["Eth45/1(Port45)", "Eth45/2(Port45)", "Eth45/3(Port45)", "Eth45/4(Port45)"], + "4x100G[50G](4)": ["Eth45/1(Port45)", "Eth45/2(Port45)", "Eth45/3(Port45)", "Eth45/4(Port45)"], + "1x100G(4)": ["Eth45(Port45)"], + "2x50G(4)": ["Eth45/1(Port45)", "Eth45/2(Port45)"] + } + }, + + "Ethernet360": { + "index": "46,46,46,46,46,46,46,46", + "lanes": "217,218,219,220,221,222,223,224", + "breakout_modes": { + "1x800G": ["Eth46(Port46)"], + "1x400G": ["Eth46(Port46)"], + "2x400G[200G]": ["Eth46/1(Port46)", "Eth46/2(Port46)"], + "4x200G[100G]": ["Eth46/1(Port46)", "Eth46/2(Port46)", "Eth46/3(Port46)", "Eth46/4(Port46)"], + "4x100G[50G](4)": ["Eth46/1(Port46)", "Eth46/2(Port46)", "Eth46/3(Port46)", "Eth46/4(Port46)"], + "1x100G(4)": ["Eth46(Port46)"], + "2x50G(4)": ["Eth46/1(Port46)", "Eth46/2(Port46)"] + } + }, + + "Ethernet368": { + "index": "47,47,47,47,47,47,47,47", + "lanes": "249,250,251,252,253,254,255,256", + "breakout_modes": { + "1x800G": ["Eth47(Port47)"], + "1x400G": ["Eth47(Port47)"], + "2x400G[200G]": ["Eth47/1(Port47)", "Eth47/2(Port47)"], + "4x200G[100G]": ["Eth47/1(Port47)", "Eth47/2(Port47)", "Eth47/3(Port47)", "Eth47/4(Port47)"], + "4x100G[50G](4)": ["Eth47/1(Port47)", "Eth47/2(Port47)", "Eth47/3(Port47)", "Eth47/4(Port47)"], + "1x100G(4)": ["Eth47(Port47)"], + "2x50G(4)": ["Eth47/1(Port47)", "Eth47/2(Port47)"] + } + }, + + "Ethernet376": { + "index": "48,48,48,48,48,48,48,48", + "lanes": "241,242,243,244,245,246,247,248", + "breakout_modes": { + "1x800G": ["Eth48(Port48)"], + "1x400G": ["Eth48(Port48)"], + "2x400G[200G]": ["Eth48/1(Port48)", "Eth48/2(Port48)"], + "4x200G[100G]": ["Eth48/1(Port48)", "Eth48/2(Port48)", "Eth48/3(Port48)", "Eth48/4(Port48)"], + "4x100G[50G](4)": ["Eth48/1(Port48)", "Eth48/2(Port48)", "Eth48/3(Port48)", "Eth48/4(Port48)"], + "1x100G(4)": ["Eth48(Port48)"], + "2x50G(4)": ["Eth48/1(Port48)", "Eth48/2(Port48)"] + } + }, + + "Ethernet384": { + "index": "49,49,49,49,49,49,49,49", + "lanes": "273,274,275,276,277,278,279,280", + "breakout_modes": { + "1x800G": ["Eth49(Port49)"], + "1x400G": ["Eth49(Port49)"], + "2x400G[200G]": ["Eth49/1(Port49)", "Eth49/2(Port49)"], + "4x200G[100G]": ["Eth49/1(Port49)", "Eth49/2(Port49)", "Eth49/3(Port49)", "Eth49/4(Port49)"], + "4x100G[50G](4)": ["Eth49/1(Port49)", "Eth49/2(Port49)", "Eth49/3(Port49)", "Eth49/4(Port49)"], + "1x100G(4)": ["Eth49(Port49)"], + "2x50G(4)": ["Eth49/1(Port49)", "Eth49/2(Port49)"] + } + }, + + "Ethernet392": { + "index": "50,50,50,50,50,50,50,50", + "lanes": "281,282,283,284,285,286,287,288", + "breakout_modes": { + "1x800G": ["Eth50(Port50)"], + "1x400G": ["Eth50(Port50)"], + "2x400G[200G]": ["Eth50/1(Port50)", "Eth50/2(Port50)"], + "4x200G[100G]": ["Eth50/1(Port50)", "Eth50/2(Port50)", "Eth50/3(Port50)", "Eth50/4(Port50)"], + "4x100G[50G](4)": ["Eth50/1(Port50)", "Eth50/2(Port50)", "Eth50/3(Port50)", "Eth50/4(Port50)"], + "1x100G(4)": ["Eth50(Port50)"], + "2x50G(4)": ["Eth50/1(Port50)", "Eth50/2(Port50)"] + } + }, + + "Ethernet400": { + "index": "51,51,51,51,51,51,51,51", + "lanes": "305,306,307,308,309,310,311,312", + "breakout_modes": { + "1x800G": ["Eth51(Port51)"], + "1x400G": ["Eth51(Port51)"], + "2x400G[200G]": ["Eth51/1(Port51)", "Eth51/2(Port51)"], + "4x200G[100G]": ["Eth51/1(Port51)", "Eth51/2(Port51)", "Eth51/3(Port51)", "Eth51/4(Port51)"], + "4x100G[50G](4)": ["Eth51/1(Port51)", "Eth51/2(Port51)", "Eth51/3(Port51)", "Eth51/4(Port51)"], + "1x100G(4)": ["Eth51(Port51)"], + "2x50G(4)": ["Eth51/1(Port51)", "Eth51/2(Port51)"] + } + }, + + "Ethernet408": { + "index": "52,52,52,52,52,52,52,52", + "lanes": "313,314,315,316,317,318,319,320", + "breakout_modes": { + "1x800G": ["Eth52(Port52)"], + "1x400G": ["Eth52(Port52)"], + "2x400G[200G]": ["Eth52/1(Port52)", "Eth52/2(Port52)"], + "4x200G[100G]": ["Eth52/1(Port52)", "Eth52/2(Port52)", "Eth52/3(Port52)", "Eth52/4(Port52)"], + "4x100G[50G](4)": ["Eth52/1(Port52)", "Eth52/2(Port52)", "Eth52/3(Port52)", "Eth52/4(Port52)"], + "1x100G(4)": ["Eth52(Port52)"], + "2x50G(4)": ["Eth52/1(Port52)", "Eth52/2(Port52)"] + } + }, + + "Ethernet416": { + "index": "53,53,53,53,53,53,53,53", + "lanes": "337,338,339,340,341,342,343,344", + "breakout_modes": { + "1x800G": ["Eth53(Port53)"], + "1x400G": ["Eth53(Port53)"], + "2x400G[200G]": ["Eth53/1(Port53)", "Eth53/2(Port53)"], + "4x200G[100G]": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"], + "4x100G[50G](4)": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"], + "1x100G(4)": ["Eth53(Port53)"], + "2x50G(4)": ["Eth53/1(Port53)", "Eth53/2(Port53)"] + } + }, + + "Ethernet424": { + "index": "54,54,54,54,54,54,54,54", + "lanes": "345,346,347,348,349,350,351,352", + "breakout_modes": { + "1x800G": ["Eth54(Port54)"], + "1x400G": ["Eth54(Port54)"], + "2x400G[200G]": ["Eth54/1(Port54)", "Eth54/2(Port54)"], + "4x200G[100G]": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"], + "4x100G[50G](4)": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"], + "1x100G(4)": ["Eth54(Port54)"], + "2x50G(4)": ["Eth54/1(Port54)", "Eth54/2(Port54)"] + } + }, + + "Ethernet432": { + "index": "55,55,55,55,55,55,55,55", + "lanes": "369,370,371,372,373,374,375,376", + "breakout_modes": { + "1x800G": ["Eth55(Port55)"], + "1x400G": ["Eth55(Port55)"], + "2x400G[200G]": ["Eth55/1(Port55)", "Eth55/2(Port55)"], + "4x200G[100G]": ["Eth55/1(Port55)", "Eth55/2(Port55)", "Eth55/3(Port55)", "Eth55/4(Port55)"], + "4x100G[50G](4)": ["Eth55/1(Port55)", "Eth55/2(Port55)", "Eth55/3(Port55)", "Eth55/4(Port55)"], + "1x100G(4)": ["Eth55(Port55)"], + "2x50G(4)": ["Eth55/1(Port55)", "Eth55/2(Port55)"] + } + }, + + "Ethernet440": { + "index": "56,56,56,56,56,56,56,56", + "lanes": "377,378,379,380,381,382,383,384", + "breakout_modes": { + "1x800G": ["Eth56(Port56)"], + "1x400G": ["Eth56(Port56)"], + "2x400G[200G]": ["Eth56/1(Port56)", "Eth56/2(Port56)"], + "4x200G[100G]": ["Eth56/1(Port56)", "Eth56/2(Port56)", "Eth56/3(Port56)", "Eth56/4(Port56)"], + "4x100G[50G](4)": ["Eth56/1(Port56)", "Eth56/2(Port56)", "Eth56/3(Port56)", "Eth56/4(Port56)"], + "1x100G(4)": ["Eth56(Port56)"], + "2x50G(4)": ["Eth56/1(Port56)", "Eth56/2(Port56)"] + } + }, + + "Ethernet448": { + "index": "57,57,57,57,57,57,57,57", + "lanes": "401,402,403,404,405,406,407,408", + "breakout_modes": { + "1x800G": ["Eth57(Port57)"], + "1x400G": ["Eth57(Port57)"], + "2x400G[200G]": ["Eth57/1(Port57)", "Eth57/2(Port57)"], + "4x200G[100G]": ["Eth57/1(Port57)", "Eth57/2(Port57)", "Eth57/3(Port57)", "Eth57/4(Port57)"], + "4x100G[50G](4)": ["Eth57/1(Port57)", "Eth57/2(Port57)", "Eth57/3(Port57)", "Eth57/4(Port57)"], + "1x100G(4)": ["Eth57(Port57)"], + "2x50G(4)": ["Eth57/1(Port57)", "Eth57/2(Port57)"] + } + }, + + "Ethernet456": { + "index": "58,58,58,58,58,58,58,58", + "lanes": "409,410,411,412,413,414,415,416", + "breakout_modes": { + "1x800G": ["Eth58(Port58)"], + "1x400G": ["Eth58(Port58)"], + "2x400G[200G]": ["Eth58/1(Port58)", "Eth58/2(Port58)"], + "4x200G[100G]": ["Eth58/1(Port58)", "Eth58/2(Port58)", "Eth58/3(Port58)", "Eth58/4(Port58)"], + "4x100G[50G](4)": ["Eth58/1(Port58)", "Eth58/2(Port58)", "Eth58/3(Port58)", "Eth58/4(Port58)"], + "1x100G(4)": ["Eth58(Port58)"], + "2x50G(4)": ["Eth58/1(Port58)", "Eth58/2(Port58)"] + } + }, + + "Ethernet464": { + "index": "59,59,59,59,59,59,59,59", + "lanes": "433,434,435,436,437,438,439,440", + "breakout_modes": { + "1x800G": ["Eth59(Port59)"], + "1x400G": ["Eth59(Port59)"], + "2x400G[200G]": ["Eth59/1(Port59)", "Eth59/2(Port59)"], + "4x200G[100G]": ["Eth59/1(Port59)", "Eth59/2(Port59)", "Eth59/3(Port59)", "Eth59/4(Port59)"], + "4x100G[50G](4)": ["Eth59/1(Port59)", "Eth59/2(Port59)", "Eth59/3(Port59)", "Eth59/4(Port59)"], + "1x100G(4)": ["Eth59(Port59)"], + "2x50G(4)": ["Eth59/1(Port59)", "Eth59/2(Port59)"] + } + }, + + "Ethernet472": { + "index": "60,60,60,60,60,60,60,60", + "lanes": "441,442,443,444,445,446,447,448", + "breakout_modes": { + "1x800G": ["Eth60(Port60)"], + "1x400G": ["Eth60(Port60)"], + "2x400G[200G]": ["Eth60/1(Port60)", "Eth60/2(Port60)"], + "4x200G[100G]": ["Eth60/1(Port60)", "Eth60/2(Port60)", "Eth60/3(Port60)", "Eth60/4(Port60)"], + "4x100G[50G](4)": ["Eth60/1(Port60)", "Eth60/2(Port60)", "Eth60/3(Port60)", "Eth60/4(Port60)"], + "1x100G(4)": ["Eth60(Port60)"], + "2x50G(4)": ["Eth60/1(Port60)", "Eth60/2(Port60)"] + } + }, + + "Ethernet480": { + "index": "61,61,61,61,61,61,61,61", + "lanes": "465,466,467,468,469,470,471,472", + "breakout_modes": { + "1x800G": ["Eth61(Port61)"], + "1x400G": ["Eth61(Port61)"], + "2x400G[200G]": ["Eth61/1(Port61)", "Eth61/2(Port61)"], + "4x200G[100G]": ["Eth61/1(Port61)", "Eth61/2(Port61)", "Eth61/3(Port61)", "Eth61/4(Port61)"], + "4x100G[50G](4)": ["Eth61/1(Port61)", "Eth61/2(Port61)", "Eth61/3(Port61)", "Eth61/4(Port61)"], + "1x100G(4)": ["Eth61(Port61)"], + "2x50G(4)": ["Eth61/1(Port61)", "Eth61/2(Port61)"] + } + }, + + "Ethernet488": { + "index": "62,62,62,62,62,62,62,62", + "lanes": "473,474,475,476,477,478,479,480", + "breakout_modes": { + "1x800G": ["Eth62(Port62)"], + "1x400G": ["Eth62(Port62)"], + "2x400G[200G]": ["Eth62/1(Port62)", "Eth62/2(Port62)"], + "4x200G[100G]": ["Eth62/1(Port62)", "Eth62/2(Port62)", "Eth62/3(Port62)", "Eth62/4(Port62)"], + "4x100G[50G](4)": ["Eth62/1(Port62)", "Eth62/2(Port62)", "Eth62/3(Port62)", "Eth62/4(Port62)"], + "1x100G(4)": ["Eth62(Port62)"], + "2x50G(4)": ["Eth62/1(Port62)", "Eth62/2(Port62)"] + } + }, + + "Ethernet496": { + "index": "63,63,63,63,63,63,63,63", + "lanes": "505,506,507,508,509,510,511,512", + "breakout_modes": { + "1x800G": ["Eth63(Port63)"], + "1x400G": ["Eth63(Port63)"], + "2x400G[200G]": ["Eth63/1(Port63)", "Eth63/2(Port63)"], + "4x200G[100G]": ["Eth63/1(Port63)", "Eth63/2(Port63)", "Eth63/3(Port63)", "Eth63/4(Port63)"], + "4x100G[50G](4)": ["Eth63/1(Port63)", "Eth63/2(Port63)", "Eth63/3(Port63)", "Eth63/4(Port63)"], + "1x100G(4)": ["Eth63(Port63)"], + "2x50G(4)": ["Eth63/1(Port63)", "Eth63/2(Port63)"] + } + }, + + "Ethernet504": { + "index": "64,64,64,64,64,64,64,64", + "lanes": "497,498,499,500,501,502,503,504", + "breakout_modes": { + "1x800G": ["Eth64(Port64)"], + "1x400G": ["Eth64(Port64)"], + "2x400G[200G]": ["Eth64/1(Port64)", "Eth64/2(Port64)"], + "4x200G[100G]": ["Eth64/1(Port64)", "Eth64/2(Port64)", "Eth64/3(Port64)", "Eth64/4(Port64)"], + "4x100G[50G](4)": ["Eth64/1(Port64)", "Eth64/2(Port64)", "Eth64/3(Port64)", "Eth64/4(Port64)"], + "1x100G(4)": ["Eth64(Port64)"], + "2x50G(4)": ["Eth64/1(Port64)", "Eth64/2(Port64)"] + } + }, + + "Ethernet512": { + "index": "65", + "lanes": "514", + "breakout_modes": { + "1x25G[10G,1G]": ["Eth65(Port65)"] + } + }, + + "Ethernet513": { + "index": "66", + "lanes": "513", + "breakout_modes": { + "1x25G[10G,1G]": ["Eth66(Port66)"] + } + } + } +} + diff --git a/device/accton/x86_64-accton_as9817_64d-r0/platform_asic b/device/accton/x86_64-accton_as9817_64d-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/accton/x86_64-accton_as9817_64d-r0/platform_components.json b/device/accton/x86_64-accton_as9817_64d-r0/platform_components.json new file mode 100644 index 000000000000..0a87e0be1bef --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/platform_components.json @@ -0,0 +1,13 @@ +{ + "chassis": { + "AS9817-64D-O-AC-F": { + "component": { + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { }, + "FPGA": { }, + "BIOS": { } + } + } + } +} diff --git a/device/accton/x86_64-accton_as9817_64d-r0/platform_env.conf b/device/accton/x86_64-accton_as9817_64d-r0/platform_env.conf new file mode 100644 index 000000000000..aee1c756bf5e --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/platform_env.conf @@ -0,0 +1,2 @@ +SYNCD_SHM_SIZE=1G +is_ltsw_chip=1 diff --git a/device/accton/x86_64-accton_as9817_64d-r0/platform_reboot b/device/accton/x86_64-accton_as9817_64d-r0/platform_reboot new file mode 100755 index 000000000000..a3d1a4c5972e --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/platform_reboot @@ -0,0 +1,10 @@ +#!/bin/bash + +echo "Do sync" +sync + +echo "Stop pmon.service" +systemctl stop pmon.service + +# echo "Stop as9817_64d-platform-monitor.service" +# systemctl stop as9817_64d-platform-monitor.service diff --git a/device/accton/x86_64-accton_as9817_64d-r0/plugins/ssd_util.py b/device/accton/x86_64-accton_as9817_64d-r0/plugins/ssd_util.py new file mode 100644 index 000000000000..1984747612bb --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/plugins/ssd_util.py @@ -0,0 +1,29 @@ +# ssd_util.py +# +# Platform-specific SSD interface for SONiC +## + +try: + from sonic_platform_base.sonic_ssd.ssd_generic import SsdUtil as MainSsdUtil + from sonic_platform_base.sonic_ssd.ssd_generic import NOT_AVAILABLE + from sonic_py_common import logger +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "ssd_util.py" + +# Global logger instance +log = logger.Logger(SYSLOG_IDENTIFIER) + +class SsdUtil(MainSsdUtil): + """Platform-specific SsdUtil class""" + + def __init__(self, diskdev): + super(SsdUtil, self).__init__(diskdev) + + # If it has no vendor tool to read SSD information, + # ssd_util.py will use generic SSD information + # for vendor SSD information. + if self.vendor_ssd_info == NOT_AVAILABLE or \ + len(self.vendor_ssd_info.strip()) == 0: + self.vendor_ssd_info = self.ssd_info diff --git a/device/accton/x86_64-accton_as9817_64d-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as9817_64d-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..98506b46146d --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sensors.conf b/device/accton/x86_64-accton_as9817_64d-r0/sensors.conf new file mode 100644 index 000000000000..be3edb54d46d --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sensors.conf @@ -0,0 +1,37 @@ +chip "as9817_64_fan-isa-0000" + label fan1 "Fan 1 Front" + label fan2 "Fan 2 Front" + label fan3 "Fan 3 Front" + label fan4 "Fan 4 Front" + label fan5 "Fan 1 Rear" + label fan6 "Fan 2 Rear" + label fan7 "Fan 3 Rear" + label fan8 "Fan 4 Rear" + +chip "as9817_64_thermal-isa-0000" + label temp1 "MB_RearCenter_temp(0x48)" + label temp2 "MB_RearRight_temp(0x49)" + label temp3 "MB_RearCenter_temp(0x4A)" + label temp4 "MB_RearLeft_temp(0x4B)" + label temp5 "MB_FrontLeft_temp(0x4C)" + label temp6 "MB_FrontRight_temp(0x4D)" + label temp7 "FB_temp(0x4D)" + label temp8 "FB_temp(0x4E)" + +chip "as9817_64_psu-isa-0000" + label in0 "PSU 1 Voltage" + label fan1 "PSU 1 Fan" + label temp1 "PSU 1 Temperature" + label power1 "PSU 1 Power" + label curr1 "PSU 1 Current" + +chip "as9817_64_psu-isa-0001" + label in1 "PSU 2 Voltage" + label fan2 "PSU 2 Fan" + label temp2 "PSU 2 Temperature" + label power2 "PSU 2 Power" + label curr2 "PSU 2 Current" + +chip "nvme-pci-1600" + label temp1 "nvme0 Temperature" + ignore temp2 diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/__init__.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/__init__.py new file mode 120000 index 000000000000..0afddffd75a3 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/__init__.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/__init__.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/chassis.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/chassis.py new file mode 120000 index 000000000000..b61a75a71900 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/chassis.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/chassis.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/component.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/component.py new file mode 120000 index 000000000000..8a68ecbbcb3d --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/component.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/component.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/eeprom.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/eeprom.py new file mode 120000 index 000000000000..bc123ebe0b92 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/eeprom.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/eeprom.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/event.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/event.py new file mode 120000 index 000000000000..4571262cc580 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/event.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/event.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/fan.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/fan.py new file mode 120000 index 000000000000..b6369354699e --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/fan.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/fan.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/fan_drawer.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/fan_drawer.py new file mode 120000 index 000000000000..8998d3576abf --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/fan_drawer.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/fan_drawer.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/helper.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/helper.py new file mode 120000 index 000000000000..6138e3317dca --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/helper.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/helper.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/pcie.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/pcie.py new file mode 120000 index 000000000000..4e58f01dd116 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/pcie.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/pcie.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/platform.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/platform.py new file mode 120000 index 000000000000..72c8abaeeea6 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/platform.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/platform.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/psu.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/psu.py new file mode 120000 index 000000000000..e93934eac078 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/psu.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/psu.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/sfp.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/sfp.py new file mode 120000 index 000000000000..267662f4f5a1 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/sfp.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/sfp.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/thermal.py b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/thermal.py new file mode 120000 index 000000000000..51d9e5016787 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/sonic_platform/thermal.py @@ -0,0 +1 @@ +../../x86_64-accton_as9817_64o-r0/sonic_platform/thermal.py \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64d-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as9817_64d-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..5af0e4067aef --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/system_health_monitoring_config.json @@ -0,0 +1,13 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "STATUS_LED_COLOR_RED", + "normal": "STATUS_LED_COLOR_OFF", + "booting": "STATUS_LED_COLOR_OFF" + } +} diff --git a/device/accton/x86_64-accton_as9817_64d-r0/warm-reboot_plugin b/device/accton/x86_64-accton_as9817_64d-r0/warm-reboot_plugin new file mode 120000 index 000000000000..a94494bc5674 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64d-r0/warm-reboot_plugin @@ -0,0 +1 @@ +platform_reboot \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/hwsku.json b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/hwsku.json new file mode 100644 index 000000000000..ff7e639496b9 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/hwsku.json @@ -0,0 +1,332 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet8": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet16": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet24": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet32": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet40": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet48": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet56": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet64": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet72": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet80": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet88": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet96": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet104": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet112": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet120": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet128": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet136": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet144": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet152": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet160": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet168": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet176": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet184": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet192": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet200": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet208": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet216": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet224": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet232": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet240": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet248": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet256": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet264": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet272": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet280": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet288": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet296": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet304": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet312": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet320": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet328": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet336": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet344": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet352": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet360": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet368": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet376": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet384": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet392": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet400": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet408": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet416": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet424": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet432": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet440": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet448": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet456": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet464": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet472": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet480": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet488": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet496": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet504": { + "default_brkout_mode": "1x800G", + "autoneg": "off" + }, + + "Ethernet512": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + + "Ethernet513": { + "default_brkout_mode": "1x25G[10G,1G]" + } + } +} + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/port_config.ini b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/port_config.ini new file mode 100644 index 000000000000..0ff85cd60131 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 25,26,27,28,29,30,31,32 Eth1(Port1) 1 800000 +Ethernet8 9,10,11,12,13,14,15,16 Eth2(Port2) 2 800000 +Ethernet16 49,50,51,52,53,54,55,56 Eth3(Port3) 3 800000 +Ethernet24 33,34,35,36,37,38,39,40 Eth4(Port4) 4 800000 +Ethernet32 81,82,83,84,85,86,87,88 Eth5(Port5) 5 800000 +Ethernet40 65,66,67,68,69,70,71,72 Eth6(Port6) 6 800000 +Ethernet48 113,114,115,116,117,118,119,120 Eth7(Port7) 7 800000 +Ethernet56 97,98,99,100,101,102,103,104 Eth8(Port8) 8 800000 +Ethernet64 145,146,147,148,149,150,151,152 Eth9(Port9) 9 800000 +Ethernet72 129,130,131,132,133,134,135,136 Eth10(Port10) 10 800000 +Ethernet80 177,178,179,180,181,182,183,184 Eth11(Port11) 11 800000 +Ethernet88 161,162,163,164,165,166,167,168 Eth12(Port12) 12 800000 +Ethernet96 209,210,211,212,213,214,215,216 Eth13(Port13) 13 800000 +Ethernet104 193,194,195,196,197,198,199,200 Eth14(Port14) 14 800000 +Ethernet112 241,242,243,244,245,246,247,248 Eth15(Port15) 15 800000 +Ethernet120 225,226,227,228,229,230,231,232 Eth16(Port16) 16 800000 +Ethernet128 281,282,283,284,285,286,287,288 Eth17(Port17) 17 800000 +Ethernet136 265,266,267,268,269,270,271,272 Eth18(Port18) 18 800000 +Ethernet144 305,306,307,308,309,310,311,312 Eth19(Port19) 19 800000 +Ethernet152 289,290,291,292,293,294,295,296 Eth20(Port20) 20 800000 +Ethernet160 337,338,339,340,341,342,343,344 Eth21(Port21) 21 800000 +Ethernet168 321,322,323,324,325,326,327,328 Eth22(Port22) 22 800000 +Ethernet176 369,370,371,372,373,374,375,376 Eth23(Port23) 23 800000 +Ethernet184 353,354,355,356,357,358,359,360 Eth24(Port24) 24 800000 +Ethernet192 401,402,403,404,405,406,407,408 Eth25(Port25) 25 800000 +Ethernet200 385,386,387,388,389,390,391,392 Eth26(Port26) 26 800000 +Ethernet208 433,434,435,436,437,438,439,440 Eth27(Port27) 27 800000 +Ethernet216 417,418,419,420,421,422,423,424 Eth28(Port28) 28 800000 +Ethernet224 465,466,467,468,469,470,471,472 Eth29(Port29) 29 800000 +Ethernet232 449,450,451,452,453,454,455,456 Eth30(Port30) 30 800000 +Ethernet240 497,498,499,500,501,502,503,504 Eth31(Port31) 31 800000 +Ethernet248 481,482,483,484,485,486,487,488 Eth32(Port32) 32 800000 +Ethernet256 1,2,3,4,5,6,7,8 Eth33(Port33) 33 800000 +Ethernet264 17,18,19,20,21,22,23,24 Eth34(Port34) 34 800000 +Ethernet272 41,42,43,44,45,46,47,48 Eth35(Port35) 35 800000 +Ethernet280 57,58,59,60,61,62,63,64 Eth36(Port36) 36 800000 +Ethernet288 73,74,75,76,77,78,79,80 Eth37(Port37) 37 800000 +Ethernet296 89,90,91,92,93,94,95,96 Eth38(Port38) 38 800000 +Ethernet304 105,106,107,108,109,110,111,112 Eth39(Port39) 39 800000 +Ethernet312 121,122,123,124,125,126,127,128 Eth40(Port40) 40 800000 +Ethernet320 137,138,139,140,141,142,143,144 Eth41(Port41) 41 800000 +Ethernet328 153,154,155,156,157,158,159,160 Eth42(Port42) 42 800000 +Ethernet336 169,170,171,172,173,174,175,176 Eth43(Port43) 43 800000 +Ethernet344 185,186,187,188,189,190,191,192 Eth44(Port44) 44 800000 +Ethernet352 201,202,203,204,205,206,207,208 Eth45(Port45) 45 800000 +Ethernet360 217,218,219,220,221,222,223,224 Eth46(Port46) 46 800000 +Ethernet368 233,234,235,236,237,238,239,240 Eth47(Port47) 47 800000 +Ethernet376 249,250,251,252,253,254,255,256 Eth48(Port48) 48 800000 +Ethernet384 257,258,259,260,261,262,263,264 Eth49(Port49) 49 800000 +Ethernet392 273,274,275,276,277,278,279,280 Eth50(Port50) 50 800000 +Ethernet400 297,298,299,300,301,302,303,304 Eth51(Port51) 51 800000 +Ethernet408 313,314,315,316,317,318,319,320 Eth52(Port52) 52 800000 +Ethernet416 329,330,331,332,333,334,335,336 Eth53(Port53) 53 800000 +Ethernet424 345,346,347,348,349,350,351,352 Eth54(Port54) 54 800000 +Ethernet432 361,362,363,364,365,366,367,368 Eth55(Port55) 55 800000 +Ethernet440 377,378,379,380,381,382,383,384 Eth56(Port56) 56 800000 +Ethernet448 393,394,395,396,397,398,399,400 Eth57(Port57) 57 800000 +Ethernet456 409,410,411,412,413,414,415,416 Eth58(Port58) 58 800000 +Ethernet464 425,426,427,428,429,430,431,432 Eth59(Port59) 59 800000 +Ethernet472 441,442,443,444,445,446,447,448 Eth60(Port60) 60 800000 +Ethernet480 457,458,459,460,461,462,463,464 Eth61(Port61) 61 800000 +Ethernet488 473,474,475,476,477,478,479,480 Eth62(Port62) 62 800000 +Ethernet496 489,490,491,492,493,494,495,496 Eth63(Port63) 63 800000 +Ethernet504 505,506,507,508,509,510,511,512 Eth64(Port64) 64 800000 +Ethernet512 514 Eth65(Port65) 65 25000 +Ethernet513 513 Eth66(Port66) 66 25000 diff --git a/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/sai.profile b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/sai.profile new file mode 100644 index 000000000000..42b45089159a --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th5-as9817-64o-64x800G.config.yml diff --git a/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/th5-as9817-64o-64x800G.config.yml b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/th5-as9817-64o-64x800G.config.yml new file mode 100644 index 000000000000..508af9c68753 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/Accton-AS9817-64O/th5-as9817-64o-64x800G.config.yml @@ -0,0 +1,1138 @@ +--- +bcm_device: + 0: + global: + pktio_mode: 1 + vlan_flooding_l2mc_num_reserved: 0 + ipv6_lpm_128b_enable: 1 + shared_block_mask_section: uc_bc + skip_protocol_default_entries: 1 + # LTSW uses value 1 for ALPM combined mode + l3_alpm_template: 1 + l3_alpm_hit_skip: 1 + sai_feat_tail_timestamp : 1 + sai_field_group_auto_prioritize: 1 + #l3_intf_vlan_split_egress for MTU at L3IF + l3_intf_vlan_split_egress : 1 + pfc_deadlock_seq_control : 1 + sai_tunnel_support: 2 + bcm_tunnel_term_compatible_mode: 1 + l3_ecmp_member_first_lkup_mem_size: 12288 + sai_l3_byte1_udf_disable: 1 + #For PPIU Mode, Set resources for counters in global mode counters ll + global_flexctr_ing_action_num_reserved: 20 + global_flexctr_ing_pool_num_reserved: 8 + global_flexctr_ing_op_profile_num_reserved: 20 + global_flexctr_ing_group_num_reserved: 2 + global_flexctr_egr_action_num_reserved: 8 + global_flexctr_egr_pool_num_reserved: 5 + global_flexctr_egr_op_profile_num_reserved: 10 + global_flexctr_egr_group_num_reserved: 1 + flowtracker_enable: 1 + flowtracker_hardware_learn_enable: 2 + flowtracker_flexctr_alloc_enable: 1 + flowtracker_max_flows: 131072 +... +--- +device: + 0: + PC_PM_CORE: + ? + PC_PM_ID: 1 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x32107645 + TX_LANE_MAP: 0x51407326 + RX_POLARITY_FLIP: 0xa7 + TX_POLARITY_FLIP: 0x8e + ? + PC_PM_ID: 2 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x15674032 + TX_LANE_MAP: 0x62305147 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x0b + ? + PC_PM_ID: 3 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x72406351 + TX_LANE_MAP: 0x41573062 + RX_POLARITY_FLIP: 0x4b + TX_POLARITY_FLIP: 0x05 + ? + PC_PM_ID: 4 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65072143 + TX_LANE_MAP: 0x25073614 + RX_POLARITY_FLIP: 0x00 + TX_POLARITY_FLIP: 0x63 + ? + PC_PM_ID: 5 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x36741052 + TX_LANE_MAP: 0x43015276 + RX_POLARITY_FLIP: 0x6d + TX_POLARITY_FLIP: 0x25 + ? + PC_PM_ID: 6 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65701432 + TX_LANE_MAP: 0x46507132 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x36 + ? + PC_PM_ID: 7 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x53206147 + TX_LANE_MAP: 0x20153476 + RX_POLARITY_FLIP: 0x8e + TX_POLARITY_FLIP: 0x2d + ? + PC_PM_ID: 8 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x47015623 + TX_LANE_MAP: 0x50741263 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x6e + ? + PC_PM_ID: 9 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x40216735 + TX_LANE_MAP: 0x41307265 + RX_POLARITY_FLIP: 0xe7 + TX_POLARITY_FLIP: 0xa2 + ? + PC_PM_ID: 10 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65701432 + TX_LANE_MAP: 0x46507132 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x26 + ? + PC_PM_ID: 11 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x53206147 + TX_LANE_MAP: 0x20153476 + RX_POLARITY_FLIP: 0x8e + TX_POLARITY_FLIP: 0x2d + ? + PC_PM_ID: 12 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x47015623 + TX_LANE_MAP: 0x50741263 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x6e + ? + PC_PM_ID: 13 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x40216735 + TX_LANE_MAP: 0x41307265 + RX_POLARITY_FLIP: 0xe7 + TX_POLARITY_FLIP: 0xa2 + ? + PC_PM_ID: 14 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65701432 + TX_LANE_MAP: 0x46507132 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x26 + ? + PC_PM_ID: 15 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x53206147 + TX_LANE_MAP: 0x20153476 + RX_POLARITY_FLIP: 0x8e + TX_POLARITY_FLIP: 0x2d + ? + PC_PM_ID: 16 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x47015623 + TX_LANE_MAP: 0x50741263 + RX_POLARITY_FLIP: 0xa9 + TX_POLARITY_FLIP: 0x6e + ? + PC_PM_ID: 17 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x27653140 + TX_LANE_MAP: 0x04763512 + RX_POLARITY_FLIP: 0xbd + TX_POLARITY_FLIP: 0xdd + ? + PC_PM_ID: 18 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x30175246 + TX_LANE_MAP: 0x01263475 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x59 + ? + PC_PM_ID: 19 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x04673521 + TX_LANE_MAP: 0x56427031 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0xd6 + ? + PC_PM_ID: 20 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x21750364 + TX_LANE_MAP: 0x26304517 + RX_POLARITY_FLIP: 0x9c + TX_POLARITY_FLIP: 0x81 + ? + PC_PM_ID: 21 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x27653140 + TX_LANE_MAP: 0x04763512 + RX_POLARITY_FLIP: 0xbd + TX_POLARITY_FLIP: 0xdd + ? + PC_PM_ID: 22 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x30175246 + TX_LANE_MAP: 0x01263475 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x59 + ? + PC_PM_ID: 23 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x04673521 + TX_LANE_MAP: 0x56427031 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0xd6 + ? + PC_PM_ID: 24 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x21750364 + TX_LANE_MAP: 0x26304517 + RX_POLARITY_FLIP: 0x9c + TX_POLARITY_FLIP: 0x81 + ? + PC_PM_ID: 25 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x27653140 + TX_LANE_MAP: 0x04763512 + RX_POLARITY_FLIP: 0xbd + TX_POLARITY_FLIP: 0xdd + ? + PC_PM_ID: 26 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x30175246 + TX_LANE_MAP: 0x01263475 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x59 + ? + PC_PM_ID: 27 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x04673521 + TX_LANE_MAP: 0x46527031 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0x72 + ? + PC_PM_ID: 28 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x54237601 + TX_LANE_MAP: 0x16032457 + RX_POLARITY_FLIP: 0x4e + TX_POLARITY_FLIP: 0xfa + ? + PC_PM_ID: 29 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x72604351 + TX_LANE_MAP: 0x64571023 + RX_POLARITY_FLIP: 0xee + TX_POLARITY_FLIP: 0xd3 + ? + PC_PM_ID: 30 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x46750132 + TX_LANE_MAP: 0x37162504 + RX_POLARITY_FLIP: 0xe3 + TX_POLARITY_FLIP: 0x1f + ? + PC_PM_ID: 31 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x03512674 + TX_LANE_MAP: 0x43517062 + RX_POLARITY_FLIP: 0x13 + TX_POLARITY_FLIP: 0x4b + ? + PC_PM_ID: 32 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x05371426 + TX_LANE_MAP: 0x27315406 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0xaa + ? + PC_PM_ID: 33 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x20136754 + TX_LANE_MAP: 0x51704362 + RX_POLARITY_FLIP: 0xe3 + TX_POLARITY_FLIP: 0xe0 + ? + PC_PM_ID: 34 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x14062537 + TX_LANE_MAP: 0x02317645 + RX_POLARITY_FLIP: 0x96 + TX_POLARITY_FLIP: 0xd3 + ? + PC_PM_ID: 35 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x63517240 + TX_LANE_MAP: 0x41573062 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x7d + ? + PC_PM_ID: 36 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65174032 + TX_LANE_MAP: 0x25371604 + RX_POLARITY_FLIP: 0xbc + TX_POLARITY_FLIP: 0x4b + ? + PC_PM_ID: 37 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x07541362 + TX_LANE_MAP: 0x62035174 + RX_POLARITY_FLIP: 0x09 + TX_POLARITY_FLIP: 0xb0 + ? + PC_PM_ID: 38 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x47501632 + TX_LANE_MAP: 0x64507132 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0xbc + ? + PC_PM_ID: 39 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x73204165 + TX_LANE_MAP: 0x20153674 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0x23 + ? + PC_PM_ID: 40 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65017423 + TX_LANE_MAP: 0x50761243 + RX_POLARITY_FLIP: 0x9c + TX_POLARITY_FLIP: 0x5f + ? + PC_PM_ID: 41 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60214537 + TX_LANE_MAP: 0x61307245 + RX_POLARITY_FLIP: 0xbd + TX_POLARITY_FLIP: 0x0a + ? + PC_PM_ID: 42 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x47501632 + TX_LANE_MAP: 0x64507132 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0xac + ? + PC_PM_ID: 43 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x73204165 + TX_LANE_MAP: 0x20153674 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0x23 + ? + PC_PM_ID: 44 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65017423 + TX_LANE_MAP: 0x50761243 + RX_POLARITY_FLIP: 0x9c + TX_POLARITY_FLIP: 0x5f + ? + PC_PM_ID: 45 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x60214537 + TX_LANE_MAP: 0x61307245 + RX_POLARITY_FLIP: 0xbd + TX_POLARITY_FLIP: 0x0a + ? + PC_PM_ID: 46 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x47501632 + TX_LANE_MAP: 0x64507132 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0xac + ? + PC_PM_ID: 47 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x73204165 + TX_LANE_MAP: 0x20153674 + RX_POLARITY_FLIP: 0xd2 + TX_POLARITY_FLIP: 0x23 + ? + PC_PM_ID: 48 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x65017423 + TX_LANE_MAP: 0x50761243 + RX_POLARITY_FLIP: 0x9c + TX_POLARITY_FLIP: 0x5f + ? + PC_PM_ID: 49 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x25473160 + TX_LANE_MAP: 0x06743512 + RX_POLARITY_FLIP: 0xb2 + TX_POLARITY_FLIP: 0xe5 + ? + PC_PM_ID: 50 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x30157264 + TX_LANE_MAP: 0x01243675 + RX_POLARITY_FLIP: 0xd1 + TX_POLARITY_FLIP: 0x43 + ? + PC_PM_ID: 51 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06453721 + TX_LANE_MAP: 0x54627031 + RX_POLARITY_FLIP: 0x1b + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 52 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x21570346 + TX_LANE_MAP: 0x24306517 + RX_POLARITY_FLIP: 0xd1 + TX_POLARITY_FLIP: 0xe0 + ? + PC_PM_ID: 53 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x25473160 + TX_LANE_MAP: 0x06743512 + RX_POLARITY_FLIP: 0xb2 + TX_POLARITY_FLIP: 0xe5 + ? + PC_PM_ID: 54 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x30157264 + TX_LANE_MAP: 0x01243675 + RX_POLARITY_FLIP: 0xd1 + TX_POLARITY_FLIP: 0x43 + ? + PC_PM_ID: 55 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06453721 + TX_LANE_MAP: 0x54627031 + RX_POLARITY_FLIP: 0x1b + TX_POLARITY_FLIP: 0x9c + ? + PC_PM_ID: 56 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x21570346 + TX_LANE_MAP: 0x24306517 + RX_POLARITY_FLIP: 0xd1 + TX_POLARITY_FLIP: 0xe0 + ? + PC_PM_ID: 57 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x45273160 + TX_LANE_MAP: 0x06743512 + RX_POLARITY_FLIP: 0x12 + TX_POLARITY_FLIP: 0xe5 + ? + PC_PM_ID: 58 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x30157264 + TX_LANE_MAP: 0x01243675 + RX_POLARITY_FLIP: 0xd1 + TX_POLARITY_FLIP: 0x43 + ? + PC_PM_ID: 59 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x06453721 + TX_LANE_MAP: 0x64527031 + RX_POLARITY_FLIP: 0x1b + TX_POLARITY_FLIP: 0x38 + ? + PC_PM_ID: 60 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x74206531 + TX_LANE_MAP: 0x24013657 + RX_POLARITY_FLIP: 0xd6 + TX_POLARITY_FLIP: 0xaa + ? + PC_PM_ID: 61 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x72604351 + TX_LANE_MAP: 0x64571023 + RX_POLARITY_FLIP: 0x12 + TX_POLARITY_FLIP: 0xd3 + ? + PC_PM_ID: 62 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x46750132 + TX_LANE_MAP: 0x37162504 + RX_POLARITY_FLIP: 0x2a + TX_POLARITY_FLIP: 0xfb + ? + PC_PM_ID: 63 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x03512674 + TX_LANE_MAP: 0x43517062 + RX_POLARITY_FLIP: 0xdc + TX_POLARITY_FLIP: 0x4b + ? + PC_PM_ID: 64 + CORE_INDEX: 0 + : + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP: 0x05371426 + TX_LANE_MAP: 0x27315406 + RX_POLARITY_FLIP: 0xb0 + TX_POLARITY_FLIP: 0xd2 +... +--- +device: + 0: + PC_PORT_PHYS_MAP: + ? + PORT_ID: 0 + : + PC_PHYS_PORT_ID: 0 + ? + PORT_ID: 1 + : + PC_PHYS_PORT_ID: 1 + ? + PORT_ID: 2 + : + PC_PHYS_PORT_ID: 9 + ? + PORT_ID: 11 + : + PC_PHYS_PORT_ID: 17 + ? + PORT_ID: 12 + : + PC_PHYS_PORT_ID: 25 + ? + PORT_ID: 22 + : + PC_PHYS_PORT_ID: 33 + ? + PORT_ID: 23 + : + PC_PHYS_PORT_ID: 41 + ? + PORT_ID: 33 + : + PC_PHYS_PORT_ID: 49 + ? + PORT_ID: 34 + : + PC_PHYS_PORT_ID: 57 + ? + PORT_ID: 44 + : + PC_PHYS_PORT_ID: 65 + ? + PORT_ID: 45 + : + PC_PHYS_PORT_ID: 73 + ? + PORT_ID: 55 + : + PC_PHYS_PORT_ID: 81 + ? + PORT_ID: 56 + : + PC_PHYS_PORT_ID: 89 + ? + PORT_ID: 66 + : + PC_PHYS_PORT_ID: 97 + ? + PORT_ID: 67 + : + PC_PHYS_PORT_ID: 105 + ? + PORT_ID: 77 + : + PC_PHYS_PORT_ID: 113 + ? + PORT_ID: 78 + : + PC_PHYS_PORT_ID: 121 + ? + PORT_ID: 88 + : + PC_PHYS_PORT_ID: 129 + ? + PORT_ID: 89 + : + PC_PHYS_PORT_ID: 137 + ? + PORT_ID: 99 + : + PC_PHYS_PORT_ID: 145 + ? + PORT_ID: 100 + : + PC_PHYS_PORT_ID: 153 + ? + PORT_ID: 110 + : + PC_PHYS_PORT_ID: 161 + ? + PORT_ID: 111 + : + PC_PHYS_PORT_ID: 169 + ? + PORT_ID: 121 + : + PC_PHYS_PORT_ID: 177 + ? + PORT_ID: 122 + : + PC_PHYS_PORT_ID: 185 + ? + PORT_ID: 132 + : + PC_PHYS_PORT_ID: 193 + ? + PORT_ID: 133 + : + PC_PHYS_PORT_ID: 201 + ? + PORT_ID: 143 + : + PC_PHYS_PORT_ID: 209 + ? + PORT_ID: 144 + : + PC_PHYS_PORT_ID: 217 + ? + PORT_ID: 154 + : + PC_PHYS_PORT_ID: 225 + ? + PORT_ID: 155 + : + PC_PHYS_PORT_ID: 233 + ? + PORT_ID: 165 + : + PC_PHYS_PORT_ID: 241 + ? + PORT_ID: 166 + : + PC_PHYS_PORT_ID: 249 + ? + PORT_ID: 176 + : + PC_PHYS_PORT_ID: 257 + ? + PORT_ID: 177 + : + PC_PHYS_PORT_ID: 265 + ? + PORT_ID: 187 + : + PC_PHYS_PORT_ID: 273 + ? + PORT_ID: 188 + : + PC_PHYS_PORT_ID: 281 + ? + PORT_ID: 198 + : + PC_PHYS_PORT_ID: 289 + ? + PORT_ID: 199 + : + PC_PHYS_PORT_ID: 297 + ? + PORT_ID: 209 + : + PC_PHYS_PORT_ID: 305 + ? + PORT_ID: 210 + : + PC_PHYS_PORT_ID: 313 + ? + PORT_ID: 220 + : + PC_PHYS_PORT_ID: 321 + ? + PORT_ID: 221 + : + PC_PHYS_PORT_ID: 329 + ? + PORT_ID: 231 + : + PC_PHYS_PORT_ID: 337 + ? + PORT_ID: 232 + : + PC_PHYS_PORT_ID: 345 + ? + PORT_ID: 242 + : + PC_PHYS_PORT_ID: 353 + ? + PORT_ID: 243 + : + PC_PHYS_PORT_ID: 361 + ? + PORT_ID: 253 + : + PC_PHYS_PORT_ID: 369 + ? + PORT_ID: 254 + : + PC_PHYS_PORT_ID: 377 + ? + PORT_ID: 264 + : + PC_PHYS_PORT_ID: 385 + ? + PORT_ID: 265 + : + PC_PHYS_PORT_ID: 393 + ? + PORT_ID: 275 + : + PC_PHYS_PORT_ID: 401 + ? + PORT_ID: 276 + : + PC_PHYS_PORT_ID: 409 + ? + PORT_ID: 286 + : + PC_PHYS_PORT_ID: 417 + ? + PORT_ID: 287 + : + PC_PHYS_PORT_ID: 425 + ? + PORT_ID: 297 + : + PC_PHYS_PORT_ID: 433 + ? + PORT_ID: 298 + : + PC_PHYS_PORT_ID: 441 + ? + PORT_ID: 308 + : + PC_PHYS_PORT_ID: 449 + ? + PORT_ID: 309 + : + PC_PHYS_PORT_ID: 457 + ? + PORT_ID: 319 + : + PC_PHYS_PORT_ID: 465 + ? + PORT_ID: 320 + : + PC_PHYS_PORT_ID: 473 + ? + PORT_ID: 330 + : + PC_PHYS_PORT_ID: 481 + ? + PORT_ID: 331 + : + PC_PHYS_PORT_ID: 489 + ? + PORT_ID: 341 + : + PC_PHYS_PORT_ID: 497 + ? + PORT_ID: 342 + : + PC_PHYS_PORT_ID: 505 + ? + PORT_ID: 76 + : + PC_PHYS_PORT_ID: 513 + ? + PORT_ID: 164 + : + PC_PHYS_PORT_ID: 514 +... +--- +device: + 0: + PC_PORT: + ? + PORT_ID: [[1, 2], [11, 12], [22, 23], [33, 34], [44, 45], [55, 56], [66, 67], [77, 78], [88, 89], [99, 100], [110, 111], [121, 122], [132, 133], [143, 144], [154, 155], [165, 166], [176, 177], [187, 188], [198, 199], [209, 210], [220, 221], [231, 232], [242, 243], [253, 254], [264, 265], [275, 276], [286, 287], [297, 298], [308, 309], [319, 320], [330, 331], [341, 342]] + : + ENABLE: 0 + SPEED: 800000 + NUM_LANES: 8 + FEC_MODE: PC_FEC_RS544_2XN + MAX_FRAME_SIZE: 9416 + ? + PORT_ID: [76, 164] + : + ENABLE: 0 + SPEED: 25000 + NUM_LANES: 1 + FEC_MODE: PC_FEC_NONE + MAX_FRAME_SIZE: 9416 + ? + PORT_ID: 0 + : + ENABLE: 1 + SPEED: 10000 + NUM_LANES: 1 + FEC_MODE: PC_FEC_NONE + + PC_PMD_FIRMWARE: + ? + PORT_ID: [[1, 2], [11, 12], [22, 23], [33, 34], [44, 45], [55, 56], [66, 67], [77, 78], [88, 89], [99, 100], [110, 111], [121, 122], [132, 133], [143, 144], [154, 155], [165, 166], [176, 177], [187, 188], [198, 199], [209, 210], [220, 221], [231, 232], [242, 243], [253, 254], [264, 265], [275, 276], [286, 287], [297, 298], [308, 309], [319, 320], [330, 331], [341, 342]] + : + MEDIUM_TYPE_AUTO: 0 + MEDIUM_TYPE: PC_PHY_MEDIUM_COPPER + NORMAL_REACH_PAM4_AUTO: 1 + NORMAL_REACH_PAM4: 0xff + EXTENDED_REACH_PAM4_AUTO: 1 + EXTENDED_REACH_PAM4: 0xff + LP_TX_PRECODER_ON_AUTO: 1 + LP_TX_PRECODER_ON: 1 +... +--- +device: + 0: + # Per pipe flex counter configuration. Enable PPIU Mode + CTR_EFLEX_CONFIG: + CTR_ING_EFLEX_OPERMODE_PIPEUNIQUE: 1 + CTR_ING_EFLEX_OPERMODE_PIPE_INSTANCE_UNIQUE: 1 + CTR_EGR_EFLEX_OPERMODE_PIPEUNIQUE: 1 + CTR_EGR_EFLEX_OPERMODE_PIPE_INSTANCE_UNIQUE: 1 + + # IFP mode + FP_CONFIG: + FP_ING_OPERMODE: GLOBAL_PIPE_AWARE + DEVICE_CONFIG: + AUTOLOAD_BOARD_SETTINGS: 0 +... diff --git a/device/accton/x86_64-accton_as9817_64o-r0/custom_led.bin b/device/accton/x86_64-accton_as9817_64o-r0/custom_led.bin new file mode 100644 index 000000000000..382e876203d7 Binary files /dev/null and b/device/accton/x86_64-accton_as9817_64o-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as9817_64o-r0/default_sku b/device/accton/x86_64-accton_as9817_64o-r0/default_sku new file mode 100644 index 000000000000..f8d9b4a13e4c --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/default_sku @@ -0,0 +1 @@ +Accton-AS9817-64O t1 diff --git a/device/accton/x86_64-accton_as9817_64o-r0/fast-reboot_plugin b/device/accton/x86_64-accton_as9817_64o-r0/fast-reboot_plugin new file mode 120000 index 000000000000..295bfa58fbf3 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/fast-reboot_plugin @@ -0,0 +1 @@ +warm-reboot_plugin \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64o-r0/installer.conf b/device/accton/x86_64-accton_as9817_64o-r0/installer.conf new file mode 100644 index 000000000000..f16c4fd21270 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off pcie_aspm=off modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801,ast,ice" diff --git a/device/accton/x86_64-accton_as9817_64o-r0/led_proc_init.soc b/device/accton/x86_64-accton_as9817_64o-r0/led_proc_init.soc new file mode 100644 index 000000000000..ee89b29b479e --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/led_proc_init.soc @@ -0,0 +1,3 @@ +led 0 load /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/accton/x86_64-accton_as9817_64o-r0/pcie.yaml b/device/accton/x86_64-accton_as9817_64o-r0/pcie.yaml new file mode 100644 index 000000000000..dece12c1c957 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/pcie.yaml @@ -0,0 +1,452 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 09a2 + name: 'System peripheral: Intel Corporation Ice Lake Memory Map/VT-d (rev 04)' +- bus: '00' + dev: '00' + fn: '1' + id: 09a4 + name: 'System peripheral: Intel Corporation Ice Lake Mesh 2 PCIe (rev 04)' +- bus: '00' + dev: '00' + fn: '2' + id: 09a3 + name: 'System peripheral: Intel Corporation Ice Lake RAS (rev 04)' +- bus: '00' + dev: '00' + fn: '3' + id: 09a5 + name: 'System peripheral: Intel Corporation Device 09a5 (rev 04)' +- bus: '00' + dev: '00' + fn: '4' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: '00' + dev: '01' + fn: '0' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '1' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '2' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '3' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '4' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '5' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '6' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '01' + fn: '7' + id: '0b00' + name: 'System peripheral: Intel Corporation Ice Lake CBDMA [QuickData Technology]' +- bus: '00' + dev: '02' + fn: '0' + id: 09a6 + name: 'System peripheral: Intel Corporation Ice Lake MSM' +- bus: '00' + dev: '02' + fn: '1' + id: 09a7 + name: 'System peripheral: Intel Corporation Ice Lake PMON MSM' +- bus: '00' + dev: '02' + fn: '4' + id: '3456' + name: 'Non-Essential Instrumentation [1300]: Intel Corporation Ice Lake NorthPeak + (rev 01)' +- bus: '00' + dev: '06' + fn: '0' + id: 18da + name: 'PCI bridge: Intel Corporation Device 18da (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 18a4 + name: 'PCI bridge: Intel Corporation Device 18a4 (rev 11)' +- bus: '00' + dev: 0b + fn: '0' + id: 18a6 + name: 'PCI bridge: Intel Corporation Device 18a6 (rev 11)' +- bus: '00' + dev: 0e + fn: '0' + id: 18f2 + name: 'SATA controller: Intel Corporation Device 18f2 (rev 11)' +- bus: '00' + dev: 0f + fn: '0' + id: 18ac + name: 'System peripheral: Intel Corporation Device 18ac (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 18a8 + name: 'PCI bridge: Intel Corporation Device 18a8 (rev 11)' +- bus: '00' + dev: '14' + fn: '0' + id: 18ad + name: 'PCI bridge: Intel Corporation Device 18ad (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 18d3 + name: 'Communication controller: Intel Corporation Device 18d3 (rev 11)' +- bus: '00' + dev: '18' + fn: '1' + id: 18d4 + name: 'Communication controller: Intel Corporation Device 18d4 (rev 11)' +- bus: '00' + dev: '18' + fn: '4' + id: 18d6 + name: 'Communication controller: Intel Corporation Device 18d6 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 18d8 + name: 'Serial controller: Intel Corporation Device 18d8 (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 18d8 + name: 'Serial controller: Intel Corporation Device 18d8 (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 18d8 + name: 'Serial controller: Intel Corporation Device 18d8 (rev 11)' +- bus: '00' + dev: 1a + fn: '3' + id: 18d9 + name: 'Unassigned class [ff00]: Intel Corporation Device 18d9 (rev 11)' +- bus: '00' + dev: 1d + fn: '0' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: '00' + dev: 1e + fn: '0' + id: 18d0 + name: 'USB controller: Intel Corporation Device 18d0 (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 18dc + name: 'ISA bridge: Intel Corporation Device 18dc (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 18df + name: 'SMBus: Intel Corporation Device 18df (rev 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 18e0 + name: 'Serial bus controller: Intel Corporation Device 18e0 (rev 11)' +- bus: '00' + dev: 1f + fn: '7' + id: 18e1 + name: 'Non-Essential Instrumentation [1300]: Intel Corporation Device 18e1 (rev + 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 18ee + name: 'Co-processor: Intel Corporation 200xx Series QAT (rev 11)' +- bus: '02' + dev: '00' + fn: '0' + id: '7021' + name: 'Memory controller: Xilinx Corporation Device 7021' +- bus: '03' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '04' + dev: '00' + fn: '0' + id: '1150' + name: 'PCI bridge: ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge (rev 06)' +- bus: '05' + dev: '00' + fn: '0' + id: '2000' + name: 'VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family + (rev 52)' +- bus: '06' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '14' + dev: '00' + fn: '0' + id: 09a2 + name: 'System peripheral: Intel Corporation Ice Lake Memory Map/VT-d (rev 04)' +- bus: '14' + dev: '00' + fn: '1' + id: 09a4 + name: 'System peripheral: Intel Corporation Ice Lake Mesh 2 PCIe (rev 04)' +- bus: '14' + dev: '00' + fn: '2' + id: 09a3 + name: 'System peripheral: Intel Corporation Ice Lake RAS (rev 04)' +- bus: '14' + dev: '00' + fn: '3' + id: 09a5 + name: 'System peripheral: Intel Corporation Device 09a5 (rev 04)' +- bus: '14' + dev: '00' + fn: '4' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: '14' + dev: '02' + fn: '0' + id: 347a + name: 'PCI bridge: Intel Corporation Device 347a (rev 06)' +- bus: '14' + dev: '03' + fn: '0' + id: 347b + name: 'PCI bridge: Intel Corporation Device 347b (rev 06)' +- bus: '15' + dev: '00' + fn: '0' + id: f900 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM78900 Switch ASIC + [Tomahawk5] (rev 11)' +- bus: '16' + dev: '00' + fn: '0' + id: '5013' + name: 'Non-Volatile memory controller: Phison Electronics Corporation PS5013 E13 + NVMe Controller (rev 01)' +- bus: f3 + dev: '00' + fn: '0' + id: 09a2 + name: 'System peripheral: Intel Corporation Ice Lake Memory Map/VT-d (rev 04)' +- bus: f3 + dev: '00' + fn: '1' + id: 09a4 + name: 'System peripheral: Intel Corporation Ice Lake Mesh 2 PCIe (rev 04)' +- bus: f3 + dev: '00' + fn: '2' + id: 09a3 + name: 'System peripheral: Intel Corporation Ice Lake RAS (rev 04)' +- bus: f3 + dev: '00' + fn: '3' + id: 09a5 + name: 'System peripheral: Intel Corporation Device 09a5 (rev 04)' +- bus: f3 + dev: '00' + fn: '4' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: f3 + dev: '04' + fn: '0' + id: 18d1 + name: 'PCI bridge: Intel Corporation Device 18d1' +- bus: f4 + dev: '00' + fn: '0' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: f4 + dev: '00' + fn: '1' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: f4 + dev: '00' + fn: '2' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: f4 + dev: '00' + fn: '3' + id: 124c + name: 'Ethernet controller: Intel Corporation Ethernet Connection E823-L for backplane' +- bus: fe + dev: '00' + fn: '0' + id: '3450' + name: 'System peripheral: Intel Corporation Device 3450' +- bus: fe + dev: '00' + fn: '1' + id: '3451' + name: 'System peripheral: Intel Corporation Device 3451' +- bus: fe + dev: '00' + fn: '2' + id: '3452' + name: 'System peripheral: Intel Corporation Device 3452' +- bus: fe + dev: '00' + fn: '3' + id: 0998 + name: 'Host bridge: Intel Corporation Ice Lake IEH' +- bus: fe + dev: '00' + fn: '5' + id: '3455' + name: 'System peripheral: Intel Corporation Device 3455' +- bus: fe + dev: 0b + fn: '0' + id: '3448' + name: 'System peripheral: Intel Corporation Device 3448' +- bus: fe + dev: 0b + fn: '1' + id: '3448' + name: 'System peripheral: Intel Corporation Device 3448' +- bus: fe + dev: 0b + fn: '2' + id: 344b + name: 'System peripheral: Intel Corporation Device 344b' +- bus: fe + dev: 0c + fn: '0' + id: 344a + name: 'Performance counters: Intel Corporation Device 344a' +- bus: fe + dev: 1a + fn: '0' + id: '2880' + name: 'Performance counters: Intel Corporation Device 2880' +- bus: ff + dev: '00' + fn: '0' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: '00' + fn: '1' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: '00' + fn: '2' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: '00' + fn: '3' + id: 344c + name: 'System peripheral: Intel Corporation Device 344c' +- bus: ff + dev: 0a + fn: '0' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 0a + fn: '1' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 0a + fn: '2' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 0a + fn: '3' + id: 344d + name: 'System peripheral: Intel Corporation Device 344d' +- bus: ff + dev: 1d + fn: '0' + id: 344f + name: 'System peripheral: Intel Corporation Device 344f' +- bus: ff + dev: 1d + fn: '1' + id: '3457' + name: 'System peripheral: Intel Corporation Device 3457' +- bus: ff + dev: 1e + fn: '0' + id: '3458' + name: 'System peripheral: Intel Corporation Device 3458 (rev 01)' +- bus: ff + dev: 1e + fn: '1' + id: '3459' + name: 'System peripheral: Intel Corporation Device 3459 (rev 01)' +- bus: ff + dev: 1e + fn: '2' + id: 345a + name: 'System peripheral: Intel Corporation Device 345a (rev 01)' +- bus: ff + dev: 1e + fn: '3' + id: 345b + name: 'System peripheral: Intel Corporation Device 345b (rev 01)' +- bus: ff + dev: 1e + fn: '4' + id: 345c + name: 'System peripheral: Intel Corporation Device 345c (rev 01)' +- bus: ff + dev: 1e + fn: '5' + id: 345d + name: 'System peripheral: Intel Corporation Device 345d (rev 01)' +- bus: ff + dev: 1e + fn: '6' + id: 345e + name: 'System peripheral: Intel Corporation Device 345e (rev 01)' +- bus: ff + dev: 1e + fn: '7' + id: 345f + name: 'System peripheral: Intel Corporation Device 345f (rev 01)' diff --git a/device/accton/x86_64-accton_as9817_64o-r0/platform.json b/device/accton/x86_64-accton_as9817_64o-r0/platform.json new file mode 100644 index 000000000000..ebe0ff704e37 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/platform.json @@ -0,0 +1,1383 @@ +{ + "chassis": { + "name": "AS9817-64O", + "thermal_manager":false, + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_RED", "STATUS_LED_COLOR_OFF"] + }, + "components": [ + { + "name": "CPLD1" + }, + { + "name": "CPLD2" + }, + { + "name": "CPLD3" + }, + { + "name": "FPGA" + }, + { + "name": "BIOS" + } + ], + "fans": [ + { + "name": "FAN-1F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-1R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-1F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-1R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray2", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-2F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray3", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-3F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray4", + "status_led": { + "controllable": false + }, + "num_fans" : 2, + "fans": [ + { + "name": "FAN-4F", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4R", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + } + ], + "psus": [ + { + "name": "PSU-1", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU-1 FAN-1", + "speed": { + "controllable": false + }, + "status_led": { + "controllable": false + } + } + ], + "thermals": [ + { + "name": "PSU-1 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-1 temp sensor 2", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-1 temp sensor 3", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + }, + { + "name": "PSU-2", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU-2 FAN-1", + "speed": { + "controllable": false + }, + "status_led": { + "controllable": false + } + } + ], + "thermals": [ + { + "name": "PSU-2 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-2 temp sensor 2", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "PSU-2 temp sensor 3", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + } + ], + "thermals": [ + { + "name": "MB_RearCenter_temp(0x48)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearRight_temp(0x49)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearCenter_temp(0x4A)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearLeft_temp(0x4B)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_FrontLeft_temp(0x4C)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_FrontRight_temp(0x4D)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "FB_temp(0x4D)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "FB_temp(0x4E)", + "controllable": false, + "low-threshold": false, + "high-threshold": false, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "CPU_Package_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_0_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_1_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_2_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_3_temp", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + } + ], + "sfps": [ + { + "name": "Ethernet0" + }, + { + "name": "Ethernet8" + }, + { + "name": "Ethernet16" + }, + { + "name": "Ethernet24" + }, + { + "name": "Ethernet32" + }, + { + "name": "Ethernet40" + }, + { + "name": "Ethernet48" + }, + { + "name": "Ethernet56" + }, + { + "name": "Ethernet64" + }, + { + "name": "Ethernet72" + }, + { + "name": "Ethernet80" + }, + { + "name": "Ethernet88" + }, + { + "name": "Ethernet96" + }, + { + "name": "Ethernet104" + }, + { + "name": "Ethernet112" + }, + { + "name": "Ethernet120" + }, + { + "name": "Ethernet128" + }, + { + "name": "Ethernet136" + }, + { + "name": "Ethernet144" + }, + { + "name": "Ethernet152" + }, + { + "name": "Ethernet160" + }, + { + "name": "Ethernet168" + }, + { + "name": "Ethernet176" + }, + { + "name": "Ethernet184" + }, + { + "name": "Ethernet192" + }, + { + "name": "Ethernet200" + }, + { + "name": "Ethernet208" + }, + { + "name": "Ethernet216" + }, + { + "name": "Ethernet224" + }, + { + "name": "Ethernet232" + }, + { + "name": "Ethernet240" + }, + { + "name": "Ethernet248" + }, + { + "name": "Ethernet256" + }, + { + "name": "Ethernet264" + }, + { + "name": "Ethernet272" + }, + { + "name": "Ethernet280" + }, + { + "name": "Ethernet288" + }, + { + "name": "Ethernet296" + }, + { + "name": "Ethernet304" + }, + { + "name": "Ethernet312" + }, + { + "name": "Ethernet320" + }, + { + "name": "Ethernet328" + }, + { + "name": "Ethernet336" + }, + { + "name": "Ethernet344" + }, + { + "name": "Ethernet352" + }, + { + "name": "Ethernet360" + }, + { + "name": "Ethernet368" + }, + { + "name": "Ethernet376" + }, + { + "name": "Ethernet384" + }, + { + "name": "Ethernet392" + }, + { + "name": "Ethernet400" + }, + { + "name": "Ethernet408" + }, + { + "name": "Ethernet416" + }, + { + "name": "Ethernet424" + }, + { + "name": "Ethernet432" + }, + { + "name": "Ethernet440" + }, + { + "name": "Ethernet448" + }, + { + "name": "Ethernet456" + }, + { + "name": "Ethernet464" + }, + { + "name": "Ethernet472" + }, + { + "name": "Ethernet480" + }, + { + "name": "Ethernet488" + }, + { + "name": "Ethernet496" + }, + { + "name": "Ethernet504" + }, + { + "name": "Ethernet512" + }, + { + "name": "Ethernet513" + } + ] + }, + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1,1,1,1,1", + "lanes": "25,26,27,28,29,30,31,32", + "breakout_modes": { + "1x800G": ["Eth1(Port1)"], + "1x400G": ["Eth1(Port1)"], + "2x400G[200G]": ["Eth1/1(Port1)", "Eth1/2(Port1)"], + "4x200G[100G]": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"], + "4x100G[50G](4)": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"], + "1x100G(4)": ["Eth1(Port1)"], + "2x50G(4)": ["Eth1/1(Port1)", "Eth1/2(Port1)"] + } + }, + + "Ethernet8": { + "index": "2,2,2,2,2,2,2,2", + "lanes": "9,10,11,12,13,14,15,16", + "breakout_modes": { + "1x800G": ["Eth2(Port2)"], + "1x400G": ["Eth2(Port2)"], + "2x400G[200G]": ["Eth2/1(Port2)", "Eth2/2(Port2)"], + "4x200G[100G]": ["Eth2/1(Port2)", "Eth2/2(Port2)", "Eth2/3(Port2)", "Eth2/4(Port2)"], + "4x100G[50G](4)": ["Eth2/1(Port2)", "Eth2/2(Port2)", "Eth2/3(Port2)", "Eth2/4(Port2)"], + "1x100G(4)": ["Eth2(Port2)"], + "2x50G(4)": ["Eth2/1(Port2)", "Eth2/2(Port2)"] + } + }, + + "Ethernet16": { + "index": "3,3,3,3,3,3,3,3", + "lanes": "49,50,51,52,53,54,55,56", + "breakout_modes": { + "1x800G": ["Eth3(Port3)"], + "1x400G": ["Eth3(Port3)"], + "2x400G[200G]": ["Eth3/1(Port3)", "Eth3/2(Port3)"], + "4x200G[100G]": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"], + "4x100G[50G](4)": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"], + "1x100G(4)": ["Eth3(Port3)"], + "2x50G(4)": ["Eth3/1(Port3)", "Eth3/2(Port3)"] + } + }, + + "Ethernet24": { + "index": "4,4,4,4,4,4,4,4", + "lanes": "33,34,35,36,37,38,39,40", + "breakout_modes": { + "1x800G": ["Eth4(Port4)"], + "1x400G": ["Eth4(Port4)"], + "2x400G[200G]": ["Eth4/1(Port4)", "Eth4/2(Port4)"], + "4x200G[100G]": ["Eth4/1(Port4)", "Eth4/2(Port4)", "Eth4/3(Port4)", "Eth4/4(Port4)"], + "4x100G[50G](4)": ["Eth4/1(Port4)", "Eth4/2(Port4)", "Eth4/3(Port4)", "Eth4/4(Port4)"], + "1x100G(4)": ["Eth4(Port4)"], + "2x50G(4)": ["Eth4/1(Port4)", "Eth4/2(Port4)"] + } + }, + + "Ethernet32": { + "index": "5,5,5,5,5,5,5,5", + "lanes": "81,82,83,84,85,86,87,88", + "breakout_modes": { + "1x800G": ["Eth5(Port5)"], + "1x400G": ["Eth5(Port5)"], + "2x400G[200G]": ["Eth5/1(Port5)", "Eth5/2(Port5)"], + "4x200G[100G]": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"], + "4x100G[50G](4)": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"], + "1x100G(4)": ["Eth5(Port5)"], + "2x50G(4)": ["Eth5/1(Port5)", "Eth5/2(Port5)"] + } + }, + + "Ethernet40": { + "index": "6,6,6,6,6,6,6,6", + "lanes": "65,66,67,68,69,70,71,72", + "breakout_modes": { + "1x800G": ["Eth6(Port6)"], + "1x400G": ["Eth6(Port6)"], + "2x400G[200G]": ["Eth6/1(Port6)", "Eth6/2(Port6)"], + "4x200G[100G]": ["Eth6/1(Port6)", "Eth6/2(Port6)", "Eth6/3(Port6)", "Eth6/4(Port6)"], + "4x100G[50G](4)": ["Eth6/1(Port6)", "Eth6/2(Port6)", "Eth6/3(Port6)", "Eth6/4(Port6)"], + "1x100G(4)": ["Eth6(Port6)"], + "2x50G(4)": ["Eth6/1(Port6)", "Eth6/2(Port6)"] + } + }, + + "Ethernet48": { + "index": "7,7,7,7,7,7,7,7", + "lanes": "113,114,115,116,117,118,119,120", + "breakout_modes": { + "1x800G": ["Eth7(Port7)"], + "1x400G": ["Eth7(Port7)"], + "2x400G[200G]": ["Eth7/1(Port7)", "Eth7/2(Port7)"], + "4x200G[100G]": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"], + "4x100G[50G](4)": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"], + "1x100G(4)": ["Eth7(Port7)"], + "2x50G(4)": ["Eth7/1(Port7)", "Eth7/2(Port7)"] + } + }, + + "Ethernet56": { + "index": "8,8,8,8,8,8,8,8", + "lanes": "97,98,99,100,101,102,103,104", + "breakout_modes": { + "1x800G": ["Eth8(Port8)"], + "1x400G": ["Eth8(Port8)"], + "2x400G[200G]": ["Eth8/1(Port8)", "Eth8/2(Port8)"], + "4x200G[100G]": ["Eth8/1(Port8)", "Eth8/2(Port8)", "Eth8/3(Port8)", "Eth8/4(Port8)"], + "4x100G[50G](4)": ["Eth8/1(Port8)", "Eth8/2(Port8)", "Eth8/3(Port8)", "Eth8/4(Port8)"], + "1x100G(4)": ["Eth8(Port8)"], + "2x50G(4)": ["Eth8/1(Port8)", "Eth8/2(Port8)"] + } + }, + + "Ethernet64": { + "index": "9,9,9,9,9,9,9,9", + "lanes": "145,146,147,148,149,150,151,152", + "breakout_modes": { + "1x800G": ["Eth9(Port9)"], + "1x400G": ["Eth9(Port9)"], + "2x400G[200G]": ["Eth9/1(Port9)", "Eth9/2(Port9)"], + "4x200G[100G]": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"], + "4x100G[50G](4)": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"], + "1x100G(4)": ["Eth9(Port9)"], + "2x50G(4)": ["Eth9/1(Port9)", "Eth9/2(Port9)"] + } + }, + + "Ethernet72": { + "index": "10,10,10,10,10,10,10,10", + "lanes": "129,130,131,132,133,134,135,136", + "breakout_modes": { + "1x800G": ["Eth10(Port10)"], + "1x400G": ["Eth10(Port10)"], + "2x400G[200G]": ["Eth10/1(Port10)", "Eth10/2(Port10)"], + "4x200G[100G]": ["Eth10/1(Port10)", "Eth10/2(Port10)", "Eth10/3(Port10)", "Eth10/4(Port10)"], + "4x100G[50G](4)": ["Eth10/1(Port10)", "Eth10/2(Port10)", "Eth10/3(Port10)", "Eth10/4(Port10)"], + "1x100G(4)": ["Eth10(Port10)"], + "2x50G(4)": ["Eth10/1(Port10)", "Eth10/2(Port10)"] + } + }, + + "Ethernet80": { + "index": "11,11,11,11,11,11,11,11", + "lanes": "177,178,179,180,181,182,183,184", + "breakout_modes": { + "1x800G": ["Eth11(Port11)"], + "1x400G": ["Eth11(Port11)"], + "2x400G[200G]": ["Eth11/1(Port11)", "Eth11/2(Port11)"], + "4x200G[100G]": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"], + "4x100G[50G](4)": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"], + "1x100G(4)": ["Eth11(Port11)"], + "2x50G(4)": ["Eth11/1(Port11)", "Eth11/2(Port11)"] + } + }, + + "Ethernet88": { + "index": "12,12,12,12,12,12,12,12", + "lanes": "161,162,163,164,165,166,167,168", + "breakout_modes": { + "1x800G": ["Eth12(Port12)"], + "1x400G": ["Eth12(Port12)"], + "2x400G[200G]": ["Eth12/1(Port12)", "Eth12/2(Port12)"], + "4x200G[100G]": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"], + "4x100G[50G](4)": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"], + "1x100G(4)": ["Eth17(Port17)"], + "2x50G(4)": ["Eth17/1(Port17)", "Eth17/2(Port17)"] + } + }, + + "Ethernet136": { + "index": "18,18,18,18,18,18,18,18", + "lanes": "265,266,267,268,269,270,271,272", + "breakout_modes": { + "1x800G": ["Eth18(Port18)"], + "1x400G": ["Eth18(Port18)"], + "2x400G[200G]": ["Eth18/1(Port18)", "Eth18/2(Port18)"], + "4x200G[100G]": ["Eth18/1(Port18)", "Eth18/2(Port18)", "Eth18/3(Port18)", "Eth18/4(Port18)"], + "4x100G[50G](4)": ["Eth18/1(Port18)", "Eth18/2(Port18)", "Eth18/3(Port18)", "Eth18/4(Port18)"], + "1x100G(4)": ["Eth18(Port18)"], + "2x50G(4)": ["Eth18/1(Port18)", "Eth18/2(Port18)"] + } + }, + + "Ethernet144": { + "index": "19,19,19,19,19,19,19,19", + "lanes": "305,306,307,308,309,310,311,312", + "breakout_modes": { + "1x800G": ["Eth19(Port19)"], + "1x400G": ["Eth19(Port19)"], + "2x400G[200G]": ["Eth19/1(Port19)", "Eth19/2(Port19)"], + "4x200G[100G]": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"], + "4x100G[50G](4)": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"], + "1x100G(4)": ["Eth19(Port19)"], + "2x50G(4)": ["Eth19/1(Port19)", "Eth19/2(Port19)"] + } + }, + + "Ethernet152": { + "index": "20,20,20,20,20,20,20,20", + "lanes": "289,290,291,292,293,294,295,296", + "breakout_modes": { + "1x800G": ["Eth20(Port20)"], + "1x400G": ["Eth20(Port20)"], + "2x400G[200G]": ["Eth20/1(Port20)", "Eth20/2(Port20)"], + "4x200G[100G]": ["Eth20/1(Port20)", "Eth20/2(Port20)", "Eth20/3(Port20)", "Eth20/4(Port20)"], + "4x100G[50G](4)": ["Eth20/1(Port20)", "Eth20/2(Port20)", "Eth20/3(Port20)", "Eth20/4(Port20)"], + "1x100G(4)": ["Eth20(Port20)"], + "2x50G(4)": ["Eth20/1(Port20)", "Eth20/2(Port20)"] + } + }, + + "Ethernet160": { + "index": "21,21,21,21,21,21,21,21", + "lanes": "337,338,339,340,341,342,343,344", + "breakout_modes": { + "1x800G": ["Eth21(Port21)"], + "1x400G": ["Eth21(Port21)"], + "2x400G[200G]": ["Eth21/1(Port21)", "Eth21/2(Port21)"], + "4x200G[100G]": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"], + "4x100G[50G](4)": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"], + "1x100G(4)": ["Eth21(Port21)"], + "2x50G(4)": ["Eth21/1(Port21)", "Eth21/2(Port21)"] + } + }, + + "Ethernet168": { + "index": "22,22,22,22,22,22,22,22", + "lanes": "321,322,323,324,325,326,327,328", + "breakout_modes": { + "1x800G": ["Eth22(Port22)"], + "1x400G": ["Eth22(Port22)"], + "2x400G[200G]": ["Eth22/1(Port22)", "Eth22/2(Port22)"], + "4x200G[100G]": ["Eth22/1(Port22)", "Eth22/2(Port22)", "Eth22/3(Port22)", "Eth22/4(Port22)"], + "4x100G[50G](4)": ["Eth22/1(Port22)", "Eth22/2(Port22)", "Eth22/3(Port22)", "Eth22/4(Port22)"], + "1x100G(4)": ["Eth22(Port22)"], + "2x50G(4)": ["Eth22/1(Port22)", "Eth22/2(Port22)"] + } + }, + + "Ethernet176": { + "index": "23,23,23,23,23,23,23,23", + "lanes": "369,370,371,372,373,374,375,376", + "breakout_modes": { + "1x800G": ["Eth23(Port23)"], + "1x400G": ["Eth23(Port23)"], + "2x400G[200G]": ["Eth23/1(Port23)", "Eth23/2(Port23)"], + "4x200G[100G]": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"], + "4x100G[50G](4)": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"], + "1x100G(4)": ["Eth23(Port23)"], + "2x50G(4)": ["Eth23/1(Port23)", "Eth23/2(Port23)"] + } + }, + + "Ethernet184": { + "index": "24,24,24,24,24,24,24,24", + "lanes": "353,354,355,356,357,358,359,360", + "breakout_modes": { + "1x800G": ["Eth24(Port24)"], + "1x400G": ["Eth24(Port24)"], + "2x400G[200G]": ["Eth24/1(Port24)", "Eth24/2(Port24)"], + "4x200G[100G]": ["Eth24/1(Port24)", "Eth24/2(Port24)", "Eth24/3(Port24)", "Eth24/4(Port24)"], + "4x100G[50G](4)": ["Eth24/1(Port24)", "Eth24/2(Port24)", "Eth24/3(Port24)", "Eth24/4(Port24)"], + "1x100G(4)": ["Eth24(Port24)"], + "2x50G(4)": ["Eth24/1(Port24)", "Eth24/2(Port24)"] + } + }, + + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "401,402,403,404,405,406,407,408", + "breakout_modes": { + "1x800G": ["Eth25(Port25)"], + "1x400G": ["Eth25(Port25)"], + "2x400G[200G]": ["Eth25/1(Port25)", "Eth25/2(Port25)"], + "4x200G[100G]": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"], + "4x100G[50G](4)": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"], + "1x100G(4)": ["Eth25(Port25)"], + "2x50G(4)": ["Eth25/1(Port25)", "Eth25/2(Port25)"] + } + }, + + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "385,386,387,388,389,390,391,392", + "breakout_modes": { + "1x800G": ["Eth26(Port26)"], + "1x400G": ["Eth26(Port26)"], + "2x400G[200G]": ["Eth26/1(Port26)", "Eth26/2(Port26)"], + "4x200G[100G]": ["Eth26/1(Port26)", "Eth26/2(Port26)", "Eth26/3(Port26)", "Eth26/4(Port26)"], + "4x100G[50G](4)": ["Eth26/1(Port26)", "Eth26/2(Port26)", "Eth26/3(Port26)", "Eth26/4(Port26)"], + "1x100G(4)": ["Eth26(Port26)"], + "2x50G(4)": ["Eth26/1(Port26)", "Eth26/2(Port26)"] + } + }, + + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "433,434,435,436,437,438,439,440", + "breakout_modes": { + "1x800G": ["Eth27(Port27)"], + "1x400G": ["Eth27(Port27)"], + "2x400G[200G]": ["Eth27/1(Port27)", "Eth27/2(Port27)"], + "4x200G[100G]": ["Eth32/1(Port32)", "Eth32/2(Port32)", "Eth32/3(Port32)", "Eth32/4(Port32)"], + "4x100G[50G](4)": ["Eth32/1(Port32)", "Eth32/2(Port32)", "Eth32/3(Port32)", "Eth32/4(Port32)"], + "1x100G(4)": ["Eth32(Port32)"], + "2x50G(4)": ["Eth32/1(Port32)", "Eth32/2(Port32)"] + } + }, + + "Ethernet256": { + "index": "33,33,33,33,33,33,33,33", + "lanes": "1,2,3,4,5,6,7,8", + "breakout_modes": { + "1x800G": ["Eth33(Port33)"], + "1x400G": ["Eth33(Port33)"], + "2x400G[200G]": ["Eth33/1(Port33)", "Eth33/2(Port33)"], + "4x200G[100G]": ["Eth33/1(Port33)", "Eth33/2(Port33)", "Eth33/3(Port33)", "Eth33/4(Port33)"], + "4x100G[50G](4)": ["Eth33/1(Port33)", "Eth33/2(Port33)", "Eth33/3(Port33)", "Eth33/4(Port33)"], + "1x100G(4)": ["Eth33(Port33)"], + "2x50G(4)": ["Eth33/1(Port33)", "Eth33/2(Port33)"] + } + }, + + "Ethernet264": { + "index": "34,34,34,34,34,34,34,34", + "lanes": "17,18,19,20,21,22,23,24", + "breakout_modes": { + "1x800G": ["Eth34(Port34)"], + "1x400G": ["Eth34(Port34)"], + "2x400G[200G]": ["Eth34/1(Port34)", "Eth34/2(Port34)"], + "4x200G[100G]": ["Eth34/1(Port34)", "Eth34/2(Port34)", "Eth34/3(Port34)", "Eth34/4(Port34)"], + "4x100G[50G](4)": ["Eth34/1(Port34)", "Eth34/2(Port34)", "Eth34/3(Port34)", "Eth34/4(Port34)"], + "1x100G(4)": ["Eth34(Port34)"], + "2x50G(4)": ["Eth34/1(Port34)", "Eth34/2(Port34)"] + } + }, + + "Ethernet272": { + "index": "35,35,35,35,35,35,35,35", + "lanes": "41,42,43,44,45,46,47,48", + "breakout_modes": { + "1x800G": ["Eth35(Port35)"], + "1x400G": ["Eth35(Port35)"], + "2x400G[200G]": ["Eth35/1(Port35)", "Eth35/2(Port35)"], + "4x200G[100G]": ["Eth35/1(Port35)", "Eth35/2(Port35)", "Eth35/3(Port35)", "Eth35/4(Port35)"], + "4x100G[50G](4)": ["Eth35/1(Port35)", "Eth35/2(Port35)", "Eth35/3(Port35)", "Eth35/4(Port35)"], + "1x100G(4)": ["Eth35(Port35)"], + "2x50G(4)": ["Eth35/1(Port35)", "Eth35/2(Port35)"] + } + }, + + "Ethernet280": { + "index": "36,36,36,36,36,36,36,36", + "lanes": "57,58,59,60,61,62,63,64", + "breakout_modes": { + "1x800G": ["Eth36(Port36)"], + "1x400G": ["Eth36(Port36)"], + "2x400G[200G]": ["Eth36/1(Port36)", "Eth36/2(Port36)"], + "4x200G[100G]": ["Eth36/1(Port36)", "Eth36/2(Port36)", "Eth36/3(Port36)", "Eth36/4(Port36)"], + "4x100G[50G](4)": ["Eth36/1(Port36)", "Eth36/2(Port36)", "Eth36/3(Port36)", "Eth36/4(Port36)"], + "1x100G(4)": ["Eth36(Port36)"], + "2x50G(4)": ["Eth36/1(Port36)", "Eth36/2(Port36)"] + } + }, + + "Ethernet288": { + "index": "37,37,37,37,37,37,37,37", + "lanes": "73,74,75,76,77,78,79,80", + "breakout_modes": { + "1x800G": ["Eth37(Port37)"], + "1x400G": ["Eth37(Port37)"], + "2x400G[200G]": ["Eth37/1(Port37)", "Eth37/2(Port37)"], + "4x200G[100G]": ["Eth37/1(Port37)", "Eth37/2(Port37)", "Eth37/3(Port37)", "Eth37/4(Port37)"], + "4x100G[50G](4)": ["Eth37/1(Port37)", "Eth37/2(Port37)", "Eth37/3(Port37)", "Eth37/4(Port37)"], + "1x100G(4)": ["Eth37(Port37)"], + "2x50G(4)": ["Eth37/1(Port37)", "Eth37/2(Port37)"] + } + }, + + "Ethernet296": { + "index": "38,38,38,38,38,38,38,38", + "lanes": "89,90,91,92,93,94,95,96", + "breakout_modes": { + "1x800G": ["Eth38(Port38)"], + "1x400G": ["Eth38(Port38)"], + "2x400G[200G]": ["Eth38/1(Port38)", "Eth38/2(Port38)"], + "4x200G[100G]": ["Eth38/1(Port38)", "Eth38/2(Port38)", "Eth38/3(Port38)", "Eth38/4(Port38)"], + "4x100G[50G](4)": ["Eth38/1(Port38)", "Eth38/2(Port38)", "Eth38/3(Port38)", "Eth38/4(Port38)"], + "1x100G(4)": ["Eth38(Port38)"], + "2x50G(4)": ["Eth38/1(Port38)", "Eth38/2(Port38)"] + } + }, + + "Ethernet304": { + "index": "39,39,39,39,39,39,39,39", + "lanes": "105,106,107,108,109,110,111,112", + "breakout_modes": { + "1x800G": ["Eth39(Port39)"], + "1x400G": ["Eth39(Port39)"], + "2x400G[200G]": ["Eth39/1(Port39)", "Eth39/2(Port39)"], + "4x200G[100G]": ["Eth39/1(Port39)", "Eth39/2(Port39)", "Eth39/3(Port39)", "Eth39/4(Port39)"], + "4x100G[50G](4)": ["Eth39/1(Port39)", "Eth39/2(Port39)", "Eth39/3(Port39)", "Eth39/4(Port39)"], + "1x100G(4)": ["Eth39(Port39)"], + "2x50G(4)": ["Eth39/1(Port39)", "Eth39/2(Port39)"] + } + }, + + "Ethernet312": { + "index": "40,40,40,40,40,40,40,40", + "lanes": "121,122,123,124,125,126,127,128", + "breakout_modes": { + "1x800G": ["Eth40(Port40)"], + "1x400G": ["Eth40(Port40)"], + "2x400G[200G]": ["Eth40/1(Port40)", "Eth40/2(Port40)"], + "4x200G[100G]": ["Eth40/1(Port40)", "Eth40/2(Port40)", "Eth40/3(Port40)", "Eth40/4(Port40)"], + "4x100G[50G](4)": ["Eth40/1(Port40)", "Eth40/2(Port40)", "Eth40/3(Port40)", "Eth40/4(Port40)"], + "1x100G(4)": ["Eth40(Port40)"], + "2x50G(4)": ["Eth40/1(Port40)", "Eth40/2(Port40)"] + } + }, + + "Ethernet320": { + "index": "41,41,41,41,41,41,41,41", + "lanes": "137,138,139,140,141,142,143,144", + "breakout_modes": { + "1x800G": ["Eth41(Port41)"], + "1x400G": ["Eth41(Port41)"], + "2x400G[200G]": ["Eth41/1(Port41)", "Eth41/2(Port41)"], + "4x200G[100G]": ["Eth41/1(Port41)", "Eth41/2(Port41)", "Eth41/3(Port41)", "Eth41/4(Port41)"], + "4x100G[50G](4)": ["Eth41/1(Port41)", "Eth41/2(Port41)", "Eth41/3(Port41)", "Eth41/4(Port41)"], + "1x100G(4)": ["Eth41(Port41)"], + "2x50G(4)": ["Eth41/1(Port41)", "Eth41/2(Port41)"] + } + }, + + "Ethernet328": { + "index": "42,42,42,42,42,42,42,42", + "lanes": "153,154,155,156,157,158,159,160", + "breakout_modes": { + "1x800G": ["Eth42(Port42)"], + "1x400G": ["Eth42(Port42)"], + "2x400G[200G]": ["Eth42/1(Port42)", "Eth42/2(Port42)"], + "4x200G[100G]": ["Eth42/1(Port42)", "Eth42/2(Port42)", "Eth42/3(Port42)", "Eth42/4(Port42)"], + "4x100G[50G](4)": ["Eth42/1(Port42)", "Eth42/2(Port42)", "Eth42/3(Port42)", "Eth42/4(Port42)"], + "1x100G(4)": ["Eth42(Port42)"], + "2x50G(4)": ["Eth42/1(Port42)", "Eth42/2(Port42)"] + } + }, + + "Ethernet336": { + "index": "43,43,43,43,43,43,43,43", + "lanes": "169,170,171,172,173,174,175,176", + "breakout_modes": { + "1x800G": ["Eth43(Port43)"], + "1x400G": ["Eth43(Port43)"], + "2x400G[200G]": ["Eth43/1(Port43)", "Eth43/2(Port43)"], + "4x200G[100G]": ["Eth43/1(Port43)", "Eth43/2(Port43)", "Eth43/3(Port43)", "Eth43/4(Port43)"], + "4x100G[50G](4)": ["Eth43/1(Port43)", "Eth43/2(Port43)", "Eth43/3(Port43)", "Eth43/4(Port43)"], + "1x100G(4)": ["Eth43(Port43)"], + "2x50G(4)": ["Eth43/1(Port43)", "Eth43/2(Port43)"] + } + }, + + "Ethernet344": { + "index": "44,44,44,44,44,44,44,44", + "lanes": "185,186,187,188,189,190,191,192", + "breakout_modes": { + "1x800G": ["Eth44(Port44)"], + "1x400G": ["Eth44(Port44)"], + "2x400G[200G]": ["Eth44/1(Port44)", "Eth44/2(Port44)"], + "4x200G[100G]": ["Eth44/1(Port44)", "Eth44/2(Port44)", "Eth44/3(Port44)", "Eth44/4(Port44)"], + "4x100G[50G](4)": ["Eth44/1(Port44)", "Eth44/2(Port44)", "Eth44/3(Port44)", "Eth44/4(Port44)"], + "1x100G(4)": ["Eth44(Port44)"], + "2x50G(4)": ["Eth44/1(Port44)", "Eth44/2(Port44)"] + } + }, + + "Ethernet352": { + "index": "45,45,45,45,45,45,45,45", + "lanes": "201,202,203,204,205,206,207,208", + "breakout_modes": { + "1x800G": ["Eth45(Port45)"], + "1x400G": ["Eth45(Port45)"], + "2x400G[200G]": ["Eth45/1(Port45)", "Eth45/2(Port45)"], + "4x200G[100G]": ["Eth45/1(Port45)", "Eth45/2(Port45)", "Eth45/3(Port45)", "Eth45/4(Port45)"], + "4x100G[50G](4)": ["Eth45/1(Port45)", "Eth45/2(Port45)", "Eth45/3(Port45)", "Eth45/4(Port45)"], + "1x100G(4)": ["Eth45(Port45)"], + "2x50G(4)": ["Eth45/1(Port45)", "Eth45/2(Port45)"] + } + }, + + "Ethernet360": { + "index": "46,46,46,46,46,46,46,46", + "lanes": "217,218,219,220,221,222,223,224", + "breakout_modes": { + "1x800G": ["Eth46(Port46)"], + "1x400G": ["Eth46(Port46)"], + "2x400G[200G]": ["Eth46/1(Port46)", "Eth46/2(Port46)"], + "4x200G[100G]": ["Eth46/1(Port46)", "Eth46/2(Port46)", "Eth46/3(Port46)", "Eth46/4(Port46)"], + "4x100G[50G](4)": ["Eth46/1(Port46)", "Eth46/2(Port46)", "Eth46/3(Port46)", "Eth46/4(Port46)"], + "1x100G(4)": ["Eth46(Port46)"], + "2x50G(4)": ["Eth46/1(Port46)", "Eth46/2(Port46)"] + } + }, + + "Ethernet368": { + "index": "47,47,47,47,47,47,47,47", + "lanes": "233,234,235,236,237,238,239,240", + "breakout_modes": { + "1x800G": ["Eth47(Port47)"], + "1x400G": ["Eth47(Port47)"], + "2x400G[200G]": ["Eth47/1(Port47)", "Eth47/2(Port47)"], + "4x200G[100G]": ["Eth47/1(Port47)", "Eth47/2(Port47)", "Eth47/3(Port47)", "Eth47/4(Port47)"], + "4x100G[50G](4)": ["Eth47/1(Port47)", "Eth47/2(Port47)", "Eth47/3(Port47)", "Eth47/4(Port47)"], + "1x100G(4)": ["Eth47(Port47)"], + "2x50G(4)": ["Eth47/1(Port47)", "Eth47/2(Port47)"] + } + }, + + "Ethernet376": { + "index": "48,48,48,48,48,48,48,48", + "lanes": "249,250,251,252,253,254,255,256", + "breakout_modes": { + "1x800G": ["Eth48(Port48)"], + "1x400G": ["Eth48(Port48)"], + "2x400G[200G]": ["Eth48/1(Port48)", "Eth48/2(Port48)"], + "4x200G[100G]": ["Eth48/1(Port48)", "Eth48/2(Port48)", "Eth48/3(Port48)", "Eth48/4(Port48)"], + "4x100G[50G](4)": ["Eth48/1(Port48)", "Eth48/2(Port48)", "Eth48/3(Port48)", "Eth48/4(Port48)"], + "1x100G(4)": ["Eth48(Port48)"], + "2x50G(4)": ["Eth48/1(Port48)", "Eth48/2(Port48)"] + } + }, + + "Ethernet384": { + "index": "49,49,49,49,49,49,49,49", + "lanes": "257,258,259,260,261,262,263,264", + "breakout_modes": { + "1x800G": ["Eth49(Port49)"], + "1x400G": ["Eth49(Port49)"], + "2x400G[200G]": ["Eth49/1(Port49)", "Eth49/2(Port49)"], + "4x200G[100G]": ["Eth49/1(Port49)", "Eth49/2(Port49)", "Eth49/3(Port49)", "Eth49/4(Port49)"], + "4x100G[50G](4)": ["Eth49/1(Port49)", "Eth49/2(Port49)", "Eth49/3(Port49)", "Eth49/4(Port49)"], + "1x100G(4)": ["Eth49(Port49)"], + "2x50G(4)": ["Eth49/1(Port49)", "Eth49/2(Port49)"] + } + }, + + "Ethernet392": { + "index": "50,50,50,50,50,50,50,50", + "lanes": "273,274,275,276,277,278,279,280", + "breakout_modes": { + "1x800G": ["Eth50(Port50)"], + "1x400G": ["Eth50(Port50)"], + "2x400G[200G]": ["Eth50/1(Port50)", "Eth50/2(Port50)"], + "4x200G[100G]": ["Eth50/1(Port50)", "Eth50/2(Port50)", "Eth50/3(Port50)", "Eth50/4(Port50)"], + "4x100G[50G](4)": ["Eth50/1(Port50)", "Eth50/2(Port50)", "Eth50/3(Port50)", "Eth50/4(Port50)"], + "1x100G(4)": ["Eth50(Port50)"], + "2x50G(4)": ["Eth50/1(Port50)", "Eth50/2(Port50)"] + } + }, + + "Ethernet400": { + "index": "51,51,51,51,51,51,51,51", + "lanes": "297,298,299,300,301,302,303,304", + "breakout_modes": { + "1x800G": ["Eth51(Port51)"], + "1x400G": ["Eth51(Port51)"], + "2x400G[200G]": ["Eth51/1(Port51)", "Eth51/2(Port51)"], + "4x200G[100G]": ["Eth51/1(Port51)", "Eth51/2(Port51)", "Eth51/3(Port51)", "Eth51/4(Port51)"], + "4x100G[50G](4)": ["Eth51/1(Port51)", "Eth51/2(Port51)", "Eth51/3(Port51)", "Eth51/4(Port51)"], + "1x100G(4)": ["Eth51(Port51)"], + "2x50G(4)": ["Eth51/1(Port51)", "Eth51/2(Port51)"] + } + }, + + "Ethernet408": { + "index": "52,52,52,52,52,52,52,52", + "lanes": "313,314,315,316,317,318,319,320", + "breakout_modes": { + "1x800G": ["Eth52(Port52)"], + "1x400G": ["Eth52(Port52)"], + "2x400G[200G]": ["Eth52/1(Port52)", "Eth52/2(Port52)"], + "4x200G[100G]": ["Eth52/1(Port52)", "Eth52/2(Port52)", "Eth52/3(Port52)", "Eth52/4(Port52)"], + "4x100G[50G](4)": ["Eth52/1(Port52)", "Eth52/2(Port52)", "Eth52/3(Port52)", "Eth52/4(Port52)"], + "1x100G(4)": ["Eth52(Port52)"], + "2x50G(4)": ["Eth52/1(Port52)", "Eth52/2(Port52)"] + } + }, + + "Ethernet416": { + "index": "53,53,53,53,53,53,53,53", + "lanes": "329,330,331,332,333,334,335,336", + "breakout_modes": { + "1x800G": ["Eth53(Port53)"], + "1x400G": ["Eth53(Port53)"], + "2x400G[200G]": ["Eth53/1(Port53)", "Eth53/2(Port53)"], + "4x200G[100G]": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"], + "4x100G[50G](4)": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"], + "1x100G(4)": ["Eth53(Port53)"], + "2x50G(4)": ["Eth53/1(Port53)", "Eth53/2(Port53)"] + } + }, + + "Ethernet424": { + "index": "54,54,54,54,54,54,54,54", + "lanes": "345,346,347,348,349,350,351,352", + "breakout_modes": { + "1x800G": ["Eth54(Port54)"], + "1x400G": ["Eth54(Port54)"], + "2x400G[200G]": ["Eth54/1(Port54)", "Eth54/2(Port54)"], + "4x200G[100G]": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"], + "4x100G[50G](4)": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"], + "1x100G(4)": ["Eth54(Port54)"], + "2x50G(4)": ["Eth54/1(Port54)", "Eth54/2(Port54)"] + } + }, + + "Ethernet432": { + "index": "55,55,55,55,55,55,55,55", + "lanes": "361,362,363,364,365,366,367,368", + "breakout_modes": { + "1x800G": ["Eth55(Port55)"], + "1x400G": ["Eth55(Port55)"], + "2x400G[200G]": ["Eth55/1(Port55)", "Eth55/2(Port55)"], + "4x200G[100G]": ["Eth55/1(Port55)", "Eth55/2(Port55)", "Eth55/3(Port55)", "Eth55/4(Port55)"], + "4x100G[50G](4)": ["Eth55/1(Port55)", "Eth55/2(Port55)", "Eth55/3(Port55)", "Eth55/4(Port55)"], + "1x100G(4)": ["Eth55(Port55)"], + "2x50G(4)": ["Eth55/1(Port55)", "Eth55/2(Port55)"] + } + }, + + "Ethernet440": { + "index": "56,56,56,56,56,56,56,56", + "lanes": "377,378,379,380,381,382,383,384", + "breakout_modes": { + "1x800G": ["Eth56(Port56)"], + "1x400G": ["Eth56(Port56)"], + "2x400G[200G]": ["Eth56/1(Port56)", "Eth56/2(Port56)"], + "4x200G[100G]": ["Eth56/1(Port56)", "Eth56/2(Port56)", "Eth56/3(Port56)", "Eth56/4(Port56)"], + "4x100G[50G](4)": ["Eth56/1(Port56)", "Eth56/2(Port56)", "Eth56/3(Port56)", "Eth56/4(Port56)"], + "1x100G(4)": ["Eth56(Port56)"], + "2x50G(4)": ["Eth56/1(Port56)", "Eth56/2(Port56)"] + } + }, + + "Ethernet448": { + "index": "57,57,57,57,57,57,57,57", + "lanes": "393,394,395,396,397,398,399,400", + "breakout_modes": { + "1x800G": ["Eth57(Port57)"], + "1x400G": ["Eth57(Port57)"], + "2x400G[200G]": ["Eth57/1(Port57)", "Eth57/2(Port57)"], + "4x200G[100G]": ["Eth57/1(Port57)", "Eth57/2(Port57)", "Eth57/3(Port57)", "Eth57/4(Port57)"], + "4x100G[50G](4)": ["Eth57/1(Port57)", "Eth57/2(Port57)", "Eth57/3(Port57)", "Eth57/4(Port57)"], + "1x100G(4)": ["Eth57(Port57)"], + "2x50G(4)": ["Eth57/1(Port57)", "Eth57/2(Port57)"] + } + }, + + "Ethernet456": { + "index": "58,58,58,58,58,58,58,58", + "lanes": "409,410,411,412,413,414,415,416", + "breakout_modes": { + "1x800G": ["Eth58(Port58)"], + "1x400G": ["Eth58(Port58)"], + "2x400G[200G]": ["Eth58/1(Port58)", "Eth58/2(Port58)"], + "4x200G[100G]": ["Eth58/1(Port58)", "Eth58/2(Port58)", "Eth58/3(Port58)", "Eth58/4(Port58)"], + "4x100G[50G](4)": ["Eth58/1(Port58)", "Eth58/2(Port58)", "Eth58/3(Port58)", "Eth58/4(Port58)"], + "1x100G(4)": ["Eth58(Port58)"], + "2x50G(4)": ["Eth58/1(Port58)", "Eth58/2(Port58)"] + } + }, + + "Ethernet464": { + "index": "59,59,59,59,59,59,59,59", + "lanes": "425,426,427,428,429,430,431,432", + "breakout_modes": { + "1x800G": ["Eth59(Port59)"], + "1x400G": ["Eth59(Port59)"], + "2x400G[200G]": ["Eth59/1(Port59)", "Eth59/2(Port59)"], + "4x200G[100G]": ["Eth59/1(Port59)", "Eth59/2(Port59)", "Eth59/3(Port59)", "Eth59/4(Port59)"], + "4x100G[50G](4)": ["Eth59/1(Port59)", "Eth59/2(Port59)", "Eth59/3(Port59)", "Eth59/4(Port59)"], + "1x100G(4)": ["Eth59(Port59)"], + "2x50G(4)": ["Eth59/1(Port59)", "Eth59/2(Port59)"] + } + }, + + "Ethernet472": { + "index": "60,60,60,60,60,60,60,60", + "lanes": "441,442,443,444,445,446,447,448", + "breakout_modes": { + "1x800G": ["Eth60(Port60)"], + "1x400G": ["Eth60(Port60)"], + "2x400G[200G]": ["Eth60/1(Port60)", "Eth60/2(Port60)"], + "4x200G[100G]": ["Eth60/1(Port60)", "Eth60/2(Port60)", "Eth60/3(Port60)", "Eth60/4(Port60)"], + "4x100G[50G](4)": ["Eth60/1(Port60)", "Eth60/2(Port60)", "Eth60/3(Port60)", "Eth60/4(Port60)"], + "1x100G(4)": ["Eth60(Port60)"], + "2x50G(4)": ["Eth60/1(Port60)", "Eth60/2(Port60)"] + } + }, + + "Ethernet480": { + "index": "61,61,61,61,61,61,61,61", + "lanes": "457,458,459,460,461,462,463,464", + "breakout_modes": { + "1x800G": ["Eth61(Port61)"], + "1x400G": ["Eth61(Port61)"], + "2x400G[200G]": ["Eth61/1(Port61)", "Eth61/2(Port61)"], + "4x200G[100G]": ["Eth61/1(Port61)", "Eth61/2(Port61)", "Eth61/3(Port61)", "Eth61/4(Port61)"], + "4x100G[50G](4)": ["Eth61/1(Port61)", "Eth61/2(Port61)", "Eth61/3(Port61)", "Eth61/4(Port61)"], + "1x100G(4)": ["Eth61(Port61)"], + "2x50G(4)": ["Eth61/1(Port61)", "Eth61/2(Port61)"] + } + }, + + "Ethernet488": { + "index": "62,62,62,62,62,62,62,62", + "lanes": "473,474,475,476,477,478,479,480", + "breakout_modes": { + "1x800G": ["Eth62(Port62)"], + "1x400G": ["Eth62(Port62)"], + "2x400G[200G]": ["Eth62/1(Port62)", "Eth62/2(Port62)"], + "4x200G[100G]": ["Eth62/1(Port62)", "Eth62/2(Port62)", "Eth62/3(Port62)", "Eth62/4(Port62)"], + "4x100G[50G](4)": ["Eth62/1(Port62)", "Eth62/2(Port62)", "Eth62/3(Port62)", "Eth62/4(Port62)"], + "1x100G(4)": ["Eth62(Port62)"], + "2x50G(4)": ["Eth62/1(Port62)", "Eth62/2(Port62)"] + } + }, + + "Ethernet496": { + "index": "63,63,63,63,63,63,63,63", + "lanes": "489,490,491,492,493,494,495,496", + "breakout_modes": { + "1x800G": ["Eth63(Port63)"], + "1x400G": ["Eth63(Port63)"], + "2x400G[200G]": ["Eth63/1(Port63)", "Eth63/2(Port63)"], + "4x200G[100G]": ["Eth63/1(Port63)", "Eth63/2(Port63)", "Eth63/3(Port63)", "Eth63/4(Port63)"], + "4x100G[50G](4)": ["Eth63/1(Port63)", "Eth63/2(Port63)", "Eth63/3(Port63)", "Eth63/4(Port63)"], + "1x100G(4)": ["Eth63(Port63)"], + "2x50G(4)": ["Eth63/1(Port63)", "Eth63/2(Port63)"] + } + }, + + "Ethernet504": { + "index": "64,64,64,64,64,64,64,64", + "lanes": "505,506,507,508,509,510,511,512", + "breakout_modes": { + "1x800G": ["Eth64(Port64)"], + "1x400G": ["Eth64(Port64)"], + "2x400G[200G]": ["Eth64/1(Port64)", "Eth64/2(Port64)"], + "4x200G[100G]": ["Eth64/1(Port64)", "Eth64/2(Port64)", "Eth64/3(Port64)", "Eth64/4(Port64)"], + "4x100G[50G](4)": ["Eth64/1(Port64)", "Eth64/2(Port64)", "Eth64/3(Port64)", "Eth64/4(Port64)"], + "1x100G(4)": ["Eth64(Port64)"], + "2x50G(4)": ["Eth64/1(Port64)", "Eth64/2(Port64)"] + } + }, + + "Ethernet512": { + "index": "65", + "lanes": "514", + "breakout_modes": { + "1x25G[10G,1G]": ["Eth65(Port65)"] + } + }, + + "Ethernet513": { + "index": "66", + "lanes": "513", + "breakout_modes": { + "1x25G[10G,1G]": ["Eth66(Port66)"] + } + } + } +} + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/platform_asic b/device/accton/x86_64-accton_as9817_64o-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/accton/x86_64-accton_as9817_64o-r0/platform_components.json b/device/accton/x86_64-accton_as9817_64o-r0/platform_components.json new file mode 100644 index 000000000000..5224f4a9d889 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/platform_components.json @@ -0,0 +1,13 @@ +{ + "chassis": { + "AS9817-64O-O-AC-F": { + "component": { + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { }, + "FPGA": { }, + "BIOS": { } + } + } + } +} diff --git a/device/accton/x86_64-accton_as9817_64o-r0/platform_env.conf b/device/accton/x86_64-accton_as9817_64o-r0/platform_env.conf new file mode 100644 index 000000000000..aee1c756bf5e --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/platform_env.conf @@ -0,0 +1,2 @@ +SYNCD_SHM_SIZE=1G +is_ltsw_chip=1 diff --git a/device/accton/x86_64-accton_as9817_64o-r0/platform_reboot b/device/accton/x86_64-accton_as9817_64o-r0/platform_reboot new file mode 100755 index 000000000000..a4d724470676 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/platform_reboot @@ -0,0 +1,10 @@ +#!/bin/bash + +echo "Do sync" +sync + +echo "Stop pmon.service" +systemctl stop pmon.service + +# echo "Stop as9817_64o-platform-monitor.service" +# systemctl stop as9817_64o-platform-monitor.service diff --git a/device/accton/x86_64-accton_as9817_64o-r0/plugins/ssd_util.py b/device/accton/x86_64-accton_as9817_64o-r0/plugins/ssd_util.py new file mode 100644 index 000000000000..1984747612bb --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/plugins/ssd_util.py @@ -0,0 +1,29 @@ +# ssd_util.py +# +# Platform-specific SSD interface for SONiC +## + +try: + from sonic_platform_base.sonic_ssd.ssd_generic import SsdUtil as MainSsdUtil + from sonic_platform_base.sonic_ssd.ssd_generic import NOT_AVAILABLE + from sonic_py_common import logger +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "ssd_util.py" + +# Global logger instance +log = logger.Logger(SYSLOG_IDENTIFIER) + +class SsdUtil(MainSsdUtil): + """Platform-specific SsdUtil class""" + + def __init__(self, diskdev): + super(SsdUtil, self).__init__(diskdev) + + # If it has no vendor tool to read SSD information, + # ssd_util.py will use generic SSD information + # for vendor SSD information. + if self.vendor_ssd_info == NOT_AVAILABLE or \ + len(self.vendor_ssd_info.strip()) == 0: + self.vendor_ssd_info = self.ssd_info diff --git a/device/accton/x86_64-accton_as9817_64o-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as9817_64o-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..98506b46146d --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sensors.conf b/device/accton/x86_64-accton_as9817_64o-r0/sensors.conf new file mode 100644 index 000000000000..be3edb54d46d --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sensors.conf @@ -0,0 +1,37 @@ +chip "as9817_64_fan-isa-0000" + label fan1 "Fan 1 Front" + label fan2 "Fan 2 Front" + label fan3 "Fan 3 Front" + label fan4 "Fan 4 Front" + label fan5 "Fan 1 Rear" + label fan6 "Fan 2 Rear" + label fan7 "Fan 3 Rear" + label fan8 "Fan 4 Rear" + +chip "as9817_64_thermal-isa-0000" + label temp1 "MB_RearCenter_temp(0x48)" + label temp2 "MB_RearRight_temp(0x49)" + label temp3 "MB_RearCenter_temp(0x4A)" + label temp4 "MB_RearLeft_temp(0x4B)" + label temp5 "MB_FrontLeft_temp(0x4C)" + label temp6 "MB_FrontRight_temp(0x4D)" + label temp7 "FB_temp(0x4D)" + label temp8 "FB_temp(0x4E)" + +chip "as9817_64_psu-isa-0000" + label in0 "PSU 1 Voltage" + label fan1 "PSU 1 Fan" + label temp1 "PSU 1 Temperature" + label power1 "PSU 1 Power" + label curr1 "PSU 1 Current" + +chip "as9817_64_psu-isa-0001" + label in1 "PSU 2 Voltage" + label fan2 "PSU 2 Fan" + label temp2 "PSU 2 Temperature" + label power2 "PSU 2 Power" + label curr2 "PSU 2 Current" + +chip "nvme-pci-1600" + label temp1 "nvme0 Temperature" + ignore temp2 diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/__init__.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..706e2313249c --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ['chassis', 'eeprom', 'platform', 'psu', 'sfp', 'thermal', 'fan', 'fan_drawer'] +from . import platform diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/chassis.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..7e0f414529a9 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/chassis.py @@ -0,0 +1,263 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys + +try: + from sonic_platform_base.chassis_base import ChassisBase + from .helper import APIHelper + from .event import SfpEvent +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 4 +NUM_PSU = 2 +NUM_THERMAL = 13 +NUM_PORT = 66 +NUM_COMPONENT = 5 + +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" +PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" +SYSLED_FNODE= "/sys/devices/platform/as9817_64_led/led_alarm" +SYSLED_MODES = { + "0" : "STATUS_LED_COLOR_OFF", + "10" : "STATUS_LED_COLOR_RED", +} + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + ChassisBase.__init__(self) + self._api_helper = APIHelper() + self.is_host = self._api_helper.is_host() + + self.config_data = {} + + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + self.__initialize_components() + self.__initialize_sfp() + self.__initialize_eeprom() + + def __initialize_sfp(self): + from sonic_platform.sfp import Sfp + intf_name = self._api_helper.get_intf_name() + for index in range(NUM_PORT): + sfp = Sfp(index, intf_name.get(index + 1, "Unknown")) + self._sfp_list.append(sfp) + self._sfpevent = SfpEvent(self._sfp_list) + self.sfp_module_initialized = True + + def __initialize_fan(self): + from sonic_platform.fan_drawer import FanDrawer + for fant_index in range(NUM_FAN_TRAY): + fandrawer = FanDrawer(fant_index) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + def __initialize_psu(self): + from sonic_platform.psu import Psu + for index in range(NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + for index in range(NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Tlv + self._eeprom = Tlv() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._eeprom.get_model() + + def get_presence(self): + """ + Retrieves the presence of the Chassis + Returns: + bool: True if Chassis is present, False if not + """ + return True + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.get_mac() + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._eeprom.get_pn() + + def get_serial(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.get_serial() + + def get_revision(self): + """ + Retrieves the hardware revision number for the chassis + Returns: + A string containing the hardware revision number for this chassis. + """ + return self._eeprom.get_revision() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.get_eeprom() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + description = 'None' + + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) \ + if self.is_host \ + else (PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) + prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) \ + if self.is_host \ + else (PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) + + sw_reboot_cause = self._api_helper.read_txt_file(reboot_cause_path) or "Unknown" + prev_sw_reboot_cause = self._api_helper.read_txt_file(prev_reboot_cause_path) or "Unknown" + + if sw_reboot_cause != "Unknown": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = sw_reboot_cause + elif prev_reboot_cause_path != "Unknown": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = prev_sw_reboot_cause + + return (reboot_cause, description) + + def get_change_event(self, timeout=0): + # SFP event + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return self._sfpevent.get_sfp_event(timeout) + + def get_sfp(self, index): + """ + Retrieves sfp represented by (1-based) index + Args: + index: An integer, the index (1-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 1. + For example, 1 for Ethernet0, 2 for Ethernet4 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + if not self.sfp_module_initialized: + self.__initialize_sfp() + + try: + # The index will start from 1 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_port_or_cage_type(self, index): + from sonic_platform_base.sfp_base import SfpBase + + if index in range(1, 65): + return (SfpBase.SFP_PORT_TYPE_BIT_QSFP | SfpBase.SFP_PORT_TYPE_BIT_QSFP_PLUS | + SfpBase.SFP_PORT_TYPE_BIT_QSFP28 | SfpBase.SFP_PORT_TYPE_BIT_QSFPDD | + SfpBase.SFP_PORT_TYPE_BIT_OSFP) + else: + return SfpBase.SFP_PORT_TYPE_BIT_SFP | SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_SFP28 + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def initizalize_system_led(self): + return True + + def get_status_led(self): + val = self._api_helper.read_txt_file(SYSLED_FNODE) + return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN" + + def set_status_led(self, color): + mode = None + for key, val in SYSLED_MODES.items(): + if val == color: + mode = key + break + if mode is None: + return False + else: + return self._api_helper.write_txt_file(SYSLED_FNODE, mode) + + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/component.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/component.py new file mode 100644 index 000000000000..39dae1411bab --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/component.py @@ -0,0 +1,161 @@ +############################################################################# +# Edgecore +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +try: + import os + import json + from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper + from sonic_py_common.general import getstatusoutput_noshell +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PLATFORM_SYSFS_PATH = "/sys/devices/platform" +CPLD_SYSFS_MAPPING = { + "CPLD1": "as9817_64_fpga/cpld1_version", + "CPLD2": "as9817_64_fpga/cpld2_version", + "CPLD3": "as9817_64_fan/hwmon/hwmon*/version", + "FPGA": "as9817_64_sys/fpga_version", +} +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +COMPONENT_LIST= [ + ("CPLD1", "CPLD 1"), + ("CPLD2", "CPLD 2"), + ("CPLD3", "FAN CPLD"), + ("FPGA", "FPGA"), + ("BIOS", "Basic Input/Output System") +] + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index=0): + ComponentBase.__init__(self) + self._api_helper = APIHelper() + self.index = component_index + self.name = self.get_name() + + def __get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def __get_cpld_version(self, cpld_name): + # Retrieves the CPLD firmware version + cpld_version = 'None' + try: + cpld_path = CPLD_SYSFS_MAPPING[cpld_name] + version_path = "{}/{}".format(PLATFORM_SYSFS_PATH, cpld_path) + cpld_version_raw = self._api_helper.glob_read_txt_file(version_path) + if cpld_version_raw is not None: + cpld_version = "{}".format(float(cpld_version_raw)) + except Exception as e: + pass + + return cpld_version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][0] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_LIST[self.index][1] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + + if self.name == "BIOS": + fw_version = self.__get_bios_version() + elif "CPLD" in self.name or "FPGA" in self.name: + cpld_version = self.__get_cpld_version(self.name) + fw_version = cpld_version + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + return False + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/eeprom.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/eeprom.py new file mode 100644 index 000000000000..bb61bc0b39ed --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/eeprom.py @@ -0,0 +1,138 @@ +try: + import os + import sys + import re + if sys.version_info[0] >= 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' +NULL = 'N/A' + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(Tlv, self).__init__(self._eeprom_path, 0, '', True) + self._eeprom = self._load_eeprom() + + def __parse_output(self, decode_output): + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + _eeprom_info_dict = dict() + + for line in lines: + try: + match = re.search( + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)(.+)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + + _eeprom_info_dict[idx] = value + except Exception: + pass + + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + try: + self.read_eeprom_db() + except Exception: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if 'ok' not in status: + return False + + if not os.path.exists(CACHE_ROOT): + try: + os.makedirs(CACHE_ROOT) + except Exception: + pass + + # + # only the eeprom classes that inherit from eeprom_base + # support caching. Others will work normally + # + try: + self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE)) + except Exception: + pass + + e = self.read_eeprom() + if e is None: + return 0 + + try: + self.update_cache(e) + except Exception: + pass + + self.decode_eeprom(e) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + (is_valid, valid_crc) = self.is_checksum_valid(e) + if not is_valid: + return False + + return self.__parse_output(decode_output) + + def _valid_tlv(self, eeprom_data): + tlvinfo_type_codes_list = [ + self._TLV_CODE_PRODUCT_NAME, + self._TLV_CODE_PART_NUMBER, + self._TLV_CODE_SERIAL_NUMBER, + self._TLV_CODE_MAC_BASE, + self._TLV_CODE_MANUF_DATE, + self._TLV_CODE_DEVICE_VERSION, + self._TLV_CODE_LABEL_REVISION, + self._TLV_CODE_PLATFORM_NAME, + self._TLV_CODE_ONIE_VERSION, + self._TLV_CODE_MAC_SIZE, + self._TLV_CODE_MANUF_NAME, + self._TLV_CODE_MANUF_COUNTRY, + self._TLV_CODE_VENDOR_NAME, + self._TLV_CODE_DIAG_VERSION, + self._TLV_CODE_SERVICE_TAG, + self._TLV_CODE_VENDOR_EXT, + self._TLV_CODE_CRC_32 + ] + + for code in tlvinfo_type_codes_list: + code_str = "0x{:X}".format(code) + eeprom_data[code_str] = eeprom_data.get(code_str, NULL) + return eeprom_data + + def get_eeprom(self): + return self._valid_tlv(self._eeprom) + + def get_pn(self): + return self._eeprom.get('0x22', NULL) + + def get_serial(self): + return self._eeprom.get('0x23', NULL) + + def get_mac(self): + return self._eeprom.get('0x24', NULL) + + def get_model(self): + return self._eeprom.get('0x21', NULL) + + def get_revision(self): + return self._eeprom.get('0x27', NULL) + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/event.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/event.py new file mode 100644 index 000000000000..936758c3e413 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/event.py @@ -0,0 +1,113 @@ +try: + import time + from sonic_py_common.logger import Logger + from .sfp import Sfp +except ImportError as e: + raise ImportError(repr(e) + " - required module not found") + +POLL_INTERVAL_IN_SEC = 1 + +# SFP errors that will block eeprom accessing +SFP_BLOCKING_ERRORS = [ + Sfp.SFP_ERROR_BIT_I2C_STUCK, + Sfp.SFP_ERROR_BIT_BAD_EEPROM, + Sfp.SFP_ERROR_BIT_UNSUPPORTED_CABLE, + Sfp.SFP_ERROR_BIT_HIGH_TEMP, + Sfp.SFP_ERROR_BIT_BAD_CABLE +] + +class SfpEvent: + ''' Listen to insert/remove sfp events ''' + + def __init__(self, sfp_list): + self._sfp_list = sfp_list + self._logger = Logger() + self._sfp_change_event_data = {'present': 0} + + def get_presence_bitmap(self): + bitmap = 0 + for sfp in self._sfp_list: + modpres = sfp.get_presence() + i=sfp.get_position_in_parent() - 1 + if modpres: + bitmap = bitmap | (1 << i) + return bitmap + + def get_sfp_event(self, timeout=2000): + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + + if timeout < 1000: + cd_ms = 1000 + else: + cd_ms = timeout + + while cd_ms > 0: + bitmap = self.get_presence_bitmap() + changed_ports = self._sfp_change_event_data['present'] ^ bitmap + if changed_ports != 0: + break + time.sleep(POLL_INTERVAL_IN_SEC) + # timeout=0 means wait for event forever + if timeout != 0: + cd_ms = cd_ms - POLL_INTERVAL_IN_SEC * 1000 + + if changed_ports != 0: + for sfp in self._sfp_list: + i=sfp.get_position_in_parent() - 1 + if (changed_ports & (1 << i)) == 0: + continue + + if (bitmap & (1 << i)) == 0: + port_dict[i+1] = '0' + else: + # sfp_state_bits = self.get_sfp_state_bits(sfp, True) + # sfp_state_bits = self.check_sfp_blocking_errors(sfp_state_bits) + # port_dict[i+1] = str(sfp_state_bits) + + # In xcvrd, its current implementation does not + # expect to identify the value when more than one bit is set + # in the return value, and will run into the problem + # + port_dict[i+1] = '1' + + # Update the cache dict + self._sfp_change_event_data['present'] = bitmap + return True, change_dict + else: + return True, change_dict + + def get_sfp_state_bits(self, sfp, present): + sfp_state_bits = 0 + + if present is True: + sfp_state_bits |= Sfp.SFP_STATUS_BIT_INSERTED + else: + return sfp_state_bits + + status = sfp.validate_eeprom() + if status is None: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK + return sfp_state_bits + elif status is not True: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_BAD_EEPROM + return sfp_state_bits + + status = sfp.validate_temperature() + if status is None: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK + return sfp_state_bits + elif status is not True: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_HIGH_TEMP + return sfp_state_bits + + return sfp_state_bits + + def check_sfp_blocking_errors(self, sfp_state_bits): + for i in SFP_BLOCKING_ERRORS: + if (i & sfp_state_bits) == 0: + continue + sfp_state_bits |= Sfp.SFP_ERROR_BIT_BLOCKING + + return sfp_state_bits diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/fan.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..844b8d579d55 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/fan.py @@ -0,0 +1,293 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.fan_base import FanBase + import os.path + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +TARGET_SPEED_PATH = "/tmp/fan_target_speed" +PSU_FAN_MAX_RPM = 29952 # PMBus MFR_FAN_SPEED_MAX(0xC3) +FAN_HWMON_PATH = "/sys/devices/platform/as9817_64_fan/hwmon/hwmon*/fan" +PSU_HWMON_PATH = { + 0: "/sys/devices/platform/as9817_64_psu.0/hwmon/hwmon*/psu1", + 1: "/sys/devices/platform/as9817_64_psu.1/hwmon/hwmon*/psu2", +} + +fan_list = { + 0: {"name":"FAN-1F", "ss_index":1}, + 1: {"name":"FAN-1R", "ss_index":5}, + 2: {"name":"FAN-2F", "ss_index":2}, + 3: {"name":"FAN-2R", "ss_index":6}, + 4: {"name":"FAN-3F", "ss_index":3}, + 5: {"name":"FAN-3R", "ss_index":7}, + 6: {"name":"FAN-4F", "ss_index":4}, + 7: {"name":"FAN-4R", "ss_index":8}, +} + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, + fan_tray_index, + fan_index=0, + is_psu_fan=False, + psu_index=0): + self._api_helper = APIHelper() + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + self.is_psu_fan = is_psu_fan + self.psu_index = psu_index + + if self.is_psu_fan: + self.psu_hwmon_path = PSU_HWMON_PATH[psu_index] + else: + self.hwmon_path = FAN_HWMON_PATH + str(fan_list[fan_tray_index * 2 + fan_index]["ss_index"]) + FanBase.__init__(self) + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = self.FAN_DIRECTION_NOT_APPLICABLE + if not self.is_psu_fan: + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_dir") + if val is not None: + direction = self.FAN_DIRECTION_EXHAUST \ + if val == "F2B" \ + else self.FAN_DIRECTION_INTAKE + else: + val = self._api_helper.glob_read_txt_file(self.psu_hwmon_path + '_power_good') + if val is None or int(val, 10)==0: + return self.FAN_DIRECTION_NOT_APPLICABLE + + val = self._api_helper.glob_read_txt_file(self.psu_hwmon_path + "_fan_dir") + if val is not None: + direction = self.FAN_DIRECTION_EXHAUST \ + if val == "F2B" \ + else self.FAN_DIRECTION_INTAKE + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + """ + speed = 0 + if self.is_psu_fan: + psu_fan_speed_rpm = self._api_helper.glob_read_txt_file( + self.psu_hwmon_path + "_fan1_input") + if psu_fan_speed_rpm is not None: + speed = (int(psu_fan_speed_rpm, 10)) * 100 / PSU_FAN_MAX_RPM + else: + return 0 + elif self.get_presence(): + fan_input = self._api_helper.glob_read_txt_file(self.hwmon_path + "_input") + + fan_target = self._api_helper.glob_read_txt_file(self.hwmon_path + "_target") + + if fan_input is None or fan_target is None: + return 0 + + speed = (int(fan_input) * self.get_target_speed()) / int(fan_target) + + speed = int(speed) + if speed > 100: + speed = 100 + return int(speed) + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + speed = 0 + if self.is_psu_fan: + fan_speed_rpm = self._api_helper.glob_read_txt_file( + self.psu_hwmon_path + "_fan1_input") + if fan_speed_rpm is not None: + speed = (int(fan_speed_rpm, 10)) * 100 / PSU_FAN_MAX_RPM + speed = 100 if (speed > 100) else speed + else: + return 0 + elif self.get_presence(): + if os.path.isfile(TARGET_SPEED_PATH): + speed = self._api_helper.read_txt_file(TARGET_SPEED_PATH) + else: + speed = self._api_helper.glob_read_txt_file(self.hwmon_path + '_pwm') + if speed is None: + return 0 + + return int(speed) + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 20 + + speed = 0 + if not self.is_psu_fan: + speed = self._api_helper.glob_read_txt_file(self.hwmon_path + '_tolerance') + if speed is None: + return 0 + + return int(speed) + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + + """ + + if not self.is_psu_fan and self.get_presence(): + ret = self._api_helper.glob_write_txt_file(self.hwmon_path + '_pwm', speed) + if ret == True: + self._api_helper.write_txt_file(TARGET_SPEED_PATH, int(speed)) + return ret + + return False + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + return False #Not supported + + def get_status_led(self): + """ + Gets the state of the fan status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.is_psu_fan: + return None + + return { + True: self.STATUS_LED_COLOR_GREEN, + False: self.STATUS_LED_COLOR_RED + }.get(self.get_status(), self.STATUS_LED_COLOR_OFF) + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + if self.is_psu_fan: + val = self._api_helper.glob_read_txt_file(self.psu_hwmon_path + "_present") + else: + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_present") + + if val is not None: + return int(val, 10)==1 + else: + return False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if self.is_psu_fan: + val = self._api_helper.glob_read_txt_file(self.psu_hwmon_path + '_power_good') + if val is None or int(val, 10)==0: + return False + + val = self._api_helper.glob_read_txt_file(self.psu_hwmon_path + '_fan1_input') + if val is not None: + return int(val, 10)!=0 + else: + return False + else: + val = self._api_helper.glob_read_txt_file(self.hwmon_path + '_fault') + if val is not None: + return int(val, 10)==0 + else: + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = fan_list[self.fan_tray_index * 2 + self.fan_index]["name"] \ + if not self.is_psu_fan \ + else "PSU-{} FAN-{}".format(self.psu_index+1, self.fan_index+1) + + return fan_name + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return "N/A" + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + return (self.fan_index+1) \ + if not self.is_psu_fan else (self.psu_index+1) + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True if not self.is_psu_fan else False + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/fan_drawer.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..7fe57322e3b6 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/fan_drawer.py @@ -0,0 +1,98 @@ +######################################################################## +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 0-based in platforms + self.fantrayindex = fantray_index + self.__initialize_fan_drawer() + + def __initialize_fan_drawer(self): + from sonic_platform.fan import Fan + for i in range(FANS_PER_FANTRAY): + self._fan_list.append(Fan(self.fantrayindex, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex+1) + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return self._fan_list[0].get_presence() + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._fan_list[0].get_model() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._fan_list[0].get_serial() + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self._fan_list[0].get_status() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + return (self.fantrayindex+1) + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/helper.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/helper.py new file mode 100644 index 000000000000..1bc7ee5ac80c --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/helper.py @@ -0,0 +1,426 @@ +import os +import struct +import json +import fcntl +import glob +from mmap import * +from sonic_py_common import device_info +from sonic_py_common import logger +from threading import Lock +from typing import cast +from sonic_py_common.general import getstatusoutput_noshell_pipe +from sonic_py_common.general import getstatusoutput_noshell + +HOST_CHK_CMD = ["docker"] +EMPTY_STRING = "" +MACHINE_CONF_FILE = "/host/machine.conf" +HOST_PLATFORM_JSON_FILE = "/usr/share/sonic/device/{}/platform.json" +PMON_PLATFORM_JSON_FILE = "/usr/share/sonic/platform/platform.json" +INTF_KEY = "interfaces" + + +class APIHelper(): + + def __init__(self): + pass + + def is_host(self): + try: + status, output = getstatusoutput_noshell(HOST_CHK_CMD) + return status == 0 + except Exception: + return False + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def read_txt_file(self, file_path): + try: + with open(file_path, encoding='unicode_escape', errors='replace') as fd: + data = fd.read() + ret = data.strip() + if len(ret) > 0: + return ret + except IOError: + pass + return None + + def glob_read_txt_file(self, file_path): + for filename in glob.glob(file_path): + try: + with open(filename, encoding='unicode_escape', errors='replace') as fd: + data = fd.read() + ret = data.strip() + if len(ret) > 0: + return ret + except IOError as e: + pass + + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + fd.flush() + except IOError: + return False + return True + + def glob_write_txt_file(self, file_path, value): + for filename in glob.glob(file_path): + try: + with open(filename, 'w') as fd: + fd.write(str(value)) + fd.flush() + return True + except IOError as e: + pass + + return False + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + try: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'raw', str(netfn), str(cmd)]) + if err == [0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_fru_id(self, id, key=None): + status = True + result = "" + try: + if (key is None): + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)]) + else: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)], ['grep', str(key)]) + if err == [0] or err == [0, 0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + try: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'sensor', 'thresh', str(id), str(threshold_key), str(value)]) + if err == [0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def get_intf_name(self): + """ + Fetches interface names indexed by port numbers from platform.json file. + + Returns: + - A dictionary with port indices as keys and interface names as values. + Example: {1: 'Ethernet0', ...}. + - Returns an empty dictionary on errors or if key not found. + """ + platform_json_file_path = PMON_PLATFORM_JSON_FILE + if self.is_host(): + platform = "None" + with open(MACHINE_CONF_FILE, 'r') as file: + for line in file: + if 'onie_platform=' in line: + platform = line.strip().split('=')[1] + break + platform_json_file_path = HOST_PLATFORM_JSON_FILE.format(platform) + + port_dict = {} + try: + with open(platform_json_file_path) as fp: + port_dict = json.load(fp) + except Exception as e: + pass + + intf_name_by_index = {} + if INTF_KEY in port_dict: + for intf_name, port_info in port_dict[INTF_KEY].items(): + if 'index' in port_info: + fp_port_index = int(port_info['index'].split(",")[0]) + intf_name_by_index[fp_port_index] = intf_name + + return intf_name_by_index + + +class FileLock: + """ + Due to pmon docker not installing the py-filelock, this class + implements a simple file lock feature. + Ref: https://github.com/tox-dev/py-filelock/blob/main/src/filelock/ + """ + + def __init__(self, lock_file): + self._lock_file = lock_file + self._thread_lock = Lock() + self.is_locked = False + + def acquire(self): + with self._thread_lock: + if self.is_locked: + return + + fd = os.open(self._lock_file, flags=(os.O_RDWR | os.O_CREAT | os.O_TRUNC)) + fcntl.flock(fd, fcntl.LOCK_EX) + self._lock_file_fd = fd + self.is_locked = True + + def release(self): + with self._thread_lock: + if self.is_locked: + fd = cast(int, self._lock_file_fd) + self._lock_file_fd = None + fcntl.flock(fd, fcntl.LOCK_UN) + os.close(fd) + self.is_locked = False + + def __enter__(self): + self.acquire() + return self + + def __exit__(self, exc_type, exc_val, traceback): + self.release() + + def __del__(self): + self.release() + + +DEVICE_THRESHOLD_JSON_PATH = "/tmp/device_threshold.json" + +class DeviceThreshold: + HIGH_THRESHOLD = 'high_threshold' + LOW_THRESHOLD = 'low_threshold' + HIGH_CRIT_THRESHOLD = 'high_critical_threshold' + LOW_CRIT_THRESHOLD = 'low_critical_threshold' + NOT_AVAILABLE = 'N/A' + + def __init__(self, th_name = NOT_AVAILABLE): + self.flock = FileLock("{}.lock".format(DEVICE_THRESHOLD_JSON_PATH)) + self.name = th_name + self.__log = logger.Logger(log_identifier="DeviceThreshold") + + self.__db_data = {} + self.__db_mtime = 0 + + def __reload_db(self): + try: + db_data = {} + with self.flock: + with open(DEVICE_THRESHOLD_JSON_PATH, "r") as db_file: + db_data = json.load(db_file) + except Exception as e: + return None + + return db_data + + def __get_data(self, field): + """ + Retrieves data frome JSON file by field + + Args : + field: String + + Returns: + A string if getting is successfully, 'N/A' if not + """ + if os.path.exists(DEVICE_THRESHOLD_JSON_PATH): + new_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) + if new_mtime != self.__db_mtime: + new_data = self.__reload_db() + if new_data is not None: + self.__db_data = new_data + self.__db_mtime = new_mtime + + if self.name not in self.__db_data.keys(): + return self.NOT_AVAILABLE + + if field not in self.__db_data[self.name].keys(): + return self.NOT_AVAILABLE + + return self.__db_data[self.name][field] + + def __set_data(self, field, new_val): + """ + Set data to JSON file by field + + Args : + field: String + new_val: String + + Returns: + A boolean, True if setting is set successfully, False if not + """ + if self.name not in self.__db_data.keys(): + self.__db_data[self.name] = {} + + old_val = self.__db_data[self.name].get(field, None) + if old_val is not None and old_val == new_val: + return True + + self.__db_data[self.name][field] = new_val + + try: + with self.flock: + db_data = {} + mode = "r+" if os.path.exists(DEVICE_THRESHOLD_JSON_PATH) else "w+" + with open(DEVICE_THRESHOLD_JSON_PATH, mode) as db_file: + if mode == "r+": + db_data = json.load(db_file) + + if self.name not in db_data.keys(): + db_data[self.name] = {} + + db_data[self.name][field] = new_val + + if mode == "r+": + db_file.seek(0) + # erase old data + db_file.truncate(0) + # write all data + json.dump(db_data, db_file, indent=4) + self.__db_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) + except Exception as e: + self.__log.log_error('{}'.format(str(e))) + return False + + return True + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature from JSON file. + + Returns: + string : the high threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.HIGH_THRESHOLD) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.HIGH_THRESHOLD, temperature) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature from JSON file. + + Returns: + string : the low threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.LOW_THRESHOLD) + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.LOW_THRESHOLD, temperature) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature from JSON file. + + Returns: + string : the high critical threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.HIGH_CRIT_THRESHOLD) + + def set_high_critical_threshold(self, temperature): + """ + Sets the high critical threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.HIGH_CRIT_THRESHOLD, temperature) + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature from JSON file. + + Returns: + string : the low critical threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.LOW_CRIT_THRESHOLD) + + def set_low_critical_threshold(self, temperature): + """ + Sets the low critical threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.LOW_CRIT_THRESHOLD, temperature) diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/pcie.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/pcie.py new file mode 100644 index 000000000000..73d3627dbf70 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/pcie.py @@ -0,0 +1,19 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# Base PCIe class +############################################################################# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Pcie(PcieUtil): + """Edgecore Platform-specific PCIe class""" + + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) \ No newline at end of file diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/platform.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..2f2c2a447fcf --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/platform.py @@ -0,0 +1,21 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/psu.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..24fb8a2af848 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/psu.py @@ -0,0 +1,281 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/" + +PSU_NAME_LIST = ["PSU-1", "PSU-2"] +PSU_NUM_FAN = [1, 1] +PSU_HWMON_PATH = { + 0: "/sys/devices/platform/as9817_64_psu.0/hwmon/hwmon*/psu1", + 1: "/sys/devices/platform/as9817_64_psu.1/hwmon/hwmon*/psu2", +} + +THERMAL_COUNT_PER_PSU = 3 + +SYSLED_FNODE= { + 0: "/sys/devices/platform/as9817_64_led/led_psu1", + 1: "/sys/devices/platform/as9817_64_led/led_psu2" +} + +SYSLED_MODES = { + "0" : PsuBase.STATUS_LED_COLOR_OFF, + "16" : PsuBase.STATUS_LED_COLOR_GREEN, + "10" : PsuBase.STATUS_LED_COLOR_RED +} + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index=0): + PsuBase.__init__(self) + self.index = psu_index + self._api_helper = APIHelper() + + self.hwmon_path = PSU_HWMON_PATH[psu_index] + + self.__initialize_fan() + self.__initialize_thermal() + + def __initialize_fan(self): + from sonic_platform.fan import Fan + for fan_index in range(0, PSU_NUM_FAN[self.index]): + fan = Fan(fan_index, is_psu_fan=True, psu_index=self.index) + self._fan_list.append(fan) + + def __initialize_thermal(self): + from sonic_platform.thermal import Thermal + for thermal_id in range(0, THERMAL_COUNT_PER_PSU): + thermal = Thermal(thermal_index=thermal_id, is_psu=True, psu_index=self.index) + self._thermal_list.append(thermal) + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.get_status() is not True: + return 0.0 + + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_vout") + if val is not None: + return float(val)/ 1000 + else: + return 0.0 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.get_status() is not True: + return 0.0 + + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_iout") + if val is not None: + return float(val)/1000 + else: + return 0.0 + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.get_status() is not True: + return 0.0 + + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_pout") + if val is not None: + return float(val)/1000 + else: + return 0.0 + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the PSU status LED + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + """ + + return False #Controlled by BMC + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + val = self._api_helper.read_txt_file(SYSLED_FNODE[self.index]) + return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN" + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + return self._thermal_list[1].get_temperature() + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return self._thermal_list[1].get_high_threshold() + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return 12.57 + + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_vout_max") + if val is not None: + return float(val)/ 1000 + else: + return 0.0 + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return 11.83 + + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_vout_min") + if val is not None: + return float(val)/ 1000 + else: + return 0.0 + + def get_maximum_supplied_power(self): + """ + Retrieves the maximum supplied power by PSU + Returns: + A float number, the maximum power output in Watts. + e.g. 1200.1 + """ + return 3000.0 + + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_pout_max") + if val is not None: + return float(val)/1000 + else: + return 0.0 + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return PSU_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_present") + if val is not None: + return int(val, 10) == 1 + else: + return False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_power_good") + if val is not None: + return int(val, 10) == 1 + else: + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model = self._api_helper.glob_read_txt_file(self.hwmon_path + "_model") + if model is None: + return "N/A" + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + serial = self._api_helper.glob_read_txt_file(self.hwmon_path + "_serial") + if serial is None: + return "N/A" + return serial + + def get_revision(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + revision = None + if revision is None: + return "N/A" + return revision + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return self.index+1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/sfp.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/sfp.py new file mode 100644 index 000000000000..b355d02befcc --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/sfp.py @@ -0,0 +1,491 @@ +############################################################################# +# Edgecore +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +try: + import time + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FPGA_PCIE_PATH = "/sys/devices/platform/as9817_64_fpga/" +EEPROM_PATH = '/sys/bus/i2c/devices/{}-00{}/eeprom' + +class Sfp(SfpOptoeBase): + """Platform-specific Sfp class""" + + # Port number + PORT_START = 1 + PORT_END = 66 + + SFP_TYPE_CODE_LIST = [ + 0x03, # SFP/SFP+/SFP28 + 0x0b # DWDM-SFP/SFP+ + ] + QSFP_TYPE_CODE_LIST = [ + 0x0c, # QSFP + 0x0d, # QSFP+ or later + 0x11, # QSFP28 or later + 0xe1 # QSFP28 EDFA + ] + QSFP_DD_TYPE_CODE_LIST = [ + 0x18, # QSFP-DD Double Density 8X Pluggable Transceiver + 0x1E # QSFP+ or later with CMIS + ] + OSFP_TYPE_CODE_LIST = [ + 0x19 # OSFP + ] + + SFP_TYPE = "SFP" + QSFP_TYPE = "QSFP" + OSFP_TYPE = "OSFP" + QSFP_DD_TYPE = "QSFP_DD" + + UPDATE_DONE = "Done" + EEPROM_DATA_NOT_READY = "eeprom not ready" + UNKNOWN_SFP_TYPE_ID = "unknow sfp ID" + + _port_to_i2c_mapping = { + 1:2, 2:3, 3:4, 4:5, + 5:6, 6:7, 7:8, 8:9, + 9:10, 10:11, 11:12, 12:13, + 13:14, 14:15, 15:16, 16:17, + 17:18, 18:19, 19:20, 20:21, + 21:22, 22:23, 23:24, 24:25, + 25:26, 26:27, 27:28, 28:29, + 29:30, 30:31, 31:32, 32:33, + 33:34, 34:35, 35:36, 36:37, + 37:38, 38:39, 39:40, 40:41, + 41:42, 42:43, 43:44, 44:45, + 45:46, 46:47, 47:48, 48:49, + 49:50, 50:51, 51:52, 52:53, + 53:54, 54:55, 55:56, 56:57, + 57:58, 58:59, 59:60, 60:61, + 61:62, 62:63, 63:64, 64:65, + 65:66, 66:67, + } + + def __init__(self, sfp_index=0, intf_name="Unknown"): + SfpOptoeBase.__init__(self) + self._api_helper=APIHelper() + + # Init index + self.port_num = sfp_index + 1 + self.index = self.port_num + + self.name = intf_name + + # Init eeprom path + self.port_to_eeprom_mapping = {} + 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], "50") + + # SONiC will use 'sfp_type' for configuring the media type. + self.sfp_type = self.QSFP_TYPE + self.update_sfp_type() + + def get_eeprom_path(self): + # print(self.port_to_eeprom_mapping[self.port_num]) + return self.port_to_eeprom_mapping[self.port_num] + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_path = "{}{}{}".format(FPGA_PCIE_PATH, 'module_reset_', self.port_num) + + val = self._api_helper.read_txt_file(reset_path) + if val is not None: + return int(val, 10) == 1 + + return False + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.port_num > 64: + # SFP doesn't support this feature + return False + + if self.sfp_type in [self.QSFP_DD_TYPE, self.OSFP_TYPE]: + api = self.get_xcvr_api() + return api.get_lpmode() + else: + lpmode_path = "{}{}{}".format(FPGA_PCIE_PATH, '/module_lp_mode_', self.port_num) + + val=self._api_helper.read_txt_file(lpmode_path) + if val is not None: + return int(val, 10)==1 + + return False + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + if not self.get_presence(): + return False + + # Check for invalid port_num + if self.port_num > 64: + return False # SFP doesn't support this feature + + reset_path = "{}{}{}".format(FPGA_PCIE_PATH, 'module_reset_', self.port_num) + ret = self._api_helper.write_txt_file(reset_path, 1) + if ret is not True: + return ret + + time.sleep(0.2) + ret = self._api_helper.write_txt_file(reset_path, 0) + time.sleep(0.2) + + return ret + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if not self.get_presence(): + return False + + if self.port_num > 64: + return False # SFP doesn't support this feature + + if self.sfp_type in [self.QSFP_DD_TYPE, self.OSFP_TYPE]: + api = self.get_xcvr_api() + ret = api.set_lpmode(lpmode) + else: + lpmode_path = "{}{}{}".format(FPGA_PCIE_PATH, 'module_lp_mode_', self.port_num) + + if lpmode is True: + ret = self._api_helper.write_txt_file(lpmode_path, 1) #enable lpmode + else: + ret = self._api_helper.write_txt_file(lpmode_path, 0) #disable lpmode + + return ret + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if not self.get_presence(): + return False + + if self.port_num < 65: + api = self.get_xcvr_api() + if api is None: + return False + + ret = api.tx_disable(tx_disable) + else: + txdisable_path = "{}{}{}".format(FPGA_PCIE_PATH, 'module_tx_disable_', self.port_num) + + if tx_disable is True: + ret = self._api_helper.write_txt_file(txdisable_path, 1) #enable tx_disable + else: + ret = self._api_helper.write_txt_file(txdisable_path, 0) #disable tx_disable + + return ret + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + present_path = "{}{}{}".format(FPGA_PCIE_PATH, '/module_present_', self.port_num) + + val = self._api_helper.read_txt_file(present_path) + if val is not None: + return int(val, 10)==1 + + return False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return self.port_num + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def update_sfp_type(self): + """ + Updates the sfp type + + """ + if not self.get_presence(): + return self.EEPROM_DATA_NOT_READY + + ret = self.UPDATE_DONE + eeprom_raw = [] + eeprom_raw = self.read_eeprom(0, 1) + if eeprom_raw and hasattr(self,'sfp_type'): + if eeprom_raw[0] in self.SFP_TYPE_CODE_LIST: + self.sfp_type = self.SFP_TYPE + elif eeprom_raw[0] in self.QSFP_TYPE_CODE_LIST: + self.sfp_type = self.QSFP_TYPE + elif eeprom_raw[0] in self.QSFP_DD_TYPE_CODE_LIST: + self.sfp_type = self.QSFP_DD_TYPE + elif eeprom_raw[0] in self.OSFP_TYPE_CODE_LIST: + self.sfp_type = self.OSFP_TYPE + else: + ret = self.UNKNOWN_SFP_TYPE_ID + else: + ret = self.EEPROM_DATA_NOT_READY + + return ret + + def validate_eeprom_sfp(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(0, 96) + if eeprom_raw is None: + return False + + for i in range(0, 63): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[63]: + return False + + checksum_test = 0 + for i in range(64, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + checksum_test = 0 + eeprom_raw = self.read_eeprom(384, 96) + if eeprom_raw is None: + return False + + for i in range(0, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + return True + + def validate_eeprom_qsfp(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(128, 96) + if eeprom_raw is None: + return None + + for i in range(0, 63): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[63]: + return False + + checksum_test = 0 + for i in range(64, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + return True + + def validate_eeprom_cmis(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(128, 95) + if eeprom_raw is None: + return None + + for i in range(0, 94): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[94]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + checksum_test = 0 + eeprom_raw = self.read_eeprom(258, 126) + if eeprom_raw is None: + return None + + for i in range(0, 125): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[125]: + return False + + checksum_test = 0 + eeprom_raw = self.read_eeprom(384, 128) + if eeprom_raw is None: + return None + + for i in range(0, 127): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[127]: + return False + + # CMIS_5.0 starts to support the checksum of page 04h + cmis_rev = float(api.get_cmis_rev()) + if cmis_rev >= 5.0: + checksum_test = 0 + eeprom_raw = self.read_eeprom(640, 128) + if eeprom_raw is None: + return None + + for i in range(0, 127): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[127]: + return False + + return True + + def validate_eeprom(self): + id_byte_raw = self.read_eeprom(0, 1) + if id_byte_raw is None: + return False + + id = id_byte_raw[0] + if id in self.QSFP_TYPE_CODE_LIST: + return self.validate_eeprom_qsfp() + elif id in self.SFP_TYPE_CODE_LIST: + return self.validate_eeprom_sfp() + elif id in self.QSFP_DD_TYPE_CODE_LIST: + return self.validate_eeprom_cmis() + elif id in self.OSFP_TYPE_CODE_LIST: + return self.validate_eeprom_cmis() + else: + return False + + def validate_temperature(self): + temperature = self.get_temperature() + if temperature is None: + return False + + threshold_dict = self.get_transceiver_threshold_info() + if threshold_dict is None: + return False + + if isinstance(temperature, float) is not True: + return True + + if isinstance(threshold_dict['temphighalarm'], float) is not True: + return True + + return threshold_dict['temphighalarm'] > temperature + + def __get_error_description(self): + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + + err_stat = self.SFP_STATUS_BIT_INSERTED + + status = self.validate_eeprom() + if status is not True: + err_stat = (err_stat | self.SFP_ERROR_BIT_BAD_EEPROM) + + status = self.validate_temperature() + if status is not True: + err_stat = (err_stat | self.SFP_ERROR_BIT_HIGH_TEMP) + + if err_stat is self.SFP_STATUS_BIT_INSERTED: + return self.SFP_STATUS_OK + else: + err_desc = '' + cnt = 0 + for key in self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT: + if (err_stat & key) != 0: + if cnt > 0: + err_desc = err_desc + "|" + cnt = cnt + 1 + err_desc = err_desc + self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT[key] + + return err_desc + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + + Returns: + String that represents the current error descriptions of vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + + try: + state = super().get_error_description() + if state is None: + return self.SFP_STATUS_OK + return state + except NotImplementedError: + return self.__get_error_description() diff --git a/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/thermal.py b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/thermal.py new file mode 100644 index 000000000000..78653ce4ca05 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/sonic_platform/thermal.py @@ -0,0 +1,466 @@ +############################################################################# +# Edgecore +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .helper import DeviceThreshold, APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +THERMAL_COUNT_PER_PSU = 3 + +NOT_AVAILABLE = DeviceThreshold.NOT_AVAILABLE +HIGH_THRESHOLD = DeviceThreshold.HIGH_THRESHOLD +LOW_THRESHOLD = DeviceThreshold.LOW_THRESHOLD +HIGH_CRIT_THRESHOLD = DeviceThreshold.HIGH_CRIT_THRESHOLD +LOW_CRIT_THRESHOLD = DeviceThreshold.LOW_CRIT_THRESHOLD + +# Default thresholds +DEFAULT_THRESHOLD = { + 'MB_RearCenter_temp(0x48)' : { + HIGH_THRESHOLD : '70.9', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '80.9', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_RearRight_temp(0x49)' : { + HIGH_THRESHOLD : '58.6', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '68.6', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_RearCenter_temp(0x4A)' : { + HIGH_THRESHOLD : '74.8', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '84.8', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_RearLeft_temp(0x4B)' : { + HIGH_THRESHOLD : '68.4', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '78.4', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_FrontLeft_temp(0x4C)' : { + HIGH_THRESHOLD : '73.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '83.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_FrontRight_temp(0x4D)' : { + HIGH_THRESHOLD : '59.1', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '69.1', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'FB_temp(0x4D)' : { + HIGH_THRESHOLD : '60.8', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '70.8', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'FB_temp(0x4E)' : { + HIGH_THRESHOLD : '60.9', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '70.9', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Package_temp' : { + HIGH_THRESHOLD : '90.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '100.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_0_temp' : { + HIGH_THRESHOLD : '90.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '100.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_1_temp' : { + HIGH_THRESHOLD : '90.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '100.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_2_temp' : { + HIGH_THRESHOLD : '90.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '100.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_3_temp' : { + HIGH_THRESHOLD : '90.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '100.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-1 temp sensor 1' : { + HIGH_THRESHOLD : '70.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '75.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-1 temp sensor 2' : { + HIGH_THRESHOLD : '125.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '130.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-1 temp sensor 3' : { + HIGH_THRESHOLD : '110.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '115.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-2 temp sensor 1' : { + HIGH_THRESHOLD : '70.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '75.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-2 temp sensor 2' : { + HIGH_THRESHOLD : '125.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '130.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-2 temp sensor 3' : { + HIGH_THRESHOLD : '110.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '115.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + } +} + +HWMON_PATH = { + True: { + 0: { + 0: {"hwmon_path":"as9817_64_psu.0/hwmon/hwmon*/psu1", "ss_index":1}, + 1: {"hwmon_path":"as9817_64_psu.0/hwmon/hwmon*/psu1", "ss_index":2}, + 2: {"hwmon_path":"as9817_64_psu.0/hwmon/hwmon*/psu1", "ss_index":3}, + }, + 1: { + 0: {"hwmon_path":"as9817_64_psu.1/hwmon/hwmon*/psu2", "ss_index":1}, + 1: {"hwmon_path":"as9817_64_psu.1/hwmon/hwmon*/psu2", "ss_index":2}, + 2: {"hwmon_path":"as9817_64_psu.1/hwmon/hwmon*/psu2", "ss_index":3}, + } + }, + False: { + 0: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":1}, + 1: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":2}, + 2: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":3}, + 3: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":4}, + 4: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":5}, + 5: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":6}, + 6: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":7}, + 7: {"hwmon_path":"as9817_64_thermal/hwmon/hwmon*/", "ss_index":8}, + 8: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":1}, + 9: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":2}, + 10: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":3}, + 11: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":4}, + 12: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":5} + } +} + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + PSU_THERMAL_NAME_LIST = [] + SYSFS_PATH_PREFIX = "/sys/devices/platform" + + def __init__(self, thermal_index=0, is_psu=False, psu_index=0): + self._api_helper = APIHelper() + self.index = thermal_index + self.is_psu = is_psu + self.is_cpu = False + self.psu_index = psu_index + self.hwmon_path = None + self.ss_index = 0 + self.min_temperature = None + self.max_temperature = None + + # Add thermal name + for thermal_name in DEFAULT_THRESHOLD.keys(): + if "PSU" in thermal_name: + self.PSU_THERMAL_NAME_LIST.append(thermal_name) + else: + self.THERMAL_NAME_LIST.append(thermal_name) + + # Threshold Configuration + self.__conf = DeviceThreshold(self.get_name()) + # Default threshold. + self.__default_threshold = DEFAULT_THRESHOLD[self.get_name()] + + sysfs_path = None + hwmon_path = HWMON_PATH.get(self.is_psu, None) + if self.is_psu: + # Set hwmon path + psu_hwmon_path = hwmon_path.get(self.psu_index, None) + if psu_hwmon_path is not None: + sysfs_path = psu_hwmon_path.get(self.index, None) + else : + # Set hwmon path + sysfs_path = hwmon_path.get(self.index, None) + if self.index in range(8,13): + self.is_cpu = True + + if sysfs_path is not None: + self.hwmon_path = "{}/{}".format(self.SYSFS_PATH_PREFIX, + sysfs_path["hwmon_path"]) + self.ss_index = sysfs_path["ss_index"] + + def __get_temp(self, temp_file): + if not self.is_psu: + temp_file_path = os.path.join(self.hwmon_path, temp_file) + else: + temp_file_path = temp_file + + raw_temp = self._api_helper.glob_read_txt_file(temp_file_path) + if raw_temp is not None: + return float(raw_temp) / 1000 + else: + return 0.0 + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if not self.is_psu: + temp_file = "temp{}_input".format(self.ss_index) + else: + temp_file = self.hwmon_path + "_temp{}_input".format(self.ss_index) + + current = self.__get_temp(temp_file) + + if self.min_temperature is None or \ + current < self.min_temperature: + self.min_temperature = current + + if self.max_temperature is None or \ + current > self.max_temperature: + self.max_temperature = current + + return current + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + value = self.__conf.get_high_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[HIGH_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be more than the default value. + default_value = self.__default_threshold[HIGH_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value > float(default_value): + return False + + try: + self.__conf.set_high_threshold(str(value)) + except Exception: + return False + + return True + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal by 1-based index + Actions should be taken immediately if the temperature becomes higher than the high critical + threshold otherwise the device will be damaged. + + :param index: An integer, 1-based index of the thermal sensor of which to query status + :return: A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + value = self.__conf.get_high_critical_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_high_critical_threshold(self, temperature): + """ + Sets the critical high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be more than the default value. + default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value > float(default_value): + return False + + try: + self.__conf.set_high_critical_threshold(str(value)) + except Exception: + return False + + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + if self.is_psu: + return self.PSU_THERMAL_NAME_LIST[(self.psu_index * THERMAL_COUNT_PER_PSU) + self.index] + else: + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + if self.is_cpu: + return True + + if self.is_psu: + val = self._api_helper.glob_read_txt_file(self.hwmon_path + "_present") + if val is not None: + return int(val, 10) == 1 + else: + return False + + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_txt = self._api_helper.glob_read_txt_file(temp_file_path) + if raw_txt is not None: + return True + else: + return False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if self.is_cpu: + return True + + if self.is_psu: + temp_file = self.hwmon_path + "_temp_fault" + psu_temp_fault = self._api_helper.glob_read_txt_file(temp_file) + if psu_temp_fault is None: + psu_temp_fault = '1' + return self.get_presence() and (not int(psu_temp_fault)) + + file_str = "temp{}_input".format(self.ss_index) + file_path = os.path.join(self.hwmon_path, file_str) + + raw_txt = self._api_helper.glob_read_txt_file(file_path) + if raw_txt is None: + return False + else: + return int(raw_txt) != 0 + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return "N/A" + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return self.index+1 + + def is_replaceable(self): + """ + Retrieves whether thermal module is replaceable + Returns: + A boolean value, True if replaceable, False if not + """ + return False + + def get_minimum_recorded(self): + """ + Retrieves the minimum recorded temperature of thermal + Returns: + A float number, the minimum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.min_temperature is None: + self.get_temperature() + + return self.min_temperature + + def get_maximum_recorded(self): + """ + Retrieves the maximum recorded temperature of thermal + Returns: + A float number, the maximum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.max_temperature is None: + self.get_temperature() + + return self.max_temperature diff --git a/device/accton/x86_64-accton_as9817_64o-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as9817_64o-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..5af0e4067aef --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/system_health_monitoring_config.json @@ -0,0 +1,13 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "STATUS_LED_COLOR_RED", + "normal": "STATUS_LED_COLOR_OFF", + "booting": "STATUS_LED_COLOR_OFF" + } +} diff --git a/device/accton/x86_64-accton_as9817_64o-r0/warm-reboot_plugin b/device/accton/x86_64-accton_as9817_64o-r0/warm-reboot_plugin new file mode 120000 index 000000000000..a94494bc5674 --- /dev/null +++ b/device/accton/x86_64-accton_as9817_64o-r0/warm-reboot_plugin @@ -0,0 +1 @@ +platform_reboot \ No newline at end of file diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 1af454dbc3a7..6cbba9f6e88b 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -47,6 +47,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_AS5835_54T_PLATFORM_MODULE) \ $(ACCTON_AS7312_54XS_PLATFORM_MODULE) \ $(ACCTON_AS7315_27XB_PLATFORM_MODULE) \ + $(ACCTON_AS9817_64O_PLATFORM_MODULE) \ + $(ACCTON_AS9817_64D_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 85e7ff1f5641..35b9e5f30228 100755 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -20,6 +20,8 @@ ACCTON_AS9726_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 +ACCTON_AS9817_64O_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS9817_64D_PLATFORM_MODULE_VERSION = 1.1 export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION @@ -41,6 +43,8 @@ export ACCTON_AS9726_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 +export ACCTON_AS9817_64O_PLATFORM_MODULE_VERSION +export ACCTON_AS9817_64D_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 @@ -123,3 +127,11 @@ $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS 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))) + +ACCTON_AS9817_64O_PLATFORM_MODULE = sonic-platform-accton-as9817-64o_$(ACCTON_AS9817_64O_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS9817_64O_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9817_64o-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9817_64O_PLATFORM_MODULE))) + +ACCTON_AS9817_64D_PLATFORM_MODULE = sonic-platform-accton-as9817-64d_$(ACCTON_AS9817_64D_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS9817_64D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9817_64d-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9817_64D_PLATFORM_MODULE))) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/Makefile new file mode 100644 index 000000000000..316e5f03e1ef --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=i2c-ocores.o accton_as9817_64_fpga.o accton_as9817_64_fan.o \ + accton_as9817_64_psu.o accton_as9817_64_thermal.o accton_as9817_64_sys.o \ + accton_as9817_64_leds.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_fan.c new file mode 120000 index 000000000000..ea548cbb6bdc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_fan.c @@ -0,0 +1 @@ +../../as9817-64o/modules/accton_as9817_64_fan.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_fpga.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_fpga.c new file mode 120000 index 000000000000..77f2ebed4f16 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_fpga.c @@ -0,0 +1 @@ +../../as9817-64o/modules/accton_as9817_64_fpga.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_leds.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_leds.c new file mode 120000 index 000000000000..182adf0b175d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_leds.c @@ -0,0 +1 @@ +../../as9817-64o/modules/accton_as9817_64_leds.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_psu.c new file mode 120000 index 000000000000..c8b593cdc75d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_psu.c @@ -0,0 +1 @@ +../../as9817-64o/modules/accton_as9817_64_psu.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_sys.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_sys.c new file mode 120000 index 000000000000..f06627b3e331 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_sys.c @@ -0,0 +1 @@ +../../as9817-64o/modules/accton_as9817_64_sys.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_thermal.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_thermal.c new file mode 120000 index 000000000000..97a5e9bc72b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/accton_as9817_64_thermal.c @@ -0,0 +1 @@ +../../as9817-64o/modules/accton_as9817_64_thermal.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/i2c-ocores.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/i2c-ocores.c new file mode 120000 index 000000000000..5fa3b06e3f32 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/modules/i2c-ocores.c @@ -0,0 +1 @@ +../../as9817-64o/modules/i2c-ocores.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/service/as9817_64d-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/service/as9817_64d-platform-init.service new file mode 100644 index 000000000000..b5ccb915fb9f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/service/as9817_64d-platform-init.service @@ -0,0 +1,15 @@ +[Unit] +Description=Accton AS9817-64D Platform Initialization Service +Before=pmon.service determine-reboot-cause.service system-health.service +DefaultDependencies=no + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/bin/accton_as9817_64d_util.py install + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/service/as9817_64d-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/service/as9817_64d-platform-monitor.service new file mode 100644 index 000000000000..33ff15b8f6f7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/service/as9817_64d-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS9817-64D Platform Monitoring service +Before=pmon.service +After=as9817_64d-platform-init.service +Requires=as9817_64d-platform-init.service + +[Service] +ExecStart=/usr/local/bin/accton_as9817_64_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/setup.py new file mode 100755 index 000000000000..9036385f4860 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='as9817_64d', + version='1.0', + description='Module to initialize Accton AS9817-64D platforms', + + packages=['as9817_64d'], + package_dir={'as9817_64d': 'as9817-64d/classes'}, +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/sonic_platform_setup.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/sonic_platform_setup.py new file mode 100644 index 000000000000..3334ed35e3be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/sonic_platform_setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +DEVICE_NAME = 'accton' +HW_SKU = 'x86_64-accton_as9817_64d-r0' + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Accton Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Roger Ho', + maintainer_email='roger530_ho@edge-core.com', + packages=[ + 'sonic_platform', + ], + package_dir={ + 'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)}, + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Plugins', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/utils/accton_as9817_64_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/utils/accton_as9817_64_monitor.py new file mode 120000 index 000000000000..3dc98c69a8b5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/utils/accton_as9817_64_monitor.py @@ -0,0 +1 @@ +../../as9817-64o/utils/accton_as9817_64_monitor.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64d/utils/accton_as9817_64d_util.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/utils/accton_as9817_64d_util.py new file mode 100755 index 000000000000..958796e957a6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64d/utils/accton_as9817_64d_util.py @@ -0,0 +1,663 @@ +#!/usr/bin/env python3 +# +# 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: accton_as9817_64d_util.py [-h] [-d] [-f] {install,clean,threshold} ... + +AS9817-64D Platform Utility + +optional arguments: + -h, --help show this help message and exit + -d, --debug run with debug mode + -f, --force ignore error during installation or clean + +Utility Command: + {install,clean,threshold} + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + threshold : modify thermal threshold +""" +import subprocess +import sys +import logging +import re +import time +import os +import glob +import argparse +from sonic_py_common.general import getstatusoutput_noshell + + +PROJECT_NAME = 'as9817_64d' +version = '0.1.0' +verbose = False +DEBUG = False +FAN_PWM = 67 +args = [] +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 + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + util_parser = argparse.ArgumentParser(description="AS9817-64D Platform Utility") + util_parser.add_argument("-d", "--debug", dest='debug', action='store_true', default=False, + help="run with debug mode") + util_parser.add_argument("-f", "--force", dest='force', action='store_true', default=False, + help="ignore error during installation or clean") + subcommand = util_parser.add_subparsers(dest='cmd', title='Utility Command', required=True) + subcommand.add_parser('install', help=': install drivers and generate related sysfs nodes') + subcommand.add_parser('clean', help=': uninstall drivers and remove related sysfs nodes') + threshold_parser = subcommand.add_parser('threshold', help=': modify thermal threshold') + threshold_parser.add_argument("-l", dest='list', action='store_true', default=False, + help="list avaliable thermal") + threshold_parser.add_argument("-t", dest='thermal', type=str, metavar='THERMAL_NAME', + help="thermal name, ex: -t 'Temp sensor 1'") + threshold_parser.add_argument("-ht", dest='high_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high threshold: %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + threshold_parser.add_argument("-hct", dest='high_crit_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high critical threshold : %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + args = util_parser.parse_args() + + if DEBUG == True: + print(args) + print(len(sys.argv)) + + DEBUG = args.debug + FORCE = 1 if args.force else 0 + + if args.cmd == 'install': + do_install() + elif args.cmd == 'clean': + do_uninstall() + elif args.cmd == 'threshold': + do_threshold() + + return 0 + +def show_help(): + print(__doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}) + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print("[DEBUG]"+txt) + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = subprocess.getstatusoutput(cmd) + #status, output = getstatusoutput_noshell(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("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +ipmi_ko = [ + 'modprobe ipmi_msghandler', + 'modprobe ipmi_ssif', + 'modprobe ipmi_si', + 'modprobe ipmi_devintf'] + +ATTEMPTS = 5 +INTERVAL = 3 + +def init_ipmi_dev_intf(): + attempts = ATTEMPTS + interval = INTERVAL + + while attempts: + for i in range(0, len(ipmi_ko)): + subprocess.getstatusoutput(ipmi_ko[i]) + + if os.path.exists('/dev/ipmi0') or os.path.exists('/dev/ipmidev/0'): + return (0, (ATTEMPTS - attempts) * interval) + + for i in reversed(range(0, len(ipmi_ko))): + rm = ipmi_ko[i].replace("modprobe", "modprobe -rq") + subprocess.getstatusoutput(rm) + + attempts -= 1 + time.sleep(interval) + + return (1, ATTEMPTS * interval) + +def init_ipmi_oem_cmd(): + attempts = ATTEMPTS + interval = INTERVAL + + while attempts: + status, output = subprocess.getstatusoutput('ipmitool raw 0x34 0x95') + if status: + attempts -= 1 + time.sleep(interval) + continue + + return (0, (ATTEMPTS - attempts) * interval) + + return (1, ATTEMPTS * interval) + +def init_ipmi(): + attempts = ATTEMPTS + interval = 60 + + while attempts: + attempts -= 1 + + (status, elapsed_dev) = init_ipmi_dev_intf() + if status: + time.sleep(interval - elapsed_dev) + continue + + (status, elapsed_oem) = init_ipmi_oem_cmd() + if status: + time.sleep(interval - elapsed_dev - elapsed_oem) + continue + + print('IPMI dev interface is ready.') + return 0 + + print('Failed to initialize IPMI dev interface') + return 1 + + +kos = [ + 'modprobe i2c_dev', + 'modprobe i2c_i801', + 'modprobe i2c_ismt', + 'modprobe optoe', + 'modprobe at24', + 'modprobe i2c-ocores', + 'modprobe accton_as9817_64_fpga', + 'modprobe accton_as9817_64_fan', + 'modprobe accton_as9817_64_psu', + 'modprobe accton_as9817_64_thermal', + 'modprobe accton_as9817_64_sys', + 'modprobe accton_as9817_64_leds' +] + +#EERPOM +eeprom_mknod =[ + 'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + +def eeprom_check(): + cmd = ["i2cget", "-f", "-y", "0", "0x56"] + status, output = getstatusoutput_noshell(cmd) + return status + +def driver_install(): + global FORCE + + # Load 10G ethernet driver + status, output = log_os_system("modprobe ice", 1) + if status: + if FORCE == 0: + return status + + status = init_ipmi() + if status: + if FORCE == 0: + return status + + status, output = log_os_system("depmod -ae", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + print("Done driver_install") + + return 0 + +def driver_uninstall(): + global FORCE + + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [ + 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, + 18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33, + 34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49, + 50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65, + 66,67 +] + +osfp_start = 0 +osfp_end = 63 + +mknod =[ + +] + +mkfile = [ + '/tmp/device_threshold.json', + '/tmp/device_threshold.json.lock' +] + +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 + + # Select I2C relay channel to MB_EEPROM + log_os_system("i2cset -f -a -y 0 0x78 0x00 0x01", 1) + time.sleep(0.2) + + ret=eeprom_check() + if ret==0: + log_os_system(eeprom_mknod[0], 1) + time.sleep(0.2) + exists = os.path.isfile('/sys/bus/i2c/devices/0-0056/eeprom') + if (exists is False): + subprocess.call('echo 0x56 > /sys/bus/i2c/devices/i2c-1/delete_device', shell=True) + + for i in range(0,len(sfp_map)): + if i > osfp_end: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe3 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print(output) + if FORCE == 0: + return status + + # Release RESET pin for all QSFP-DD. + for i in range(0, (osfp_end + 1)): + status, output = log_os_system("echo 0 > /sys/devices/platform/as9817_64_fpga/module_reset_{}".format(i + 1), 1) + if status: + print(output) + + # Disable Low Power Mode for all QSFP-DD. + for i in range(0, (osfp_end + 1)): + status, output = log_os_system("echo 0 > /sys/devices/platform/as9817_64_fpga/module_lp_mode_{}".format(i + 1), 1) + if status: + print(output) + + # Prevent permission issues between root or admin users for sonic_platform/helper.py + for i in range(0,len(mkfile)): + try: + # Create empty file + open(mkfile[i], 'a').close() + os.chmod(mkfile[i], 0o644) + except OSError: + print('Failed : creating the file %s.' % (mkfile[i])) + os.chmod(mkfile[i], 0o644) + if FORCE == 0: + return -1 + + print("Done device_install") + return + +def device_uninstall(): + global FORCE + + 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 + + for i in range(len(mknod)): + target = mknod[-(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 + + # Deal with for del 0x56 sysfs device + exists = os.path.isfile('/sys/bus/i2c/devices/0-0056/eeprom') + if (exists is True): + target = eeprom_mknod[0] #0x56 + + 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 + + for i in range(0,len(mkfile)): + status, output = log_os_system('rm -f ' + mkfile[i], 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 + +PLATFORM_ROOT_PATH = '/usr/share/sonic/device' +PLATFORM_API2_WHL_FILE_PY3 ='sonic_platform-1.0-py3-none-any.whl' +def do_sonic_platform_install(): + device_path = "{}{}{}{}".format(PLATFORM_ROOT_PATH, '/x86_64-accton_', PROJECT_NAME, '-r0') + SONIC_PLATFORM_BSP_WHL_PKG_PY3 = "/".join([device_path, PLATFORM_API2_WHL_FILE_PY3]) + + #Check API2.0 on py whl file + status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0) + if status: + if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_PY3): + status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG_PY3, 1) + if status: + print("Error: Failed to install {}".format(PLATFORM_API2_WHL_FILE_PY3)) + return status + else: + print("Successfully installed {} package".format(PLATFORM_API2_WHL_FILE_PY3)) + else: + print('{} is not found'.format(PLATFORM_API2_WHL_FILE_PY3)) + else: + print('{} has installed'.format(PLATFORM_API2_WHL_FILE_PY3)) + + return + +def do_sonic_platform_clean(): + status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0) + if status: + print('{} does not install, not need to uninstall'.format(PLATFORM_API2_WHL_FILE_PY3)) + + else: + status, output = log_os_system("pip3 uninstall sonic-platform -y", 0) + if status: + print('Error: Failed to uninstall {}'.format(PLATFORM_API2_WHL_FILE_PY3)) + return status + else: + print('{} is uninstalled'.format(PLATFORM_API2_WHL_FILE_PY3)) + + return + +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....") + + # Turn off LOC LED if needed + log_os_system("echo 0 > /sys/devices/platform/as9817_64_led/led_loc", 1) + + # Chnage all fan_pwm to 67% + for filename in glob.glob("/sys/devices/platform/as9817_64_fan/hwmon/*/fan*_pwm"): + try: + with open(filename, 'w') as fd: + fd.write(str(FAN_PWM)) + except IOError as e: + pass + + do_sonic_platform_install() + + 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 + + do_sonic_platform_clean() + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +THRESHOLD_RANGE_LOW = 30.0 +THRESHOLD_RANGE_HIGH = 110.0 +# Code to initialize chassis object +init_chassis_code = \ + "import sonic_platform.platform\n"\ + "platform = sonic_platform.platform.Platform()\n"\ + "chassis = platform.get_chassis()\n\n" + +# Looking for thermal +looking_for_thermal_code = \ + "thermal = None\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " if '{}' == tmp.get_name():\n"\ + " thermal = tmp\n"\ + " break\n"\ + "if thermal == None:\n"\ + " print('{} not found!')\n"\ + " exit(1)\n\n" + +def avaliable_thermals(): + global init_chassis_code + + get_all_thermal_name_code = \ + "thermal_list = []\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " thermal_list.append(tmp.get_name())\n"\ + "print(str(thermal_list)[1:-1])\n" + + all_code = "{}{}".format(init_chassis_code, get_all_thermal_name_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status != 0: + return "" + return output + +def restricted_float(x): + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + try: + x = float(x) + except ValueError: + raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,)) + + if x < THRESHOLD_RANGE_LOW or x > THRESHOLD_RANGE_HIGH: + raise argparse.ArgumentTypeError("%r not in range [%.1f ~ %.1f]" % + (x, THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + + return x + +def get_high_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def get_high_crit_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_crit_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_critical_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_critical_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_crit_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def do_threshold(): + global args, init_chassis_code, looking_for_thermal_code + + if args.list: + print("Thermals: " + avaliable_thermals()) + return + + if args.thermal is None: + print("The following arguments are required: -t") + return + + set_threshold_code = "" + if args.high_threshold is not None: + if args.high_crit_threshold is not None and \ + args.high_threshold >= args.high_crit_threshold: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + high_crit = get_high_crit_threshold(args.thermal) + if high_crit is not None and \ + args.high_threshold >= high_crit: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_threshold({}) is False:\n"\ + " print('{}: set_high_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_threshold method!')\n"\ + "print('Apply the new high threshold successfully.')\n"\ + "\n".format(args.high_threshold, args.thermal) + + if args.high_crit_threshold is not None: + high = get_high_threshold(args.thermal) + if high is not None and \ + args.high_crit_threshold <= high: + print("Invalid Threshold!(High critical threshold can not " \ + "be less than or equal to high threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_critical_threshold({}) is False:\n"\ + " print('{}: set_high_critical_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_critical_threshold method!')\n"\ + "print('Apply the new high critical threshold successfully.')\n"\ + "\n".format(args.high_crit_threshold, args.thermal) + + if set_threshold_code == "": + return + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(args.thermal, args.thermal), set_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + print(output) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/Makefile new file mode 100644 index 000000000000..316e5f03e1ef --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=i2c-ocores.o accton_as9817_64_fpga.o accton_as9817_64_fan.o \ + accton_as9817_64_psu.o accton_as9817_64_thermal.o accton_as9817_64_sys.o \ + accton_as9817_64_leds.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_fan.c new file mode 100644 index 000000000000..02efd48dcb92 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_fan.c @@ -0,0 +1,756 @@ +/* + * Copyright (C) Roger Ho + * + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9817_64_fan" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_FAN_READ_CMD 0x14 +#define IPMI_FAN_WRITE_CMD 0x15 +#define IPMI_FAN_READ_RPM_CMD 0x20 +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_ERR_RETRY_TIMES 1 +#define IPMI_FAN_REG_READ_CMD 0x20 +#define IPMI_FAN_REG_WRITE_CMD 0x21 +#define MAX_FAN_SPEED_RPM 33000 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_dir(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_threshold(struct device *dev, struct device_attribute *da, + char *buf); +static int as9817_64_fan_probe(struct platform_device *pdev); +static int as9817_64_fan_remove(struct platform_device *pdev); + +enum fan_id { + FAN_1, + FAN_2, + FAN_3, + FAN_4, + FAN_5, + FAN_6, + FAN_7, + FAN_8, + NUM_OF_FAN, + NUM_OF_FAN_MODULE = NUM_OF_FAN +}; + +enum fan_data_index { + FAN_PRESENT, + FAN_PWM, + FAN_SPEED0, + FAN_SPEED1, + FAN_DATA_COUNT, + + FAN_TARGET_SPEED0 = 0, + FAN_TARGET_SPEED1, + FAN_SPEED_TOLERANCE, + FAN_SPEED_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + struct ipmi_user *user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as9817_64_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + /* 4 bytes for each fan, the last 2 bytes is fan dir */ + unsigned char ipmi_resp[NUM_OF_FAN * FAN_DATA_COUNT + 2]; + unsigned char ipmi_resp_cpld[2]; + unsigned char ipmi_resp_speed[NUM_OF_FAN * FAN_SPEED_DATA_COUNT]; + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[3]; /* 0: FAN id, 1: 0x02, 2: PWM */ +}; + +struct as9817_64_fan_data *data = NULL; + +static struct platform_driver as9817_64_fan_driver = { + .probe = as9817_64_fan_probe, + .remove = as9817_64_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define FAN_PRESENT_ATTR_ID(index) FAN##index##_PRESENT +#define FAN_PWM_ATTR_ID(index) FAN##index##_PWM +#define FAN_RPM_ATTR_ID(index) FAN##index##_INPUT +#define FAN_DIR_ATTR_ID(index) FAN##index##_DIR +#define FAN_FAULT_ATTR_ID(index) FAN##index##_FAULT +#define FAN_RPM_TARGET_ATTR_ID(index) FAN##index##_TARGET +#define FAN_RPM_TOLERANCE_ATTR_ID(index) FAN##index##_TOLERANCE + +#define FAN_ATTR(fan_id) \ + FAN_PRESENT_ATTR_ID(fan_id), \ + FAN_PWM_ATTR_ID(fan_id), \ + FAN_RPM_ATTR_ID(fan_id), \ + FAN_DIR_ATTR_ID(fan_id), \ + FAN_FAULT_ATTR_ID(fan_id) + +#define FAN_RPM_THRESHOLD_ATTR(fan_id) \ + FAN_RPM_TARGET_ATTR_ID(fan_id), \ + FAN_RPM_TOLERANCE_ATTR_ID(fan_id) + +enum as9817_64_fan_sysfs_attrs { + FAN_ATTR(1), + FAN_ATTR(2), + FAN_ATTR(3), + FAN_ATTR(4), + FAN_ATTR(5), + FAN_ATTR(6), + FAN_ATTR(7), + FAN_ATTR(8), + NUM_OF_FAN_ATTR, + FAN_VERSION, + FAN_MAX_RPM, + NUM_OF_PER_FAN_ATTR = (NUM_OF_FAN_ATTR/NUM_OF_FAN), + FAN_RPM_THRESHOLD_ATTR(1), + FAN_RPM_THRESHOLD_ATTR(2), + FAN_RPM_THRESHOLD_ATTR(3), + FAN_RPM_THRESHOLD_ATTR(4), + FAN_RPM_THRESHOLD_ATTR(5), + FAN_RPM_THRESHOLD_ATTR(6), + FAN_RPM_THRESHOLD_ATTR(7), + FAN_RPM_THRESHOLD_ATTR(8) +}; + +/* fan attributes */ +#define DECLARE_FAN_VER_SENSOR_DEVICE_ATTR() \ + static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, FAN_VERSION) +#define DECLARE_FAN_VER_ATTR() \ + &sensor_dev_attr_version.dev_attr.attr + +#define DECLARE_FAN_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, show_fan, NULL, \ + FAN##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, show_fan, \ + set_fan, FAN##index##_PWM); \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, show_fan, NULL, \ + FAN##index##_INPUT); \ + static SENSOR_DEVICE_ATTR(fan##index##_dir, S_IRUGO, show_dir, NULL, \ + FAN##index##_DIR); \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, show_fan, NULL, \ + FAN##index##_FAULT); \ + static SENSOR_DEVICE_ATTR(fan##index##_target, S_IRUGO, show_threshold, \ + NULL, FAN##index##_TARGET); \ + static SENSOR_DEVICE_ATTR(fan##index##_tolerance, S_IRUGO, show_threshold,\ + NULL, FAN##index##_TOLERANCE) + +static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, show_fan, NULL, \ + FAN_MAX_RPM); +#define DECLARE_FAN_MAX_RPM_ATTR(index) \ + &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr + +#define DECLARE_FAN_ATTR(index) \ + &sensor_dev_attr_fan##index##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_pwm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_dir.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_target.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_tolerance.dev_attr.attr + +DECLARE_FAN_SENSOR_DEVICE_ATTR(1); +DECLARE_FAN_SENSOR_DEVICE_ATTR(2); +DECLARE_FAN_SENSOR_DEVICE_ATTR(3); +DECLARE_FAN_SENSOR_DEVICE_ATTR(4); +DECLARE_FAN_SENSOR_DEVICE_ATTR(5); +DECLARE_FAN_SENSOR_DEVICE_ATTR(6); +DECLARE_FAN_SENSOR_DEVICE_ATTR(7); +DECLARE_FAN_SENSOR_DEVICE_ATTR(8); +DECLARE_FAN_VER_SENSOR_DEVICE_ATTR(); + +static struct attribute *as9817_64_fan_attrs[] = { + /* fan attributes */ + DECLARE_FAN_ATTR(1), + DECLARE_FAN_ATTR(2), + DECLARE_FAN_ATTR(3), + DECLARE_FAN_ATTR(4), + DECLARE_FAN_ATTR(5), + DECLARE_FAN_ATTR(6), + DECLARE_FAN_ATTR(7), + DECLARE_FAN_ATTR(8), + DECLARE_FAN_VER_ATTR(), + DECLARE_FAN_MAX_RPM_ATTR(), + NULL +}; +ATTRIBUTE_GROUPS(as9817_64_fan); + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int _ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Send an IPMI command with retry */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int status = 0, retry = 0; + + for (retry = 0; retry <= IPMI_ERR_RETRY_TIMES; retry++) { + status = _ipmi_send_message(ipmi,cmd, tx_data, tx_len, rx_data, rx_len); + if (unlikely(status != 0)) { + dev_err(&data->pdev->dev, "ipmi_send_message_%d err status(%d)\r\n", + retry, status); + continue; + } + + if (unlikely(ipmi->rx_result != 0)) { + dev_err(&data->pdev->dev, "ipmi_send_message_%d err result(%d)\r\n", + retry, ipmi->rx_result); + continue; + } + + break; + } + + return status; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_notice(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as9817_64_fan_data *as9817_64_fan_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) + return data; + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_tx_data[0] = IPMI_FAN_READ_RPM_CMD; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp_speed, + sizeof(data->ipmi_resp_speed)); + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + int value = 0; + int index = 0; + int present = 0; + int error = 0; + + if (attr->index == FAN_MAX_RPM) + return sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM); + + mutex_lock(&data->update_lock); + + data = as9817_64_fan_update_device(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + index = fid * FAN_DATA_COUNT; /* base index */ + present = !!data->ipmi_resp[index + FAN_PRESENT]; + + switch (attr->index) { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + case FAN7_PRESENT: + case FAN8_PRESENT: + value = present; + break; + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + index = (fid % NUM_OF_FAN_MODULE) * FAN_DATA_COUNT; + value = DIV_ROUND_CLOSEST(data->ipmi_resp[index + FAN_PWM] * 666, 100); + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + case FAN7_INPUT: + case FAN8_INPUT: + value = (int)data->ipmi_resp[index + FAN_SPEED0] | + (int)data->ipmi_resp[index + FAN_SPEED1] << 8; + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + case FAN7_FAULT: + case FAN8_FAULT: + value = (int)data->ipmi_resp[index + FAN_SPEED0] | + (int)data->ipmi_resp[index + FAN_SPEED1] << 8; + value = !value; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long pwm; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + + status = kstrtol(buf, 10, &pwm); + if (status) + return status; + + pwm = (pwm * 100) / 666; /* Convert pwm to register value */ + + mutex_lock(&data->update_lock); + + /* + * Send IPMI write command : + * BMC supports a design with four fan modules, each containing two fans. + * Since NUM_OF_FAN_MODULE is 8 in AS9817, it needs to be divided by 2. + * The result : + * fan1_pwm(Front) : ipmi_tx_data[0] = 1, fan2_pwm(Front) : ipmi_tx_data[0] = 2 + * fan3_pwm(Front) : ipmi_tx_data[0] = 3, fan4_pwm(Front) : ipmi_tx_data[0] = 4 + * fan5_pwm(Rear) : ipmi_tx_data[0] = 1, fan6_pwm(Rear) : ipmi_tx_data[0] = 2 + * fan7_pwm(Rear) : ipmi_tx_data[0] = 3, fan8_pwm(Rear) : ipmi_tx_data[0] = 4 + * + */ + data->ipmi_tx_data[0] = (fid % (NUM_OF_FAN_MODULE / 2)) + 1; + data->ipmi_tx_data[1] = 0x02; + data->ipmi_tx_data[2] = pwm; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), + NULL, 0); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update pwm to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp[fid * FAN_DATA_COUNT + FAN_PWM] = pwm; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static struct as9817_64_fan_data *as9817_64_fan_update_cpld_ver(void) +{ + int status = 0; + + data->valid = 0; + data->ipmi_tx_data[0] = 0x33; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_REG_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp_cpld, + sizeof(data->ipmi_resp_cpld)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + unsigned char major; + unsigned char minor; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_fan_update_cpld_ver(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + major = data->ipmi_resp_cpld[0]; + minor = data->ipmi_resp_cpld[1]; + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d.%d\n", major, minor); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_dir(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = (attr->index / NUM_OF_PER_FAN_ATTR); + int value = 0; + int index = 0; + int present = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_fan_update_device(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + index = fid * FAN_DATA_COUNT; /* base index */ + present = !!data->ipmi_resp[index + FAN_PRESENT]; + + value = data->ipmi_resp[NUM_OF_FAN * FAN_DATA_COUNT] | + (data->ipmi_resp[NUM_OF_FAN * FAN_DATA_COUNT + 1] << 8); + mutex_unlock(&data->update_lock); + + if (!present) + return sprintf(buf, "0\n"); + else + return sprintf(buf, "%s\n", + (value & BIT(fid % NUM_OF_FAN_MODULE)) ? "B2F" : "F2B"); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_threshold(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_fan_update_device(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case FAN1_TARGET: + case FAN2_TARGET: + case FAN3_TARGET: + case FAN4_TARGET: + case FAN5_TARGET: + case FAN6_TARGET: + case FAN7_TARGET: + case FAN8_TARGET: + value = (int)data->ipmi_resp_speed[FAN_TARGET_SPEED0] | + (int)data->ipmi_resp_speed[FAN_TARGET_SPEED1] << 8; + break; + case FAN1_TOLERANCE: + case FAN2_TOLERANCE: + case FAN3_TOLERANCE: + case FAN4_TOLERANCE: + case FAN5_TOLERANCE: + case FAN6_TOLERANCE: + case FAN7_TOLERANCE: + case FAN8_TOLERANCE: + value = (int)data->ipmi_resp_speed[FAN_SPEED_TOLERANCE]; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static int as9817_64_fan_probe(struct platform_device *pdev) +{ + int status = 0; + struct device *hwmon_dev; + + hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, DRVNAME, + NULL, as9817_64_fan_groups); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + return status; + } + + mutex_lock(&data->update_lock); + data->hwmon_dev = hwmon_dev; + mutex_unlock(&data->update_lock); + + dev_info(&pdev->dev, "Device Created\n"); + + return status; +} + +static int as9817_64_fan_remove(struct platform_device *pdev) +{ + mutex_lock(&data->update_lock); + if (data->hwmon_dev) { + hwmon_device_unregister(data->hwmon_dev); + data->hwmon_dev = NULL; + } + mutex_unlock(&data->update_lock); + + return 0; +} + +static int __init as9817_64_fan_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as9817_64_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as9817_64_fan_driver); + if (ret < 0) + goto dri_reg_err; + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) { + goto ipmi_err; + } + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as9817_64_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as9817_64_fan_exit(void) +{ + if (data) { + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + kfree(data); + } + platform_driver_unregister(&as9817_64_fan_driver); +} + +MODULE_AUTHOR("Roger Ho "); +MODULE_DESCRIPTION("as9817_64_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(as9817_64_fan_init); +module_exit(as9817_64_fan_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_fpga.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_fpga.c new file mode 100644 index 000000000000..d9cafcb3fd7d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_fpga.c @@ -0,0 +1,1189 @@ +/* + * Copyright (C) Roger Ho + * + * This module supports the accton fpga via pcie that read/write reg + * mechanism to get OSFP/SFP status ...etc. + * This includes the: + * Accton as9817_64 FPGA + * + * Copyright (C) 2017 Finisar Corp. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __STDC_WANT_LIB_EXT1__ 1 +#include +#include + +/*********************************************** + * variable define + * *********************************************/ +#define DRVNAME "as9817_64_fpga" +#define OCORES_I2C_DRVNAME "ocores-i2c" + +#define PORT_NUM (64 + 2) /* 64 OSFPs/QSFPDDs + 2 SFP28s */ + +/* + * PCIE BAR0 address + */ +#define BAR0_NUM 0 +#define BAR1_NUM 1 +#define BAR2_NUM 2 +#define REGION_LEN 0xFF +#define FPGA_PCI_VENDOR_ID 0x10ee +#define FPGA_PCI_DEVICE_ID 0x7021 + +#define FPGA_PCIE_START_OFFSET 0x0000 +#define FPGA_MAJOR_VER_REG 0x01 +#define FPGA_MINOR_VER_REG 0x02 +#define SPI_BUSY_MASK_CPLD1 0x01 +#define SPI_BUSY_MASK_CPLD2 0x02 + +#define FPGA_PCIE_START_OFFSET 0x0000 +#define FPGA_BOARD_INFO_REG (FPGA_PCIE_START_OFFSET + 0x00) + +/* CPLD 1 */ +#define CPLD1_PCIE_START_OFFSET 0x2000 +#define CPLD1_MAJOR_VER_REG (CPLD1_PCIE_START_OFFSET + 0x00) +#define CPLD1_MINOR_VER_REG (CPLD1_PCIE_START_OFFSET + 0x01) +#define XCVR_P7_P0_LPMODE_REG (CPLD1_PCIE_START_OFFSET + 0x70) +#define XCVR_P15_P8_LPMODE_REG (CPLD1_PCIE_START_OFFSET + 0x71) +#define XCVR_P39_P32_LPMODE_REG (CPLD1_PCIE_START_OFFSET + 0x72) +#define XCVR_P47_P40_LPMODE_REG (CPLD1_PCIE_START_OFFSET + 0x73) +#define XCVR_P7_P0_RESET_REG (CPLD1_PCIE_START_OFFSET + 0x78) +#define XCVR_P15_P8_RESET_REG (CPLD1_PCIE_START_OFFSET + 0x79) +#define XCVR_P39_P32_RESET_REG (CPLD1_PCIE_START_OFFSET + 0x7A) +#define XCVR_P47_P40_RESET_REG (CPLD1_PCIE_START_OFFSET + 0x7B) +#define XCVR_P7_P0_PRESENT_REG (CPLD1_PCIE_START_OFFSET + 0x88) +#define XCVR_P15_P8_PRESENT_REG (CPLD1_PCIE_START_OFFSET + 0x89) +#define XCVR_P39_P32_PRESENT_REG (CPLD1_PCIE_START_OFFSET + 0x8A) +#define XCVR_P47_P40_PRESENT_REG (CPLD1_PCIE_START_OFFSET + 0x8B) + +/* CPLD 2 */ +#define CPLD2_PCIE_START_OFFSET 0x3000 +#define CPLD2_MAJOR_VER_REG (CPLD2_PCIE_START_OFFSET + 0x00) +#define CPLD2_MINOR_VER_REG (CPLD2_PCIE_START_OFFSET + 0x01) +#define SFP_TXFAULT_REG (CPLD2_PCIE_START_OFFSET + 0x06) +#define SFP_TXDIS_REG (CPLD2_PCIE_START_OFFSET + 0x07) +#define SFP_RXLOSS_REG (CPLD2_PCIE_START_OFFSET + 0x08) +#define SFP_PRESENT_REG (CPLD2_PCIE_START_OFFSET + 0x09) +#define XCVR_P23_P16_LPMODE_REG (CPLD2_PCIE_START_OFFSET + 0x70) +#define XCVR_P31_P24_LPMODE_REG (CPLD2_PCIE_START_OFFSET + 0x71) +#define XCVR_P55_P48_LPMODE_REG (CPLD2_PCIE_START_OFFSET + 0x72) +#define XCVR_P63_P56_LPMODE_REG (CPLD2_PCIE_START_OFFSET + 0x73) +#define XCVR_P23_P16_RESET_REG (CPLD2_PCIE_START_OFFSET + 0x78) +#define XCVR_P31_P24_RESET_REG (CPLD2_PCIE_START_OFFSET + 0x79) +#define XCVR_P55_P48_RESET_REG (CPLD2_PCIE_START_OFFSET + 0x7A) +#define XCVR_P63_P56_RESET_REG (CPLD2_PCIE_START_OFFSET + 0x7B) +#define XCVR_P23_P16_PRESENT_REG (CPLD2_PCIE_START_OFFSET + 0x88) +#define XCVR_P31_P24_PRESENT_REG (CPLD2_PCIE_START_OFFSET + 0x89) +#define XCVR_P55_P48_PRESENT_REG (CPLD2_PCIE_START_OFFSET + 0x8A) +#define XCVR_P63_P56_PRESENT_REG (CPLD2_PCIE_START_OFFSET + 0x8B) + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index +#define TRANSCEIVER_TX_DISABLE_ATTR_ID(index) MODULE_TX_DISABLE_##index +#define TRANSCEIVER_TX_FAULT_ATTR_ID(index) MODULE_TX_FAULT_##index +#define TRANSCEIVER_RX_LOS_ATTR_ID(index) MODULE_RX_LOS_##index + +/*********************************************** + * macro define + * *********************************************/ +#define pcie_err(fmt, args...) \ + printk(KERN_ERR "["DRVNAME"]: " fmt " ", ##args) + +#define pcie_info(fmt, args...) \ + printk(KERN_ERR "["DRVNAME"]: " fmt " ", ##args) + + +#define LOCK(lock) \ +do { \ + spin_lock(lock); \ +} while (0) + +#define UNLOCK(lock) \ +do { \ + spin_unlock(lock); \ +} while (0) + + +/*********************************************** + * structure & variable declare + * *********************************************/ +typedef struct pci_fpga_device_s { + void __iomem *data_base_addr0; + void __iomem *data_base_addr1; + void __iomem *data_base_addr2; + resource_size_t data_region1; + resource_size_t data_region2; + struct pci_dev *pci_dev; + struct platform_device *fpga_i2c[PORT_NUM]; +} pci_fpga_device_t; + +/*fpga port status*/ +struct as9817_64_fpga_data { + u8 cpld_reg[2]; + unsigned long last_updated; /* In jiffies */ + pci_fpga_device_t pci_fpga_dev; +}; + +static struct platform_device *pdev = NULL; +extern spinlock_t cpld_access_lock; +extern int wait_spi(u32 mask, unsigned long timeout); +extern void __iomem *spi_busy_reg; + +/*********************************************** + * enum define + * *********************************************/ +enum fpga_sysfs_attributes { + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_PRESENT_ATTR_ID(55), + TRANSCEIVER_PRESENT_ATTR_ID(56), + TRANSCEIVER_PRESENT_ATTR_ID(57), + TRANSCEIVER_PRESENT_ATTR_ID(58), + TRANSCEIVER_PRESENT_ATTR_ID(59), + TRANSCEIVER_PRESENT_ATTR_ID(60), + TRANSCEIVER_PRESENT_ATTR_ID(61), + TRANSCEIVER_PRESENT_ATTR_ID(62), + TRANSCEIVER_PRESENT_ATTR_ID(63), + TRANSCEIVER_PRESENT_ATTR_ID(64), + TRANSCEIVER_PRESENT_ATTR_ID(65), + TRANSCEIVER_PRESENT_ATTR_ID(66), + /*Reset*/ + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), + TRANSCEIVER_RESET_ATTR_ID(33), + TRANSCEIVER_RESET_ATTR_ID(34), + TRANSCEIVER_RESET_ATTR_ID(35), + TRANSCEIVER_RESET_ATTR_ID(36), + TRANSCEIVER_RESET_ATTR_ID(37), + TRANSCEIVER_RESET_ATTR_ID(38), + TRANSCEIVER_RESET_ATTR_ID(39), + TRANSCEIVER_RESET_ATTR_ID(40), + TRANSCEIVER_RESET_ATTR_ID(41), + TRANSCEIVER_RESET_ATTR_ID(42), + TRANSCEIVER_RESET_ATTR_ID(43), + TRANSCEIVER_RESET_ATTR_ID(44), + TRANSCEIVER_RESET_ATTR_ID(45), + TRANSCEIVER_RESET_ATTR_ID(46), + TRANSCEIVER_RESET_ATTR_ID(47), + TRANSCEIVER_RESET_ATTR_ID(48), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(55), + TRANSCEIVER_RESET_ATTR_ID(56), + TRANSCEIVER_RESET_ATTR_ID(57), + TRANSCEIVER_RESET_ATTR_ID(58), + TRANSCEIVER_RESET_ATTR_ID(59), + TRANSCEIVER_RESET_ATTR_ID(60), + TRANSCEIVER_RESET_ATTR_ID(61), + TRANSCEIVER_RESET_ATTR_ID(62), + TRANSCEIVER_RESET_ATTR_ID(63), + TRANSCEIVER_RESET_ATTR_ID(64), + TRANSCEIVER_LPMODE_ATTR_ID(1), + TRANSCEIVER_LPMODE_ATTR_ID(2), + TRANSCEIVER_LPMODE_ATTR_ID(3), + TRANSCEIVER_LPMODE_ATTR_ID(4), + TRANSCEIVER_LPMODE_ATTR_ID(5), + TRANSCEIVER_LPMODE_ATTR_ID(6), + TRANSCEIVER_LPMODE_ATTR_ID(7), + TRANSCEIVER_LPMODE_ATTR_ID(8), + TRANSCEIVER_LPMODE_ATTR_ID(9), + TRANSCEIVER_LPMODE_ATTR_ID(10), + TRANSCEIVER_LPMODE_ATTR_ID(11), + TRANSCEIVER_LPMODE_ATTR_ID(12), + TRANSCEIVER_LPMODE_ATTR_ID(13), + TRANSCEIVER_LPMODE_ATTR_ID(14), + TRANSCEIVER_LPMODE_ATTR_ID(15), + TRANSCEIVER_LPMODE_ATTR_ID(16), + TRANSCEIVER_LPMODE_ATTR_ID(17), + TRANSCEIVER_LPMODE_ATTR_ID(18), + TRANSCEIVER_LPMODE_ATTR_ID(19), + TRANSCEIVER_LPMODE_ATTR_ID(20), + TRANSCEIVER_LPMODE_ATTR_ID(21), + TRANSCEIVER_LPMODE_ATTR_ID(22), + TRANSCEIVER_LPMODE_ATTR_ID(23), + TRANSCEIVER_LPMODE_ATTR_ID(24), + TRANSCEIVER_LPMODE_ATTR_ID(25), + TRANSCEIVER_LPMODE_ATTR_ID(26), + TRANSCEIVER_LPMODE_ATTR_ID(27), + TRANSCEIVER_LPMODE_ATTR_ID(28), + TRANSCEIVER_LPMODE_ATTR_ID(29), + TRANSCEIVER_LPMODE_ATTR_ID(30), + TRANSCEIVER_LPMODE_ATTR_ID(31), + TRANSCEIVER_LPMODE_ATTR_ID(32), + TRANSCEIVER_LPMODE_ATTR_ID(33), + TRANSCEIVER_LPMODE_ATTR_ID(34), + TRANSCEIVER_LPMODE_ATTR_ID(35), + TRANSCEIVER_LPMODE_ATTR_ID(36), + TRANSCEIVER_LPMODE_ATTR_ID(37), + TRANSCEIVER_LPMODE_ATTR_ID(38), + TRANSCEIVER_LPMODE_ATTR_ID(39), + TRANSCEIVER_LPMODE_ATTR_ID(40), + TRANSCEIVER_LPMODE_ATTR_ID(41), + TRANSCEIVER_LPMODE_ATTR_ID(42), + TRANSCEIVER_LPMODE_ATTR_ID(43), + TRANSCEIVER_LPMODE_ATTR_ID(44), + TRANSCEIVER_LPMODE_ATTR_ID(45), + TRANSCEIVER_LPMODE_ATTR_ID(46), + TRANSCEIVER_LPMODE_ATTR_ID(47), + TRANSCEIVER_LPMODE_ATTR_ID(48), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), + TRANSCEIVER_LPMODE_ATTR_ID(55), + TRANSCEIVER_LPMODE_ATTR_ID(56), + TRANSCEIVER_LPMODE_ATTR_ID(57), + TRANSCEIVER_LPMODE_ATTR_ID(58), + TRANSCEIVER_LPMODE_ATTR_ID(59), + TRANSCEIVER_LPMODE_ATTR_ID(60), + TRANSCEIVER_LPMODE_ATTR_ID(61), + TRANSCEIVER_LPMODE_ATTR_ID(62), + TRANSCEIVER_LPMODE_ATTR_ID(63), + TRANSCEIVER_LPMODE_ATTR_ID(64), + TRANSCEIVER_TX_DISABLE_ATTR_ID(65), + TRANSCEIVER_TX_DISABLE_ATTR_ID(66), + TRANSCEIVER_TX_FAULT_ATTR_ID(65), + TRANSCEIVER_TX_FAULT_ATTR_ID(66), + TRANSCEIVER_RX_LOS_ATTR_ID(65), + TRANSCEIVER_RX_LOS_ATTR_ID(66), + /* MODULE_RESET_ALL, */ + CPLD1_VERSION, + CPLD2_VERSION, + CPLD1_REG, + CPLD2_REG, +}; + + +/*********************************************** + * function declare + * *********************************************/ +static ssize_t reg_read(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t reg_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t status_read(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t status_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, status_read, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO|S_IWUSR, status_read, status_write, MODULE_RESET_##index); \ + static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO|S_IWUSR, status_read, status_write, MODULE_LPMODE_##index) +#define DECLARE_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr, \ + &sensor_dev_attr_module_lp_mode_##index.dev_attr.attr + +/* transceiver attributes */ +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(55); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(56); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(57); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(58); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(59); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(60); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(61); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(62); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(63); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(64); +static SENSOR_DEVICE_ATTR(module_present_65, S_IRUGO, status_read, NULL, MODULE_PRESENT_65); +static SENSOR_DEVICE_ATTR(module_present_66, S_IRUGO, status_read, NULL, MODULE_PRESENT_66); +//static SENSOR_DEVICE_ATTR(module_reset_all, S_IWUSR, NULL, status_write, MODULE_RESET_ALL); +static SENSOR_DEVICE_ATTR(module_tx_disable_65, S_IRUGO|S_IWUSR, status_read, + status_write, MODULE_TX_DISABLE_65); +static SENSOR_DEVICE_ATTR(module_tx_disable_66, S_IRUGO|S_IWUSR, status_read, + status_write, MODULE_TX_DISABLE_66); +static SENSOR_DEVICE_ATTR(module_tx_fault_65, S_IRUGO, status_read, NULL, MODULE_TX_FAULT_65); +static SENSOR_DEVICE_ATTR(module_tx_fault_66, S_IRUGO, status_read, NULL, MODULE_TX_FAULT_66); +static SENSOR_DEVICE_ATTR(module_rx_los_65, S_IRUGO, status_read, NULL, MODULE_RX_LOS_65); +static SENSOR_DEVICE_ATTR(module_rx_los_66, S_IRUGO, status_read, NULL, MODULE_RX_LOS_66); +static SENSOR_DEVICE_ATTR(cpld1_version, S_IRUGO, status_read, NULL, CPLD1_VERSION); +static SENSOR_DEVICE_ATTR(cpld2_version, S_IRUGO, status_read, NULL, CPLD2_VERSION); +static SENSOR_DEVICE_ATTR(cpld1_reg, S_IRUGO|S_IWUSR, reg_read, reg_write, CPLD1_REG); +static SENSOR_DEVICE_ATTR(cpld2_reg, S_IRUGO|S_IWUSR, reg_read, reg_write, CPLD2_REG); + + + +static struct attribute *fpga_transceiver_attributes[] = { + DECLARE_TRANSCEIVER_ATTR(1), + DECLARE_TRANSCEIVER_ATTR(2), + DECLARE_TRANSCEIVER_ATTR(3), + DECLARE_TRANSCEIVER_ATTR(4), + DECLARE_TRANSCEIVER_ATTR(5), + DECLARE_TRANSCEIVER_ATTR(6), + DECLARE_TRANSCEIVER_ATTR(7), + DECLARE_TRANSCEIVER_ATTR(8), + DECLARE_TRANSCEIVER_ATTR(9), + DECLARE_TRANSCEIVER_ATTR(10), + DECLARE_TRANSCEIVER_ATTR(11), + DECLARE_TRANSCEIVER_ATTR(12), + DECLARE_TRANSCEIVER_ATTR(13), + DECLARE_TRANSCEIVER_ATTR(14), + DECLARE_TRANSCEIVER_ATTR(15), + DECLARE_TRANSCEIVER_ATTR(16), + DECLARE_TRANSCEIVER_ATTR(17), + DECLARE_TRANSCEIVER_ATTR(18), + DECLARE_TRANSCEIVER_ATTR(19), + DECLARE_TRANSCEIVER_ATTR(20), + DECLARE_TRANSCEIVER_ATTR(21), + DECLARE_TRANSCEIVER_ATTR(22), + DECLARE_TRANSCEIVER_ATTR(23), + DECLARE_TRANSCEIVER_ATTR(24), + DECLARE_TRANSCEIVER_ATTR(25), + DECLARE_TRANSCEIVER_ATTR(26), + DECLARE_TRANSCEIVER_ATTR(27), + DECLARE_TRANSCEIVER_ATTR(28), + DECLARE_TRANSCEIVER_ATTR(29), + DECLARE_TRANSCEIVER_ATTR(30), + DECLARE_TRANSCEIVER_ATTR(31), + DECLARE_TRANSCEIVER_ATTR(32), + DECLARE_TRANSCEIVER_ATTR(33), + DECLARE_TRANSCEIVER_ATTR(34), + DECLARE_TRANSCEIVER_ATTR(35), + DECLARE_TRANSCEIVER_ATTR(36), + DECLARE_TRANSCEIVER_ATTR(37), + DECLARE_TRANSCEIVER_ATTR(38), + DECLARE_TRANSCEIVER_ATTR(39), + DECLARE_TRANSCEIVER_ATTR(40), + DECLARE_TRANSCEIVER_ATTR(41), + DECLARE_TRANSCEIVER_ATTR(42), + DECLARE_TRANSCEIVER_ATTR(43), + DECLARE_TRANSCEIVER_ATTR(44), + DECLARE_TRANSCEIVER_ATTR(45), + DECLARE_TRANSCEIVER_ATTR(46), + DECLARE_TRANSCEIVER_ATTR(47), + DECLARE_TRANSCEIVER_ATTR(48), + DECLARE_TRANSCEIVER_ATTR(49), + DECLARE_TRANSCEIVER_ATTR(50), + DECLARE_TRANSCEIVER_ATTR(51), + DECLARE_TRANSCEIVER_ATTR(52), + DECLARE_TRANSCEIVER_ATTR(53), + DECLARE_TRANSCEIVER_ATTR(54), + DECLARE_TRANSCEIVER_ATTR(55), + DECLARE_TRANSCEIVER_ATTR(56), + DECLARE_TRANSCEIVER_ATTR(57), + DECLARE_TRANSCEIVER_ATTR(58), + DECLARE_TRANSCEIVER_ATTR(59), + DECLARE_TRANSCEIVER_ATTR(60), + DECLARE_TRANSCEIVER_ATTR(61), + DECLARE_TRANSCEIVER_ATTR(62), + DECLARE_TRANSCEIVER_ATTR(63), + DECLARE_TRANSCEIVER_ATTR(64), + &sensor_dev_attr_module_present_65.dev_attr.attr, + &sensor_dev_attr_module_present_66.dev_attr.attr, + /* &sensor_dev_attr_module_reset_all.dev_attr.attr,*/ + &sensor_dev_attr_module_tx_disable_65.dev_attr.attr, + &sensor_dev_attr_module_tx_disable_66.dev_attr.attr, + &sensor_dev_attr_module_tx_fault_65.dev_attr.attr, + &sensor_dev_attr_module_tx_fault_66.dev_attr.attr, + &sensor_dev_attr_module_rx_los_65.dev_attr.attr, + &sensor_dev_attr_module_rx_los_66.dev_attr.attr, + &sensor_dev_attr_cpld1_version.dev_attr.attr, + &sensor_dev_attr_cpld2_version.dev_attr.attr, + &sensor_dev_attr_cpld1_reg.dev_attr.attr, + &sensor_dev_attr_cpld2_reg.dev_attr.attr, + NULL +}; + +static const struct attribute_group fpga_port_stat_group = { + .attrs = fpga_transceiver_attributes, +}; + +struct attribute_mapping { + u16 attr_base; + u16 reg; + u8 revert; +}; + +// Define an array of attribute mappings +static struct attribute_mapping attribute_mappings[] = { + [MODULE_PRESENT_1 ... MODULE_PRESENT_8] = {MODULE_PRESENT_1, XCVR_P7_P0_PRESENT_REG, 1}, + [MODULE_PRESENT_9 ... MODULE_PRESENT_16] = {MODULE_PRESENT_9, XCVR_P15_P8_PRESENT_REG, 1}, + [MODULE_PRESENT_17 ... MODULE_PRESENT_24] = {MODULE_PRESENT_17, XCVR_P23_P16_PRESENT_REG, 1}, + [MODULE_PRESENT_25 ... MODULE_PRESENT_32] = {MODULE_PRESENT_25, XCVR_P31_P24_PRESENT_REG, 1}, + [MODULE_PRESENT_33 ... MODULE_PRESENT_40] = {MODULE_PRESENT_33, XCVR_P39_P32_PRESENT_REG, 1}, + [MODULE_PRESENT_41 ... MODULE_PRESENT_48] = {MODULE_PRESENT_41, XCVR_P47_P40_PRESENT_REG, 1}, + [MODULE_PRESENT_49 ... MODULE_PRESENT_56] = {MODULE_PRESENT_49, XCVR_P55_P48_PRESENT_REG, 1}, + [MODULE_PRESENT_57 ... MODULE_PRESENT_64] = {MODULE_PRESENT_57, XCVR_P63_P56_PRESENT_REG, 1}, + [MODULE_PRESENT_65 ... MODULE_PRESENT_66] = {MODULE_PRESENT_65, SFP_PRESENT_REG, 1}, + + [MODULE_LPMODE_1 ... MODULE_LPMODE_8] = {MODULE_LPMODE_1, XCVR_P7_P0_LPMODE_REG, 1}, + [MODULE_LPMODE_9 ... MODULE_LPMODE_16] = {MODULE_LPMODE_9, XCVR_P15_P8_LPMODE_REG, 1}, + [MODULE_LPMODE_17 ... MODULE_LPMODE_24] = {MODULE_LPMODE_17, XCVR_P23_P16_LPMODE_REG, 1}, + [MODULE_LPMODE_25 ... MODULE_LPMODE_32] = {MODULE_LPMODE_25, XCVR_P31_P24_LPMODE_REG, 1}, + [MODULE_LPMODE_33 ... MODULE_LPMODE_40] = {MODULE_LPMODE_33, XCVR_P39_P32_LPMODE_REG, 1}, + [MODULE_LPMODE_41 ... MODULE_LPMODE_48] = {MODULE_LPMODE_41, XCVR_P47_P40_LPMODE_REG, 1}, + [MODULE_LPMODE_49 ... MODULE_LPMODE_56] = {MODULE_LPMODE_49, XCVR_P55_P48_LPMODE_REG, 1}, + [MODULE_LPMODE_57 ... MODULE_LPMODE_64] = {MODULE_LPMODE_57, XCVR_P63_P56_LPMODE_REG, 1}, + + [MODULE_RESET_1 ... MODULE_RESET_8] = {MODULE_RESET_1, XCVR_P7_P0_RESET_REG, 1}, + [MODULE_RESET_9 ... MODULE_RESET_16] = {MODULE_RESET_9, XCVR_P15_P8_RESET_REG, 1}, + [MODULE_RESET_17 ... MODULE_RESET_24] = {MODULE_RESET_17, XCVR_P23_P16_RESET_REG, 1}, + [MODULE_RESET_25 ... MODULE_RESET_32] = {MODULE_RESET_25, XCVR_P31_P24_RESET_REG, 1}, + [MODULE_RESET_33 ... MODULE_RESET_40] = {MODULE_RESET_33, XCVR_P39_P32_RESET_REG, 1}, + [MODULE_RESET_41 ... MODULE_RESET_48] = {MODULE_RESET_41, XCVR_P47_P40_RESET_REG, 1}, + [MODULE_RESET_49 ... MODULE_RESET_56] = {MODULE_RESET_49, XCVR_P55_P48_RESET_REG, 1}, + [MODULE_RESET_57 ... MODULE_RESET_64] = {MODULE_RESET_57, XCVR_P63_P56_RESET_REG, 1}, + + [MODULE_TX_DISABLE_65 ... MODULE_TX_DISABLE_66] ={MODULE_TX_DISABLE_65, SFP_TXDIS_REG, 0}, + [MODULE_TX_FAULT_65 ... MODULE_TX_FAULT_66] = {MODULE_TX_FAULT_65, SFP_TXFAULT_REG, 0}, + [MODULE_RX_LOS_65 ... MODULE_RX_LOS_66] = {MODULE_RX_LOS_65, SFP_RXLOSS_REG, 0}, +}; + +static inline unsigned int fpga_read(const void __iomem *addr, u32 spi_mask) +{ + wait_spi(spi_mask, usecs_to_jiffies(20)); + return ioread8(addr); +} + +static inline void fpga_write(void __iomem *addr, u8 val, u32 spi_mask) +{ + wait_spi(spi_mask, usecs_to_jiffies(20)); + iowrite8(val, addr); +} + +static ssize_t reg_read(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9817_64_fpga_data *fpga_ctl = dev_get_drvdata(dev); + void __iomem *addr; + ssize_t ret = -EINVAL; + u8 reg_val; + u32 spi_mask; + + switch(attr->index) + { + case CPLD1_REG: + addr = fpga_ctl->pci_fpga_dev.data_base_addr1 + + CPLD1_PCIE_START_OFFSET + + fpga_ctl->cpld_reg[attr->index - CPLD1_REG]; + spi_mask = SPI_BUSY_MASK_CPLD1; + break; + case CPLD2_REG: + addr = fpga_ctl->pci_fpga_dev.data_base_addr2 + + CPLD2_PCIE_START_OFFSET + + fpga_ctl->cpld_reg[attr->index - CPLD1_REG]; + spi_mask = SPI_BUSY_MASK_CPLD2; + break; + default: + ret = -EINVAL; + goto exit; + } + + LOCK(&cpld_access_lock); + reg_val = fpga_read(addr, spi_mask); + UNLOCK(&cpld_access_lock); + ret = sprintf(buf, "0x%02x\n", reg_val); + +exit: + return ret; +} + +static ssize_t reg_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9817_64_fpga_data *fpga_ctl = dev_get_drvdata(dev); + void __iomem *base; + int args; + char *opt, tmp[32] = {0}; + char *tmp_p; + size_t copy_size; + u8 input[2] = {0}; + u32 spi_mask; + + switch(attr->index) + { + case CPLD1_REG: + base = fpga_ctl->pci_fpga_dev.data_base_addr1 + + CPLD1_PCIE_START_OFFSET; + spi_mask = SPI_BUSY_MASK_CPLD1; + break; + case CPLD2_REG: + base = fpga_ctl->pci_fpga_dev.data_base_addr2 + + CPLD2_PCIE_START_OFFSET; + spi_mask = SPI_BUSY_MASK_CPLD2; + break; + default: + return -EINVAL; + } + + copy_size = (count < sizeof(tmp)) ? count : sizeof(tmp) - 1; + #ifdef __STDC_LIB_EXT1__ + memcpy_s(tmp, copy_size, buf, copy_size); + #else + memcpy(tmp, buf, copy_size); + #endif + tmp[copy_size] = '\0'; + + args = 0; + tmp_p = tmp; + while (args < 2 && (opt = strsep(&tmp_p, " ")) != NULL) { + if (kstrtou8(opt, 16, &input[args]) == 0) { + args++; + } + } + + switch(args) + { + case 2: + /* Write value to register */ + LOCK(&cpld_access_lock); + fpga_write(base + input[0], input[1], spi_mask); + UNLOCK(&cpld_access_lock); + break; + case 1: + /* Read value from register */ + fpga_ctl->cpld_reg[attr->index - CPLD1_REG] = input[0]; + break; + default: + return -EINVAL; + } + + return count; +} + +static ssize_t status_read(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9817_64_fpga_data *fpga_ctl = dev_get_drvdata(dev); + ssize_t ret = -EINVAL; + u16 reg; + u8 major, minor, reg_val; + u8 bits_shift; + + switch(attr->index) + { + case CPLD1_VERSION: + LOCK(&cpld_access_lock); + reg = CPLD1_MAJOR_VER_REG; + major = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr1 + reg, + SPI_BUSY_MASK_CPLD1); + reg = CPLD1_MINOR_VER_REG; + minor = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr1 + reg, + SPI_BUSY_MASK_CPLD1); + UNLOCK(&cpld_access_lock); + + ret = sprintf(buf, "%d.%d\n", major, minor); + break; + case CPLD2_VERSION: + LOCK(&cpld_access_lock); + reg = CPLD2_MAJOR_VER_REG; + major = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr2 + reg, + SPI_BUSY_MASK_CPLD2); + reg = CPLD2_MINOR_VER_REG; + minor = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr2 + reg, + SPI_BUSY_MASK_CPLD2); + UNLOCK(&cpld_access_lock); + + ret = sprintf(buf, "%d.%d\n", major, minor); + break; + case MODULE_PRESENT_1 ... MODULE_RX_LOS_66: + reg = attribute_mappings[attr->index].reg; + LOCK(&cpld_access_lock); + if ((reg & 0xF000) == CPLD1_PCIE_START_OFFSET) { + reg_val = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr1 + reg, + SPI_BUSY_MASK_CPLD1); + } else if ((reg & 0xF000) == CPLD2_PCIE_START_OFFSET) { + reg_val = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr2 + reg, + SPI_BUSY_MASK_CPLD2); + } + UNLOCK(&cpld_access_lock); + + bits_shift = attr->index - attribute_mappings[attr->index].attr_base; + reg_val = (reg_val >> bits_shift) & 0x01; + if (attribute_mappings[attr->index].revert) { + reg_val = !reg_val; + } + + ret = sprintf(buf, "%u\n", reg_val); + break; + default: + break; + } + + return ret; +} + +static ssize_t status_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9817_64_fpga_data *fpga_ctl = dev_get_drvdata(dev); + void __iomem *addr; + int status; + u16 reg; + u8 input; + u8 reg_val, bit_mask, should_set_bit; + u32 spi_mask; + + status = kstrtou8(buf, 10, &input); + if (status) { + return status; + } + + reg = attribute_mappings[attr->index].reg; + if ((reg & 0xF000) == CPLD1_PCIE_START_OFFSET) { + spi_mask = SPI_BUSY_MASK_CPLD1; + addr = fpga_ctl->pci_fpga_dev.data_base_addr1; + } else if ((reg & 0xF000) == CPLD2_PCIE_START_OFFSET) { + spi_mask = SPI_BUSY_MASK_CPLD2; + addr = fpga_ctl->pci_fpga_dev.data_base_addr2; + } + bit_mask = 0x01 << (attr->index - attribute_mappings[attr->index].attr_base); + should_set_bit = attribute_mappings[attr->index].revert ? !input : input; + + LOCK(&cpld_access_lock); + reg_val = fpga_read(addr + reg, spi_mask); + if (should_set_bit) { + reg_val |= bit_mask; + } else { + reg_val &= ~bit_mask; + } + fpga_write(addr + reg, reg_val, spi_mask); + UNLOCK(&cpld_access_lock); + + return count; +} + +struct _port_data { + u16 offset; + u16 mask; /* SPI Busy mask : 0x01 --> CPLD1, 0x02 --> CPLD2 */ +}; +/* ============PCIe Bar Offset to I2C Master Mapping============== */ +static const struct _port_data port[PORT_NUM]= { + {0x2100, SPI_BUSY_MASK_CPLD1},/* 0x2100 - 0x2110 CPLD1 I2C Master Port0 */ + {0x2120, SPI_BUSY_MASK_CPLD1},/* 0x2120 - 0x2130 CPLD1 I2C Master Port1 */ + {0x2140, SPI_BUSY_MASK_CPLD1},/* 0x2140 - 0x2150 CPLD1 I2C Master Port2 */ + {0x2160, SPI_BUSY_MASK_CPLD1},/* 0x2160 - 0x2170 CPLD1 I2C Master Port3 */ + {0x2180, SPI_BUSY_MASK_CPLD1},/* 0x2180 - 0x2190 CPLD1 I2C Master Port4 */ + {0x21A0, SPI_BUSY_MASK_CPLD1},/* 0x21A0 - 0x21B0 CPLD1 I2C Master Port5 */ + {0x21C0, SPI_BUSY_MASK_CPLD1},/* 0x21C0 - 0x21D0 CPLD1 I2C Master Port6 */ + {0x21E0, SPI_BUSY_MASK_CPLD1},/* 0x21E0 - 0x21F0 CPLD1 I2C Master Port7 */ + {0x2200, SPI_BUSY_MASK_CPLD1},/* 0x2200 - 0x2210 CPLD1 I2C Master Port8 */ + {0x2220, SPI_BUSY_MASK_CPLD1},/* 0x2220 - 0x2230 CPLD1 I2C Master Port9 */ + {0x2240, SPI_BUSY_MASK_CPLD1},/* 0x2240 - 0x2250 CPLD1 I2C Master Port10 */ + {0x2260, SPI_BUSY_MASK_CPLD1},/* 0x2260 - 0x2270 CPLD1 I2C Master Port11 */ + {0x2280, SPI_BUSY_MASK_CPLD1},/* 0x2280 - 0x2290 CPLD1 I2C Master Port12 */ + {0x22A0, SPI_BUSY_MASK_CPLD1},/* 0x22A0 - 0x22B0 CPLD1 I2C Master Port13 */ + {0x22C0, SPI_BUSY_MASK_CPLD1},/* 0x22C0 - 0x22D0 CPLD1 I2C Master Port14 */ + {0x22E0, SPI_BUSY_MASK_CPLD1},/* 0x22E0 - 0x22F0 CPLD1 I2C Master Port15 */ + {0x3100, SPI_BUSY_MASK_CPLD2},/* 0x3100 - 0x3110 CPLD2 I2C Master Port16 */ + {0x3120, SPI_BUSY_MASK_CPLD2},/* 0x3120 - 0x3130 CPLD2 I2C Master Port17 */ + {0x3140, SPI_BUSY_MASK_CPLD2},/* 0x3140 - 0x3150 CPLD2 I2C Master Port18 */ + {0x3160, SPI_BUSY_MASK_CPLD2},/* 0x3160 - 0x3170 CPLD2 I2C Master Port19 */ + {0x3180, SPI_BUSY_MASK_CPLD2},/* 0x3180 - 0x3190 CPLD2 I2C Master Port20 */ + {0x31A0, SPI_BUSY_MASK_CPLD2},/* 0x31A0 - 0x31B0 CPLD2 I2C Master Port21 */ + {0x31C0, SPI_BUSY_MASK_CPLD2},/* 0x31C0 - 0x31D0 CPLD2 I2C Master Port22 */ + {0x31E0, SPI_BUSY_MASK_CPLD2},/* 0x31E0 - 0x31F0 CPLD2 I2C Master Port23 */ + {0x3200, SPI_BUSY_MASK_CPLD2},/* 0x3200 - 0x3210 CPLD2 I2C Master Port24 */ + {0x3220, SPI_BUSY_MASK_CPLD2},/* 0x3220 - 0x3230 CPLD2 I2C Master Port25 */ + {0x3240, SPI_BUSY_MASK_CPLD2},/* 0x3240 - 0x3250 CPLD2 I2C Master Port26 */ + {0x3260, SPI_BUSY_MASK_CPLD2},/* 0x3260 - 0x3270 CPLD2 I2C Master Port27 */ + {0x3280, SPI_BUSY_MASK_CPLD2},/* 0x3280 - 0x3290 CPLD2 I2C Master Port28 */ + {0x32A0, SPI_BUSY_MASK_CPLD2},/* 0x32A0 - 0x32B0 CPLD2 I2C Master Port29 */ + {0x32C0, SPI_BUSY_MASK_CPLD2},/* 0x32C0 - 0x34D0 CPLD2 I2C Master Port30 */ + {0x32E0, SPI_BUSY_MASK_CPLD2},/* 0x32E0 - 0x3490 CPLD2 I2C Master Port31 */ + {0x2300, SPI_BUSY_MASK_CPLD1},/* 0x2300 - 0x2330 CPLD1 I2C Master Port32 */ + {0x2320, SPI_BUSY_MASK_CPLD1},/* 0x2320 - 0x2310 CPLD1 I2C Master Port33 */ + {0x2340, SPI_BUSY_MASK_CPLD1},/* 0x2340 - 0x2370 CPLD1 I2C Master Port34 */ + {0x2360, SPI_BUSY_MASK_CPLD1},/* 0x2360 - 0x2350 CPLD1 I2C Master Port35 */ + {0x2380, SPI_BUSY_MASK_CPLD1},/* 0x2380 - 0x23B0 CPLD1 I2C Master Port36 */ + {0x23A0, SPI_BUSY_MASK_CPLD1},/* 0x23A0 - 0x2390 CPLD1 I2C Master Port37 */ + {0x23C0, SPI_BUSY_MASK_CPLD1},/* 0x23C0 - 0x23F0 CPLD1 I2C Master Port38 */ + {0x23E0, SPI_BUSY_MASK_CPLD1},/* 0x23E0 - 0x23D0 CPLD1 I2C Master Port39 */ + {0x2400, SPI_BUSY_MASK_CPLD1},/* 0x2400 - 0x2430 CPLD1 I2C Master Port40 */ + {0x2420, SPI_BUSY_MASK_CPLD1},/* 0x2420 - 0x2410 CPLD1 I2C Master Port41 */ + {0x2440, SPI_BUSY_MASK_CPLD1},/* 0x2440 - 0x2470 CPLD1 I2C Master Port42 */ + {0x2460, SPI_BUSY_MASK_CPLD1},/* 0x2460 - 0x2450 CPLD1 I2C Master Port43 */ + {0x2480, SPI_BUSY_MASK_CPLD1},/* 0x2480 - 0x24B0 CPLD1 I2C Master Port44 */ + {0x24A0, SPI_BUSY_MASK_CPLD1},/* 0x24A0 - 0x2490 CPLD1 I2C Master Port45 */ + {0x24C0, SPI_BUSY_MASK_CPLD1},/* 0x24C0 - 0x24F0 CPLD1 I2C Master Port46 */ + {0x24E0, SPI_BUSY_MASK_CPLD1},/* 0x24E0 - 0x24D0 CPLD1 I2C Master Port47 */ + {0x3300, SPI_BUSY_MASK_CPLD2},/* 0x3300 - 0x3330 CPLD2 I2C Master Port48 */ + {0x3320, SPI_BUSY_MASK_CPLD2},/* 0x3320 - 0x3310 CPLD2 I2C Master Port49 */ + {0x3340, SPI_BUSY_MASK_CPLD2},/* 0x3340 - 0x3370 CPLD2 I2C Master Port50 */ + {0x3360, SPI_BUSY_MASK_CPLD2},/* 0x3360 - 0x3350 CPLD2 I2C Master Port51 */ + {0x3380, SPI_BUSY_MASK_CPLD2},/* 0x3380 - 0x33B0 CPLD2 I2C Master Port52 */ + {0x33A0, SPI_BUSY_MASK_CPLD2},/* 0x33A0 - 0x3390 CPLD2 I2C Master Port53 */ + {0x33C0, SPI_BUSY_MASK_CPLD2},/* 0x33C0 - 0x33F0 CPLD2 I2C Master Port54 */ + {0x33E0, SPI_BUSY_MASK_CPLD2},/* 0x33E0 - 0x33D0 CPLD2 I2C Master Port55 */ + {0x3400, SPI_BUSY_MASK_CPLD2},/* 0x3400 - 0x3430 CPLD2 I2C Master Port56 */ + {0x3420, SPI_BUSY_MASK_CPLD2},/* 0x3420 - 0x3410 CPLD2 I2C Master Port57 */ + {0x3440, SPI_BUSY_MASK_CPLD2},/* 0x3440 - 0x3470 CPLD2 I2C Master Port58 */ + {0x3460, SPI_BUSY_MASK_CPLD2},/* 0x3460 - 0x3450 CPLD2 I2C Master Port59 */ + {0x3480, SPI_BUSY_MASK_CPLD2},/* 0x3480 - 0x32F0 CPLD2 I2C Master Port60 */ + {0x34A0, SPI_BUSY_MASK_CPLD2},/* 0x34A0 - 0x32D0 CPLD2 I2C Master Port61 */ + {0x34C0, SPI_BUSY_MASK_CPLD2},/* 0x34C0 - 0x34B0 CPLD2 I2C Master Port62 */ + {0x34E0, SPI_BUSY_MASK_CPLD2},/* 0x34E0 - 0x34F0 CPLD2 I2C Master Port63 */ + {0x3500, SPI_BUSY_MASK_CPLD2},/* 0x3500 - 0x3510 CPLD2 I2C Master SFP-28 Port64 */ + {0x3520, SPI_BUSY_MASK_CPLD2},/* 0x3520 - 0x3530 CPLD2 I2C Master SFP-28 Port65 */ +}; + +static struct ocores_i2c_platform_data as9817_64_platform_data = { + .reg_io_width = 1, + .reg_shift = 2, + /* + * PRER_L and PRER_H are calculated based on clock_khz and bus_khz + * in i2c-ocores.c:ocores_init. + */ +#if 0 + /* SCL 400KHZ in FPGA spec. => PRER_L = 0x0B, PRER_H = 0x00 */ + .clock_khz = 24000, + .bus_khz = 400, +#else + /* SCL 100KHZ in FPGA spec. => PRER_L = 0x2F, PRER_H = 0x00 */ + .clock_khz = 24000, + .bus_khz = 100, +#endif +}; + +struct platform_device *ocore_i2c_device_add(unsigned int id, unsigned long bar_base, + unsigned int offset) +{ + struct resource res = DEFINE_RES_MEM(bar_base + offset, 0x20); + struct platform_device *pdev; + int err; + + pdev = platform_device_alloc(OCORES_I2C_DRVNAME, id); + if (!pdev) { + err = -ENOMEM; + pcie_err("Port%u device allocation failed (%d)\n", (id & 0xFF), err); + goto exit; + } + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + pcie_err("Port%u device resource addition failed (%d)\n", (id & 0xFF), err); + goto exit_device_put; + } + + err = platform_device_add_data(pdev, &as9817_64_platform_data, + sizeof(struct ocores_i2c_platform_data)); + if (err) { + pcie_err("Port%u platform data allocation failed (%d)\n", (id & 0xFF), err); + goto exit_device_put; + } + + err = platform_device_add(pdev); + if (err) { + pcie_err("Port%u device addition failed (%d)\n", (id & 0xFF), err); + goto exit_device_put; + } + + return pdev; + +exit_device_put: + platform_device_put(pdev); +exit: + return NULL; +} + +static int as9817_64_pcie_fpga_stat_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct as9817_64_fpga_data *fpga_ctl; + struct pci_dev *pcidev; + struct resource *ret; + int i; + int status = 0, err = 0; + unsigned long bar_base; + unsigned int val; + + fpga_ctl = devm_kzalloc(dev, sizeof(struct as9817_64_fpga_data), GFP_KERNEL); + if (!fpga_ctl) { + return -ENOMEM; + } + platform_set_drvdata(pdev, fpga_ctl); + + pcidev = pci_get_device(FPGA_PCI_VENDOR_ID, FPGA_PCI_DEVICE_ID, NULL); + if (!pcidev) { + dev_err(dev, "Cannot found PCI device(%x:%x)\n", + FPGA_PCI_VENDOR_ID, FPGA_PCI_DEVICE_ID); + return -ENODEV; + } + fpga_ctl->pci_fpga_dev.pci_dev = pcidev; + + err = pci_enable_device(pcidev); + if (err != 0) { + dev_err(dev, "Cannot enable PCI device(%x:%x)\n", + FPGA_PCI_VENDOR_ID, FPGA_PCI_DEVICE_ID); + status = -ENODEV; + goto exit_pci_disable; + } + /* enable PCI bus-mastering */ + pci_set_master(pcidev); + + /* + * Detect platform for changing the setting behavior of LP mode. + */ + fpga_ctl->pci_fpga_dev.data_base_addr0 = pci_iomap(pcidev, BAR0_NUM, 0); + if (fpga_ctl->pci_fpga_dev.data_base_addr0 == NULL) { + dev_err(dev, "Failed to map BAR0\n"); + status = -EIO; + goto exit_pci_disable; + } + + val = ioread8(fpga_ctl->pci_fpga_dev.data_base_addr0 + FPGA_BOARD_INFO_REG); + switch (val & 0x0C) + { + case 0x00: /* OSFP */ + case 0x08: /* OSFP_ROT */ + dev_info(dev, "Platform: AS9817-64O\n"); + break; + case 0x04: /* QDD */ + case 0x0C: /* QDD_ROT */ + for (i = MODULE_LPMODE_1; i <= MODULE_LPMODE_64; i++) { + attribute_mappings[i].revert = 0; + } + dev_info(dev, "Platform: AS9817-64D\n"); + break; + default: + dev_warn(dev, "Unknown platform detected\n"); + break; + } + + /* + * The register address of SPI Busy is 0x33. + * It can not only read one byte. It needs to read four bytes from 0x30. + * The value is obtained by '(ioread32(spi_busy_reg) >> 24) & 0xFF'. + */ + spi_busy_reg = fpga_ctl->pci_fpga_dev.data_base_addr0 + 0x30; + + + + /* + * Cannot use 'pci_request_regions(pcidev, DRVNAME)' + * to request all Region 1, Region 2 because another + * address will be allocated by the i2c-ocores.ko. + */ + fpga_ctl->pci_fpga_dev.data_base_addr1 = pci_iomap(pcidev, BAR1_NUM, 0); + if (fpga_ctl->pci_fpga_dev.data_base_addr1 == NULL) { + dev_err(dev, "Failed to map BAR1\n"); + status = -EIO; + goto exit_pci_iounmap0; + } + fpga_ctl->pci_fpga_dev.data_region1 = pci_resource_start(pcidev, BAR1_NUM) + CPLD1_PCIE_START_OFFSET; + ret = request_mem_region(fpga_ctl->pci_fpga_dev.data_region1, REGION_LEN, DRVNAME"_cpld1"); + if (ret == NULL) { + dev_err(dev, "[%s] cannot request region\n", DRVNAME"_cpld1"); + status = -EIO; + goto exit_pci_iounmap1; + } + dev_info(dev, "(BAR%d resource: Start=0x%lx, Length=0x%x)", BAR1_NUM, + (unsigned long)fpga_ctl->pci_fpga_dev.data_region1, REGION_LEN); + + fpga_ctl->pci_fpga_dev.data_base_addr2 = pci_iomap(pcidev, BAR2_NUM, 0); + if (fpga_ctl->pci_fpga_dev.data_base_addr2 == NULL) { + dev_err(dev, "Failed to map BAR2\n"); + status = -EIO; + goto exit_pci_release1; + } + fpga_ctl->pci_fpga_dev.data_region2 = pci_resource_start(pcidev, BAR2_NUM) + CPLD2_PCIE_START_OFFSET; + ret = request_mem_region(fpga_ctl->pci_fpga_dev.data_region2, REGION_LEN, DRVNAME"_cpld2"); + if (ret == NULL) { + dev_err(dev, "[%s] cannot request region\n", DRVNAME"_cpld2"); + status = -EIO; + goto exit_pci_iounmap2; + } + dev_info(dev, "(BAR%d resource: Start=0x%lx, Length=0x%x)", BAR2_NUM, + (unsigned long)fpga_ctl->pci_fpga_dev.data_region2, REGION_LEN); + + /* Create I2C ocore devices first, then create the FPGA sysfs. + * To prevent the application from accessing an ocore device + * that has not been fully created due to the port status + * being present. + */ + + /* + * Create ocore_i2c device for OSFP EEPROM + */ + for (i = 0; i < PORT_NUM; i++) { + switch (i) + { + case 0 ... 15: + case 32 ... 47: + bar_base = pci_resource_start(pcidev, BAR1_NUM); + break; + case 16 ... 31: + case 48 ... 65: + bar_base = pci_resource_start(pcidev, BAR2_NUM); + break; + default: + break; + } + fpga_ctl->pci_fpga_dev.fpga_i2c[i] = + ocore_i2c_device_add((i | (port[i].mask << 8)), bar_base, port[i].offset); + if (IS_ERR(fpga_ctl->pci_fpga_dev.fpga_i2c[i])) { + status = PTR_ERR(fpga_ctl->pci_fpga_dev.fpga_i2c[i]); + dev_err(dev, "rc:%d, unload Port%u[0x%ux] device\n", + status, i, port[i].offset); + goto exit_ocores_device; + } + } + + status = sysfs_create_group(&pdev->dev.kobj, &fpga_port_stat_group); + if (status) { + goto exit_ocores_device; + } + + return 0; + +exit_ocores_device: + while (i > 0) { + i--; + platform_device_unregister(fpga_ctl->pci_fpga_dev.fpga_i2c[i]); + } + release_mem_region(fpga_ctl->pci_fpga_dev.data_region2, REGION_LEN); +exit_pci_iounmap2: + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr2); +exit_pci_release1: + release_mem_region(fpga_ctl->pci_fpga_dev.data_region1, REGION_LEN); +exit_pci_iounmap1: + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr1); +exit_pci_iounmap0: + spi_busy_reg = NULL; + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr0); +exit_pci_disable: + pci_disable_device(fpga_ctl->pci_fpga_dev.pci_dev); + + return status; +} + +static int as9817_64_pcie_fpga_stat_remove(struct platform_device *pdev) +{ + struct as9817_64_fpga_data *fpga_ctl = platform_get_drvdata(pdev); + + if (pci_is_enabled(fpga_ctl->pci_fpga_dev.pci_dev)) { + int i; + + sysfs_remove_group(&pdev->dev.kobj, &fpga_port_stat_group); + /* Unregister ocore_i2c device */ + for (i = 0; i < PORT_NUM; i++) { + platform_device_unregister(fpga_ctl->pci_fpga_dev.fpga_i2c[i]); + } + spi_busy_reg = NULL; + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr0); + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr1); + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr2); + release_mem_region(fpga_ctl->pci_fpga_dev.data_region1, REGION_LEN); + release_mem_region(fpga_ctl->pci_fpga_dev.data_region2, REGION_LEN); + pci_disable_device(fpga_ctl->pci_fpga_dev.pci_dev); + } + + return 0; +} + +static struct platform_driver pcie_fpga_port_stat_driver = { + .probe = as9817_64_pcie_fpga_stat_probe, + .remove = as9817_64_pcie_fpga_stat_remove, + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, +}; + +static int __init as9817_64_pcie_fpga_init(void) +{ + int status = 0; + + /* + * Create FPGA platform driver and device + */ + status = platform_driver_register(&pcie_fpga_port_stat_driver); + if (status < 0) { + return status; + } + + pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(pdev)) { + status = PTR_ERR(pdev); + goto exit_pci; + } + + return status; + +exit_pci: + platform_driver_unregister(&pcie_fpga_port_stat_driver); + + return status; +} + +static void __exit as9817_64_pcie_fpga_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&pcie_fpga_port_stat_driver); +} + + +module_init(as9817_64_pcie_fpga_init); +module_exit(as9817_64_pcie_fpga_exit); + +MODULE_AUTHOR("Roger Ho "); +MODULE_DESCRIPTION("AS9817-64O/AS9817-64D FPGA via PCIE"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_leds.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_leds.c new file mode 100644 index 000000000000..67b7d013c05f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_leds.c @@ -0,0 +1,540 @@ +/* + * Copyright (C) Roger Ho + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9817_64_led" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_LED_READ_CMD 0x1A +#define IPMI_LED_WRITE_CMD 0x1B +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_ERR_RETRY_TIMES 1 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_led(struct device *dev, struct device_attribute *attr, + char *buf); +static int as9817_64_led_probe(struct platform_device *pdev); +static int as9817_64_led_remove(struct platform_device *pdev); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + struct ipmi_user * user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as9817_64_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[6]; /* 0:Loc 1:Diag 2:Gnss 3:Fan 4:Psu1 5:Psu2 */ + struct ipmi_data ipmi; +}; + +struct as9817_64_led_data *data = NULL; + +static struct platform_driver as9817_64_led_driver = { + .probe = as9817_64_led_probe, + .remove = as9817_64_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum ipmi_led_light_mode { + IPMI_LED_MODE_OFF, + IPMI_LED_MODE_RED = 2, + IPMI_LED_MODE_RED_BLINKING = 3, + IPMI_LED_MODE_GREEN = 4, + IPMI_LED_MODE_GREEN_BLINKING = 5, + IPMI_LED_MODE_BLUE = 8, + IPMI_LED_MODE_BLUE_BLINKING = 9, + IPMI_LED_MODE_CYAN = 0xC, + IPMI_LED_MODE_WHITE = 0xE, + IPMI_LED_MODE_AMBER = 0x10, + IPMI_LED_MODE_ORANGE = 0x20, +}; + +enum led_light_mode { + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_ORANGE = 12, + LED_MODE_ORANGE_BLINKING = 13, + LED_MODE_YELLOW = 14, + LED_MODE_YELLOW_BLINKING = 15, + LED_MODE_GREEN = 16, + LED_MODE_GREEN_BLINKING = 17, + LED_MODE_BLUE = 18, + LED_MODE_BLUE_BLINKING = 19, + LED_MODE_PURPLE = 20, + LED_MODE_PURPLE_BLINKING = 21, + LED_MODE_AUTO = 22, + LED_MODE_AUTO_BLINKING = 23, + LED_MODE_WHITE = 24, + LED_MODE_WHITE_BLINKING = 25, + LED_MODE_CYAN = 26, + LED_MODE_CYAN_BLINKING = 27, + LED_MODE_UNKNOWN = 99 +}; + +enum as9817_64_led_sysfs_attrs { + LED_LOC, + LED_DIAG, + LED_ALARM, + LED_FAN, + LED_PSU1, + LED_PSU2 +}; + +static SENSOR_DEVICE_ATTR(led_loc, S_IWUSR | S_IRUGO, show_led, set_led, + LED_LOC); +static SENSOR_DEVICE_ATTR(led_diag, S_IWUSR | S_IRUGO, show_led, set_led, + LED_DIAG); +static SENSOR_DEVICE_ATTR(led_alarm, S_IWUSR | S_IRUGO, show_led, set_led, + LED_ALARM); +static SENSOR_DEVICE_ATTR(led_fan, S_IWUSR | S_IRUGO, show_led, set_led, + LED_FAN); +static SENSOR_DEVICE_ATTR(led_psu1, S_IWUSR | S_IRUGO, show_led, set_led, + LED_PSU1); +static SENSOR_DEVICE_ATTR(led_psu2, S_IWUSR | S_IRUGO, show_led, set_led, + LED_PSU2); + +static struct attribute *as9817_64_led_attributes[] = { + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_diag.dev_attr.attr, + &sensor_dev_attr_led_alarm.dev_attr.attr, + &sensor_dev_attr_led_fan.dev_attr.attr, + &sensor_dev_attr_led_psu1.dev_attr.attr, + &sensor_dev_attr_led_psu2.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9817_64_led_group = { + .attrs = as9817_64_led_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int _ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Send an IPMI command with retry */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int status = 0, retry = 0; + + for (retry = 0; retry <= IPMI_ERR_RETRY_TIMES; retry++) { + status = _ipmi_send_message(ipmi, cmd, tx_data, tx_len, rx_data, rx_len); + if (unlikely(status != 0)) { + dev_err(&data->pdev->dev, "ipmi_send_message_%d err status(%d)\r\n", + retry, status); + continue; + } + + if (unlikely(ipmi->rx_result != 0)) { + dev_err(&data->pdev->dev, "ipmi_send_message_%d err result(%d)\r\n", + retry, ipmi->rx_result); + continue; + } + + break; + } + + return status; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_notice(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as9817_64_led_data *as9817_64_led_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_LED_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_led_update_device(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + switch (data->ipmi_resp[attr->index]) { + case IPMI_LED_MODE_OFF: + value = LED_MODE_OFF; + break; + case IPMI_LED_MODE_RED: + value = LED_MODE_RED; + break; + case IPMI_LED_MODE_RED_BLINKING: + value = LED_MODE_RED_BLINKING; + break; + case IPMI_LED_MODE_GREEN: + value = LED_MODE_GREEN; + break; + case IPMI_LED_MODE_GREEN_BLINKING: + value = LED_MODE_GREEN_BLINKING; + break; + case IPMI_LED_MODE_BLUE: + value = LED_MODE_BLUE; + break; + case IPMI_LED_MODE_BLUE_BLINKING: + value = LED_MODE_BLUE_BLINKING; + break; + case IPMI_LED_MODE_CYAN: + value = LED_MODE_CYAN; + break; + case IPMI_LED_MODE_WHITE: + value = LED_MODE_WHITE; + break; + case IPMI_LED_MODE_AMBER: + value = LED_MODE_YELLOW; + break; + case IPMI_LED_MODE_ORANGE: + value = LED_MODE_ORANGE; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = kstrtol(buf, 10, &mode); + if (status) + return status; + + mutex_lock(&data->update_lock); + + data = as9817_64_led_update_device(); + if (!data->valid) { + status = -EIO; + goto exit; + } + + data->ipmi_resp[0] = attr->index + 1; + + switch (mode) { + case LED_MODE_OFF: + data->ipmi_resp[1] = IPMI_LED_MODE_OFF; + break; + case LED_MODE_RED: + data->ipmi_resp[1] = IPMI_LED_MODE_RED; + break; + case LED_MODE_RED_BLINKING: + data->ipmi_resp[1] = IPMI_LED_MODE_RED_BLINKING; + break; + case LED_MODE_GREEN: + data->ipmi_resp[1] = IPMI_LED_MODE_GREEN; + break; + case LED_MODE_GREEN_BLINKING: + data->ipmi_resp[1] = IPMI_LED_MODE_GREEN_BLINKING; + break; + case LED_MODE_BLUE: + data->ipmi_resp[1] = IPMI_LED_MODE_BLUE; + break; + case LED_MODE_BLUE_BLINKING: + data->ipmi_resp[1] = IPMI_LED_MODE_BLUE_BLINKING; + break; + case LED_MODE_CYAN: + data->ipmi_resp[1] = IPMI_LED_MODE_CYAN; + break; + case LED_MODE_WHITE: + data->ipmi_resp[1] = IPMI_LED_MODE_WHITE; + break; + case LED_MODE_YELLOW: + data->ipmi_resp[1] = IPMI_LED_MODE_AMBER; + break; + case LED_MODE_ORANGE: + data->ipmi_resp[1] = IPMI_LED_MODE_ORANGE; + break; + default: + status = -EINVAL; + goto exit; + } + + /* Send IPMI write command */ + status = ipmi_send_message(&data->ipmi, IPMI_LED_WRITE_CMD, + data->ipmi_resp, 2, NULL, 0); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = count; + data->valid = 0; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as9817_64_led_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as9817_64_led_group); + if (status) + goto exit; + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as9817_64_led_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &as9817_64_led_group); + + return 0; +} + +static int __init as9817_64_led_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as9817_64_led_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as9817_64_led_driver); + if (ret < 0) + goto dri_reg_err; + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as9817_64_led_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as9817_64_led_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as9817_64_led_driver); + kfree(data); +} + +MODULE_AUTHOR("Roger Ho "); +MODULE_DESCRIPTION("as9817_64_led driver"); +MODULE_LICENSE("GPL"); + +module_init(as9817_64_led_init); +module_exit(as9817_64_led_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_psu.c new file mode 100644 index 000000000000..1c145365a032 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_psu.c @@ -0,0 +1,1058 @@ +/* + * Copyright (C) Roger Ho + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9817_64_psu" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_PSU_READ_CMD 0x16 +#define IPMI_PSU_MODEL_NAME_CMD 0x10 +#define IPMI_PSU_SERIAL_NUM_CMD 0x11 +#define IPMI_PSU_FAN_DIR_CMD 0x13 +#define IPMI_PSU_INFO_CMD 0x20 +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_ERR_RETRY_TIMES 1 +#define IPMI_MODEL_SERIAL_LEN 32 +#define IPMI_FAN_DIR_LEN 3 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_psu(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t show_psu_info(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *attr, + char *buf); +static int as9817_64_psu_probe(struct platform_device *pdev); +static int as9817_64_psu_remove(struct platform_device *pdev); + +enum psu_id { + PSU_1, + PSU_2, + NUM_OF_PSU +}; + +enum psu_data_index { + PSU_PRESENT = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD_CPLD, + PSU_POWER_GOOD_PMBUS, + PSU_OVER_VOLTAGE, + PSU_OVER_CURRENT, + PSU_POWER_ON, + PSU_VIN0, + PSU_VIN1, + PSU_VIN2, + PSU_VOUT0, + PSU_VOUT1, + PSU_VOUT2, + PSU_IIN0, + PSU_IIN1, + PSU_IIN2, + PSU_IOUT0, + PSU_IOUT1, + PSU_IOUT2, + PSU_PIN0, + PSU_PIN1, + PSU_PIN2, + PSU_PIN3, + PSU_POUT0, + PSU_POUT1, + PSU_POUT2, + PSU_POUT3, + PSU_TEMP1_0, + PSU_TEMP1_1, + PSU_TEMP2_0, + PSU_TEMP2_1, + PSU_TEMP3_0, + PSU_TEMP3_1, + PSU_FAN0, + PSU_FAN1, + PSU_VOUT_MODE, + PSU_STATUS_COUNT, + PSU_MODEL = 0, + PSU_SERIAL = 0, + PSU_TEMP1_MAX0 = 2, + PSU_TEMP1_MAX1, + PSU_TEMP1_MIN0, + PSU_TEMP1_MIN1, + PSU_TEMP2_MAX0, + PSU_TEMP2_MAX1, + PSU_TEMP2_MIN0, + PSU_TEMP2_MIN1, + PSU_TEMP3_MAX0, + PSU_TEMP3_MAX1, + PSU_TEMP3_MIN0, + PSU_TEMP3_MIN1, + PSU_VIN_UPPER_CRIT0, + PSU_VIN_UPPER_CRIT1, + PSU_VIN_UPPER_CRIT2, + PSU_VIN_MAX0, + PSU_VIN_MAX1, + PSU_VIN_MAX2, + PSU_VIN_MIN0, + PSU_VIN_MIN1, + PSU_VIN_MIN2, + PSU_VIN_LOWER_CRIT0, + PSU_VIN_LOWER_CRIT1, + PSU_VIN_LOWER_CRIT2, + PSU_VOUT_MAX0, + PSU_VOUT_MAX1, + PSU_VOUT_MAX2, + PSU_VOUT_MIN0, + PSU_VOUT_MIN1, + PSU_VOUT_MIN2, + PSU_IIN_MAX0, + PSU_IIN_MAX1, + PSU_IIN_MAX2, + PSU_IOUT_MAX0, + PSU_IOUT_MAX1, + PSU_IOUT_MAX2, + PSU_PIN_MAX0, + PSU_PIN_MAX1, + PSU_PIN_MAX2, + PSU_PIN_MAX3, + PSU_POUT_MAX0, + PSU_POUT_MAX1, + PSU_POUT_MAX2, + PSU_POUT_MAX3, + PSU_INFO_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + struct ipmi_user * user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct ipmi_psu_resp_data { + unsigned char status[PSU_STATUS_COUNT]; + unsigned char info[PSU_INFO_COUNT]; + char serial[IPMI_MODEL_SERIAL_LEN+1]; + char model[IPMI_MODEL_SERIAL_LEN+1]; + char fandir[IPMI_FAN_DIR_LEN+1]; +}; + +struct as9817_64_psu_data { + struct platform_device *pdev[2]; + struct device *hwmon_dev[2]; + struct mutex update_lock; + char valid[2]; /* != 0 if registers are valid, 0: PSU1, 1: PSU2 */ + unsigned long last_updated[2]; /* In jiffies, 0: PSU1, 1: PSU2 */ + struct ipmi_data ipmi; + struct ipmi_psu_resp_data ipmi_resp[2]; /* 0: PSU1, 1: PSU2 */ + unsigned char ipmi_tx_data[2]; +}; + +struct as9817_64_psu_data *data = NULL; + +static struct platform_driver as9817_64_psu_driver = { + .probe = as9817_64_psu_probe, + .remove = as9817_64_psu_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define PSU_PRESENT_ATTR_ID(index) PSU##index##_PRESENT +#define PSU_POWERGOOD_ATTR_ID(index) PSU##index##_POWER_GOOD +#define PSU_VIN_ATTR_ID(index) PSU##index##_VIN +#define PSU_VOUT_ATTR_ID(index) PSU##index##_VOUT +#define PSU_IIN_ATTR_ID(index) PSU##index##_IIN +#define PSU_IOUT_ATTR_ID(index) PSU##index##_IOUT +#define PSU_PIN_ATTR_ID(index) PSU##index##_PIN +#define PSU_POUT_ATTR_ID(index) PSU##index##_POUT +#define PSU_MODEL_ATTR_ID(index) PSU##index##_MODEL +#define PSU_SERIAL_ATTR_ID(index) PSU##index##_SERIAL +#define PSU_TEMP1_INPUT_ATTR_ID(index) PSU##index##_TEMP1_INPUT +#define PSU_TEMP2_INPUT_ATTR_ID(index) PSU##index##_TEMP2_INPUT +#define PSU_TEMP3_INPUT_ATTR_ID(index) PSU##index##_TEMP3_INPUT +#define PSU_FAN_INPUT_ATTR_ID(index) PSU##index##_FAN_INPUT +#define PSU_FAN_DIR_ATTR_ID(index) PSU##index##_FAN_DIR + +#define PSU_TEMP1_INPUT_MAX_ATTR_ID(index) PSU##index##_TEMP1_INPUT_MAX +#define PSU_TEMP1_INPUT_MIN_ATTR_ID(index) PSU##index##_TEMP1_INPUT_MIN +#define PSU_TEMP2_INPUT_MAX_ATTR_ID(index) PSU##index##_TEMP2_INPUT_MAX +#define PSU_TEMP2_INPUT_MIN_ATTR_ID(index) PSU##index##_TEMP2_INPUT_MIN +#define PSU_TEMP3_INPUT_MAX_ATTR_ID(index) PSU##index##_TEMP3_INPUT_MAX +#define PSU_TEMP3_INPUT_MIN_ATTR_ID(index) PSU##index##_TEMP3_INPUT_MIN +#define PSU_VIN_MAX_ATTR_ID(index) PSU##index##_VIN_MAX +#define PSU_VIN_MIN_ATTR_ID(index) PSU##index##_VIN_MIN +#define PSU_VIN_UPPER_CRIT_ATTR_ID(index) PSU##index##_VIN_UPPER_CRIT +#define PSU_VIN_LOWER_CRIT_ATTR_ID(index) PSU##index##_VIN_LOWER_CRIT +#define PSU_VOUT_MAX_ATTR_ID(index) PSU##index##_VOUT_MAX +#define PSU_VOUT_MIN_ATTR_ID(index) PSU##index##_VOUT_MIN +#define PSU_IIN_MAX_ATTR_ID(index) PSU##index##_IIN_MAX +#define PSU_IOUT_MAX_ATTR_ID(index) PSU##index##_IOUT_MAX +#define PSU_PIN_MAX_ATTR_ID(index) PSU##index##_PIN_MAX +#define PSU_POUT_MAX_ATTR_ID(index) PSU##index##_POUT_MAX + +#define PSU_ATTR(psu_id) \ + PSU_PRESENT_ATTR_ID(psu_id), \ + PSU_POWERGOOD_ATTR_ID(psu_id), \ + PSU_VIN_ATTR_ID(psu_id), \ + PSU_VOUT_ATTR_ID(psu_id), \ + PSU_IIN_ATTR_ID(psu_id), \ + PSU_IOUT_ATTR_ID(psu_id), \ + PSU_PIN_ATTR_ID(psu_id), \ + PSU_POUT_ATTR_ID(psu_id), \ + PSU_MODEL_ATTR_ID(psu_id), \ + PSU_SERIAL_ATTR_ID(psu_id), \ + PSU_TEMP1_INPUT_ATTR_ID(psu_id), \ + PSU_TEMP2_INPUT_ATTR_ID(psu_id), \ + PSU_TEMP3_INPUT_ATTR_ID(psu_id), \ + PSU_FAN_INPUT_ATTR_ID(psu_id), \ + PSU_FAN_DIR_ATTR_ID(psu_id), \ + PSU_TEMP1_INPUT_MAX_ATTR_ID(psu_id), \ + PSU_TEMP1_INPUT_MIN_ATTR_ID(psu_id), \ + PSU_TEMP2_INPUT_MAX_ATTR_ID(psu_id), \ + PSU_TEMP2_INPUT_MIN_ATTR_ID(psu_id), \ + PSU_TEMP3_INPUT_MAX_ATTR_ID(psu_id), \ + PSU_TEMP3_INPUT_MIN_ATTR_ID(psu_id), \ + PSU_VIN_MAX_ATTR_ID(psu_id), \ + PSU_VIN_MIN_ATTR_ID(psu_id), \ + PSU_VIN_UPPER_CRIT_ATTR_ID(psu_id), \ + PSU_VIN_LOWER_CRIT_ATTR_ID(psu_id), \ + PSU_VOUT_MAX_ATTR_ID(psu_id), \ + PSU_VOUT_MIN_ATTR_ID(psu_id), \ + PSU_IIN_MAX_ATTR_ID(psu_id), \ + PSU_IOUT_MAX_ATTR_ID(psu_id), \ + PSU_PIN_MAX_ATTR_ID(psu_id), \ + PSU_POUT_MAX_ATTR_ID(psu_id) + +enum as9817_64_psu_sysfs_attrs { + /* psu attributes */ + PSU_ATTR(1), + PSU_ATTR(2), + NUM_OF_PSU_ATTR, + NUM_OF_PER_PSU_ATTR = (NUM_OF_PSU_ATTR/NUM_OF_PSU) +}; + +/* psu attributes */ +#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, show_psu, NULL, \ + PSU##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(psu##index##_power_good, S_IRUGO, show_psu, NULL,\ + PSU##index##_POWER_GOOD); \ + static SENSOR_DEVICE_ATTR(psu##index##_vin, S_IRUGO, show_psu, NULL, \ + PSU##index##_VIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_psu, NULL, \ + PSU##index##_VOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_iin, S_IRUGO, show_psu, NULL, \ + PSU##index##_IIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_iout, S_IRUGO, show_psu, NULL, \ + PSU##index##_IOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_pin, S_IRUGO, show_psu, NULL, \ + PSU##index##_PIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_pout, S_IRUGO, show_psu, NULL, \ + PSU##index##_POUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_model, S_IRUGO, show_string, NULL, \ + PSU##index##_MODEL); \ + static SENSOR_DEVICE_ATTR(psu##index##_serial, S_IRUGO, show_string, NULL,\ + PSU##index##_SERIAL);\ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input, S_IRUGO, show_psu,NULL,\ + PSU##index##_TEMP1_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp2_input, S_IRUGO, show_psu,NULL,\ + PSU##index##_TEMP2_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp3_input, S_IRUGO, show_psu,NULL,\ + PSU##index##_TEMP3_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_fan1_input, S_IRUGO, show_psu, NULL,\ + PSU##index##_FAN_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_fan_dir, S_IRUGO, show_string, NULL,\ + PSU##index##_FAN_DIR); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_TEMP1_INPUT_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input_min, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_TEMP1_INPUT_MIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp2_input_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_TEMP2_INPUT_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp2_input_min, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_TEMP2_INPUT_MIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp3_input_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_TEMP3_INPUT_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_temp3_input_min, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_TEMP3_INPUT_MIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_vin_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_VIN_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_vin_min, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_VIN_MIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_vin_upper_crit, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_VIN_UPPER_CRIT); \ + static SENSOR_DEVICE_ATTR(psu##index##_vin_lower_crit, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_VIN_LOWER_CRIT); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_VOUT_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout_min, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_VOUT_MIN); \ + static SENSOR_DEVICE_ATTR(psu##index##_iin_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_IIN_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_iout_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_IOUT_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_pin_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_PIN_MAX); \ + static SENSOR_DEVICE_ATTR(psu##index##_pout_max, S_IRUGO, \ + show_psu_info, NULL, PSU##index##_POUT_MAX) + +#define DECLARE_PSU_ATTR(index) \ + &sensor_dev_attr_psu##index##_present.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_power_good.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vin.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iin.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pin.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_model.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_serial.dev_attr.attr,\ + &sensor_dev_attr_psu##index##_temp1_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp2_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp3_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_fan1_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_fan_dir.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp1_input_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp1_input_min.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp2_input_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp2_input_min.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp3_input_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_temp3_input_min.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vin_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vin_min.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vin_upper_crit.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vin_lower_crit.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vout_max.dev_attr.attr,\ + &sensor_dev_attr_psu##index##_vout_min.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iin_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iout_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pin_max.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pout_max.dev_attr.attr + +DECLARE_PSU_SENSOR_DEVICE_ATTR(1); +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_psu, NULL, PSU1_VOUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu, NULL, PSU1_IOUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu, NULL, PSU1_POUT); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_psu, NULL, PSU1_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_psu, NULL, PSU1_FAN_INPUT); + +static struct attribute *as9817_64_psu1_attrs[] = { + /* psu attributes */ + DECLARE_PSU_ATTR(1), + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + NULL +}; +static struct attribute_group as9817_64_psu1_group = { + .attrs = as9817_64_psu1_attrs, +}; +/* ATTRIBUTE_GROUPS(as9817_64_psu1); */ + +DECLARE_PSU_SENSOR_DEVICE_ATTR(2); +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu, NULL, PSU2_VOUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu, NULL, PSU2_IOUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu, NULL, PSU2_POUT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_psu, NULL, PSU2_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_psu, NULL, PSU2_FAN_INPUT); +static struct attribute *as9817_64_psu2_attrs[] = { + /* psu attributes */ + DECLARE_PSU_ATTR(2), + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + NULL +}; +static struct attribute_group as9817_64_psu2_group = { + .attrs = as9817_64_psu2_attrs, +}; +/* ATTRIBUTE_GROUPS(as9817_64_psu2); */ + +const struct attribute_group *as9817_64_psu_groups[][2] = { + {&as9817_64_psu1_group, NULL}, + {&as9817_64_psu2_group, NULL} +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + pr_err("Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int _ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + pr_err("request_timeout=%x\n", err); + return err; +ipmi_req_err: + pr_err("request_settime=%x\n", err); + return err; +addr_err: + pr_err("validate_addr=%x\n", err); + return err; +} + +/* Send an IPMI command with retry */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int status = 0, retry = 0; + + for (retry = 0; retry <= IPMI_ERR_RETRY_TIMES; retry++) { + status = _ipmi_send_message(ipmi, cmd, tx_data, tx_len, rx_data, rx_len); + if (unlikely(status != 0)) { + pr_err("ipmi_send_message_%d err status(%d)\r\n", retry, status); + continue; + } + + if (unlikely(ipmi->rx_result != 0)) { + pr_err("ipmi_send_message_%d err result(%d)\r\n", retry, ipmi->rx_result); + continue; + } + + break; + } + + return status; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + pr_notice("Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct as9817_64_psu_data *as9817_64_psu_update_device(struct device_attribute *da) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int status = 0; + + if (time_before(jiffies, data->last_updated[pid] + HZ * 5) && data->valid[pid]) + return data; + + data->valid[pid] = 0; + /* To be compatible for older BMC firmware */ + data->ipmi_resp[pid].status[PSU_VOUT_MODE] = 0xff; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = pid + 1; /* PSU ID base id for ipmi start from 1 */ + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp[pid].status, + sizeof(data->ipmi_resp[pid].status)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get model name from ipmi */ + data->ipmi_tx_data[1] = IPMI_PSU_MODEL_NAME_CMD; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, + data->ipmi_tx_data, 2, + data->ipmi_resp[pid].model, + sizeof(data->ipmi_resp[pid].model) - 1); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get serial number from ipmi */ + data->ipmi_tx_data[1] = IPMI_PSU_SERIAL_NUM_CMD; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, + data->ipmi_tx_data, 2, + data->ipmi_resp[pid].serial, + sizeof(data->ipmi_resp[pid].serial) - 1); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get fan direction from ipmi */ + data->ipmi_tx_data[1] = IPMI_PSU_FAN_DIR_CMD; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, + data->ipmi_tx_data, 2, + data->ipmi_resp[pid].fandir, + sizeof(data->ipmi_resp[pid].fandir) - 1); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get capability from ipmi */ + data->ipmi_tx_data[1] = IPMI_PSU_INFO_CMD; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, + data->ipmi_tx_data, 2, + data->ipmi_resp[pid].info, + sizeof(data->ipmi_resp[pid].info)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated[pid] = jiffies; + data->valid[pid] = 1; + +exit: + return data; +} + +#define VALIDATE_PRESENT_RETURN(id) \ +do { \ + if (data->ipmi_resp[id].status[PSU_PRESENT] == 0) { \ + mutex_unlock(&data->update_lock); \ + return -ENXIO; \ + } \ +} while (0) + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + u32 value = 0; + int present = 0; + int error = 0; + int multiplier = 1000; + + mutex_lock(&data->update_lock); + + data = as9817_64_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + present = !!(data->ipmi_resp[pid].status[PSU_PRESENT]); + + switch (attr->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + value = present; + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + VALIDATE_PRESENT_RETURN(pid); + value = data->ipmi_resp[pid].status[PSU_POWER_GOOD_PMBUS]; + break; + case PSU1_IIN: + case PSU2_IIN: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_IIN0] | + (u32)data->ipmi_resp[pid].status[PSU_IIN1] << 8 | + (u32)data->ipmi_resp[pid].status[PSU_IIN2] << 16); + break; + case PSU1_IOUT: + case PSU2_IOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_IOUT0] | + (u32)data->ipmi_resp[pid].status[PSU_IOUT1] << 8 | + (u32)data->ipmi_resp[pid].status[PSU_IOUT2] << 16); + break; + case PSU1_VIN: + case PSU2_VIN: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_VIN0] | + (u32)data->ipmi_resp[pid].status[PSU_VIN1] << 8 | + (u32)data->ipmi_resp[pid].status[PSU_VIN2] << 16); + break; + case PSU1_VOUT: + case PSU2_VOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_VOUT0] | + (u32)data->ipmi_resp[pid].status[PSU_VOUT1] << 8 | + (u32)data->ipmi_resp[pid].status[PSU_VOUT2] << 16); + break; + case PSU1_PIN: + case PSU2_PIN: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_PIN0] | + (u32)data->ipmi_resp[pid].status[PSU_PIN1] << 8 | + (u32)data->ipmi_resp[pid].status[PSU_PIN2] << 16 | + (u32)data->ipmi_resp[pid].status[PSU_PIN3] << 24); + value /= 1000; // Convert to milliwatt + break; + case PSU1_POUT: + case PSU2_POUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_POUT0] | + (u32)data->ipmi_resp[pid].status[PSU_POUT1] << 8 | + (u32)data->ipmi_resp[pid].status[PSU_POUT2] << 16 | + (u32)data->ipmi_resp[pid].status[PSU_POUT3] << 24); + value /= 1000; // Convert to milliwatt + break; + case PSU1_TEMP1_INPUT: + case PSU2_TEMP1_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].status[PSU_TEMP1_0] | + (u16)data->ipmi_resp[pid].status[PSU_TEMP1_1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP2_INPUT: + case PSU2_TEMP2_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].status[PSU_TEMP2_0] | + (u16)data->ipmi_resp[pid].status[PSU_TEMP2_1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP3_INPUT: + case PSU2_TEMP3_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].status[PSU_TEMP3_0] | + (u16)data->ipmi_resp[pid].status[PSU_TEMP3_1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_FAN_INPUT: + case PSU2_FAN_INPUT: + VALIDATE_PRESENT_RETURN(pid); + multiplier = 1; + value = ((u32)data->ipmi_resp[pid].status[PSU_FAN0] | + (u32)data->ipmi_resp[pid].status[PSU_FAN1] << 8); + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", present ? value : 0); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_psu_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + s32 value = 0; + int present = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + present = !!(data->ipmi_resp[pid].status[PSU_PRESENT]); + + switch (attr->index) { + case PSU1_TEMP1_INPUT_MAX: + case PSU2_TEMP1_INPUT_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].info[PSU_TEMP1_MAX0] | + (u16)data->ipmi_resp[pid].info[PSU_TEMP1_MAX1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP1_INPUT_MIN: + case PSU2_TEMP1_INPUT_MIN: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].info[PSU_TEMP1_MIN0] | + (u16)data->ipmi_resp[pid].info[PSU_TEMP1_MIN1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP2_INPUT_MAX: + case PSU2_TEMP2_INPUT_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].info[PSU_TEMP2_MAX0] | + (u16)data->ipmi_resp[pid].info[PSU_TEMP2_MAX1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP2_INPUT_MIN: + case PSU2_TEMP2_INPUT_MIN: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].info[PSU_TEMP2_MIN0] | + (u16)data->ipmi_resp[pid].info[PSU_TEMP2_MIN1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP3_INPUT_MAX: + case PSU2_TEMP3_INPUT_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].info[PSU_TEMP3_MAX0] | + (u16)data->ipmi_resp[pid].info[PSU_TEMP3_MAX1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_TEMP3_INPUT_MIN: + case PSU2_TEMP3_INPUT_MIN: + VALIDATE_PRESENT_RETURN(pid); + value = (s16)((u16)data->ipmi_resp[pid].info[PSU_TEMP3_MIN0] | + (u16)data->ipmi_resp[pid].info[PSU_TEMP3_MIN1] << 8); + value *= 1000; // Convert to millidegree Celsius + break; + case PSU1_VIN_UPPER_CRIT: + case PSU2_VIN_UPPER_CRIT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_VIN_UPPER_CRIT0] | + (u32)data->ipmi_resp[pid].info[PSU_VIN_UPPER_CRIT1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_VIN_UPPER_CRIT2] << 16); + break; + case PSU1_VIN_LOWER_CRIT: + case PSU2_VIN_LOWER_CRIT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_VIN_LOWER_CRIT0] | + (u32)data->ipmi_resp[pid].info[PSU_VIN_LOWER_CRIT1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_VIN_LOWER_CRIT2] << 16); + break; + case PSU1_VIN_MAX: + case PSU2_VIN_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_VIN_MAX0] | + (u32)data->ipmi_resp[pid].info[PSU_VIN_MAX1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_VIN_MAX2] << 16); + break; + case PSU1_VIN_MIN: + case PSU2_VIN_MIN: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_VIN_MIN0] | + (u32)data->ipmi_resp[pid].info[PSU_VIN_MIN1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_VIN_MIN2] << 16); + break; + case PSU1_VOUT_MAX: + case PSU2_VOUT_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_VOUT_MAX0] | + (u32)data->ipmi_resp[pid].info[PSU_VOUT_MAX1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_VOUT_MAX2] << 16); + break; + case PSU1_VOUT_MIN: + case PSU2_VOUT_MIN: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_VOUT_MIN0] | + (u32)data->ipmi_resp[pid].info[PSU_VOUT_MIN1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_VOUT_MIN2] << 16); + break; + case PSU1_IIN_MAX: + case PSU2_IIN_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_IIN_MAX0] | + (u32)data->ipmi_resp[pid].info[PSU_IIN_MAX1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_IIN_MAX2] << 16); + break; + case PSU1_IOUT_MAX: + case PSU2_IOUT_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_IOUT_MAX0] | + (u32)data->ipmi_resp[pid].info[PSU_IOUT_MAX1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_IOUT_MAX2] << 16); + break; + case PSU1_PIN_MAX: + case PSU2_PIN_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_PIN_MAX0] | + (u32)data->ipmi_resp[pid].info[PSU_PIN_MAX1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_PIN_MAX2] << 16 | + (u32)data->ipmi_resp[pid].info[PSU_PIN_MAX3] << 24); + value /= 1000; // Convert to milliwatt + break; + case PSU1_POUT_MAX: + case PSU2_POUT_MAX: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].info[PSU_POUT_MAX0] | + (u32)data->ipmi_resp[pid].info[PSU_POUT_MAX1] << 8 | + (u32)data->ipmi_resp[pid].info[PSU_POUT_MAX2] << 16 | + (u32)data->ipmi_resp[pid].info[PSU_POUT_MAX3] << 24); + value /= 1000; // Convert to milliwatt + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", present ? value : 0); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + char *str = NULL; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU1_MODEL: + case PSU2_MODEL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].model; + break; + case PSU1_SERIAL: + case PSU2_SERIAL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].serial; + break; + case PSU1_FAN_DIR: + case PSU2_FAN_DIR: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].fandir; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", str); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static int as9817_64_psu_probe(struct platform_device *pdev) +{ + int status = 0; + struct device *hwmon_dev = NULL; + + hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, DRVNAME, + NULL, as9817_64_psu_groups[pdev->id]); + if (IS_ERR(hwmon_dev)) { + status = PTR_ERR(hwmon_dev); + return status; + } + + mutex_lock(&data->update_lock); + data->hwmon_dev[pdev->id] = hwmon_dev; + mutex_unlock(&data->update_lock); + + dev_info(&pdev->dev, "PSU%d device created\n", pdev->id + 1); + + return 0; +} + +static int as9817_64_psu_remove(struct platform_device *pdev) +{ + mutex_lock(&data->update_lock); + if (data->hwmon_dev[pdev->id]) { + hwmon_device_unregister(data->hwmon_dev[pdev->id]); + data->hwmon_dev[pdev->id] = NULL; + } + mutex_unlock(&data->update_lock); + + return 0; +} + +static int __init as9817_64_psu_init(void) +{ + int ret; + int i; + + data = kzalloc(sizeof(struct as9817_64_psu_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as9817_64_psu_driver); + if (ret < 0) + goto dri_reg_err; + + for (i = 0; i < NUM_OF_PSU; i++) { + data->pdev[i] = platform_device_register_simple(DRVNAME, i, NULL, 0); + if (IS_ERR(data->pdev[i])) { + ret = PTR_ERR(data->pdev[i]); + goto dev_reg_err; + } + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0); + if (ret) { + goto ipmi_err; + } + + return 0; + +ipmi_err: + while (i > 0) { + i--; + platform_device_unregister(data->pdev[i]); + } +dev_reg_err: + platform_driver_unregister(&as9817_64_psu_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as9817_64_psu_exit(void) +{ + int i; + + ipmi_destroy_user(data->ipmi.user); + for (i = 0; i < NUM_OF_PSU; i++) { + platform_device_unregister(data->pdev[i]); + } + platform_driver_unregister(&as9817_64_psu_driver); + kfree(data); +} + +MODULE_AUTHOR("Roger Ho "); +MODULE_DESCRIPTION("as9817_64_psu driver"); +MODULE_LICENSE("GPL"); + +module_init(as9817_64_psu_init); +module_exit(as9817_64_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_sys.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_sys.c new file mode 100644 index 000000000000..c574c6cffb34 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_sys.c @@ -0,0 +1,464 @@ +/* + * Copyright (C) Roger Ho + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9817_64_sys" +#define ACCTON_IPMI_NETFN 0x34 + +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_ERR_RETRY_TIMES 1 +#define IPMI_READ_MAX_LEN 128 + +#define EEPROM_NAME "eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ + +#define IPMI_SYSEEPROM_READ_CMD 0x18 +#define IPMI_CPLD_READ_CMD 0x20 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static int as9817_64_sys_probe(struct platform_device *pdev); +static int as9817_64_sys_remove(struct platform_device *pdev); +static ssize_t show_version(struct device *dev, + struct device_attribute *da, char *buf); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + struct ipmi_user * user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as9817_64_sys_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct ipmi_data ipmi; + unsigned char ipmi_resp_eeprom[EEPROM_SIZE]; + unsigned char ipmi_resp_cpld[2]; + unsigned char ipmi_tx_data[2]; + struct bin_attribute eeprom; /* eeprom data */ +}; + +struct as9817_64_sys_data *data = NULL; + +static struct platform_driver as9817_64_sys_driver = { + .probe = as9817_64_sys_probe, + .remove = as9817_64_sys_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as9817_64_sys_sysfs_attrs { + FPGA_VER, /* FPGA version */ +}; + +static SENSOR_DEVICE_ATTR(fpga_version, S_IRUGO, show_version, NULL, FPGA_VER); + +static struct attribute *as9817_64_sys_attributes[] = { + &sensor_dev_attr_fpga_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9817_64_sys_group = { + .attrs = as9817_64_sys_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int _ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Send an IPMI command with retry */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int status = 0, retry = 0; + + for (retry = 0; retry <= IPMI_ERR_RETRY_TIMES; retry++) { + status = _ipmi_send_message(ipmi,cmd, tx_data, tx_len, rx_data, rx_len); + if (unlikely(status != 0)) { + dev_err(&data->pdev->dev, + "ipmi_send_message_%d err status(%d)\r\n", + retry, status); + continue; + } + + if (unlikely(ipmi->rx_result != 0)) { + dev_err(&data->pdev->dev, + "ipmi_send_message_%d err rx_result(%d)\r\n", + retry, ipmi->rx_result); + continue; + } + + break; + } + + return status; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_notice(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } + else { + ipmi->rx_msg_len = 0; + } + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t sys_eeprom_read(loff_t off, char *buf, size_t count) +{ + int status = 0; + unsigned char length = 0; + + if ((off + count) > EEPROM_SIZE) + return -EINVAL; + + length = (count >= IPMI_READ_MAX_LEN) ? IPMI_READ_MAX_LEN : count; + data->ipmi_tx_data[0] = (off & 0xff); + data->ipmi_tx_data[1] = length; + status = ipmi_send_message(&data->ipmi, IPMI_SYSEEPROM_READ_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), + data->ipmi_resp_eeprom + off, length); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = length; /* Read length */ + memcpy(buf, data->ipmi_resp_eeprom + off, length); + +exit: + return status; +} + +static ssize_t sysfs_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Read data from chip, protecting against concurrent updates + * from this host + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sys_eeprom_read(off, buf, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + +static int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IRUGO; + eeprom->read = sysfs_bin_read; + eeprom->size = EEPROM_SIZE; + eeprom->write = NULL; + + /* Create eeprom file */ + return sysfs_create_bin_file(kobj, eeprom); +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, + struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static struct as9817_64_sys_data *as9817_64_sys_update_fpga_ver(void) +{ + int status = 0; + + data->valid = 0; + data->ipmi_tx_data[0] = 0x60; + status = ipmi_send_message(&data->ipmi, IPMI_CPLD_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp_cpld, + sizeof(data->ipmi_resp_cpld)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_version(struct device *dev, + struct device_attribute *da, char *buf) +{ + unsigned char major; + unsigned char minor; + int error = 0; + + mutex_lock(&data->update_lock); + + data = as9817_64_sys_update_fpga_ver(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + major = data->ipmi_resp_cpld[0]; + minor = data->ipmi_resp_cpld[1]; + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d.%d\n", major, minor); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static int as9817_64_sys_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom); + if (status) + goto exit; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &as9817_64_sys_group); + if (status) + goto exit; + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int as9817_64_sys_remove(struct platform_device *pdev) +{ + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom); + sysfs_remove_group(&pdev->dev.kobj, &as9817_64_sys_group); + + return 0; +} + +static int __init as9817_64_sys_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as9817_64_sys_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as9817_64_sys_driver); + if (ret < 0) + goto dri_reg_err; + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as9817_64_sys_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as9817_64_sys_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as9817_64_sys_driver); + kfree(data); +} + +MODULE_AUTHOR("Roger Ho "); +MODULE_DESCRIPTION("as9817_64_sys driver"); +MODULE_LICENSE("GPL"); + +module_init(as9817_64_sys_init); +module_exit(as9817_64_sys_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_thermal.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_thermal.c new file mode 100644 index 000000000000..ea34c2964dc7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/accton_as9817_64_thermal.c @@ -0,0 +1,507 @@ +/* + * Copyright (C) Roger Ho + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9817_64_thermal" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_THERMAL_READ_CMD 0x12 +#define THERMAL_COUNT 8 +#define THERMAL_DATA_LEN 3 +#define THERMAL_DATA_COUNT (THERMAL_COUNT * THERMAL_DATA_LEN) + +#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_ERR_RETRY_TIMES 1 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf); +#ifdef ENABLE_THRESHOLD +static ssize_t show_threshold(struct device *dev, struct device_attribute *da, + char *buf); +#endif +static int as9817_64_thermal_probe(struct platform_device *pdev); +static int as9817_64_thermal_remove(struct platform_device *pdev); + +enum temp_data_index { + TEMP_ADDR, + TEMP_FAULT, + TEMP_INPUT, + TEMP_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + struct ipmi_user * user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct as9817_64_thermal_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + char ipmi_resp[THERMAL_DATA_COUNT]; /* 3 bytes for each thermal */ + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[2]; /* 0: thermal id, 1: temp */ +}; + +#ifdef ENABLE_THRESHOLD +static s8 temp_max_alarm[THERMAL_COUNT] = { 85, 85, 85, 79, 92, 85, 92, 92}; +static s8 temp_max[THERMAL_COUNT] = { 80, 80, 80, 74, 87, 80, 87, 87 }; +static s8 temp_min[THERMAL_COUNT] = { -45, -45, -45, -45, -45, -45, -45, -45 }; +static s8 temp_min_alarm[THERMAL_COUNT] = { -50, -50, -50, -50, -50, -50, -50, -50 }; +#endif + +struct as9817_64_thermal_data *data = NULL; + +static struct platform_driver as9817_64_thermal_driver = { + .probe = as9817_64_thermal_probe, + .remove = as9817_64_thermal_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum as9817_64_thermal_sysfs_attrs { + TEMP1_INPUT, // 0x48 + TEMP2_INPUT, // 0x49 + TEMP3_INPUT, // 0x4A + TEMP4_INPUT, // 0x4B + TEMP5_INPUT, // 0x4C + TEMP6_INPUT, // 0x4D + TEMP7_INPUT, // FAN 0x4D + TEMP8_INPUT, // FAN 0x4E + TEMP1_MAX_ALARM, + TEMP2_MAX_ALARM, + TEMP3_MAX_ALARM, + TEMP4_MAX_ALARM, + TEMP5_MAX_ALARM, + TEMP6_MAX_ALARM, + TEMP7_MAX_ALARM, + TEMP8_MAX_ALARM, + TEMP1_MAX, + TEMP2_MAX, + TEMP3_MAX, + TEMP4_MAX, + TEMP5_MAX, + TEMP6_MAX, + TEMP7_MAX, + TEMP8_MAX, + TEMP1_MIN, + TEMP2_MIN, + TEMP3_MIN, + TEMP4_MIN, + TEMP5_MIN, + TEMP6_MIN, + TEMP7_MIN, + TEMP8_MIN, + TEMP1_MIN_ALARM, + TEMP2_MIN_ALARM, + TEMP3_MIN_ALARM, + TEMP4_MIN_ALARM, + TEMP5_MIN_ALARM, + TEMP6_MIN_ALARM, + TEMP7_MIN_ALARM, + TEMP8_MIN_ALARM, +}; + +#ifdef ENABLE_THRESHOLD +// Read only temp_input +#define DECLARE_THERMAL_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, show_temp, \ + NULL, TEMP##index##_INPUT); \ + static SENSOR_DEVICE_ATTR(temp##index##_crit, S_IRUGO, show_threshold,\ + NULL, TEMP##index##_MAX_ALARM); \ + static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO, show_threshold,\ + NULL, TEMP##index##_MAX); \ + static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO, show_threshold,\ + NULL, TEMP##index##_MIN); \ + static SENSOR_DEVICE_ATTR(temp##index##_lcrit, S_IRUGO, show_threshold,\ + NULL, TEMP##index##_MIN_ALARM) + +#define DECLARE_THERMAL_ATTR(index) \ + &sensor_dev_attr_temp##index##_input.dev_attr.attr, \ + &sensor_dev_attr_temp##index##_crit.dev_attr.attr, \ + &sensor_dev_attr_temp##index##_max.dev_attr.attr, \ + &sensor_dev_attr_temp##index##_min.dev_attr.attr, \ + &sensor_dev_attr_temp##index##_lcrit.dev_attr.attr +#else +#define DECLARE_THERMAL_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, show_temp, \ + NULL, TEMP##index##_INPUT); + +#define DECLARE_THERMAL_ATTR(index) \ + &sensor_dev_attr_temp##index##_input.dev_attr.attr +#endif + +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(1); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(2); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(3); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(4); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(5); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(6); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(7); +DECLARE_THERMAL_SENSOR_DEVICE_ATTR(8); + +static struct attribute *as9817_64_thermal_attrs[] = { + DECLARE_THERMAL_ATTR(1), + DECLARE_THERMAL_ATTR(2), + DECLARE_THERMAL_ATTR(3), + DECLARE_THERMAL_ATTR(4), + DECLARE_THERMAL_ATTR(5), + DECLARE_THERMAL_ATTR(6), + DECLARE_THERMAL_ATTR(7), + DECLARE_THERMAL_ATTR(8), + NULL +}; +ATTRIBUTE_GROUPS(as9817_64_thermal); + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int _ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Send an IPMI command with retry */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int status = 0, retry = 0; + + for (retry = 0; retry <= IPMI_ERR_RETRY_TIMES; retry++) { + status = _ipmi_send_message(ipmi, cmd, tx_data, tx_len, rx_data, rx_len); + if (unlikely(status != 0)) { + dev_err(&data->pdev->dev, "ipmi cmd(%x) err status(%d)\r\n", + cmd, status); + continue; + } + + if (unlikely(ipmi->rx_result != 0)) { + dev_err(&data->pdev->dev, "ipmi cmd(%x) err result(%d)\r\n", + cmd, ipmi->rx_result); + continue; + } + + break; + } + + return status; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_notice(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +#ifdef ENABLE_THRESHOLD +static ssize_t show_threshold(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + mutex_lock(&data->update_lock); + + switch (attr->index) { + case TEMP1_MAX_ALARM ... TEMP8_MAX_ALARM: + status = (int)temp_max_alarm[attr->index - TEMP1_MAX_ALARM]; + break; + case TEMP1_MAX ... TEMP8_MAX: + status = (int)temp_max[attr->index - TEMP1_MAX]; + break; + case TEMP1_MIN ... TEMP8_MIN: + status = (int)temp_min[attr->index - TEMP1_MIN]; + break; + case TEMP1_MIN_ALARM ... TEMP8_MIN_ALARM: + status = (int)temp_min_alarm[attr->index - TEMP1_MIN_ALARM]; + break; + default: + status = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", status * 1000); + +exit: + mutex_unlock(&data->update_lock); + return status; +} +#endif + +static ssize_t show_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status = 0; + int index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 5) || !data->valid) { + data->valid = 0; + + status = ipmi_send_message(&data->ipmi, IPMI_THERMAL_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + /* Get temp fault status */ + index = attr->index * TEMP_DATA_COUNT + TEMP_FAULT; + if (unlikely(data->ipmi_resp[index] == 0)) { + status = -EIO; + goto exit; + } + + /* Get temperature in degree celsius */ + index = attr->index * TEMP_DATA_COUNT + TEMP_INPUT; + status = ((s8)data->ipmi_resp[index]) * 1000; + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as9817_64_thermal_probe(struct platform_device *pdev) +{ + int status = 0; + struct device *hwmon_dev; + + hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, DRVNAME, + NULL, as9817_64_thermal_groups); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + return status; + } + + mutex_lock(&data->update_lock); + data->hwmon_dev = hwmon_dev; + mutex_unlock(&data->update_lock); + + dev_info(&pdev->dev, "Device Created\n"); + + return status; +} + +static int as9817_64_thermal_remove(struct platform_device *pdev) +{ + mutex_lock(&data->update_lock); + if (data->hwmon_dev) { + hwmon_device_unregister(data->hwmon_dev); + data->hwmon_dev = NULL; + } + mutex_unlock(&data->update_lock); + + return 0; +} + +static int __init as9817_64_thermal_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as9817_64_thermal_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&as9817_64_thermal_driver); + if (ret < 0) + goto dri_reg_err; + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) { + goto ipmi_err; + } + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&as9817_64_thermal_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as9817_64_thermal_exit(void) +{ + if (data) { + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&as9817_64_thermal_driver); + kfree(data); + } +} + +MODULE_AUTHOR("Roger Ho "); +MODULE_DESCRIPTION("as9817_64_thermal driver"); +MODULE_LICENSE("GPL"); + +module_init(as9817_64_thermal_init); +module_exit(as9817_64_thermal_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/i2c-ocores.c b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/i2c-ocores.c new file mode 100644 index 000000000000..b73b619df4d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/modules/i2c-ocores.c @@ -0,0 +1,959 @@ + +// SPDX-License-Identifier: GPL-2.0 +/* + * i2c-ocores.c: I2C bus driver for OpenCores I2C controller + * (https://opencores.org/project/i2c/overview) + * + * Peter Korsgaard + * + * Support for the GRLIB port of the controller by + * Andreas Larsson + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 'process_lock' exists because ocores_process() and ocores_process_timeout() + * can't run in parallel. + */ +struct ocores_i2c { + void __iomem *base; + int iobase; + u32 reg_shift; + u32 reg_io_width; + unsigned long flags; + wait_queue_head_t wait; + struct i2c_adapter adap; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + spinlock_t process_lock; + struct clk *clk; + int ip_clock_khz; + int bus_clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); +}; + +/* registers */ +#define OCI2C_PRELOW 0 +#define OCI2C_PREHIGH 1 +#define OCI2C_CONTROL 2 +#define OCI2C_DATA 3 +#define OCI2C_CMD 4 /* write only */ +#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ + +#define OCI2C_CTRL_IEN 0x40 +#define OCI2C_CTRL_EN 0x80 + +#define OCI2C_CMD_START 0x91 +#define OCI2C_CMD_STOP 0x41 +#define OCI2C_CMD_READ 0x21 +#define OCI2C_CMD_WRITE 0x11 +#define OCI2C_CMD_READ_ACK 0x21 +#define OCI2C_CMD_READ_NACK 0x29 +#define OCI2C_CMD_IACK 0x01 + +#define OCI2C_STAT_IF 0x01 +#define OCI2C_STAT_TIP 0x02 +#define OCI2C_STAT_ARBLOST 0x20 +#define OCI2C_STAT_BUSY 0x40 +#define OCI2C_STAT_NACK 0x80 + +#define STATE_DONE 0 +#define STATE_START 1 +#define STATE_WRITE 2 +#define STATE_READ 3 +#define STATE_ERROR 4 + +#define TYPE_OCORES 0 +#define TYPE_GRLIB 1 +#define TYPE_SIFIVE_REV0 2 + +#define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */ + +static unsigned int timeout = 1; +module_param(timeout , uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(timeout, "Tiemout for ocores_poll_wait, in unit of milliseconds."); + +static unsigned int debug = 1; +module_param(debug , uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug, "Enable or disable debug message. 1 -> enable, 0 -> disable"); + +spinlock_t cpld_access_lock; +EXPORT_SYMBOL(cpld_access_lock); + +#define LOCK(lock) \ +do { \ + spin_lock(lock); \ +} while (0) + +#define UNLOCK(lock) \ +do { \ + spin_unlock(lock); \ +} while (0) + +void __iomem *spi_busy_reg=NULL; +EXPORT_SYMBOL(spi_busy_reg); +int wait_spi(u32 mask, unsigned long timeout) { + u32 data; + u32 ri = 0; + unsigned long j; + + /* pr_info("CPLD %u, Will time-out at jiffie %lu\n", cpld_id,timeout); */ + if (!spi_busy_reg) { + return -EFAULT; + } + + j = jiffies + timeout; + while(1) { + data = ioread32(spi_busy_reg); + /* pr_info("@ %u, Read spi_busy_reg: 0x%08x 0x%08x\n", ri, data, mask); */ + if (!((( data >> 24) & 0xFF) & mask)) { + break; + } + + if (time_after(jiffies, j)) { + if (debug) { + pr_warn("@ %u, wait_spi TIMEOUT \n", ri); + } + return -ETIMEDOUT; + } + + ri++; + } + + return 0; +} +EXPORT_SYMBOL(wait_spi); + +static int wait_cpld(struct ocores_i2c *i2c, unsigned long timeout) { + struct platform_device *pdev; + struct device *dev; + + if (!i2c->adap.dev.parent) { + return -EFAULT; + } + + /* Get SPI Busy mask from pdev->id */ + dev = i2c->adap.dev.parent; + pdev = container_of(dev, struct platform_device, dev); + wait_spi((pdev->id & 0xFF00) >> 8, timeout); + + return 0; +} + +static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg) +{ + return ioread16be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg) +{ + return ioread32be(i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_io_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + outb(value, i2c->iobase + reg); +} + +static inline u8 oc_getreg_io_8(struct ocores_i2c *i2c, int reg) +{ + return inb(i2c->iobase + reg); +} + +static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +{ + wait_cpld(i2c, usecs_to_jiffies(20)); + i2c->setreg(i2c, reg, value); +} + +static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +{ + wait_cpld(i2c, usecs_to_jiffies(20)); + return i2c->getreg(i2c, reg); +} + +static void ocores_process(struct ocores_i2c *i2c, u8 stat) +{ + struct i2c_msg *msg = i2c->msg; + unsigned long flags; + struct device *dev = i2c->adap.dev.parent; + + /* + * If we spin here is because we are in timeout, so we are going + * to be in STATE_ERROR. See ocores_process_timeout() + */ + spin_lock_irqsave(&i2c->process_lock, flags); + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); + goto out; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + if (debug) { + dev_warn(dev, "I2C %s arbitration lost", i2c->adap.name); + } + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + goto out; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + if (debug) { + dev_warn(dev, "I2C %s, no ACK from slave 0x%02x", + i2c->adap.name, msg->addr); + } + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + goto out; + } + } else { + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + u8 addr = i2c_8bit_addr_from_msg(msg); + + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + goto out; + } + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + goto out; + } + } + + if (i2c->state == STATE_READ) { + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } + +out: + spin_unlock_irqrestore(&i2c->process_lock, flags); + +} + +static irqreturn_t ocores_isr(int irq, void *dev_id) +{ + struct ocores_i2c *i2c = dev_id; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + + if (i2c->flags & OCORES_FLAG_BROKEN_IRQ) { + if ((stat & OCI2C_STAT_IF) && !(stat & OCI2C_STAT_BUSY)) + return IRQ_NONE; + } else if (!(stat & OCI2C_STAT_IF)) { + return IRQ_NONE; + } + ocores_process(i2c, stat); + + return IRQ_HANDLED; +} + +/** + * Process timeout event + * @i2c: ocores I2C device instance + */ +static void ocores_process_timeout(struct ocores_i2c *i2c) +{ + unsigned long flags; + + spin_lock_irqsave(&i2c->process_lock, flags); + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + spin_unlock_irqrestore(&i2c->process_lock, flags); +} + +/** + * Wait until something change in a given register + * @i2c: ocores I2C device instance + * @reg: register to query + * @mask: bitmask to apply on register value + * @val: expected result + * @timeout: timeout in jiffies + * + * Timeout is necessary to avoid to stay here forever when the chip + * does not answer correctly. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_wait(struct ocores_i2c *i2c, + int reg, u8 mask, u8 val, + const unsigned long timeout) +{ + unsigned long j; + + j = jiffies + timeout; + while (1) { + u8 status = oc_getreg(i2c, reg); + + if ((status & mask) == val) + break; + + if (time_after(jiffies, j)) + return -ETIMEDOUT; + } + return 0; +} + +/** + * Wait until is possible to process some data + * @i2c: ocores I2C device instance + * + * Used when the device is in polling mode (interrupts disabled). + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_poll_wait(struct ocores_i2c *i2c) +{ + u8 mask; + int err; + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) { + /* transfer is over */ + mask = OCI2C_STAT_BUSY; + } else { + /* on going transfer */ + mask = OCI2C_STAT_TIP; + /* + * We wait for the data to be transferred (8bit), + * then we start polling on the ACK/NACK bit + */ + udelay((8 * 1000) / i2c->bus_clock_khz); + } + + /* + * once we are here we expect to get the expected result immediately + * so if after 1ms we timeout then something is broken. + */ + err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(timeout)); + if (err) { + if (debug) { + dev_warn(i2c->adap.dev.parent, + "%s: STATUS timeout, bit 0x%x did not clear in %ums(msecs_to_jiffies(%u)=%lu)\n", + __func__, mask, timeout, timeout, msecs_to_jiffies(timeout)); + } + } + return err; +} + +/** + * It handles an IRQ-less transfer + * @i2c: ocores I2C device instance + * + * Even if IRQ are disabled, the I2C OpenCore IP behavior is exactly the same + * (only that IRQ are not produced). This means that we can re-use entirely + * ocores_isr(), we just add our polling code around it. + * + * It can run in atomic context + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_process_polling(struct ocores_i2c *i2c) +{ + irqreturn_t ret; + int err; + + while (1) { + err = ocores_poll_wait(i2c); + if (err) { + break; /* timeout */ + } + + ret = ocores_isr(-1, i2c); + if (ret == IRQ_NONE) + break; /* all messages have been transferred */ + else { + if (i2c->flags & OCORES_FLAG_BROKEN_IRQ) + if (i2c->state == STATE_DONE) + break; + } + } + + return err; +} + +static int ocores_xfer_core(struct ocores_i2c *i2c, + struct i2c_msg *msgs, int num, + bool polling) +{ + int ret = 0; + u8 ctrl; + + LOCK(&cpld_access_lock); + + ctrl = oc_getreg(i2c, OCI2C_CONTROL); + if (polling) + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~OCI2C_CTRL_IEN); + else + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg)); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (polling) { + ret = ocores_process_polling(i2c); + } else { + if (wait_event_timeout(i2c->wait, + (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ) == 0) + ret = -ETIMEDOUT; + } + if (ret) { + ocores_process_timeout(i2c); + UNLOCK(&cpld_access_lock); + return ret; + } + + UNLOCK(&cpld_access_lock); + return (i2c->state == STATE_DONE) ? num : -EIO; +} + +static int ocores_xfer_polling(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return ocores_xfer_core(i2c_get_adapdata(adap), msgs, num, true); +} + +static int ocores_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return ocores_xfer_core(i2c_get_adapdata(adap), msgs, num, false); +} + +static int ocores_init(struct device *dev, struct ocores_i2c *i2c) +{ + struct device *org; + int prescale; + int diff; + u8 ctrl; + + /* Temporary assignment for checking SPI Busy status. */ + org = i2c->adap.dev.parent; + i2c->adap.dev.parent = dev; + + LOCK(&cpld_access_lock); + ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); + oc_setreg(i2c, OCI2C_CONTROL, ctrl); + UNLOCK(&cpld_access_lock); + + prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1; + prescale = clamp(prescale, 0, 0xffff); + + diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz; + if (abs(diff) > i2c->bus_clock_khz / 10) { + i2c->adap.dev.parent = org; + dev_err(dev, + "Unsupported clock settings: core: %d KHz, bus: %d KHz\n", + i2c->ip_clock_khz, i2c->bus_clock_khz); + return -EINVAL; + } + + dev_info(dev, "OCI2C_PRELOW=0x%02x OCI2C_PREHIGH=0x%02x\n", + prescale & 0xff, prescale >> 8); + LOCK(&cpld_access_lock); + oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + /* Init the device */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN); + UNLOCK(&cpld_access_lock); + + i2c->adap.dev.parent = org; + + return 0; +} + + +static u32 ocores_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm ocores_algorithm = { + .master_xfer = ocores_xfer, + .master_xfer_atomic = ocores_xfer_polling, + .functionality = ocores_func, +}; + +static const struct i2c_adapter ocores_adapter = { + .owner = THIS_MODULE, + .name = "i2c-ocores", + .class = I2C_CLASS_DEPRECATED, + .algo = &ocores_algorithm, +}; + +static const struct of_device_id ocores_i2c_match[] = { + { + .compatible = "opencores,i2c-ocores", + .data = (void *)TYPE_OCORES, + }, + { + .compatible = "aeroflexgaisler,i2cmst", + .data = (void *)TYPE_GRLIB, + }, + { + .compatible = "sifive,fu540-c000-i2c", + .data = (void *)TYPE_SIFIVE_REV0, + }, + { + .compatible = "sifive,i2c0", + .data = (void *)TYPE_SIFIVE_REV0, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ocores_i2c_match); + +#ifdef CONFIG_OF +/* + * Read and write functions for the GRLIB port of the controller. Registers are + * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one + * register. The subsequent registers have their offsets decreased accordingly. + */ +static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) +{ + u32 rd; + int rreg = reg; + + if (reg != OCI2C_PRELOW) + rreg--; + rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PREHIGH) + return (u8)(rd >> 8); + else + return (u8)rd; +} + +static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value) +{ + u32 curr, wr; + int rreg = reg; + + if (reg != OCI2C_PRELOW) + rreg--; + if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { + curr = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PRELOW) + wr = (curr & 0xff00) | value; + else + wr = (((u32)value) << 8) | (curr & 0xff); + } else { + wr = value; + } + iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift)); +} + +static int ocores_i2c_of_probe(struct platform_device *pdev, + struct ocores_i2c *i2c) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + u32 val; + u32 clock_frequency; + bool clock_frequency_present; + + if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { + /* no 'reg-shift', check for deprecated 'regstep' */ + if (!of_property_read_u32(np, "regstep", &val)) { + if (!is_power_of_2(val)) { + dev_err(&pdev->dev, "invalid regstep %d\n", + val); + return -EINVAL; + } + i2c->reg_shift = ilog2(val); + dev_warn(&pdev->dev, + "regstep property deprecated, use reg-shift\n"); + } + } + + clock_frequency_present = !of_property_read_u32(np, "clock-frequency", + &clock_frequency); + i2c->bus_clock_khz = 100; + + i2c->clk = devm_clk_get(&pdev->dev, NULL); + + if (!IS_ERR(i2c->clk)) { + int ret = clk_prepare_enable(i2c->clk); + + if (ret) { + dev_err(&pdev->dev, + "clk_prepare_enable failed: %d\n", ret); + return ret; + } + i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000; + if (clock_frequency_present) + i2c->bus_clock_khz = clock_frequency / 1000; + } + + if (i2c->ip_clock_khz == 0) { + if (of_property_read_u32(np, "opencores,ip-clock-frequency", + &val)) { + if (!clock_frequency_present) { + dev_err(&pdev->dev, + "Missing required parameter 'opencores,ip-clock-frequency'\n"); + clk_disable_unprepare(i2c->clk); + return -ENODEV; + } + i2c->ip_clock_khz = clock_frequency / 1000; + dev_warn(&pdev->dev, + "Deprecated usage of the 'clock-frequency' property, please update to 'opencores,ip-clock-frequency'\n"); + } else { + i2c->ip_clock_khz = val / 1000; + if (clock_frequency_present) + i2c->bus_clock_khz = clock_frequency / 1000; + } + } + + of_property_read_u32(pdev->dev.of_node, "reg-io-width", + &i2c->reg_io_width); + + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); + if (match && (long)match->data == TYPE_GRLIB) { + dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n"); + i2c->setreg = oc_setreg_grlib; + i2c->getreg = oc_getreg_grlib; + } + + return 0; +} +#else +#define ocores_i2c_of_probe(pdev, i2c) -ENODEV +#endif + +static int ocores_i2c_probe(struct platform_device *pdev) +{ + struct ocores_i2c *i2c; + struct ocores_i2c_platform_data *pdata; + const struct of_device_id *match; + struct resource *res; + int irq; + int ret; + int i; + + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + spin_lock_init(&i2c->process_lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + i2c->base = devm_ioremap_resource(&pdev->dev, res); + dev_info(&pdev->dev, "Resouce start:0x%llx, end:0x%llx", res->start, res->end); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + } else { + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) + return -EINVAL; + i2c->iobase = res->start; + if (!devm_request_region(&pdev->dev, res->start, + resource_size(res), + pdev->name)) { + dev_err(&pdev->dev, "Can't get I/O resource.\n"); + return -EBUSY; + } + i2c->setreg = oc_setreg_io_8; + i2c->getreg = oc_getreg_io_8; + } + + pdata = dev_get_platdata(&pdev->dev); + if (pdata) { + i2c->reg_shift = pdata->reg_shift; + i2c->reg_io_width = pdata->reg_io_width; + i2c->ip_clock_khz = pdata->clock_khz; + dev_info(&pdev->dev, "Write %d KHz, ioWidth:%d, shift:%d", i2c->ip_clock_khz, pdata->reg_io_width ,pdata->reg_shift); + if (pdata->bus_khz) + i2c->bus_clock_khz = pdata->bus_khz; + else + i2c->bus_clock_khz = 100; + } else { + ret = ocores_i2c_of_probe(pdev, i2c); + if (ret) + return ret; + } + + if (i2c->reg_io_width == 0) + i2c->reg_io_width = 1; /* Set to default value */ + + if (!i2c->setreg || !i2c->getreg) { + bool be = pdata ? pdata->big_endian : + of_device_is_big_endian(pdev->dev.of_node); + + switch (i2c->reg_io_width) { + case 1: + i2c->setreg = oc_setreg_8; + i2c->getreg = oc_getreg_8; + break; + + case 2: + i2c->setreg = be ? oc_setreg_16be : oc_setreg_16; + i2c->getreg = be ? oc_getreg_16be : oc_getreg_16; + break; + + case 4: + i2c->setreg = be ? oc_setreg_32be : oc_setreg_32; + i2c->getreg = be ? oc_getreg_32be : oc_getreg_32; + break; + + default: + dev_err(&pdev->dev, "Unsupported I/O width (%d)\n", + i2c->reg_io_width); + ret = -EINVAL; + goto err_clk; + } + } + + init_waitqueue_head(&i2c->wait); + + irq = platform_get_irq_optional(pdev, 0); + if (irq == -ENXIO) { + ocores_algorithm.master_xfer = ocores_xfer_polling; + + /* + * Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for + * FU540-C000 SoC in polling mode. + */ + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); + if (match && (long)match->data == TYPE_SIFIVE_REV0) + i2c->flags |= OCORES_FLAG_BROKEN_IRQ; + } else { + if (irq < 0) + return irq; + } + + if (ocores_algorithm.master_xfer != ocores_xfer_polling) { + ret = devm_request_any_context_irq(&pdev->dev, irq, + ocores_isr, 0, + pdev->name, i2c); + if (ret) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto err_clk; + } + } + ret = ocores_init(&pdev->dev, i2c); + if (ret) { + goto err_clk; + } + /* hook up driver to tree */ + platform_set_drvdata(pdev, i2c); + i2c->adap = ocores_adapter; + i2c_set_adapdata(&i2c->adap, i2c); + i2c->adap.dev.parent = &pdev->dev; + i2c->adap.dev.of_node = pdev->dev.of_node; + + /* add i2c adapter to i2c tree */ + ret = i2c_add_adapter(&i2c->adap); + if (ret) { + goto err_clk; + } + /* add in known devices to the bus */ + if (pdata) { + for (i = 0; i < pdata->num_devices; i++){ + i2c_new_client_device(&i2c->adap, pdata->devices + i); + } + } + + return 0; + +err_clk: + clk_disable_unprepare(i2c->clk); + return ret; +} + +static int ocores_i2c_remove(struct platform_device *pdev) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + u8 ctrl; + + LOCK(&cpld_access_lock); + ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* disable i2c logic */ + ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); + oc_setreg(i2c, OCI2C_CONTROL, ctrl); + UNLOCK(&cpld_access_lock); + + /* remove adapter & data */ + i2c_del_adapter(&i2c->adap); + + if (!IS_ERR(i2c->clk)) + clk_disable_unprepare(i2c->clk); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ocores_i2c_suspend(struct device *dev) +{ + struct ocores_i2c *i2c = dev_get_drvdata(dev); + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); + oc_setreg(i2c, OCI2C_CONTROL, ctrl); + + if (!IS_ERR(i2c->clk)) + clk_disable_unprepare(i2c->clk); + return 0; +} + +static int ocores_i2c_resume(struct device *dev) +{ + struct ocores_i2c *i2c = dev_get_drvdata(dev); + + if (!IS_ERR(i2c->clk)) { + unsigned long rate; + int ret = clk_prepare_enable(i2c->clk); + + if (ret) { + dev_err(dev, + "clk_prepare_enable failed: %d\n", ret); + return ret; + } + rate = clk_get_rate(i2c->clk) / 1000; + if (rate) + i2c->ip_clock_khz = rate; + } + return ocores_init(dev, i2c); +} + +static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); +#define OCORES_I2C_PM (&ocores_i2c_pm) +#else +#define OCORES_I2C_PM NULL +#endif + +static struct platform_driver ocores_i2c_driver = { + .probe = ocores_i2c_probe, + .remove = ocores_i2c_remove, + .driver = { + .name = "ocores-i2c", + .of_match_table = ocores_i2c_match, + .pm = OCORES_I2C_PM, + }, +}; + +#if 0 +module_platform_driver(ocores_i2c_driver); +#else +static int __init ocores_i2c_as9817_64_init(void) +{ + int err; + + err = platform_driver_register(&ocores_i2c_driver); + if (err < 0) { + pr_err("Failed to register ocores_i2c_driver"); + return err; + } + + spin_lock_init(&cpld_access_lock); + + return 0; +} +static void __exit ocores_i2c_as9817_64_exit(void) +{ + platform_driver_unregister(&ocores_i2c_driver); + +} + +module_init(ocores_i2c_as9817_64_init); +module_exit(ocores_i2c_as9817_64_exit); +#endif + +MODULE_AUTHOR("Peter Korsgaard "); +MODULE_DESCRIPTION("OpenCores I2C bus driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ocores-i2c"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/service/as9817_64o-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/service/as9817_64o-platform-init.service new file mode 100644 index 000000000000..87b5353e9524 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/service/as9817_64o-platform-init.service @@ -0,0 +1,15 @@ +[Unit] +Description=Accton AS9817-64O Platform Initialization Service +Before=pmon.service determine-reboot-cause.service system-health.service +DefaultDependencies=no + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/bin/accton_as9817_64o_util.py install + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/service/as9817_64o-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/service/as9817_64o-platform-monitor.service new file mode 100644 index 000000000000..18d1d4601a83 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/service/as9817_64o-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS9817-64O Platform Monitoring service +Before=pmon.service +After=as9817_64o-platform-init.service +Requires=as9817_64o-platform-init.service + +[Service] +ExecStart=/usr/local/bin/accton_as9817_64_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/setup.py new file mode 100755 index 000000000000..191c73043c29 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='as9817_64o', + version='1.0', + description='Module to initialize Accton AS9817-64O platforms', + + packages=['as9817_64o'], + package_dir={'as9817_64o': 'as9817-64o/classes'}, +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/sonic_platform_setup.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/sonic_platform_setup.py new file mode 100644 index 000000000000..e64ec24197e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/sonic_platform_setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +DEVICE_NAME = 'accton' +HW_SKU = 'x86_64-accton_as9817_64o-r0' + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Accton Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Roger Ho', + maintainer_email='roger530_ho@edge-core.com', + packages=[ + 'sonic_platform', + ], + package_dir={ + 'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)}, + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Plugins', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/utils/accton_as9817_64_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/utils/accton_as9817_64_monitor.py new file mode 100755 index 000000000000..d32917e6e397 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/utils/accton_as9817_64_monitor.py @@ -0,0 +1,567 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -* +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 3/01/2024:Roger create for as9817_64 thermal plan +# ------------------------------------------------------------------ + +try: + import os + import sys + import getopt + import logging + import logging.config + import logging.handlers + import signal + import time + import re + from sonic_platform import platform + from swsscommon import swsscommon + from sonic_py_common.general import getstatusoutput_noshell +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +''' +1. +Idle mode: +CPU_temp <60 AND MAC_temp <60 AND no transceiver_temp (present) +Then +Fan duty to 30% (0x4) +Else +Fan duty to 60% (0x9) + +2. +CPU_temp >85 OR MAC_temp >90 OR transceiver_temp>75 +Then +Fan duty 60% to 100% (0x15) + +3. +CPU_temp <75℃ and MAC_temp <80℃ and transceiver_temp<65 +Then +Fan duty 100% to 60% (0x15) + +4. +OTP: +CPU_temp >100℃ OR MAC_temp >105℃ +a. reset all fron port +b. call ipmitool to reboot let BMC handle shutdown (1. MAC reset, 2. PSU power off) +''' + + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as9817_64_monitor' + +STATE_DB = 'STATE_DB' +TRANSCEIVER_DOM_SENSOR_TABLE = 'TRANSCEIVER_DOM_SENSOR' +TEMPERATURE_FIELD_NAME = 'temperature' +TYPE_SENSOR = 'sensors' +TYPE_TRANSCEIVER = 'sfp' +CPU_TEMPERATURE_NAME = "CPU_Package_temp" +MAC_TEMPERATURE_NAME = "MAC" + +FAN_DUTY_CYCLE_MAX = 100 +FAN_DUTY_CYCLE_DEFAULT = 60 +MONITOR_INTERVAL = 30 +TRANSCEIVER_NUM_MAX = 64 +THERMAL_NUM_MAX = 2 # cpu_temp + mac_temp + +test_temp_list = [] +exit_by_sigterm = 0 + +LEVEL_FAN_INIT = 0 +LEVEL_FAN_MIN = 1 +LEVEL_FAN_MID = 2 +LEVEL_FAN_MAX = 3 +LEVEL_FAN_OTP = 4 +LEVEL_FAN_SHUTDOWN = 6 + +# fan_state_dict: A dictionary mapping fan operation levels to descriptive string names. +# These levels correspond to various fan speed policies and potential actions based on temperature readings. +fan_state_dict = { + LEVEL_FAN_INIT: 'level_fan_init', # Initial state before any temperature checks. + LEVEL_FAN_MIN: 'level_fan_min', # State for minimum fan speed. + LEVEL_FAN_MID: 'level_fan_mid', # State for medium fan speed. + LEVEL_FAN_MAX: 'level_fan_max', # State for maximum fan speed. + LEVEL_FAN_OTP: 'level_fan_otp' # State for Over Temperature Protection (OTP) action. +} + +# FAN_POLICY: A dictionary mapping fan states to tuples containing the fan duty cycle percentage and a hex value. +# The duty cycle percentage dictates the speed of the fans. +FAN_POLICY = { + LEVEL_FAN_INIT: [30, 0x4], # Initial fan speed set to 30%. + LEVEL_FAN_MIN: [30, 0x4], # Minimum fan speed set to 30%. + LEVEL_FAN_MID: [60, 0x9], # Medium fan speed set to 60%. + LEVEL_FAN_MAX: [100, 0xf] # Maximum fan speed set to 100%. +} + + + +# fan_thermal_spec: A dictionary defining temperature thresholds for various fan speed policies. +# Each key represents a state transition with a list of tuples. +# The tuples contain the sensor type (either 'sensors' for CPU/MAC or 'sfp' for transceivers), +# and the temperature threshold in millidegrees Celsius for that transition. +# For example, "min_to_mid_temp" defines the transition from minimum to medium fan speed state, +# with separate thresholds for CPU, MAC, and each transceiver. +fan_thermal_spec={ + "min_to_mid_temp":[(TYPE_SENSOR,60000), (TYPE_SENSOR,60000)], + "mid_to_max_temp":[(TYPE_SENSOR,85000), (TYPE_SENSOR,90000)], + "max_to_otp_temp":[(TYPE_SENSOR,100000), (TYPE_SENSOR,105000)], + "max_to_mid_temp":[(TYPE_SENSOR,75000), (TYPE_SENSOR,80000)] +} +fan_thermal_spec["min_to_mid_temp"] += [(TYPE_TRANSCEIVER, 75000)] * TRANSCEIVER_NUM_MAX +fan_thermal_spec["mid_to_max_temp"] += [(TYPE_TRANSCEIVER, 75000)] * TRANSCEIVER_NUM_MAX +fan_thermal_spec["max_to_otp_temp"] += [(TYPE_TRANSCEIVER, 75000)] * TRANSCEIVER_NUM_MAX +fan_thermal_spec["max_to_mid_temp"] += [(TYPE_TRANSCEIVER, 65000)] * TRANSCEIVER_NUM_MAX + +DEBUG = False + +class device_monitor(object): + def __init__(self, log_file, log_level, test_temp = 0): + """ + Initializes the device monitor with logging and platform setup. + Parameters: + - log_file: The file path for logging output. + - log_level: The logging level to control output verbosity. + - test_temp: Indicator for test mode with mock temperature data. + Sets up logging, initializes platform chassis, fans, and SFPs, + and sets initial fan speed. + """ + self.platform_chassis = platform.Platform().get_chassis() + self.thermals = self.platform_chassis.get_all_thermals() + self.fans = self.platform_chassis.get_all_fans() + self.sfps = self.platform_chassis.get_all_sfps() + self.test_temp = test_temp + self.test_temp_revert = 0 + self.temp_test_data = 0 + self.temp_sfp_test_data = 0 + """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('%(asctime)s %(name)-12s: %(levelname)-8s %(message)s', datefmt='%H:%M:%S') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + self.sensors_thermal_val = [(TYPE_SENSOR, 0.0 , "", False)] * THERMAL_NUM_MAX + self.sfps_thermal_val = [(TYPE_TRANSCEIVER, 0.0, "", False)] * TRANSCEIVER_NUM_MAX + self.sfp_presences = 0 + self.transceiver_dom_sensor_tbl = None + self.transceiver_status_tbl = None + self.fan_policy_state = LEVEL_FAN_INIT + self.set_fan_speed(FAN_DUTY_CYCLE_DEFAULT) + + def power_off_dut(self): + """ + Executes commands to safely power off the device + in case of critical temperatures. + Ensures data integrity by syncing filesystem and trims SSDs before shutdown. + In test mode, it logs the intended power-off action without executing. + """ + # Sync log buffer to disk + cmd_str = "sync" + status, output = getstatusoutput_noshell(cmd_str.split()) + cmd_str = "/sbin/fstrim -av" + status, output = getstatusoutput_noshell(cmd_str.split()) + time.sleep(3) + + if self.test_temp: + logging.debug("Test Mode: Power Off Dut......") + return True + + # RESET BRCM MAC and POWER OFF + cmd_str = "ipmitool raw 0x34 0x94 3" + status, output = getstatusoutput_noshell(cmd_str.split()) + if status != 0: + logging.warning(output) + + return True + + def reset_front_port_all(self): + """ + Resets all front ports of the device. + In test mode, logs the action of resetting all transceivers without executing. + """ + if self.test_temp: + logging.debug("Test Mode: Set All Transceiver in RESET state......") + return True + + for port_index in range(TRANSCEIVER_NUM_MAX): + cmd_str = "echo 1 > /sys/devices/platform/as9817_64_fpga/module_reset_{}".format(port_index + 1) + status, output = getstatusoutput_noshell(cmd_str.split()) + + return True + + def enable_lpmode_front_port_all(self): + """ + Enables low power mode for all front ports (transceivers) of the device. + In test mode, logs the action of setting all transceivers to + low power mode without executing. + """ + if self.test_temp: + logging.debug("Test Mode: Set All Transceiver in LP Mode......") + return True + + for sfp in self.sfps: + if sfp.port_num > TRANSCEIVER_NUM_MAX: + continue + if sfp.get_presence(): + sfp.set_lpmode(True) + + return True + + def set_fan_speed(self, pwm): + """ + Sets the fan speed based on the PWM duty cycle value. + Parameters: + - pwm: The PWM duty cycle value (0-100) to set the fan speed. + Validates PWM value and applies it to all fans. Logs any errors or warnings. + """ + if pwm < 0 or pwm > 100: + logging.warning(("Error: Wrong duty cycle value %d" % (pwm))) + print(("Error: Wrong duty cycle value %d" % (pwm))) + return False + + logging.debug("Set FAN speed to {}".format(pwm)) + for fan in self.fans: + fan.set_speed(pwm) + time.sleep(1) + return True + + def get_cpu_temperature(self): + """ + Retrieves the CPU temperature from the thermal sensors. + Returns a tuple, ex : (sensor type, temperature in millidegrees + Celsius, sensor name, presence status). + """ + for thermal in self.thermals: + if CPU_TEMPERATURE_NAME in thermal.get_name(): + return (TYPE_SENSOR, thermal.get_temperature() * 1000.0, CPU_TEMPERATURE_NAME, True) + + return (TYPE_SENSOR, 0.0, CPU_TEMPERATURE_NAME, True) + + #bcmcmd 'show temp'|grep 'Average current temperature is' + def get_mac_temperature(self): + """ + Retrieves the MAC temperature using system commands. + Parses the command output to extract the temperature value. + Returns a tuple, ex : (sensor type, temperature in millidegrees + Celsius, sensor name, presence status). + """ + cmd = ['bcmcmd', 'show temp'] + status, output = getstatusoutput_noshell(cmd) + + if status == 0: + res_list = re.findall('Average current temperature is\s*(.+?)\n', output) + if res_list: + return (TYPE_SENSOR, float(res_list[0]) * 1000.0, MAC_TEMPERATURE_NAME, True) + logging.warning("Warning: Failed to read the MAC temperature") + return (TYPE_SENSOR, 0.0, MAC_TEMPERATURE_NAME, True) + + def get_transceiver_temperature(self, iface_name): + """ + Fetches the temperature of a specified transceiver using the STATE_DB. + Parameters: + - iface_name: The interface name of the transceiver. + Returns the temperature in degrees Celsius as a float. + """ + if self.transceiver_dom_sensor_tbl is None: + try: + state_db = swsscommon.DBConnector(STATE_DB, 0, False) + self.transceiver_dom_sensor_tbl = swsscommon.Table(state_db, TRANSCEIVER_DOM_SENSOR_TABLE) + except Exception as e: + logging.debug("{}".format(e)) + return 0.0 + + try: + (status, ret) = self.transceiver_dom_sensor_tbl.hget(iface_name, TEMPERATURE_FIELD_NAME) + if status: + return float(ret) + except (TypeError, ValueError): + pass + + return 0.0 + + def collect_temperature(self): + """ + Collects temperatures from CPU, MAC, and all transceivers. + In test mode, uses mock temperatures. Handles temperature collection + and presence detection for SFP modules. + """ + global test_temp_list + + if self.test_temp: + if self.test_temp_revert == 0: + self.temp_test_data += 2000 + self.temp_sfp_test_data += 2000 + else: + self.temp_test_data = self.temp_test_data - 2000 + self.temp_sfp_test_data = self.temp_sfp_test_data - 2000 + logging.debug('temp_test_data=%d temp_sfp_test_data=%d', + self.temp_test_data, self.temp_sfp_test_data) + + for i in range (THERMAL_NUM_MAX): + tmp = list(self.sensors_thermal_val[i]) + tmp[1] = test_temp_list[i] + self.temp_test_data + if i == 0: + tmp[2] = CPU_TEMPERATURE_NAME + elif i == 1: + tmp[2] = MAC_TEMPERATURE_NAME + self.sensors_thermal_val[i] = tuple(tmp) + + self.sfp_presences = 0 + for sfp in self.sfps: + if sfp.port_num > TRANSCEIVER_NUM_MAX: + continue + tmp = list(self.sfps_thermal_val[sfp.port_num - 1]) + tmp[2] = sfp.get_name() + if sfp.get_presence(): + tmp[1] = test_temp_list[-1] + self.temp_sfp_test_data + tmp[3] = True + self.sfp_presences += 1 + self.sfps_thermal_val[sfp.port_num - 1] = tuple(tmp) + else: + self.sensors_thermal_val[0] = self.get_cpu_temperature() #CPU core temp + self.sensors_thermal_val[1] = self.get_mac_temperature() #MAC average temp + self.sfp_presences = 0 + for sfp in self.sfps: + if sfp.port_num > TRANSCEIVER_NUM_MAX: + continue + tmp = [TYPE_TRANSCEIVER, 0.0 , sfp.get_name(), False] + if sfp.get_presence(): + tmp[1] = self.get_transceiver_temperature(sfp.get_name()) * 1000.0 + tmp[3] = True + self.sfp_presences += 1 + self.sfps_thermal_val[sfp.port_num - 1] = tuple(tmp) + + def manage_fans(self): + """ + Analyzes collected temperature data and manages fan speeds accordingly. + + Implements a state machine based on temperature thresholds to adjust + fan speeds or take emergency actions.Updates fan speeds based on + thermal policies and logs any changes or critical conditions. + """ + if self.fan_policy_state == LEVEL_FAN_INIT: + self.fan_policy_state = LEVEL_FAN_MID #This is default state + logging.debug("fan_policy_state=LEVEL_FAN_MID at default") + return + + # Collect current temperature data from all relevant sensors and transceivers. + self.collect_temperature() + + # Keep track of the original fan policy state to detect any changes. + ori_state = self.fan_policy_state + current_state = self.fan_policy_state + max_to_mid = 0 + mid_to_min = 0 + + # Variables to track the original and new duty cycles for fan speed, and fan failures. + ori_duty_cycle = 0 + new_duty_cycle = 0 + fan_fail_list = [] + + # Check fan status and determine the highest duty cycle among all fans. + for fan in self.fans: + if not fan.get_presence() or not fan.get_status() or not fan.get_speed(): + fan_fail_list.append(fan.get_name()) + else: + ori_duty_cycle = max(ori_duty_cycle, fan.get_speed()) + logging.debug('Current Fan speed = %d%%', ori_duty_cycle) + + # Aggregate all temperature readings for analysis. + thermal_val = self.sensors_thermal_val + self.sfps_thermal_val + logging.debug('self.sfp_presences=%d', self.sfp_presences) + logging.debug(f'thermal_val={ thermal_val}') + + # Analyze temperature data and adjust fan policy state based on predefined thresholds. + for i in range (THERMAL_NUM_MAX + TRANSCEIVER_NUM_MAX): + (temp_type, current_temp, name, presence) = thermal_val[i] + + # Skip non-present transceivers. + if temp_type == TYPE_TRANSCEIVER: + if presence == False: + continue + + # Determine if conditions require changing the fan speed from min to mid, mid to max, or max to critical. + if ori_state == LEVEL_FAN_MIN: + if current_temp >= fan_thermal_spec["min_to_mid_temp"][i][1]: + current_state = LEVEL_FAN_MID + logging.debug('%s current_temp=%d > fan_thermal_spec[min_to_mid_temp][%d][1]=%d', + name, current_temp, i, fan_thermal_spec["min_to_mid_temp"][i][1] ) + logging.debug("current_state=LEVEL_FAN_MID") + break + elif ori_state == LEVEL_FAN_MID: + if current_temp >= fan_thermal_spec["mid_to_max_temp"][i][1]: + current_state = LEVEL_FAN_MAX + logging.warning('- Monitor %s, temperature is %.1f. Temperature is over %.1f.', + name, current_temp / 1000.0, + fan_thermal_spec["mid_to_max_temp"][i][1] / 1000.0) + logging.debug('%s current_temp=%d > fan_thermal_spec[mid_to_max_temp][%d][1]=%d', + name, current_temp, i, fan_thermal_spec["mid_to_max_temp"][i][1]) + logging.debug("current_state=LEVEL_FAN_MAX") + break + else: + if temp_type == TYPE_SENSOR and current_temp < fan_thermal_spec["min_to_mid_temp"][i][1]: + mid_to_min += 1 + logging.debug("ori_state == LEVEL_FAN_MID, mid_to_min=%d", mid_to_min) + elif ori_state == LEVEL_FAN_MAX: + if current_temp >= fan_thermal_spec["max_to_otp_temp"][i][1]: + if temp_type == TYPE_SENSOR: + # Critical temperature condition met, initiate shutdown procedure. + logging.critical('Alarm-Critical for temperature high is detected, shutdown DUT') + # self.reset_front_port_all() + self.enable_lpmode_front_port_all() + self.power_off_dut() + if self.test_temp and self.test_temp_revert == 0: + self.test_temp_revert = 1 + elif temp_type == TYPE_TRANSCEIVER: + logging.warning('- Monitor %s, temperature is %.1f. Temperature is over %.1f.', + name, current_temp / 1000.0, + fan_thermal_spec["max_to_otp_temp"][i][1] / 1000.0) + else: + if current_temp < fan_thermal_spec["max_to_mid_temp"][i][1]: + logging.debug('%s current_temp=%d < fan_thermal_spec[max_to_mid_temp][%d][1]=%d', + name, current_temp, i, fan_thermal_spec["max_to_mid_temp"][i][1] ) + max_to_mid += 1 + + # Adjust fan state if conditions are met for transitioning between states. + if mid_to_min == THERMAL_NUM_MAX and self.sfp_presences == 0: + current_state = LEVEL_FAN_MIN + if self.test_temp and self.test_temp_revert: + self.test_temp_revert = 0 + logging.debug('self.sfp_presences=0, set to LEVEL_FAN_MIN') + + if max_to_mid == (THERMAL_NUM_MAX + self.sfp_presences): + current_state = LEVEL_FAN_MID + + # Update fan policy state and apply new fan speed based on the state. + if current_state != ori_state: + self.fan_policy_state = current_state + if current_state == LEVEL_FAN_MAX: + logging.warning('Alarm for temperature high, set duty_cycle to 100%') + + logging.debug("current_state=%s, ori_state=%s, fan_fail_list=%s sfp_presences=%d mid_to_min=%d max_to_mid=%d", + fan_state_dict[current_state], fan_state_dict[ori_state], + fan_fail_list, self.sfp_presences, mid_to_min, max_to_mid) + + # Set the fan speed to the maximum if any fan has failed, otherwise adjust according to the policy state. + if len(fan_fail_list) == 0: + new_duty_cycle = FAN_POLICY[current_state][0] + else: + new_duty_cycle = FAN_DUTY_CYCLE_MAX + for fan in fan_fail_list: + logging.warning('%s has failed, so set the duty_cycle to 100%%', fan) + + if new_duty_cycle != ori_duty_cycle: + self.set_fan_speed(new_duty_cycle) + + logging.debug("fan_policy_state=%s, new_duty_cycle=%d%% fan_fail_list=%s", + fan_state_dict[current_state], new_duty_cycle, fan_fail_list) + + return True + +def signal_handler(sig, frame): + """ + Handles signal interrupts (e.g., SIGTERM) to gracefully exit the monitoring loop. + Parameters: + - sig: The signal number. + - frame: The current stack frame. + Sets a flag to indicate the monitoring loop should exit. + """ + global exit_by_sigterm + + if sig == signal.SIGTERM: + print("Caught SIGTERM - exiting...") + exit_by_sigterm = 1 + else: + pass + +def main(argv): + """ + The main entry point for the device monitor script. + Parses command-line arguments for logging level and test mode options. + Initializes and runs the device monitor in a loop until a SIGTERM signal is received. + Parameters: + - argv: Command-line arguments passed to the script. + """ + global test_temp, test_temp_list + global exit_by_sigterm + + if os.geteuid() != 0: + print("Error: Root privileges are required") + sys.exit(1) + + signal.signal(signal.SIGTERM, signal_handler) + + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + + test_temp = 0 + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + for opt, arg in opts: + if opt == '-h': + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + print("Test mode") + if len(sys.argv) < 5: + print("temp test, need input 3 temp") + return 0 + i=0 + for x in range(2, 5): + test_temp_list.append(int(sys.argv[x]) * 1000.0) + i=i+1 + + test_temp = 1 + log_level = logging.DEBUG + print(test_temp_list) + + monitor = device_monitor(log_file, log_level, test_temp) + while True: + monitor.manage_fans() + time.sleep(MONITOR_INTERVAL) + if exit_by_sigterm == 1: + break + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9817-64o/utils/accton_as9817_64o_util.py b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/utils/accton_as9817_64o_util.py new file mode 100755 index 000000000000..91598ef0e5b8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9817-64o/utils/accton_as9817_64o_util.py @@ -0,0 +1,664 @@ +#!/usr/bin/env python3 +# +# 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: accton_as9817_64o_util.py [-h] [-d] [-f] {install,clean,threshold} ... + +AS9817-64O Platform Utility + +optional arguments: + -h, --help show this help message and exit + -d, --debug run with debug mode + -f, --force ignore error during installation or clean + +Utility Command: + {install,clean,threshold} + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + threshold : modify thermal threshold +""" +import subprocess +import sys +import logging +import re +import time +import os +import glob +import argparse +from sonic_py_common.general import getstatusoutput_noshell + + +PROJECT_NAME = 'as9817_64o' +version = '0.1.0' +verbose = False +DEBUG = False +FAN_PWM = 67 +args = [] +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 + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + util_parser = argparse.ArgumentParser(description="AS9817-64O Platform Utility") + util_parser.add_argument("-d", "--debug", dest='debug', action='store_true', default=False, + help="run with debug mode") + util_parser.add_argument("-f", "--force", dest='force', action='store_true', default=False, + help="ignore error during installation or clean") + subcommand = util_parser.add_subparsers(dest='cmd', title='Utility Command', required=True) + subcommand.add_parser('install', help=': install drivers and generate related sysfs nodes') + subcommand.add_parser('clean', help=': uninstall drivers and remove related sysfs nodes') + threshold_parser = subcommand.add_parser('threshold', help=': modify thermal threshold') + threshold_parser.add_argument("-l", dest='list', action='store_true', default=False, + help="list avaliable thermal") + threshold_parser.add_argument("-t", dest='thermal', type=str, metavar='THERMAL_NAME', + help="thermal name, ex: -t 'Temp sensor 1'") + threshold_parser.add_argument("-ht", dest='high_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high threshold: %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + threshold_parser.add_argument("-hct", dest='high_crit_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high critical threshold : %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + args = util_parser.parse_args() + + if DEBUG == True: + print(args) + print(len(sys.argv)) + + DEBUG = args.debug + #FORCE = 1 if args.force else 0 + FORCE = 1 + + if args.cmd == 'install': + do_install() + elif args.cmd == 'clean': + do_uninstall() + elif args.cmd == 'threshold': + do_threshold() + + return 0 + +def show_help(): + print(__doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}) + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print("[DEBUG]"+txt) + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = subprocess.getstatusoutput(cmd) + #status, output = getstatusoutput_noshell(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("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +ipmi_ko = [ + 'modprobe ipmi_msghandler', + 'modprobe ipmi_ssif', + 'modprobe ipmi_si', + 'modprobe ipmi_devintf'] + +ATTEMPTS = 5 +INTERVAL = 3 + +def init_ipmi_dev_intf(): + attempts = ATTEMPTS + interval = INTERVAL + + while attempts: + for i in range(0, len(ipmi_ko)): + subprocess.getstatusoutput(ipmi_ko[i]) + + if os.path.exists('/dev/ipmi0') or os.path.exists('/dev/ipmidev/0'): + return (0, (ATTEMPTS - attempts) * interval) + + for i in reversed(range(0, len(ipmi_ko))): + rm = ipmi_ko[i].replace("modprobe", "modprobe -rq") + subprocess.getstatusoutput(rm) + + attempts -= 1 + time.sleep(interval) + + return (1, ATTEMPTS * interval) + +def init_ipmi_oem_cmd(): + attempts = ATTEMPTS + interval = INTERVAL + + while attempts: + status, output = subprocess.getstatusoutput('ipmitool raw 0x34 0x95') + if status: + attempts -= 1 + time.sleep(interval) + continue + + return (0, (ATTEMPTS - attempts) * interval) + + return (1, ATTEMPTS * interval) + +def init_ipmi(): + attempts = ATTEMPTS + interval = 60 + + while attempts: + attempts -= 1 + + (status, elapsed_dev) = init_ipmi_dev_intf() + if status: + time.sleep(max(0, interval - elapsed_dev)) + continue + + (status, elapsed_oem) = init_ipmi_oem_cmd() + if status: + time.sleep(max(0, interval - elapsed_dev - elapsed_oem)) + continue + + print('IPMI dev interface is ready.') + return 0 + + print('Failed to initialize IPMI dev interface') + return 1 + + +kos = [ + 'modprobe i2c_dev', + 'modprobe i2c_i801', + 'modprobe i2c_ismt', + 'modprobe optoe', + 'modprobe at24', + 'modprobe i2c-ocores', + 'modprobe accton_as9817_64_fpga', + 'modprobe accton_as9817_64_fan', + 'modprobe accton_as9817_64_psu', + 'modprobe accton_as9817_64_thermal', + 'modprobe accton_as9817_64_sys', + 'modprobe accton_as9817_64_leds' +] + +#EERPOM +eeprom_mknod =[ + 'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + +def eeprom_check(): + cmd = ["i2cget", "-f", "-y", "0", "0x56"] + status, output = getstatusoutput_noshell(cmd) + return status + +def driver_install(): + global FORCE + + # Load 10G ethernet driver + status, output = log_os_system("modprobe ice", 1) + if status: + if FORCE == 0: + return status + + status = init_ipmi() + if status: + if FORCE == 0: + return status + + status, output = log_os_system("depmod -ae", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + print("Done driver_install") + + return 0 + +def driver_uninstall(): + global FORCE + + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [ + 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, + 18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33, + 34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49, + 50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65, + 66,67 +] + +osfp_start = 0 +osfp_end = 63 + +mknod =[ + +] + +mkfile = [ + '/tmp/device_threshold.json', + '/tmp/device_threshold.json.lock' +] + +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 + + # Select I2C relay channel to MB_EEPROM + log_os_system("i2cset -f -a -y 0 0x78 0x00 0x01", 1) + time.sleep(0.2) + + ret=eeprom_check() + if ret==0: + log_os_system(eeprom_mknod[0], 1) + time.sleep(0.2) + exists = os.path.isfile('/sys/bus/i2c/devices/0-0056/eeprom') + if (exists is False): + subprocess.call('echo 0x56 > /sys/bus/i2c/devices/i2c-1/delete_device', shell=True) + + for i in range(0,len(sfp_map)): + if i > osfp_end: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe3 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print(output) + if FORCE == 0: + return status + + # Release RESET pin for all OSFP. + for i in range(0, (osfp_end + 1)): + status, output = log_os_system("echo 0 > /sys/devices/platform/as9817_64_fpga/module_reset_{}".format(i + 1), 1) + if status: + print(output) + + # Disable Low Power Mode for all OSFP. + for i in range(0, (osfp_end + 1)): + status, output = log_os_system("echo 0 > /sys/devices/platform/as9817_64_fpga/module_lp_mode_{}".format(i + 1), 1) + if status: + print(output) + + # Prevent permission issues between root or admin users for sonic_platform/helper.py + for i in range(0,len(mkfile)): + try: + # Create empty file + open(mkfile[i], 'a').close() + os.chmod(mkfile[i], 0o644) + except OSError: + print('Failed : creating the file %s.' % (mkfile[i])) + os.chmod(mkfile[i], 0o644) + if FORCE == 0: + return -1 + + print("Done device_install") + return + +def device_uninstall(): + global FORCE + + 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 + + for i in range(len(mknod)): + target = mknod[-(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 + + # Deal with for del 0x56 sysfs device + exists = os.path.isfile('/sys/bus/i2c/devices/0-0056/eeprom') + if (exists is True): + target = eeprom_mknod[0] #0x56 + + 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 + + for i in range(0,len(mkfile)): + status, output = log_os_system('rm -f ' + mkfile[i], 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 + +PLATFORM_ROOT_PATH = '/usr/share/sonic/device' +PLATFORM_API2_WHL_FILE_PY3 ='sonic_platform-1.0-py3-none-any.whl' +def do_sonic_platform_install(): + device_path = "{}{}{}{}".format(PLATFORM_ROOT_PATH, '/x86_64-accton_', PROJECT_NAME, '-r0') + SONIC_PLATFORM_BSP_WHL_PKG_PY3 = "/".join([device_path, PLATFORM_API2_WHL_FILE_PY3]) + + #Check API2.0 on py whl file + status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0) + if status: + if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_PY3): + status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG_PY3, 1) + if status: + print("Error: Failed to install {}".format(PLATFORM_API2_WHL_FILE_PY3)) + return status + else: + print("Successfully installed {} package".format(PLATFORM_API2_WHL_FILE_PY3)) + else: + print('{} is not found'.format(PLATFORM_API2_WHL_FILE_PY3)) + else: + print('{} has installed'.format(PLATFORM_API2_WHL_FILE_PY3)) + + return + +def do_sonic_platform_clean(): + status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0) + if status: + print('{} does not install, not need to uninstall'.format(PLATFORM_API2_WHL_FILE_PY3)) + + else: + status, output = log_os_system("pip3 uninstall sonic-platform -y", 0) + if status: + print('Error: Failed to uninstall {}'.format(PLATFORM_API2_WHL_FILE_PY3)) + return status + else: + print('{} is uninstalled'.format(PLATFORM_API2_WHL_FILE_PY3)) + + return + +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....") + + # Turn off LOC LED if needed + log_os_system("echo 0 > /sys/devices/platform/as9817_64_led/led_loc", 1) + + # Chnage all fan_pwm to 67% + for filename in glob.glob("/sys/devices/platform/as9817_64_fan/hwmon/*/fan*_pwm"): + try: + with open(filename, 'w') as fd: + fd.write(str(FAN_PWM)) + except IOError as e: + pass + + do_sonic_platform_install() + + 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 + + do_sonic_platform_clean() + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +THRESHOLD_RANGE_LOW = 30.0 +THRESHOLD_RANGE_HIGH = 110.0 +# Code to initialize chassis object +init_chassis_code = \ + "import sonic_platform.platform\n"\ + "platform = sonic_platform.platform.Platform()\n"\ + "chassis = platform.get_chassis()\n\n" + +# Looking for thermal +looking_for_thermal_code = \ + "thermal = None\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " if '{}' == tmp.get_name():\n"\ + " thermal = tmp\n"\ + " break\n"\ + "if thermal == None:\n"\ + " print('{} not found!')\n"\ + " exit(1)\n\n" + +def avaliable_thermals(): + global init_chassis_code + + get_all_thermal_name_code = \ + "thermal_list = []\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " thermal_list.append(tmp.get_name())\n"\ + "print(str(thermal_list)[1:-1])\n" + + all_code = "{}{}".format(init_chassis_code, get_all_thermal_name_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status != 0: + return "" + return output + +def restricted_float(x): + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + try: + x = float(x) + except ValueError: + raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,)) + + if x < THRESHOLD_RANGE_LOW or x > THRESHOLD_RANGE_HIGH: + raise argparse.ArgumentTypeError("%r not in range [%.1f ~ %.1f]" % + (x, THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + + return x + +def get_high_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def get_high_crit_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_crit_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_critical_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_critical_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_crit_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def do_threshold(): + global args, init_chassis_code, looking_for_thermal_code + + if args.list: + print("Thermals: " + avaliable_thermals()) + return + + if args.thermal is None: + print("The following arguments are required: -t") + return + + set_threshold_code = "" + if args.high_threshold is not None: + if args.high_crit_threshold is not None and \ + args.high_threshold >= args.high_crit_threshold: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + high_crit = get_high_crit_threshold(args.thermal) + if high_crit is not None and \ + args.high_threshold >= high_crit: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_threshold({}) is False:\n"\ + " print('{}: set_high_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_threshold method!')\n"\ + "print('Apply the new high threshold successfully.')\n"\ + "\n".format(args.high_threshold, args.thermal) + + if args.high_crit_threshold is not None: + high = get_high_threshold(args.thermal) + if high is not None and \ + args.high_crit_threshold <= high: + print("Invalid Threshold!(High critical threshold can not " \ + "be less than or equal to high threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_critical_threshold({}) is False:\n"\ + " print('{}: set_high_critical_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_critical_threshold method!')\n"\ + "print('Apply the new high critical threshold successfully.')\n"\ + "\n".format(args.high_crit_threshold, args.thermal) + + if set_threshold_code == "": + return + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(args.thermal, args.thermal), set_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + print(output) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control index 4410a2f07796..0a9d471806d2 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -84,3 +84,11 @@ 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 + +Package: sonic-platform-accton-as9817-64o +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as9817-64d +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 6d9c78bcb13c..01f843012414 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -22,6 +22,7 @@ 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 as4630-54te minipack as5812-54x MODULE_DIRS += as5835-54x as9716-32d as9726-32d as5835-54t as7312-54xs as7315-27xb as5812-54t +MODULE_DIRS += as9817-64o as9817-64d MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9817-64d.install b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9817-64d.install new file mode 100644 index 000000000000..9a19e5b52d86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9817-64d.install @@ -0,0 +1 @@ +as9817-64d/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-accton_as9817_64d-r0 diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9817-64o.install b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9817-64o.install new file mode 100644 index 000000000000..5e21e630668f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9817-64o.install @@ -0,0 +1 @@ +as9817-64o/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-accton_as9817_64o-r0