diff --git a/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/buffers.json.j2 b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/buffers.json.j2 new file mode 100644 index 000000000000..4414774dd6d7 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/buffers.json.j2 @@ -0,0 +1,17 @@ +{ + "BUFFER_POOL": { + "ingress_lossy_pool": { + "size": "62490096", + "type": "ingress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool": "ingress_lossy_pool", + "size": "0", + "dynamic_th": "3" + } + } +} diff --git a/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/hwsku.json b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/hwsku.json new file mode 100644 index 000000000000..5d50b353b033 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/hwsku.json @@ -0,0 +1,268 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet8": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet16": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet24": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet32": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet40": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet48": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet56": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet64": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet72": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet80": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet88": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet96": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet104": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet112": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet120": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet128": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet136": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet144": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet152": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet160": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet168": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet176": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet184": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet192": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet200": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet208": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet216": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet224": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet232": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet240": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet248": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet256": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet264": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet272": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet280": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet288": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet296": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet304": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet312": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet320": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet328": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet336": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet344": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet352": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet360": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet368": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet376": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet384": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet392": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet400": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet408": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet416": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet424": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet432": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet440": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet448": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet456": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet464": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet472": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet480": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet488": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet496": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet504": { + "default_brkout_mode": "1x400G" + }, + + "Ethernet512": { + "default_brkout_mode": "1x10G[1G]" + }, + + "Ethernet513": { + "default_brkout_mode": "1x10G[1G]" + } + } +} + diff --git a/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/port_config.ini b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/port_config.ini new file mode 100644 index 000000000000..5907dc49d9db --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 130,131,132,133,134,135,136,137 Eth1(Port1) 1 400000 +Ethernet8 138,139,140,141,142,143,144,145 Eth2(Port2) 2 400000 +Ethernet16 146,147,148,149,150,151,152,153 Eth3(Port3) 3 400000 +Ethernet24 154,155,156,157,158,159,160,161 Eth4(Port4) 4 400000 +Ethernet32 162,163,164,165,166,167,168,169 Eth5(Port5) 5 400000 +Ethernet40 170,171,172,173,174,175,176,177 Eth6(Port6) 6 400000 +Ethernet48 178,179,180,181,182,183,184,185 Eth7(Port7) 7 400000 +Ethernet56 186,187,188,189,190,191,192,193 Eth8(Port8) 8 400000 +Ethernet64 194,195,196,197,198,199,200,201 Eth9(Port9) 9 400000 +Ethernet72 202,203,204,205,206,207,208,209 Eth10(Port10) 10 400000 +Ethernet80 250,251,252,253,254,255,256,257 Eth11(Port11) 11 400000 +Ethernet88 242,243,244,245,246,247,248,249 Eth12(Port12) 12 400000 +Ethernet96 226,227,228,229,230,231,232,233 Eth13(Port13) 13 400000 +Ethernet104 234,235,236,237,238,239,240,241 Eth14(Port14) 14 400000 +Ethernet112 218,219,220,221,222,223,224,225 Eth15(Port15) 15 400000 +Ethernet120 210,211,212,213,214,215,216,217 Eth16(Port16) 16 400000 +Ethernet128 290,291,292,293,294,295,296,297 Eth17(Port17) 17 400000 +Ethernet136 298,299,300,301,302,303,304,305 Eth18(Port18) 18 400000 +Ethernet144 282,283,284,285,286,287,288,289 Eth19(Port19) 19 400000 +Ethernet152 274,275,276,277,278,279,280,281 Eth20(Port20) 20 400000 +Ethernet160 258,259,260,261,262,263,264,265 Eth21(Port21) 21 400000 +Ethernet168 266,267,268,269,270,271,272,273 Eth22(Port22) 22 400000 +Ethernet176 306,307,308,309,310,311,312,313 Eth23(Port23) 23 400000 +Ethernet184 314,315,316,317,318,319,320,321 Eth24(Port24) 24 400000 +Ethernet192 322,323,324,325,326,327,328,329 Eth25(Port25) 25 400000 +Ethernet200 330,331,332,333,334,335,336,337 Eth26(Port26) 26 400000 +Ethernet208 338,339,340,341,342,343,344,345 Eth27(Port27) 27 400000 +Ethernet216 346,347,348,349,350,351,352,353 Eth28(Port28) 28 400000 +Ethernet224 354,355,356,357,358,359,360,361 Eth29(Port29) 29 400000 +Ethernet232 362,363,364,365,366,367,368,369 Eth30(Port30) 30 400000 +Ethernet240 370,371,372,373,374,375,376,377 Eth31(Port31) 31 400000 +Ethernet248 378,379,380,381,382,383,384,385 Eth32(Port32) 32 400000 +Ethernet256 98,99,100,101,102,103,104,105 Eth33(Port33) 33 400000 +Ethernet264 106,107,108,109,110,111,112,113 Eth34(Port34) 34 400000 +Ethernet272 114,115,116,117,118,119,120,121 Eth35(Port35) 35 400000 +Ethernet280 122,123,124,125,126,127,128,129 Eth36(Port36) 36 400000 +Ethernet288 58,59,60,61,62,63,64,65 Eth37(Port37) 37 400000 +Ethernet296 66,67,68,69,70,71,72,73 Eth38(Port38) 38 400000 +Ethernet304 50,51,52,53,54,55,56,57 Eth39(Port39) 39 400000 +Ethernet312 82,83,84,85,86,87,88,89 Eth40(Port40) 40 400000 +Ethernet320 42,43,44,45,46,47,48,49 Eth41(Port41) 41 400000 +Ethernet328 74,75,76,77,78,79,80,81 Eth42(Port42) 42 400000 +Ethernet336 34,35,36,37,38,39,40,41 Eth43(Port43) 43 400000 +Ethernet344 90,91,92,93,94,95,96,97 Eth44(Port44) 44 400000 +Ethernet352 26,27,28,29,30,31,32,33 Eth45(Port45) 45 400000 +Ethernet360 18,19,20,21,22,23,24,25 Eth46(Port46) 46 400000 +Ethernet368 2,3,4,5,6,7,8,9 Eth47(Port47) 47 400000 +Ethernet376 10,11,12,13,14,15,16,17 Eth48(Port48) 48 400000 +Ethernet384 498,499,500,501,502,503,504,505 Eth49(Port49) 49 400000 +Ethernet392 506,507,508,509,510,511,512,513 Eth50(Port50) 50 400000 +Ethernet400 490,491,492,493,494,495,496,497 Eth51(Port51) 51 400000 +Ethernet408 482,483,484,485,486,487,488,489 Eth52(Port52) 52 400000 +Ethernet416 474,475,476,477,478,479,480,481 Eth53(Port53) 53 400000 +Ethernet424 418,419,420,421,422,423,424,425 Eth54(Port54) 54 400000 +Ethernet432 466,467,468,469,470,471,472,473 Eth55(Port55) 55 400000 +Ethernet440 434,435,436,437,438,439,440,441 Eth56(Port56) 56 400000 +Ethernet448 458,459,460,461,462,463,464,465 Eth57(Port57) 57 400000 +Ethernet456 426,427,428,429,430,431,432,433 Eth58(Port58) 58 400000 +Ethernet464 450,451,452,453,454,455,456,457 Eth59(Port59) 59 400000 +Ethernet472 442,443,444,445,446,447,448,449 Eth60(Port60) 60 400000 +Ethernet480 386,387,388,389,390,391,392,393 Eth61(Port61) 61 400000 +Ethernet488 402,403,404,405,406,407,408,409 Eth62(Port62) 62 400000 +Ethernet496 394,395,396,397,398,399,400,401 Eth63(Port63) 63 400000 +Ethernet504 410,411,412,413,414,415,416,417 Eth64(Port64) 64 400000 +Ethernet512 514 Eth65(Port65) 65 10000 +Ethernet513 516 Eth66(Port66) 66 10000 diff --git a/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/qos.json.j2 b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/qos.json.j2 new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/qos.json.j2 @@ -0,0 +1 @@ +{} diff --git a/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/sai.profile b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/sai.profile new file mode 100644 index 000000000000..2dfe7d9b55c3 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th4-as9736-64x400G.config.yml diff --git a/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/th4-as9736-64x400G.config.yml b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/th4-as9736-64x400G.config.yml new file mode 100644 index 000000000000..8d39698d2062 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/Accton-AS9736-64D/th4-as9736-64x400G.config.yml @@ -0,0 +1,1186 @@ +#--- +#device: +# 0: +# DEVICE_CONFIG: +# # CORE CLOCK FREQUENCY +# CORE_CLK_FREQ: CLK_1350MHZ +# # PP CLOCK FREQUENCY +# PP_CLK_FREQ: CLK_1350MHZ +#... +--- +bcm_device: + 0: + global: + pktio_mode: 1 + rx_cosq_mapping_management_mode: 1 + vlan_default_port: 3 + l3_alpm_template: 1 + port_allow_tpid_disable: 1 +... +--- +bcm_device: + 0: + global: + dport_map_enable: 0 + port: + 68: { dport_map_port: 1 } + 72: { dport_map_port: 2 } + 76: { dport_map_port: 3 } + 80: { dport_map_port: 4 } + 85: { dport_map_port: 5 } + 89: { dport_map_port: 6 } + 93: { dport_map_port: 7 } + 97: { dport_map_port: 8 } + 102: { dport_map_port: 9 } + 106: { dport_map_port: 10 } + 131: { dport_map_port: 11 } + 127: { dport_map_port: 12 } + 119: { dport_map_port: 13 } + 123: { dport_map_port: 14 } + 114: { dport_map_port: 15 } + 110: { dport_map_port: 16 } + 153: { dport_map_port: 17 } + 157: { dport_map_port: 18 } + 148: { dport_map_port: 19 } + 144: { dport_map_port: 20 } + 136: { dport_map_port: 21 } + 140: { dport_map_port: 22 } + 161: { dport_map_port: 23 } + 165: { dport_map_port: 24 } + 170: { dport_map_port: 25 } + 174: { dport_map_port: 26 } + 178: { dport_map_port: 27 } + 182: { dport_map_port: 28 } + 187: { dport_map_port: 29 } + 191: { dport_map_port: 30 } + 195: { dport_map_port: 31 } + 199: { dport_map_port: 32 } + 51: { dport_map_port: 33 } + 55: { dport_map_port: 34 } + 59: { dport_map_port: 35 } + 63: { dport_map_port: 36 } + 29: { dport_map_port: 37 } + 34: { dport_map_port: 38 } + 25: { dport_map_port: 39 } + 42: { dport_map_port: 40 } + 21: { dport_map_port: 41 } + 38: { dport_map_port: 42 } + 17: { dport_map_port: 43 } + 46: { dport_map_port: 44 } + 13: { dport_map_port: 45 } + 9: { dport_map_port: 46 } + 1: { dport_map_port: 47 } + 5: { dport_map_port: 48 } + 263: { dport_map_port: 49 } + 267: { dport_map_port: 50 } + 259: { dport_map_port: 51 } + 255: { dport_map_port: 52 } + 250: { dport_map_port: 53 } + 221: { dport_map_port: 54 } + 246: { dport_map_port: 55 } + 229: { dport_map_port: 56 } + 242: { dport_map_port: 57 } + 225: { dport_map_port: 58 } + 238: { dport_map_port: 59 } + 233: { dport_map_port: 60 } + 204: { dport_map_port: 61 } + 212: { dport_map_port: 62 } + 208: { dport_map_port: 63 } + 216: { dport_map_port: 64 } + 152: { dport_map_port: 65 } + 50: { dport_map_port: 66 } +... +--- +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: 0x26371504 + TX_LANE_MAP: 0x37260415 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x26371504 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0xf5 + ? + 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: 0x62735140 + TX_LANE_MAP: 0x62735140 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x51406273 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0xf5 + TX_POLARITY_FLIP: 0xf5 + ? + 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: 0x52437061 + TX_LANE_MAP: 0x42537160 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaf + ? + 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: 0x52437061 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x42537160 + TX_LANE_MAP: 0x40516273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x54237061 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x23547160 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x57 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x57 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x24350716 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x41537062 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x14350726 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x51437062 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x52436071 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x15340726 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x52437061 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x34251607 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x43516270 + TX_LANE_MAP: 0x34250716 + RX_POLARITY_FLIP: 0x51 + TX_POLARITY_FLIP: 0x00 + ? + 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: 0x15042637 + TX_LANE_MAP: 0x25041637 + RX_POLARITY_FLIP: 0xc5 + TX_POLARITY_FLIP: 0xc5 + ? + 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: 0x26371504 + TX_LANE_MAP: 0x37260415 + RX_POLARITY_FLIP: 0xca + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x62735140 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0xcb + TX_POLARITY_FLIP: 0x05 + ? + 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: 0x62735140 + TX_LANE_MAP: 0x52736140 + RX_POLARITY_FLIP: 0x3a + TX_POLARITY_FLIP: 0x3a + ? + 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: 0x26371504 + TX_LANE_MAP: 0x25371604 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0xca + ? + 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: 0x37260415 + TX_LANE_MAP: 0x40617352 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0xf5 + ? + 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: 0x73624051 + TX_LANE_MAP: 0x73524061 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x51406273 + TX_LANE_MAP: 0x52406173 + RX_POLARITY_FLIP: 0xc5 + TX_POLARITY_FLIP: 0x35 + ? + 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: 0x34152607 + TX_LANE_MAP: 0x43527061 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xff + ? + 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: 0x52437061 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x51 + TX_POLARITY_FLIP: 0xab + ? + 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: 0x25340716 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x34251607 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0xaa + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x15072634 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfb + ? + 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: 0x34521670 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0x99 + TX_POLARITY_FLIP: 0x8a + ? + 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: 0x15340726 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x43526170 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x43526170 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x25340716 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x34527160 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xaa + ? + 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: 0x43516270 + TX_LANE_MAP: 0x41507362 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x53416270 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0xfa + ? + 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: 0x14350726 + TX_LANE_MAP: 0x05142637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x35241607 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x25340716 + TX_LANE_MAP: 0x14053726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x32451706 + TX_LANE_MAP: 0x15042637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x45320716 + TX_LANE_MAP: 0x14053726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x24351706 + TX_LANE_MAP: 0x04152637 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x34251607 + TX_LANE_MAP: 0x14053726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x34251607 + TX_LANE_MAP: 0x04153726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x34251607 + TX_LANE_MAP: 0x14053726 + RX_POLARITY_FLIP: 0x55 + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x34251607 + TX_LANE_MAP: 0x24351706 + RX_POLARITY_FLIP: 0x57 + TX_POLARITY_FLIP: 0xa0 + ? + 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: 0x51406273 + TX_LANE_MAP: 0x51406273 + RX_POLARITY_FLIP: 0xf5 + TX_POLARITY_FLIP: 0x35 + ? + 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: 0x62735140 + TX_LANE_MAP: 0x43627051 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0x0a + ? + 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: 0x26371504 + TX_LANE_MAP: 0x40517362 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0xf5 + ? + 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: 0x26371504 + TX_LANE_MAP: 0x26371504 + RX_POLARITY_FLIP: 0x0a + TX_POLARITY_FLIP: 0xca +... +--- +device: + 0: + PC_PORT_PHYS_MAP: + ? + PORT_ID: 0 + : + PC_PHYS_PORT_ID: 0 + ? + PORT_ID: 1 + : + PC_PHYS_PORT_ID: 1 + ? + PORT_ID: 5 + : + PC_PHYS_PORT_ID: 5 + ? + PORT_ID: 9 + : + PC_PHYS_PORT_ID: 9 + ? + PORT_ID: 13 + : + PC_PHYS_PORT_ID: 13 + ? + PORT_ID: 17 + : + PC_PHYS_PORT_ID: 17 + ? + PORT_ID: 21 + : + PC_PHYS_PORT_ID: 21 + ? + PORT_ID: 25 + : + PC_PHYS_PORT_ID: 25 + ? + PORT_ID: 29 + : + PC_PHYS_PORT_ID: 29 + ? + PORT_ID: 34 + : + PC_PHYS_PORT_ID: 33 + ? + PORT_ID: 38 + : + PC_PHYS_PORT_ID: 37 + ? + PORT_ID: 42 + : + PC_PHYS_PORT_ID: 41 + ? + PORT_ID: 46 + : + PC_PHYS_PORT_ID: 45 + ? + PORT_ID: 51 + : + PC_PHYS_PORT_ID: 49 + ? + PORT_ID: 55 + : + PC_PHYS_PORT_ID: 53 + ? + PORT_ID: 59 + : + PC_PHYS_PORT_ID: 57 + ? + PORT_ID: 63 + : + PC_PHYS_PORT_ID: 61 + ? + PORT_ID: 68 + : + PC_PHYS_PORT_ID: 65 + ? + PORT_ID: 72 + : + PC_PHYS_PORT_ID: 69 + ? + PORT_ID: 76 + : + PC_PHYS_PORT_ID: 73 + ? + PORT_ID: 80 + : + PC_PHYS_PORT_ID: 77 + ? + PORT_ID: 85 + : + PC_PHYS_PORT_ID: 81 + ? + PORT_ID: 89 + : + PC_PHYS_PORT_ID: 85 + ? + PORT_ID: 93 + : + PC_PHYS_PORT_ID: 89 + ? + PORT_ID: 97 + : + PC_PHYS_PORT_ID: 93 + ? + PORT_ID: 102 + : + PC_PHYS_PORT_ID: 97 + ? + PORT_ID: 106 + : + PC_PHYS_PORT_ID: 101 + ? + PORT_ID: 110 + : + PC_PHYS_PORT_ID: 105 + ? + PORT_ID: 114 + : + PC_PHYS_PORT_ID: 109 + ? + PORT_ID: 119 + : + PC_PHYS_PORT_ID: 113 + ? + PORT_ID: 123 + : + PC_PHYS_PORT_ID: 117 + ? + PORT_ID: 127 + : + PC_PHYS_PORT_ID: 121 + ? + PORT_ID: 131 + : + PC_PHYS_PORT_ID: 125 + ? + PORT_ID: 136 + : + PC_PHYS_PORT_ID: 129 + ? + PORT_ID: 140 + : + PC_PHYS_PORT_ID: 133 + ? + PORT_ID: 144 + : + PC_PHYS_PORT_ID: 137 + ? + PORT_ID: 148 + : + PC_PHYS_PORT_ID: 141 + ? + PORT_ID: 153 + : + PC_PHYS_PORT_ID: 145 + ? + PORT_ID: 157 + : + PC_PHYS_PORT_ID: 149 + ? + PORT_ID: 161 + : + PC_PHYS_PORT_ID: 153 + ? + PORT_ID: 165 + : + PC_PHYS_PORT_ID: 157 + ? + PORT_ID: 170 + : + PC_PHYS_PORT_ID: 161 + ? + PORT_ID: 174 + : + PC_PHYS_PORT_ID: 165 + ? + PORT_ID: 178 + : + PC_PHYS_PORT_ID: 169 + ? + PORT_ID: 182 + : + PC_PHYS_PORT_ID: 173 + ? + PORT_ID: 187 + : + PC_PHYS_PORT_ID: 177 + ? + PORT_ID: 191 + : + PC_PHYS_PORT_ID: 181 + ? + PORT_ID: 195 + : + PC_PHYS_PORT_ID: 185 + ? + PORT_ID: 199 + : + PC_PHYS_PORT_ID: 189 + ? + PORT_ID: 204 + : + PC_PHYS_PORT_ID: 193 + ? + PORT_ID: 208 + : + PC_PHYS_PORT_ID: 197 + ? + PORT_ID: 212 + : + PC_PHYS_PORT_ID: 201 + ? + PORT_ID: 216 + : + PC_PHYS_PORT_ID: 205 + ? + PORT_ID: 221 + : + PC_PHYS_PORT_ID: 209 + ? + PORT_ID: 225 + : + PC_PHYS_PORT_ID: 213 + ? + PORT_ID: 229 + : + PC_PHYS_PORT_ID: 217 + ? + PORT_ID: 233 + : + PC_PHYS_PORT_ID: 221 + ? + PORT_ID: 238 + : + PC_PHYS_PORT_ID: 225 + ? + PORT_ID: 242 + : + PC_PHYS_PORT_ID: 229 + ? + PORT_ID: 246 + : + PC_PHYS_PORT_ID: 233 + ? + PORT_ID: 250 + : + PC_PHYS_PORT_ID: 237 + ? + PORT_ID: 255 + : + PC_PHYS_PORT_ID: 241 + ? + PORT_ID: 259 + : + PC_PHYS_PORT_ID: 245 + ? + PORT_ID: 263 + : + PC_PHYS_PORT_ID: 249 + ? + PORT_ID: 267 + : + PC_PHYS_PORT_ID: 253 + ? + PORT_ID: 50 + : + PC_PHYS_PORT_ID: 258 + ? + PORT_ID: 152 + : + PC_PHYS_PORT_ID: 257 +... +--- +device: + 0: + PC_PORT: + ? + PORT_ID: [50, 152] + : + ENABLE: 0 + SPEED: 10000 + NUM_LANES: 1 + FEC_MODE: PC_FEC_NONE + ? + PORT_ID: 0 + : + ENABLE: 1 + SPEED: 10000 + NUM_LANES: 1 + FEC_MODE: PC_FEC_NONE + ? + PORT_ID: [1, 5, 9, 13, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 63, 68, 72, 76, 80, 85, 89, 93, 97, 102, 106, 110, 114, 119, 123, 127, 131, 136, 140, 144, 148, 153, 157, 161, 165, 170, 174, 178, 182, 187, 191, 195, 199, 204, 208, 212, 216, 221, 225, 229, 233, 238, 242, 246, 250, 255, 259, 263, 267] + : + ENABLE: 0 + SPEED: 400000 + NUM_LANES: 8 + FEC_MODE: PC_FEC_RS544_2XN + + PC_PMD_FIRMWARE: + ? + PORT_ID: [1, 5, 9, 13, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 63, 68, 72, 76, 80, 85, 89, 93, 97, 102, 106, 110, 114, 119, 123, 127, 131, 136, 140, 144, 148, 153, 157, 161, 165, 170, 174, 178, 182, 187, 191, 195, 199, 204, 208, 212, 216, 221, 225, 229, 233, 238, 242, 246, 250, 255, 259, 263, 267] + : + MEDIUM_TYPE_AUTO: 0 + MEDIUM_TYPE: PC_PHY_MEDIUM_COPPER +... +--- +device: + 0: + TM_THD_CONFIG: + THRESHOLD_MODE: LOSSLESS +... +--- +device: + 0: + FP_CONFIG: + FP_ING_OPERMODE: GLOBAL_PIPE_AWARE + FP_CONTROL: + FP_ING_ARP_AS_IP: 1 + FP_ING_RARP_AS_IP: 1 +... diff --git a/device/accton/x86_64-accton_as9736_64d-r0/default_sku b/device/accton/x86_64-accton_as9736_64d-r0/default_sku new file mode 100644 index 000000000000..55bf8a1ffb8e --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/default_sku @@ -0,0 +1 @@ +Accton-AS9736-64D t1 diff --git a/device/accton/x86_64-accton_as9736_64d-r0/installer.conf b/device/accton/x86_64-accton_as9736_64d-r0/installer.conf new file mode 100644 index 000000000000..17f1ce1e8b09 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_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" diff --git a/device/accton/x86_64-accton_as9736_64d-r0/pcie.yaml b/device/accton/x86_64-accton_as9736_64d-r0/pcie.yaml new file mode 100644 index 000000000000..3fb058f7c8dc --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/pcie.yaml @@ -0,0 +1,507 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '1' + id: 6f09 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '2' + id: 6f0a + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '3' + id: 6f0b + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: '16' + fn: '0' + id: 8c3a + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #1 (rev 04)' +- bus: '00' + dev: '16' + fn: '1' + id: 8c3b + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #2 (rev 04)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1c + fn: '7' + id: 8c1e + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #8 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '02' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '02' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '02' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '02' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '03' + dev: '00' + fn: '0' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '03' + dev: '00' + fn: '1' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '05' + dev: '00' + fn: '0' + id: b404 + name: 'PCI bridge: Pericom Semiconductor Device b404 (rev 01)' +- bus: '06' + dev: '01' + fn: '0' + id: b404 + name: 'PCI bridge: Pericom Semiconductor Device b404 (rev 01)' +- bus: '06' + dev: '02' + fn: '0' + id: b404 + name: 'PCI bridge: Pericom Semiconductor Device b404 (rev 01)' +- bus: '06' + dev: '03' + fn: '0' + id: b404 + name: 'PCI bridge: Pericom Semiconductor Device b404 (rev 01)' +- bus: '07' + dev: '00' + fn: '0' + id: '8664' + name: 'Class 2080: Accton Technology Corporation Device 8664' +- bus: 08 + dev: '00' + fn: '0' + id: '8664' + name: 'Class 2080: Accton Technology Corporation Device 8664' +- bus: 09 + dev: '00' + fn: '0' + id: '8664' + name: 'Class 2080: Accton Technology Corporation Device 8664' +- bus: 0a + dev: '00' + fn: '0' + id: b990 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM56990 Switch ASIC + (rev 11)' +- bus: 0e + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '4' + id: 6fe4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '5' + id: 6fe5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '6' + id: 6fe6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '7' + id: 6fe7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/accton/x86_64-accton_as9736_64d-r0/platform.json b/device/accton/x86_64-accton_as9736_64d-r0/platform.json new file mode 100644 index 000000000000..d89fdbff3f56 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/platform.json @@ -0,0 +1,1297 @@ +{ + "chassis": { + "name": "9736-64D", + "components": [ + { + "name": "SYSTEM CPLD" + }, + { + "name": "FCM CPLD" + }, + { + "name": "PSU CPLD" + }, + { + "name": "SCM CPLD" + }, + { + "name": "UDB FPGA" + }, + { + "name": "LDB FPGA" + }, + { + "name": "SMB FPGA" + }, + { + "name": "BIOS" + } + ], + "fans": [ + { + "name": "FAN-1F" + }, + { + "name": "FAN-1R" + }, + { + "name": "FAN-2F" + }, + { + "name": "FAN-2R" + }, + { + "name": "FAN-3F" + }, + { + "name": "FAN-3R" + }, + { + "name": "FAN-4F" + }, + { + "name": "FAN-4R" + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "num_fans" : 2, + "fans": [ + { + "name": "FAN-1F" + }, + { + "name": "FAN-1R" + } + ] + }, + { + "name": "FanTray2", + "num_fans" : 2, + "fans": [ + { + "name": "FAN-2F" + }, + { + "name": "FAN-2R" + } + ] + }, + { + "name": "FanTray3", + "num_fans" : 2, + "fans": [ + { + "name": "FAN-3F" + }, + { + "name": "FAN-3R" + } + ] + }, + { + "name": "FanTray4", + "num_fans" : 2, + "fans": [ + { + "name": "FAN-4F" + }, + { + "name": "FAN-4R" + } + ] + } + ], + "psus": [ + { + "name": "PSU-1", + "fans": [ + { + "name": "PSU-1 FAN-1" + } + ], + "thermals": [ + { + "name": "PSU-1 temp sensor 1", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ], + "temperature": true, + "temperature_high_threshold": true + }, + { + "name": "PSU-2", + "fans": [ + { + "name": "PSU-2 FAN-1" + } + ], + "thermals": [ + { + "name": "PSU-2 temp sensor 1", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ], + "temperature": true, + "temperature_high_threshold": true + } + ], + "thermals": [ + { + "name": "Temp sensor 1", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 2", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 3", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 4", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 5", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 6", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 7", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 8", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 9", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 10", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "Temp sensor 11", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU 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": "130,131,132,133,134,135,136,137", + "breakout_modes": { + "1x400G": ["Eth1(Port1)"], + "2x200G": ["Eth1/1(Port1)", "Eth1/2(Port1)"], + "4x100G": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"], + "1x100G[40G](4)": ["Eth1(Port1)"], + "2x50G(4)": ["Eth1/1(Port1)", "Eth1/2(Port1)"], + "4x25G[10G](4)": ["Eth1/1(Port1)", "Eth1/2(Port1)", "Eth1/3(Port1)", "Eth1/4(Port1)"] + } + }, + + "Ethernet8": { + "index": "2,2,2,2,2,2,2,2", + "lanes": "138,139,140,141,142,143,144,145", + "breakout_modes": { + "1x400G": ["Eth2(Port2)"], + "2x200G": ["Eth2/1(Port2)", "Eth2/2(Port2)"], + "4x100G": ["Eth2/1(Port2)", "Eth2/2(Port2)", "Eth2/3(Port2)", "Eth2/4(Port2)"], + "1x100G[40G](4)": ["Eth2(Port2)"], + "2x50G(4)": ["Eth2/1(Port2)", "Eth2/2(Port2)"], + "4x25G[10G](4)": ["Eth2/1(Port2)", "Eth2/2(Port2)", "Eth2/3(Port2)", "Eth2/4(Port2)"] + } + }, + + "Ethernet16": { + "index": "3,3,3,3,3,3,3,3", + "lanes": "146,147,148,149,150,151,152,153", + "breakout_modes": { + "1x400G": ["Eth3(Port3)"], + "2x200G": ["Eth3/1(Port3)", "Eth3/2(Port3)"], + "4x100G": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"], + "1x100G[40G](4)": ["Eth3(Port3)"], + "2x50G(4)": ["Eth3/1(Port3)", "Eth3/2(Port3)"], + "4x25G[10G](4)": ["Eth3/1(Port3)", "Eth3/2(Port3)", "Eth3/3(Port3)", "Eth3/4(Port3)"] + } + }, + + "Ethernet24": { + "index": "4,4,4,4,4,4,4,4", + "lanes": "154,155,156,157,158,159,160,161", + "breakout_modes": { + "1x400G": ["Eth4(Port4)"], + "2x200G": ["Eth4/1(Port4)", "Eth4/2(Port4)"], + "4x100G": ["Eth4/1(Port4)", "Eth4/2(Port4)", "Eth4/3(Port4)", "Eth4/4(Port4)"], + "1x100G[40G](4)": ["Eth4(Port4)"], + "2x50G(4)": ["Eth4/1(Port4)", "Eth4/2(Port4)"], + "4x25G[10G](4)": ["Eth4/1(Port4)", "Eth4/2(Port4)", "Eth4/3(Port4)", "Eth4/4(Port4)"] + } + }, + + "Ethernet32": { + "index": "5,5,5,5,5,5,5,5", + "lanes": "162,163,164,165,166,167,168,169", + "breakout_modes": { + "1x400G": ["Eth5(Port5)"], + "2x200G": ["Eth5/1(Port5)", "Eth5/2(Port5)"], + "4x100G": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"], + "1x100G[40G](4)": ["Eth5(Port5)"], + "2x50G(4)": ["Eth5/1(Port5)", "Eth5/2(Port5)"], + "4x25G[10G](4)": ["Eth5/1(Port5)", "Eth5/2(Port5)", "Eth5/3(Port5)", "Eth5/4(Port5)"] + } + }, + + "Ethernet40": { + "index": "6,6,6,6,6,6,6,6", + "lanes": "170,171,172,173,174,175,176,177", + "breakout_modes": { + "1x400G": ["Eth6(Port6)"], + "2x200G": ["Eth6/1(Port6)", "Eth6/2(Port6)"], + "4x100G": ["Eth6/1(Port6)", "Eth6/2(Port6)", "Eth6/3(Port6)", "Eth6/4(Port6)"], + "1x100G[40G](4)": ["Eth6(Port6)"], + "2x50G(4)": ["Eth6/1(Port6)", "Eth6/2(Port6)"], + "4x25G[10G](4)": ["Eth6/1(Port6)", "Eth6/2(Port6)", "Eth6/3(Port6)", "Eth6/4(Port6)"] + } + }, + + "Ethernet48": { + "index": "7,7,7,7,7,7,7,7", + "lanes": "178,179,180,181,182,183,184,185", + "breakout_modes": { + "1x400G": ["Eth7(Port7)"], + "2x200G": ["Eth7/1(Port7)", "Eth7/2(Port7)"], + "4x100G": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"], + "1x100G[40G](4)": ["Eth7(Port7)"], + "2x50G(4)": ["Eth7/1(Port7)", "Eth7/2(Port7)"], + "4x25G[10G](4)": ["Eth7/1(Port7)", "Eth7/2(Port7)", "Eth7/3(Port7)", "Eth7/4(Port7)"] + } + }, + + "Ethernet56": { + "index": "8,8,8,8,8,8,8,8", + "lanes": "186,187,188,189,190,191,192,193", + "breakout_modes": { + "1x400G": ["Eth8(Port8)"], + "2x200G": ["Eth8/1(Port8)", "Eth8/2(Port8)"], + "4x100G": ["Eth8/1(Port8)", "Eth8/2(Port8)", "Eth8/3(Port8)", "Eth8/4(Port8)"], + "1x100G[40G](4)": ["Eth8(Port8)"], + "2x50G(4)": ["Eth8/1(Port8)", "Eth8/2(Port8)"], + "4x25G[10G](4)": ["Eth8/1(Port8)", "Eth8/2(Port8)", "Eth8/3(Port8)", "Eth8/4(Port8)"] + } + }, + + "Ethernet64": { + "index": "9,9,9,9,9,9,9,9", + "lanes": "194,195,196,197,198,199,200,201", + "breakout_modes": { + "1x400G": ["Eth9(Port9)"], + "2x200G": ["Eth9/1(Port9)", "Eth9/2(Port9)"], + "4x100G": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"], + "1x100G[40G](4)": ["Eth9(Port9)"], + "2x50G(4)": ["Eth9/1(Port9)", "Eth9/2(Port9)"], + "4x25G[10G](4)": ["Eth9/1(Port9)", "Eth9/2(Port9)", "Eth9/3(Port9)", "Eth9/4(Port9)"] + } + }, + + "Ethernet72": { + "index": "10,10,10,10,10,10,10,10", + "lanes": "202,203,204,205,206,207,208,209", + "breakout_modes": { + "1x400G": ["Eth10(Port10)"], + "2x200G": ["Eth10/1(Port10)", "Eth10/2(Port10)"], + "4x100G": ["Eth10/1(Port10)", "Eth10/2(Port10)", "Eth10/3(Port10)", "Eth10/4(Port10)"], + "1x100G[40G](4)": ["Eth10(Port10)"], + "2x50G(4)": ["Eth10/1(Port10)", "Eth10/2(Port10)"], + "4x25G[10G](4)": ["Eth10/1(Port10)", "Eth10/2(Port10)", "Eth10/3(Port10)", "Eth10/4(Port10)"] + } + }, + + "Ethernet80": { + "index": "11,11,11,11,11,11,11,11", + "lanes": "250,251,252,253,254,255,256,257", + "breakout_modes": { + "1x400G": ["Eth11(Port11)"], + "2x200G": ["Eth11/1(Port11)", "Eth11/2(Port11)"], + "4x100G": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"], + "1x100G[40G](4)": ["Eth11(Port11)"], + "2x50G(4)": ["Eth11/1(Port11)", "Eth11/2(Port11)"], + "4x25G[10G](4)": ["Eth11/1(Port11)", "Eth11/2(Port11)", "Eth11/3(Port11)", "Eth11/4(Port11)"] + } + }, + + "Ethernet88": { + "index": "12,12,12,12,12,12,12,12", + "lanes": "242,243,244,245,246,247,248,249", + "breakout_modes": { + "1x400G": ["Eth12(Port12)"], + "2x200G": ["Eth12/1(Port12)", "Eth12/2(Port12)"], + "4x100G": ["Eth12/1(Port12)", "Eth12/2(Port12)", "Eth12/3(Port12)", "Eth12/4(Port12)"], + "1x100G[40G](4)": ["Eth12(Port12)"], + "2x50G(4)": ["Eth12/1(Port12)", "Eth12/2(Port12)"], + "4x25G[10G](4)": ["Eth12/1(Port12)", "Eth12/2(Port12)", "Eth12/3(Port12)", "Eth12/4(Port12)"] + } + }, + + "Ethernet96": { + "index": "13,13,13,13,13,13,13,13", + "lanes": "226,227,228,229,230,231,232,233", + "breakout_modes": { + "1x400G": ["Eth13(Port13)"], + "2x200G": ["Eth13/1(Port13)", "Eth13/2(Port13)"], + "4x100G": ["Eth13/1(Port13)", "Eth13/2(Port13)", "Eth13/3(Port13)", "Eth13/4(Port13)"], + "1x100G[40G](4)": ["Eth13(Port13)"], + "2x50G(4)": ["Eth13/1(Port13)", "Eth13/2(Port13)"], + "4x25G[10G](4)": ["Eth13/1(Port13)", "Eth13/2(Port13)", "Eth13/3(Port13)", "Eth13/4(Port13)"] + } + }, + + "Ethernet104": { + "index": "14,14,14,14,14,14,14,14", + "lanes": "234,235,236,237,238,239,240,241", + "breakout_modes": { + "1x400G": ["Eth14(Port14)"], + "2x200G": ["Eth14/1(Port14)", "Eth14/2(Port14)"], + "4x100G": ["Eth14/1(Port14)", "Eth14/2(Port14)", "Eth14/3(Port14)", "Eth14/4(Port14)"], + "1x100G[40G](4)": ["Eth14(Port14)"], + "2x50G(4)": ["Eth14/1(Port14)", "Eth14/2(Port14)"], + "4x25G[10G](4)": ["Eth14/1(Port14)", "Eth14/2(Port14)", "Eth14/3(Port14)", "Eth14/4(Port14)"] + } + }, + + "Ethernet112": { + "index": "15,15,15,15,15,15,15,15", + "lanes": "218,219,220,221,222,223,224,225", + "breakout_modes": { + "1x400G": ["Eth15(Port15)"], + "2x200G": ["Eth15/1(Port15)", "Eth15/2(Port15)"], + "4x100G": ["Eth15/1(Port15)", "Eth15/2(Port15)", "Eth15/3(Port15)", "Eth15/4(Port15)"], + "1x100G[40G](4)": ["Eth15(Port15)"], + "2x50G(4)": ["Eth15/1(Port15)", "Eth15/2(Port15)"], + "4x25G[10G](4)": ["Eth15/1(Port15)", "Eth15/2(Port15)", "Eth15/3(Port15)", "Eth15/4(Port15)"] + } + }, + + "Ethernet120": { + "index": "16,16,16,16,16,16,16,16", + "lanes": "210,211,212,213,214,215,216,217", + "breakout_modes": { + "1x400G": ["Eth16(Port16)"], + "2x200G": ["Eth16/1(Port16)", "Eth16/2(Port16)"], + "4x100G": ["Eth16/1(Port16)", "Eth16/2(Port16)", "Eth16/3(Port16)", "Eth16/4(Port16)"], + "1x100G[40G](4)": ["Eth16(Port16)"], + "2x50G(4)": ["Eth16/1(Port16)", "Eth16/2(Port16)"], + "4x25G[10G](4)": ["Eth16/1(Port16)", "Eth16/2(Port16)", "Eth16/3(Port16)", "Eth16/4(Port16)"] + } + }, + + "Ethernet128": { + "index": "17,17,17,17,17,17,17,17", + "lanes": "290,291,292,293,294,295,296,297", + "breakout_modes": { + "1x400G": ["Eth17(Port17)"], + "2x200G": ["Eth17/1(Port17)", "Eth17/2(Port17)"], + "4x100G": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"], + "1x100G[40G](4)": ["Eth17(Port17)"], + "2x50G(4)": ["Eth17/1(Port17)", "Eth17/2(Port17)"], + "4x25G[10G](4)": ["Eth17/1(Port17)", "Eth17/2(Port17)", "Eth17/3(Port17)", "Eth17/4(Port17)"] + } + }, + + "Ethernet136": { + "index": "18,18,18,18,18,18,18,18", + "lanes": "298,299,300,301,302,303,304,305", + "breakout_modes": { + "1x400G": ["Eth18(Port18)"], + "2x200G": ["Eth18/1(Port18)", "Eth18/2(Port18)"], + "4x100G": ["Eth18/1(Port18)", "Eth18/2(Port18)", "Eth18/3(Port18)", "Eth18/4(Port18)"], + "1x100G[40G](4)": ["Eth18(Port18)"], + "2x50G(4)": ["Eth18/1(Port18)", "Eth18/2(Port18)"], + "4x25G[10G](4)": ["Eth18/1(Port18)", "Eth18/2(Port18)", "Eth18/3(Port18)", "Eth18/4(Port18)"] + } + }, + + "Ethernet144": { + "index": "19,19,19,19,19,19,19,19", + "lanes": "282,283,284,285,286,287,288,289", + "breakout_modes": { + "1x400G": ["Eth19(Port19)"], + "2x200G": ["Eth19/1(Port19)", "Eth19/2(Port19)"], + "4x100G": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"], + "1x100G[40G](4)": ["Eth19(Port19)"], + "2x50G(4)": ["Eth19/1(Port19)", "Eth19/2(Port19)"], + "4x25G[10G](4)": ["Eth19/1(Port19)", "Eth19/2(Port19)", "Eth19/3(Port19)", "Eth19/4(Port19)"] + } + }, + + "Ethernet152": { + "index": "20,20,20,20,20,20,20,20", + "lanes": "274,275,276,277,278,279,280,281", + "breakout_modes": { + "1x400G": ["Eth20(Port20)"], + "2x200G": ["Eth20/1(Port20)", "Eth20/2(Port20)"], + "4x100G": ["Eth20/1(Port20)", "Eth20/2(Port20)", "Eth20/3(Port20)", "Eth20/4(Port20)"], + "1x100G[40G](4)": ["Eth20(Port20)"], + "2x50G(4)": ["Eth20/1(Port20)", "Eth20/2(Port20)"], + "4x25G[10G](4)": ["Eth20/1(Port20)", "Eth20/2(Port20)", "Eth20/3(Port20)", "Eth20/4(Port20)"] + } + }, + + "Ethernet160": { + "index": "21,21,21,21,21,21,21,21", + "lanes": "258,259,260,261,262,263,264,265", + "breakout_modes": { + "1x400G": ["Eth21(Port21)"], + "2x200G": ["Eth21/1(Port21)", "Eth21/2(Port21)"], + "4x100G": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"], + "1x100G[40G](4)": ["Eth21(Port21)"], + "2x50G(4)": ["Eth21/1(Port21)", "Eth21/2(Port21)"], + "4x25G[10G](4)": ["Eth21/1(Port21)", "Eth21/2(Port21)", "Eth21/3(Port21)", "Eth21/4(Port21)"] + } + }, + + "Ethernet168": { + "index": "22,22,22,22,22,22,22,22", + "lanes": "266,267,268,269,270,271,272,273", + "breakout_modes": { + "1x400G": ["Eth22(Port22)"], + "2x200G": ["Eth22/1(Port22)", "Eth22/2(Port22)"], + "4x100G": ["Eth22/1(Port22)", "Eth22/2(Port22)", "Eth22/3(Port22)", "Eth22/4(Port22)"], + "1x100G[40G](4)": ["Eth22(Port22)"], + "2x50G(4)": ["Eth22/1(Port22)", "Eth22/2(Port22)"], + "4x25G[10G](4)": ["Eth22/1(Port22)", "Eth22/2(Port22)", "Eth22/3(Port22)", "Eth22/4(Port22)"] + } + }, + + "Ethernet176": { + "index": "23,23,23,23,23,23,23,23", + "lanes": "306,307,308,309,310,311,312,313", + "breakout_modes": { + "1x400G": ["Eth23(Port23)"], + "2x200G": ["Eth23/1(Port23)", "Eth23/2(Port23)"], + "4x100G": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"], + "1x100G[40G](4)": ["Eth23(Port23)"], + "2x50G(4)": ["Eth23/1(Port23)", "Eth23/2(Port23)"], + "4x25G[10G](4)": ["Eth23/1(Port23)", "Eth23/2(Port23)", "Eth23/3(Port23)", "Eth23/4(Port23)"] + } + }, + + "Ethernet184": { + "index": "24,24,24,24,24,24,24,24", + "lanes": "314,315,316,317,318,319,320,321", + "breakout_modes": { + "1x400G": ["Eth24(Port24)"], + "2x200G": ["Eth24/1(Port24)", "Eth24/2(Port24)"], + "4x100G": ["Eth24/1(Port24)", "Eth24/2(Port24)", "Eth24/3(Port24)", "Eth24/4(Port24)"], + "1x100G[40G](4)": ["Eth24(Port24)"], + "2x50G(4)": ["Eth24/1(Port24)", "Eth24/2(Port24)"], + "4x25G[10G](4)": ["Eth24/1(Port24)", "Eth24/2(Port24)", "Eth24/3(Port24)", "Eth24/4(Port24)"] + } + }, + + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "322,323,324,325,326,327,328,329", + "breakout_modes": { + "1x400G": ["Eth25(Port25)"], + "2x200G": ["Eth25/1(Port25)", "Eth25/2(Port25)"], + "4x100G": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"], + "1x100G[40G](4)": ["Eth25(Port25)"], + "2x50G(4)": ["Eth25/1(Port25)", "Eth25/2(Port25)"], + "4x25G[10G](4)": ["Eth25/1(Port25)", "Eth25/2(Port25)", "Eth25/3(Port25)", "Eth25/4(Port25)"] + } + }, + + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "330,331,332,333,334,335,336,337", + "breakout_modes": { + "1x400G": ["Eth26(Port26)"], + "2x200G": ["Eth26/1(Port26)", "Eth26/2(Port26)"], + "4x100G": ["Eth26/1(Port26)", "Eth26/2(Port26)", "Eth26/3(Port26)", "Eth26/4(Port26)"], + "1x100G[40G](4)": ["Eth26(Port26)"], + "2x50G(4)": ["Eth26/1(Port26)", "Eth26/2(Port26)"], + "4x25G[10G](4)": ["Eth26/1(Port26)", "Eth26/2(Port26)", "Eth26/3(Port26)", "Eth26/4(Port26)"] + } + }, + + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "338,339,340,341,342,343,344,345", + "breakout_modes": { + "1x400G": ["Eth27(Port27)"], + "2x200G": ["Eth27/1(Port27)", "Eth27/2(Port27)"], + "4x100G": ["Eth27/1(Port27)", "Eth27/2(Port27)", "Eth27/3(Port27)", "Eth27/4(Port27)"], + "1x100G[40G](4)": ["Eth27(Port27)"], + "2x50G(4)": ["Eth27/1(Port27)", "Eth27/2(Port27)"], + "4x25G[10G](4)": ["Eth27/1(Port27)", "Eth27/2(Port27)", "Eth27/3(Port27)", "Eth27/4(Port27)"] + } + }, + + "Ethernet216": { + "index": "28,28,28,28,28,28,28,28", + "lanes": "346,347,348,349,350,351,352,353", + "breakout_modes": { + "1x400G": ["Eth28(Port28)"], + "2x200G": ["Eth28/1(Port28)", "Eth28/2(Port28)"], + "4x100G": ["Eth28/1(Port28)", "Eth28/2(Port28)", "Eth28/3(Port28)", "Eth28/4(Port28)"], + "1x100G[40G](4)": ["Eth28(Port28)"], + "2x50G(4)": ["Eth28/1(Port28)", "Eth28/2(Port28)"], + "4x25G[10G](4)": ["Eth28/1(Port28)", "Eth28/2(Port28)", "Eth28/3(Port28)", "Eth28/4(Port28)"] + } + }, + + "Ethernet224": { + "index": "29,29,29,29,29,29,29,29", + "lanes": "354,355,356,357,358,359,360,361", + "breakout_modes": { + "1x400G": ["Eth29(Port29)"], + "2x200G": ["Eth29/1(Port29)", "Eth29/2(Port29)"], + "4x100G": ["Eth29/1(Port29)", "Eth29/2(Port29)", "Eth29/3(Port29)", "Eth29/4(Port29)"], + "1x100G[40G](4)": ["Eth29(Port29)"], + "2x50G(4)": ["Eth29/1(Port29)", "Eth29/2(Port29)"], + "4x25G[10G](4)": ["Eth29/1(Port29)", "Eth29/2(Port29)", "Eth29/3(Port29)", "Eth29/4(Port29)"] + } + }, + + "Ethernet232": { + "index": "30,30,30,30,30,30,30,30", + "lanes": "362,363,364,365,366,367,368,369", + "breakout_modes": { + "1x400G": ["Eth30(Port30)"], + "2x200G": ["Eth30/1(Port30)", "Eth30/2(Port30)"], + "4x100G": ["Eth30/1(Port30)", "Eth30/2(Port30)", "Eth30/3(Port30)", "Eth30/4(Port30)"], + "1x100G[40G](4)": ["Eth30(Port30)"], + "2x50G(4)": ["Eth30/1(Port30)", "Eth30/2(Port30)"], + "4x25G[10G](4)": ["Eth30/1(Port30)", "Eth30/2(Port30)", "Eth30/3(Port30)", "Eth30/4(Port30)"] + } + }, + + "Ethernet240": { + "index": "31,31,31,31,31,31,31,31", + "lanes": "370,371,372,373,374,375,376,377", + "breakout_modes": { + "1x400G": ["Eth31(Port31)"], + "2x200G": ["Eth31/1(Port31)", "Eth31/2(Port31)"], + "4x100G": ["Eth31/1(Port31)", "Eth31/2(Port31)", "Eth31/3(Port31)", "Eth31/4(Port31)"], + "1x100G[40G](4)": ["Eth31(Port31)"], + "2x50G(4)": ["Eth31/1(Port31)", "Eth31/2(Port31)"], + "4x25G[10G](4)": ["Eth31/1(Port31)", "Eth31/2(Port31)", "Eth31/3(Port31)", "Eth31/4(Port31)"] + } + }, + + "Ethernet248": { + "index": "32,32,32,32,32,32,32,32", + "lanes": "378,379,380,381,382,383,384,385", + "breakout_modes": { + "1x400G": ["Eth32(Port32)"], + "2x200G": ["Eth32/1(Port32)", "Eth32/2(Port32)"], + "4x100G": ["Eth32/1(Port32)", "Eth32/2(Port32)", "Eth32/3(Port32)", "Eth32/4(Port32)"], + "1x100G[40G](4)": ["Eth32(Port32)"], + "2x50G(4)": ["Eth32/1(Port32)", "Eth32/2(Port32)"], + "4x25G[10G](4)": ["Eth32/1(Port32)", "Eth32/2(Port32)", "Eth32/3(Port32)", "Eth32/4(Port32)"] + } + }, + + "Ethernet256": { + "index": "33,33,33,33,33,33,33,33", + "lanes": "98,99,100,101,102,103,104,105", + "breakout_modes": { + "1x400G": ["Eth33(Port33)"], + "2x200G": ["Eth33/1(Port33)", "Eth33/2(Port33)"], + "4x100G": ["Eth33/1(Port33)", "Eth33/2(Port33)", "Eth33/3(Port33)", "Eth33/4(Port33)"], + "1x100G[40G](4)": ["Eth33(Port33)"], + "2x50G(4)": ["Eth33/1(Port33)", "Eth33/2(Port33)"], + "4x25G[10G](4)": ["Eth33/1(Port33)", "Eth33/2(Port33)", "Eth33/3(Port33)", "Eth33/4(Port33)"] + } + }, + + "Ethernet264": { + "index": "34,34,34,34,34,34,34,34", + "lanes": "106,107,108,109,110,111,112,113", + "breakout_modes": { + "1x400G": ["Eth34(Port34)"], + "2x200G": ["Eth34/1(Port34)", "Eth34/2(Port34)"], + "4x100G": ["Eth34/1(Port34)", "Eth34/2(Port34)", "Eth34/3(Port34)", "Eth34/4(Port34)"], + "1x100G[40G](4)": ["Eth34(Port34)"], + "2x50G(4)": ["Eth34/1(Port34)", "Eth34/2(Port34)"], + "4x25G[10G](4)": ["Eth34/1(Port34)", "Eth34/2(Port34)", "Eth34/3(Port34)", "Eth34/4(Port34)"] + } + }, + + "Ethernet272": { + "index": "35,35,35,35,35,35,35,35", + "lanes": "114,115,116,117,118,119,120,121", + "breakout_modes": { + "1x400G": ["Eth35(Port35)"], + "2x200G": ["Eth35/1(Port35)", "Eth35/2(Port35)"], + "4x100G": ["Eth35/1(Port35)", "Eth35/2(Port35)", "Eth35/3(Port35)", "Eth35/4(Port35)"], + "1x100G[40G](4)": ["Eth35(Port35)"], + "2x50G(4)": ["Eth35/1(Port35)", "Eth35/2(Port35)"], + "4x25G[10G](4)": ["Eth35/1(Port35)", "Eth35/2(Port35)", "Eth35/3(Port35)", "Eth35/4(Port35)"] + } + }, + + "Ethernet280": { + "index": "36,36,36,36,36,36,36,36", + "lanes": "122,123,124,125,126,127,128,129", + "breakout_modes": { + "1x400G": ["Eth36(Port36)"], + "2x200G": ["Eth36/1(Port36)", "Eth36/2(Port36)"], + "4x100G": ["Eth36/1(Port36)", "Eth36/2(Port36)", "Eth36/3(Port36)", "Eth36/4(Port36)"], + "1x100G[40G](4)": ["Eth36(Port36)"], + "2x50G(4)": ["Eth36/1(Port36)", "Eth36/2(Port36)"], + "4x25G[10G](4)": ["Eth36/1(Port36)", "Eth36/2(Port36)", "Eth36/3(Port36)", "Eth36/4(Port36)"] + } + }, + + "Ethernet288": { + "index": "37,37,37,37,37,37,37,37", + "lanes": "58,59,60,61,62,63,64,65", + "breakout_modes": { + "1x400G": ["Eth37(Port37)"], + "2x200G": ["Eth37/1(Port37)", "Eth37/2(Port37)"], + "4x100G": ["Eth37/1(Port37)", "Eth37/2(Port37)", "Eth37/3(Port37)", "Eth37/4(Port37)"], + "1x100G[40G](4)": ["Eth37(Port37)"], + "2x50G(4)": ["Eth37/1(Port37)", "Eth37/2(Port37)"], + "4x25G[10G](4)": ["Eth37/1(Port37)", "Eth37/2(Port37)", "Eth37/3(Port37)", "Eth37/4(Port37)"] + } + }, + + "Ethernet296": { + "index": "38,38,38,38,38,38,38,38", + "lanes": "66,67,68,69,70,71,72,73", + "breakout_modes": { + "1x400G": ["Eth38(Port38)"], + "2x200G": ["Eth38/1(Port38)", "Eth38/2(Port38)"], + "4x100G": ["Eth38/1(Port38)", "Eth38/2(Port38)", "Eth38/3(Port38)", "Eth38/4(Port38)"], + "1x100G[40G](4)": ["Eth38(Port38)"], + "2x50G(4)": ["Eth38/1(Port38)", "Eth38/2(Port38)"], + "4x25G[10G](4)": ["Eth38/1(Port38)", "Eth38/2(Port38)", "Eth38/3(Port38)", "Eth38/4(Port38)"] + } + }, + + "Ethernet304": { + "index": "39,39,39,39,39,39,39,39", + "lanes": "50,51,52,53,54,55,56,57", + "breakout_modes": { + "1x400G": ["Eth39(Port39)"], + "2x200G": ["Eth39/1(Port39)", "Eth39/2(Port39)"], + "4x100G": ["Eth39/1(Port39)", "Eth39/2(Port39)", "Eth39/3(Port39)", "Eth39/4(Port39)"], + "1x100G[40G](4)": ["Eth39(Port39)"], + "2x50G(4)": ["Eth39/1(Port39)", "Eth39/2(Port39)"], + "4x25G[10G](4)": ["Eth39/1(Port39)", "Eth39/2(Port39)", "Eth39/3(Port39)", "Eth39/4(Port39)"] + } + }, + + "Ethernet312": { + "index": "40,40,40,40,40,40,40,40", + "lanes": "82,83,84,85,86,87,88,89", + "breakout_modes": { + "1x400G": ["Eth40(Port40)"], + "2x200G": ["Eth40/1(Port40)", "Eth40/2(Port40)"], + "4x100G": ["Eth40/1(Port40)", "Eth40/2(Port40)", "Eth40/3(Port40)", "Eth40/4(Port40)"], + "1x100G[40G](4)": ["Eth40(Port40)"], + "2x50G(4)": ["Eth40/1(Port40)", "Eth40/2(Port40)"], + "4x25G[10G](4)": ["Eth40/1(Port40)", "Eth40/2(Port40)", "Eth40/3(Port40)", "Eth40/4(Port40)"] + } + }, + + "Ethernet320": { + "index": "41,41,41,41,41,41,41,41", + "lanes": "42,43,44,45,46,47,48,49", + "breakout_modes": { + "1x400G": ["Eth41(Port41)"], + "2x200G": ["Eth41/1(Port41)", "Eth41/2(Port41)"], + "4x100G": ["Eth41/1(Port41)", "Eth41/2(Port41)", "Eth41/3(Port41)", "Eth41/4(Port41)"], + "1x100G[40G](4)": ["Eth41(Port41)"], + "2x50G(4)": ["Eth41/1(Port41)", "Eth41/2(Port41)"], + "4x25G[10G](4)": ["Eth41/1(Port41)", "Eth41/2(Port41)", "Eth41/3(Port41)", "Eth41/4(Port41)"] + } + }, + + "Ethernet328": { + "index": "42,42,42,42,42,42,42,42", + "lanes": "74,75,76,77,78,79,80,81", + "breakout_modes": { + "1x400G": ["Eth42(Port42)"], + "2x200G": ["Eth42/1(Port42)", "Eth42/2(Port42)"], + "4x100G": ["Eth42/1(Port42)", "Eth42/2(Port42)", "Eth42/3(Port42)", "Eth42/4(Port42)"], + "1x100G[40G](4)": ["Eth42(Port42)"], + "2x50G(4)": ["Eth42/1(Port42)", "Eth42/2(Port42)"], + "4x25G[10G](4)": ["Eth42/1(Port42)", "Eth42/2(Port42)", "Eth42/3(Port42)", "Eth42/4(Port42)"] + } + }, + + "Ethernet336": { + "index": "43,43,43,43,43,43,43,43", + "lanes": "34,35,36,37,38,39,40,41", + "breakout_modes": { + "1x400G": ["Eth43(Port43)"], + "2x200G": ["Eth43/1(Port43)", "Eth43/2(Port43)"], + "4x100G": ["Eth43/1(Port43)", "Eth43/2(Port43)", "Eth43/3(Port43)", "Eth43/4(Port43)"], + "1x100G[40G](4)": ["Eth43(Port43)"], + "2x50G(4)": ["Eth43/1(Port43)", "Eth43/2(Port43)"], + "4x25G[10G](4)": ["Eth43/1(Port43)", "Eth43/2(Port43)", "Eth43/3(Port43)", "Eth43/4(Port43)"] + } + }, + + "Ethernet344": { + "index": "44,44,44,44,44,44,44,44", + "lanes": "90,91,92,93,94,95,96,97", + "breakout_modes": { + "1x400G": ["Eth44(Port44)"], + "2x200G": ["Eth44/1(Port44)", "Eth44/2(Port44)"], + "4x100G": ["Eth44/1(Port44)", "Eth44/2(Port44)", "Eth44/3(Port44)", "Eth44/4(Port44)"], + "1x100G[40G](4)": ["Eth44(Port44)"], + "2x50G(4)": ["Eth44/1(Port44)", "Eth44/2(Port44)"], + "4x25G[10G](4)": ["Eth44/1(Port44)", "Eth44/2(Port44)", "Eth44/3(Port44)", "Eth44/4(Port44)"] + } + }, + + "Ethernet352": { + "index": "45,45,45,45,45,45,45,45", + "lanes": "26,27,28,29,30,31,32,33", + "breakout_modes": { + "1x400G": ["Eth45(Port45)"], + "2x200G": ["Eth45/1(Port45)", "Eth45/2(Port45)"], + "4x100G": ["Eth45/1(Port45)", "Eth45/2(Port45)", "Eth45/3(Port45)", "Eth45/4(Port45)"], + "1x100G[40G](4)": ["Eth45(Port45)"], + "2x50G(4)": ["Eth45/1(Port45)", "Eth45/2(Port45)"], + "4x25G[10G](4)": ["Eth45/1(Port45)", "Eth45/2(Port45)", "Eth45/3(Port45)", "Eth45/4(Port45)"] + } + }, + + "Ethernet360": { + "index": "46,46,46,46,46,46,46,46", + "lanes": "18,19,20,21,22,23,24,25", + "breakout_modes": { + "1x400G": ["Eth46(Port46)"], + "2x200G": ["Eth46/1(Port46)", "Eth46/2(Port46)"], + "4x100G": ["Eth46/1(Port46)", "Eth46/2(Port46)", "Eth46/3(Port46)", "Eth46/4(Port46)"], + "1x100G[40G](4)": ["Eth46(Port46)"], + "2x50G(4)": ["Eth46/1(Port46)", "Eth46/2(Port46)"], + "4x25G[10G](4)": ["Eth46/1(Port46)", "Eth46/2(Port46)", "Eth46/3(Port46)", "Eth46/4(Port46)"] + } + }, + + "Ethernet368": { + "index": "47,47,47,47,47,47,47,47", + "lanes": "2,3,4,5,6,7,8,9", + "breakout_modes": { + "1x400G": ["Eth47(Port47)"], + "2x200G": ["Eth47/1(Port47)", "Eth47/2(Port47)"], + "4x100G": ["Eth47/1(Port47)", "Eth47/2(Port47)", "Eth47/3(Port47)", "Eth47/4(Port47)"], + "1x100G[40G](4)": ["Eth47(Port47)"], + "2x50G(4)": ["Eth47/1(Port47)", "Eth47/2(Port47)"], + "4x25G[10G](4)": ["Eth47/1(Port47)", "Eth47/2(Port47)", "Eth47/3(Port47)", "Eth47/4(Port47)"] + } + }, + + "Ethernet376": { + "index": "48,48,48,48,48,48,48,48", + "lanes": "10,11,12,13,14,15,16,17", + "breakout_modes": { + "1x400G": ["Eth48(Port48)"], + "2x200G": ["Eth48/1(Port48)", "Eth48/2(Port48)"], + "4x100G": ["Eth48/1(Port48)", "Eth48/2(Port48)", "Eth48/3(Port48)", "Eth48/4(Port48)"], + "1x100G[40G](4)": ["Eth48(Port48)"], + "2x50G(4)": ["Eth48/1(Port48)", "Eth48/2(Port48)"], + "4x25G[10G](4)": ["Eth48/1(Port48)", "Eth48/2(Port48)", "Eth48/3(Port48)", "Eth48/4(Port48)"] + } + }, + + "Ethernet384": { + "index": "49,49,49,49,49,49,49,49", + "lanes": "498,499,500,501,502,503,504,505", + "breakout_modes": { + "1x400G": ["Eth49(Port49)"], + "2x200G": ["Eth49/1(Port49)", "Eth49/2(Port49)"], + "4x100G": ["Eth49/1(Port49)", "Eth49/2(Port49)", "Eth49/3(Port49)", "Eth49/4(Port49)"], + "1x100G[40G](4)": ["Eth49(Port49)"], + "2x50G(4)": ["Eth49/1(Port49)", "Eth49/2(Port49)"], + "4x25G[10G](4)": ["Eth49/1(Port49)", "Eth49/2(Port49)", "Eth49/3(Port49)", "Eth49/4(Port49)"] + } + }, + + "Ethernet392": { + "index": "50,50,50,50,50,50,50,50", + "lanes": "506,507,508,509,510,511,512,513", + "breakout_modes": { + "1x400G": ["Eth50(Port50)"], + "2x200G": ["Eth50/1(Port50)", "Eth50/2(Port50)"], + "4x100G": ["Eth50/1(Port50)", "Eth50/2(Port50)", "Eth50/3(Port50)", "Eth50/4(Port50)"], + "1x100G[40G](4)": ["Eth50(Port50)"], + "2x50G(4)": ["Eth50/1(Port50)", "Eth50/2(Port50)"], + "4x25G[10G](4)": ["Eth50/1(Port50)", "Eth50/2(Port50)", "Eth50/3(Port50)", "Eth50/4(Port50)"] + } + }, + + "Ethernet400": { + "index": "51,51,51,51,51,51,51,51", + "lanes": "490,491,492,493,494,495,496,497", + "breakout_modes": { + "1x400G": ["Eth51(Port51)"], + "2x200G": ["Eth51/1(Port51)", "Eth51/2(Port51)"], + "4x100G": ["Eth51/1(Port51)", "Eth51/2(Port51)", "Eth51/3(Port51)", "Eth51/4(Port51)"], + "1x100G[40G](4)": ["Eth51(Port51)"], + "2x50G(4)": ["Eth51/1(Port51)", "Eth51/2(Port51)"], + "4x25G[10G](4)": ["Eth51/1(Port51)", "Eth51/2(Port51)", "Eth51/3(Port51)", "Eth51/4(Port51)"] + } + }, + + "Ethernet408": { + "index": "52,52,52,52,52,52,52,52", + "lanes": "482,483,484,485,486,487,488,489", + "breakout_modes": { + "1x400G": ["Eth52(Port52)"], + "2x200G": ["Eth52/1(Port52)", "Eth52/2(Port52)"], + "4x100G": ["Eth52/1(Port52)", "Eth52/2(Port52)", "Eth52/3(Port52)", "Eth52/4(Port52)"], + "1x100G[40G](4)": ["Eth52(Port52)"], + "2x50G(4)": ["Eth52/1(Port52)", "Eth52/2(Port52)"], + "4x25G[10G](4)": ["Eth52/1(Port52)", "Eth52/2(Port52)", "Eth52/3(Port52)", "Eth52/4(Port52)"] + } + }, + + "Ethernet416": { + "index": "53,53,53,53,53,53,53,53", + "lanes": "474,475,476,477,478,479,480,481", + "breakout_modes": { + "1x400G": ["Eth53(Port53)"], + "2x200G": ["Eth53/1(Port53)", "Eth53/2(Port53)"], + "4x100G": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"], + "1x100G[40G](4)": ["Eth53(Port53)"], + "2x50G(4)": ["Eth53/1(Port53)", "Eth53/2(Port53)"], + "4x25G[10G](4)": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"] + } + }, + + "Ethernet424": { + "index": "54,54,54,54,54,54,54,54", + "lanes": "418,419,420,421,422,423,424,425", + "breakout_modes": { + "1x400G": ["Eth54(Port54)"], + "2x200G": ["Eth54/1(Port54)", "Eth54/2(Port54)"], + "4x100G": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"], + "1x100G[40G](4)": ["Eth54(Port54)"], + "2x50G(4)": ["Eth54/1(Port54)", "Eth54/2(Port54)"], + "4x25G[10G](4)": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"] + } + }, + + "Ethernet432": { + "index": "55,55,55,55,55,55,55,55", + "lanes": "466,467,468,469,470,471,472,473", + "breakout_modes": { + "1x400G": ["Eth55(Port55)"], + "2x200G": ["Eth55/1(Port55)", "Eth55/2(Port55)"], + "4x100G": ["Eth55/1(Port55)", "Eth55/2(Port55)", "Eth55/3(Port55)", "Eth55/4(Port55)"], + "1x100G[40G](4)": ["Eth55(Port55)"], + "2x50G(4)": ["Eth55/1(Port55)", "Eth55/2(Port55)"], + "4x25G[10G](4)": ["Eth55/1(Port55)", "Eth55/2(Port55)", "Eth55/3(Port55)", "Eth55/4(Port55)"] + } + }, + + "Ethernet440": { + "index": "56,56,56,56,56,56,56,56", + "lanes": "434,435,436,437,438,439,440,441", + "breakout_modes": { + "1x400G": ["Eth56(Port56)"], + "2x200G": ["Eth56/1(Port56)", "Eth56/2(Port56)"], + "4x100G": ["Eth56/1(Port56)", "Eth56/2(Port56)", "Eth56/3(Port56)", "Eth56/4(Port56)"], + "1x100G[40G](4)": ["Eth56(Port56)"], + "2x50G(4)": ["Eth56/1(Port56)", "Eth56/2(Port56)"], + "4x25G[10G](4)": ["Eth56/1(Port56)", "Eth56/2(Port56)", "Eth56/3(Port56)", "Eth56/4(Port56)"] + } + }, + + "Ethernet448": { + "index": "57,57,57,57,57,57,57,57", + "lanes": "458,459,460,461,462,463,464,465", + "breakout_modes": { + "1x400G": ["Eth57(Port57)"], + "2x200G": ["Eth57/1(Port57)", "Eth57/2(Port57)"], + "4x100G": ["Eth57/1(Port57)", "Eth57/2(Port57)", "Eth57/3(Port57)", "Eth57/4(Port57)"], + "1x100G[40G](4)": ["Eth57(Port57)"], + "2x50G(4)": ["Eth57/1(Port57)", "Eth57/2(Port57)"], + "4x25G[10G](4)": ["Eth57/1(Port57)", "Eth57/2(Port57)", "Eth57/3(Port57)", "Eth57/4(Port57)"] + } + }, + + "Ethernet456": { + "index": "58,58,58,58,58,58,58,58", + "lanes": "426,427,428,429,430,431,432,433", + "breakout_modes": { + "1x400G": ["Eth58(Port58)"], + "2x200G": ["Eth58/1(Port58)", "Eth58/2(Port58)"], + "4x100G": ["Eth58/1(Port58)", "Eth58/2(Port58)", "Eth58/3(Port58)", "Eth58/4(Port58)"], + "1x100G[40G](4)": ["Eth58(Port58)"], + "2x50G(4)": ["Eth58/1(Port58)", "Eth58/2(Port58)"], + "4x25G[10G](4)": ["Eth58/1(Port58)", "Eth58/2(Port58)", "Eth58/3(Port58)", "Eth58/4(Port58)"] + } + }, + + "Ethernet464": { + "index": "59,59,59,59,59,59,59,59", + "lanes": "450,451,452,453,454,455,456,457", + "breakout_modes": { + "1x400G": ["Eth59(Port59)"], + "2x200G": ["Eth59/1(Port59)", "Eth59/2(Port59)"], + "4x100G": ["Eth59/1(Port59)", "Eth59/2(Port59)", "Eth59/3(Port59)", "Eth59/4(Port59)"], + "1x100G[40G](4)": ["Eth59(Port59)"], + "2x50G(4)": ["Eth59/1(Port59)", "Eth59/2(Port59)"], + "4x25G[10G](4)": ["Eth59/1(Port59)", "Eth59/2(Port59)", "Eth59/3(Port59)", "Eth59/4(Port59)"] + } + }, + + "Ethernet472": { + "index": "60,60,60,60,60,60,60,60", + "lanes": "442,443,444,445,446,447,448,449", + "breakout_modes": { + "1x400G": ["Eth60(Port60)"], + "2x200G": ["Eth60/1(Port60)", "Eth60/2(Port60)"], + "4x100G": ["Eth60/1(Port60)", "Eth60/2(Port60)", "Eth60/3(Port60)", "Eth60/4(Port60)"], + "1x100G[40G](4)": ["Eth60(Port60)"], + "2x50G(4)": ["Eth60/1(Port60)", "Eth60/2(Port60)"], + "4x25G[10G](4)": ["Eth60/1(Port60)", "Eth60/2(Port60)", "Eth60/3(Port60)", "Eth60/4(Port60)"] + } + }, + + "Ethernet480": { + "index": "61,61,61,61,61,61,61,61", + "lanes": "386,387,388,389,390,391,392,393", + "breakout_modes": { + "1x400G": ["Eth61(Port61)"], + "2x200G": ["Eth61/1(Port61)", "Eth61/2(Port61)"], + "4x100G": ["Eth61/1(Port61)", "Eth61/2(Port61)", "Eth61/3(Port61)", "Eth61/4(Port61)"], + "1x100G[40G](4)": ["Eth61(Port61)"], + "2x50G(4)": ["Eth61/1(Port61)", "Eth61/2(Port61)"], + "4x25G[10G](4)": ["Eth61/1(Port61)", "Eth61/2(Port61)", "Eth61/3(Port61)", "Eth61/4(Port61)"] + } + }, + + "Ethernet488": { + "index": "62,62,62,62,62,62,62,62", + "lanes": "402,403,404,405,406,407,408,409", + "breakout_modes": { + "1x400G": ["Eth62(Port62)"], + "2x200G": ["Eth62/1(Port62)", "Eth62/2(Port62)"], + "4x100G": ["Eth62/1(Port62)", "Eth62/2(Port62)", "Eth62/3(Port62)", "Eth62/4(Port62)"], + "1x100G[40G](4)": ["Eth62(Port62)"], + "2x50G(4)": ["Eth62/1(Port62)", "Eth62/2(Port62)"], + "4x25G[10G](4)": ["Eth62/1(Port62)", "Eth62/2(Port62)", "Eth62/3(Port62)", "Eth62/4(Port62)"] + } + }, + + "Ethernet496": { + "index": "63,63,63,63,63,63,63,63", + "lanes": "394,395,396,397,398,399,400,401", + "breakout_modes": { + "1x400G": ["Eth63(Port63)"], + "2x200G": ["Eth63/1(Port63)", "Eth63/2(Port63)"], + "4x100G": ["Eth63/1(Port63)", "Eth63/2(Port63)", "Eth63/3(Port63)", "Eth63/4(Port63)"], + "1x100G[40G](4)": ["Eth63(Port63)"], + "2x50G(4)": ["Eth63/1(Port63)", "Eth63/2(Port63)"], + "4x25G[10G](4)": ["Eth63/1(Port63)", "Eth63/2(Port63)", "Eth63/3(Port63)", "Eth63/4(Port63)"] + } + }, + + "Ethernet504": { + "index": "64,64,64,64,64,64,64,64", + "lanes": "410,411,412,413,414,415,416,417", + "breakout_modes": { + "1x400G": ["Eth64(Port64)"], + "2x200G": ["Eth64/1(Port64)", "Eth64/2(Port64)"], + "4x100G": ["Eth64/1(Port64)", "Eth64/2(Port64)", "Eth64/3(Port64)", "Eth64/4(Port64)"], + "1x100G[40G](4)": ["Eth64(Port64)"], + "2x50G(4)": ["Eth64/1(Port64)", "Eth64/2(Port64)"], + "4x25G[10G](4)": ["Eth64/1(Port64)", "Eth64/2(Port64)", "Eth64/3(Port64)", "Eth64/4(Port64)"] + } + }, + + "Ethernet512": { + "index": "65", + "lanes": "514", + "breakout_modes": { + "1x10G[1G]": ["Eth65(Port65)"] + } + }, + + "Ethernet513": { + "index": "66", + "lanes": "516", + "breakout_modes": { + "1x10G[1G]": ["Eth66(Port66)"] + } + } + } +} + diff --git a/device/accton/x86_64-accton_as9736_64d-r0/platform_asic b/device/accton/x86_64-accton_as9736_64d-r0/platform_asic new file mode 100644 index 000000000000..960467652765 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/accton/x86_64-accton_as9736_64d-r0/platform_env.conf b/device/accton/x86_64-accton_as9736_64d-r0/platform_env.conf new file mode 100644 index 000000000000..aee1c756bf5e --- /dev/null +++ b/device/accton/x86_64-accton_as9736_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_as9736_64d-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as9736_64d-r0/plugins/eeprom.py new file mode 100755 index 000000000000..dbaed20ff8f0 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/plugins/eeprom.py @@ -0,0 +1,13 @@ +try: + from sonic_eeprom import eeprom_tlvinfo + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/20-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as9736_64d-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as9736_64d-r0/plugins/psuutil.py new file mode 100755 index 000000000000..23e9be4b986c --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/plugins/psuutil.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "33-0050", + 2: "41-0051", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as9736_64d-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as9736_64d-r0/plugins/sfputil.py new file mode 100755 index 000000000000..805d846a0f0f --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/plugins/sfputil.py @@ -0,0 +1,210 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + QSFP_PORT_END = 64 + PORT_END = 66 + PORTS_IN_BLOCK = 66 + + FPGA_PCIE_PATH = "/sys/devices/platform/as9736_64d_fpga/" + PCIE_UDB_EEPROM_PATH = '/sys/devices/platform/pcie_udb_fpga_device.{0}/eeprom' + PCIE_LDB_EEPROM_PATH = '/sys/devices/platform/pcie_ldb_fpga_device.{0}/eeprom' + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK - 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + + for x in range(self.port_start, self.port_end+1): + if x <= 32: + self.port_to_eeprom_mapping[x] = self.PCIE_UDB_EEPROM_PATH.format(x - 1) + else: + self.port_to_eeprom_mapping[x] = self.PCIE_LDB_EEPROM_PATH.format(x - 33) + + SfpUtilBase.__init__(self) + + def __write_txt_file(self, file_path, value): + try: + reg_file = open(file_path, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_file.write(str(value)) + reg_file.close() + + return True + + def get_presence(self, port_num): + present_path = self.FPGA_PCIE_PATH + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + try: + val_file = open(present_path) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num > self.QSFP_PORT_END: #sfp not support lpmode + return False + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num > self.QSFP_PORT_END: #sfp not support lpmode: + return False + + try: + eeprom = None + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + # 0x3:Low Power Mode. "Power override" bit is 1 and "Power set" bit is 1 + # 0x9:High Power Mode. "Power override" bit is 1 ,"Power set" bit is 0 and "High Power Class Enable" bit is 1 + regval = 0x3 if lpmode else 0x9 + + buffer = create_string_buffer(1) + buffer[0] = regval + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num > self.QSFP_PORT_END: #sfp not support lpmode: + return False + if not self.get_presence(port_num): + return False # Port is not present, unable to set reset + + mod_rst_path = self.FPGA_PCIE_PATH + "module_reset_" + str(port_num) + + self.__port_to_mod_rst = mod_rst_path + + ret = self.__write_txt_file(self.__port_to_mod_rst, 1) + if ret is not True: + return ret + + time.sleep(0.2) + ret = self.__write_txt_file(self.__port_to_mod_rst, 0) + time.sleep(0.2) + + return ret + + @property + def _get_presence_bitmap(self): + + bits = [] + for x in range(self.port_start, self.port_end + 1): + bits.append(str(int(self.get_presence(x)))) + + rev = "".join(bits[::-1]) + return int(rev, 2) + + data = {'present': 0} + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + + if timeout == 0: + cd_ms = sys.maxsize + else: + cd_ms = timeout + + # poll per second + while cd_ms > 0: + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports != 0: + break + time.sleep(1) + cd_ms = cd_ms - 1000 + + if changed_ports != 0: + for port in range(self.port_start, self.port_end + 1): + # Mask off the bit corresponding to our port + mask = (1 << (port - self.port_start)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + return True, port_dict + else: + return True, {} + diff --git a/device/accton/x86_64-accton_as9736_64d-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as9736_64d-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..44bad6494229 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true +} + diff --git a/device/accton/x86_64-accton_as9736_64d-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as9736_64d-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..7aa53bcf4d30 --- /dev/null +++ b/device/accton/x86_64-accton_as9736_64d-r0/system_health_monitoring_config.json @@ -0,0 +1,14 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "STATUS_LED_COLOR_AMBER", + "normal": "STATUS_LED_COLOR_GREEN", + "booting": "STATUS_LED_COLOR_GREEN_BLINKING" + } +} diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 59a3259c9929..c5eb18d739b5 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -42,6 +42,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_AS5835_54X_PLATFORM_MODULE) \ $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ $(ACCTON_AS9726_32D_PLATFORM_MODULE) \ + $(ACCTON_AS9736_64D_PLATFORM_MODULE) \ $(ACCTON_AS5835_54T_PLATFORM_MODULE) \ $(ACCTON_AS7312_54XS_PLATFORM_MODULE) \ $(ACCTON_AS7315_27XB_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk old mode 100755 new mode 100644 index 85e7ff1f5641..923ff332c489 --- a/platform/broadcom/platform-modules-accton.mk +++ b/platform/broadcom/platform-modules-accton.mk @@ -17,6 +17,7 @@ ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 ACCTON_AS9726_32D_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS9736_64D_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 @@ -38,6 +39,7 @@ export ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION export ACCTON_AS9726_32D_PLATFORM_MODULE_VERSION +export ACCTON_AS9736_64D_PLATFORM_MODULE_VERSION export ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION export ACCTON_AS7312_54XS_PLATFORM_MODULE_VERSION export ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION @@ -116,6 +118,10 @@ ACCTON_AS9726_32D_PLATFORM_MODULE = sonic-platform-accton-as9726-32d_$(ACCTON_AS $(ACCTON_AS9726_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9726_32d-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9726_32D_PLATFORM_MODULE))) +ACCTON_AS9736_64D_PLATFORM_MODULE = sonic-platform-accton-as9736-64d_$(ACCTON_AS9736_64D_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS9736_64D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9736_64d-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9736_64D_PLATFORM_MODULE))) + ACCTON_AS5835_54T_PLATFORM_MODULE = sonic-platform-accton-as5835-54t_$(ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION)_amd64.deb $(ACCTON_AS5835_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54t-r0 $(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54T_PLATFORM_MODULE))) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/fanutil.py new file mode 100755 index 000000000000..ef1a7e657826 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/fanutil.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python +# 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.) +# 12/07/2022:Michael_Shih craete for as9736_64d +# ------------------------------------------------------------------ + +try: + import logging +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 4 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + + FAN_NODE_NUM_OF_MAP = 5 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DUTY_IDX_OF_MAP = 2 + FAN_NODE_FRONT_SPD_OF_MAP = 3 + FAN_NODE_REAR_SPD_OF_MAP = 4 + FAN_NODE_PRESENT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/25-0033/{0}' + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) + """ + _fan_device_path_mapping = {} + + _fan_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP) : 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DUTY_IDX_OF_MAP) : 'fan1_duty_cycle_percentage', + (FAN_NUM_1_IDX, FAN_NODE_FRONT_SPD_OF_MAP) : 'fan1_front_speed_rpm', + (FAN_NUM_1_IDX, FAN_NODE_REAR_SPD_OF_MAP) : 'fan1_rear_speed_rpm', + (FAN_NUM_1_IDX, FAN_NODE_PRESENT_IDX_OF_MAP): 'fan1_present', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP) : 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP) : 'fan2_duty_cycle_percentage', + (FAN_NUM_2_IDX, FAN_NODE_FRONT_SPD_OF_MAP) : 'fan2_front_speed_rpm', + (FAN_NUM_2_IDX, FAN_NODE_REAR_SPD_OF_MAP) : 'fan2_rear_speed_rpm', + (FAN_NUM_2_IDX, FAN_NODE_PRESENT_IDX_OF_MAP): 'fan2_present', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP) : 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DUTY_IDX_OF_MAP) : 'fan3_duty_cycle_percentage', + (FAN_NUM_3_IDX, FAN_NODE_FRONT_SPD_OF_MAP) : 'fan3_front_speed_rpm', + (FAN_NUM_3_IDX, FAN_NODE_REAR_SPD_OF_MAP) : 'fan3_rear_speed_rpm', + (FAN_NUM_3_IDX, FAN_NODE_PRESENT_IDX_OF_MAP): 'fan3_present', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP) : 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DUTY_IDX_OF_MAP) : 'fan4_duty_cycle_percentage', + (FAN_NUM_4_IDX, FAN_NODE_FRONT_SPD_OF_MAP) : 'fan4_front_speed_rpm', + (FAN_NUM_4_IDX, FAN_NODE_REAR_SPD_OF_MAP) : 'fan4_rear_speed_rpm', + (FAN_NUM_4_IDX, FAN_NODE_PRESENT_IDX_OF_MAP): 'fan4_present', + } + + #def _get_fan_device_node(self, fan_num, node_num): + # return self._fan_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except IOError: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except BaseException: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_device_path_mapping) + + def get_fan_device_path(self, fan_num, node_num): + return self._fan_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_present(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_PRESENT_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + duty_path = self._fan_device_path_mapping[(self.FAN_NUM_1_IDX, self.FAN_NODE_DUTY_IDX_OF_MAP)] + try: + val_file = open(duty_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + for fan_num in range(1, self.FAN_NUM_ON_MAIN_BROAD + 1): + duty_path = self._fan_device_path_mapping[(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP)] + try: + fan_file = open(duty_path, 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + fan_file.write(str(val)) + fan_file.close() + return True + + def get_fan_front_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FRONT_SPD_OF_MAP) + + def get_fan_rear_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_REAR_SPD_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + return True diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/thermalutil.py new file mode 100755 index 000000000000..cdda12e342c5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/classes/thermalutil.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# 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.) +# 04/06/2021: Michael_Shih craete for as9736_64d +# ------------------------------------------------------------------ + +try: + import logging + import glob +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_BD_SENSOR = 5 + THERMAL_NUM_CPU_CORE = 8 + THERMAL_NUM_MAX = THERMAL_NUM_BD_SENSOR + THERMAL_NUM_CPU_CORE + THERMAL_NUM_1_IDX = 1 #SMB TMP75 + THERMAL_NUM_2_IDX = 2 #UDB TMP75 + THERMAL_NUM_3_IDX = 3 #UDB TMP422 + THERMAL_NUM_4_IDX = 4 #LDB TMP422 + THERMAL_NUM_5_IDX = 5 #TH4 TMP422 + THERMAL_CPU_CORE_0_IDX = 6 #CPU Core Temp + THERMAL_CPU_CORE_1_IDX = 7 + THERMAL_CPU_CORE_2_IDX = 8 + THERMAL_CPU_CORE_3_IDX = 9 + THERMAL_CPU_CORE_4_IDX = 10 + THERMAL_CPU_CORE_5_IDX = 11 + THERMAL_CPU_CORE_6_IDX = 12 + THERMAL_CPU_CORE_7_IDX = 13 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/2-0049/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/57-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/58-004c/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/66-004d/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/14-004c/hwmon/hwmon*/temp1_input"], + THERMAL_CPU_CORE_0_IDX: ["/sys/class/hwmon/hwmon0/temp2_input"], + THERMAL_CPU_CORE_1_IDX: ["/sys/class/hwmon/hwmon0/temp3_input"], + THERMAL_CPU_CORE_2_IDX: ["/sys/class/hwmon/hwmon0/temp4_input"], + THERMAL_CPU_CORE_3_IDX: ["/sys/class/hwmon/hwmon0/temp5_input"], + THERMAL_CPU_CORE_4_IDX: ["/sys/class/hwmon/hwmon0/temp6_input"], + THERMAL_CPU_CORE_5_IDX: ["/sys/class/hwmon/hwmon0/temp7_input"], + THERMAL_CPU_CORE_6_IDX: ["/sys/class/hwmon/hwmon0/temp8_input"], + THERMAL_CPU_CORE_7_IDX: ["/sys/class/hwmon/hwmon0/temp9_input"], + } + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except BaseException: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + return 0 + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/Makefile new file mode 100755 index 000000000000..155c340b24a0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as9736_64d_cpld.o accton_as9736_64d_fan.o \ + accton_as9736_64d_psu.o accton_i2c_psu.o accton_as9736_64d_fpga.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-8-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd *.mod.c .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_cpld.c new file mode 100755 index 000000000000..438698ef82b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_cpld.c @@ -0,0 +1,936 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as9736_64d CPLD1/CPLD2/CPLD3 + * + * 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 + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as9736_64d_fpga, + as9736_64d_cpld_cpu, + as9736_64d_cpld_pdb, + as9736_64d_cpld_scm, + as9736_64d_cpld_udb /*No attribute but add i2c addr to the list.*/ +}; + +struct as9736_64d_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as9736_64d_cpld_id[] = { + { "as9736_64d_fpga", as9736_64d_fpga }, + { "as9736_64d_cpld_cpu", as9736_64d_cpld_cpu }, + { "as9736_64d_cpld_pdb", as9736_64d_cpld_pdb }, + { "as9736_64d_cpld_scm", as9736_64d_cpld_scm }, + { "as9736_64d_cpld_udb", as9736_64d_cpld_udb}, + { } +}; +MODULE_DEVICE_TABLE(i2c, as9736_64d_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index +#define CPLD_INTR_ATTR_ID(index) CPLD_INTR_##index + +enum as9736_64d_cpld_sysfs_attributes { + PSU_RIGHT_PRESENT, + PSU_LEFT_PRESENT, + PSU_LEFT_POWER_GOOD, + PSU_RIGHT_POWER_GOOD, + CPLD_VERSION, + ACCESS, + /* 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_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + 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), + CPLD_INTR_ATTR_ID(1), + CPLD_INTR_ATTR_ID(2), + CPLD_INTR_ATTR_ID(3), + CPLD_INTR_ATTR_ID(4), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static int as9736_64d_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as9736_64d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +/*reset*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +/*cpld interrupt*/ +#define DECLARE_CPLD_DEVICE_INTR_ATTR(index) \ + static SENSOR_DEVICE_ATTR(cpld_intr_##index, S_IRUGO, show_interrupt, NULL, CPLD_INTR_##index) +#define DECLARE_CPLD_INTR_ATTR(index) &sensor_dev_attr_cpld_intr_##index.dev_attr.attr + + +/* CPU-CPLD, CPLD1, CPLD2 Attributes*/ +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, show_status, NULL, PSU_LEFT_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, show_status, NULL, PSU_RIGHT_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_power_good, S_IRUGO, show_status, NULL, PSU_LEFT_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu2_power_good, S_IRUGO, show_status, NULL, PSU_RIGHT_POWER_GOOD); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); +DECLARE_CPLD_DEVICE_INTR_ATTR(1); +DECLARE_CPLD_DEVICE_INTR_ATTR(2); +DECLARE_CPLD_DEVICE_INTR_ATTR(3); +DECLARE_CPLD_DEVICE_INTR_ATTR(4); + + + +static struct attribute *as9736_64d_fpga_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9736_64d_fpga_group = { + .attrs = as9736_64d_fpga_attributes, +}; + +static struct attribute *as9736_64d_cpld_cpu_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_psu1_present.dev_attr.attr, /*left*/ + &sensor_dev_attr_psu2_present.dev_attr.attr, /*right*/ + &sensor_dev_attr_psu1_power_good.dev_attr.attr, /*left*/ + &sensor_dev_attr_psu2_power_good.dev_attr.attr, /*right*/ + NULL +}; + +static struct attribute *as9736_64d_cpld_pdb_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + NULL +}; + +static struct attribute *as9736_64d_cpld_scm_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + NULL +}; + +static struct attribute *as9736_64d_cpld_udb_attributes[] = { + NULL +}; + +static const struct attribute_group as9736_64d_cpld_cpu_group = { + .attrs = as9736_64d_cpld_cpu_attributes, +}; + +static const struct attribute_group as9736_64d_cpld_pdb_group = { + .attrs = as9736_64d_cpld_pdb_attributes, +}; + +static const struct attribute_group as9736_64d_cpld_scm_group = { + .attrs = as9736_64d_cpld_scm_attributes, +}; + +static const struct attribute_group as9736_64d_cpld_udb_group = { + .attrs = as9736_64d_cpld_udb_attributes, +}; + + +static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0; + + switch (attr->index) + { + case CPLD_INTR_1: + reg = 0x10; + break; + case CPLD_INTR_3: + reg = 0x10; + break; + case CPLD_INTR_2: + reg = 0x11; + break; + case CPLD_INTR_4: + reg = 0x11; + break; + default: + return -ENODEV; + } + mutex_lock(&data->update_lock); + status = as9736_64d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "0x%x\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case PSU_RIGHT_PRESENT: + case PSU_LEFT_PRESENT: + reg = 0x14; + mask = 0x1 << attr->index; + revert = 1; + break; + case PSU_LEFT_POWER_GOOD: + case PSU_RIGHT_POWER_GOOD: + reg = 0x90; + mask = 0x1 << (attr->index - PSU_LEFT_POWER_GOOD); + break; + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x20; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x20; + mask = 0x8; + break; + case MODULE_RXLOS_33: + reg = 0x20; + mask = 0x2; + break; + case MODULE_RXLOS_34: + reg = 0x20; + mask = 0x10; + break; + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as9736_64d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as9736_64d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as9736_64d_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as9736_64d_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as9736_64d_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as9736_64d_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val_major = 0, val_minor = 0; + struct i2c_client *client = to_i2c_client(dev); + + val_major = i2c_smbus_read_byte_data(client, 0x1); + val_minor = i2c_smbus_read_byte_data(client, 0x0); + + if (val_major < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val_major); + } + if (val_minor < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x0) err %d\n", client->addr, val_minor); + } + + return sprintf(buf, "%d.%d\n", val_major, val_minor); +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as9736_64d_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as9736_64d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + } + else + { + val =status | (mask); + } + + status = as9736_64d_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +/* + * I2C init/probing/exit functions + */ +static int as9736_64d_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as9736_64d_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as9736_64d_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + + /* Register sysfs hooks */ + switch (data->type) { + case as9736_64d_fpga: + group = &as9736_64d_fpga_group; + break; + case as9736_64d_cpld_cpu: + group = &as9736_64d_cpld_cpu_group; + break; + case as9736_64d_cpld_pdb: + group = &as9736_64d_cpld_pdb_group; + break; + case as9736_64d_cpld_scm: + group = &as9736_64d_cpld_scm_group; + break; + case as9736_64d_cpld_udb: + group = &as9736_64d_cpld_udb_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + if( data->type != as9736_64d_cpld_pdb ) { + as9736_64d_cpld_add_client(client); + } + + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as9736_64d_cpld_remove(struct i2c_client *client) +{ + struct as9736_64d_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as9736_64d_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as9736_64d_fpga: + group = &as9736_64d_fpga_group; + break; + case as9736_64d_cpld_cpu: + group = &as9736_64d_cpld_cpu_group; + break; + case as9736_64d_cpld_pdb: + group = &as9736_64d_cpld_pdb_group; + break; + case as9736_64d_cpld_scm: + group = &as9736_64d_cpld_scm_group; + break; + case as9736_64d_cpld_udb: + group = &as9736_64d_cpld_udb_group; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as9736_64d_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as9736_64d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as9736_64d_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9736_64d_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9736_64d_cpld_read); + +int as9736_64d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9736_64d_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9736_64d_cpld_write); + +static struct i2c_driver as9736_64d_cpld_driver = { + .driver = { + .name = "as9736_64d_cpld", + .owner = THIS_MODULE, + }, + .probe = as9736_64d_cpld_probe, + .remove = as9736_64d_cpld_remove, + .id_table = as9736_64d_cpld_id, +}; + +static int __init as9736_64d_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as9736_64d_cpld_driver); +} + +static void __exit as9736_64d_cpld_exit(void) +{ + i2c_del_driver(&as9736_64d_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as9736_64d_cpld_init); +module_exit(as9736_64d_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_fan.c new file mode 100755 index 000000000000..67177f07b334 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_fan.c @@ -0,0 +1,754 @@ +/* + * A hwmon driver for the Accton as9736-64d fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Michael Shih + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9736_64d_fan" + +#define FAN_DUTY_CYCLE_REG_MASK 0xFF +#define FAN_MAX_DUTY_CYCLE 100 + +int fan_tach_clock[4] = {1048, /*10.48 * 100*/ + 2097, /*20.97 * 100*/ + 4194, /*41.94 * 100*/ + 8389}; /*83.89 * 100*/ + +static struct as9736_64d_fan_data *as9736_64d_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_eeprom_protect(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_power_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_watch_dog(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x00, /* board info */ + 0x01, /* cpld major revision */ + 0x02, /* hw pcb version: R0A, R0B... */ + 0x10, /* fan 1-4 present status, bit3: port1 ~ bit0: port4*/ + 0x18, /* fan 1-4 eeprom un-protect/protect */ + 0x1a, /* fan 1-4 power enable/disable */ + 0x20, /* watchdog enable/disable */ + 0x30, /* fan 1 PWM */ + 0x31, /* fan 2 PWM */ + 0x32, /* fan 3 PWM */ + 0x33, /* fan 4 PWM */ + 0x40, /* fan 1 front tach speed(rpm) */ + 0x41, /* fan 2 front tach speed(rpm) */ + 0x42, /* fan 3 front tach speed(rpm) */ + 0x43, /* fan 4 front tach speed(rpm) */ + 0x50, /* fan 1 rear tach speed(rpm) */ + 0x51, /* fan 2 rear tach speed(rpm) */ + 0x52, /* fan 3 rear tach speed(rpm) */ + 0x53, /* fan 4 rear tach speed(rpm) */ + 0x90, /* fan tach speed setting */ +}; + +/* Each client has this additional data */ +struct as9736_64d_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, +}; + +enum sysfs_fan_attributes { + FAN_BOARD_INFO_REG, + FAN_CPLD_REVISION_REG, + FAN_HW_REVISION_REG, + FAN_PRESENT_REG, + FAN_EEPROM_PROTECT_REG, + FAN_POWER_ENABLE_REG, + FAN_WATCHDOG_REG, + FAN1_DUTY_CYCLE_PERCENTAGE, + FAN2_DUTY_CYCLE_PERCENTAGE, + FAN3_DUTY_CYCLE_PERCENTAGE, + FAN4_DUTY_CYCLE_PERCENTAGE, + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN_TACH_SPEED_REG, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN1_EEPROM_PROTECT, + FAN2_EEPROM_PROTECT, + FAN3_EEPROM_PROTECT, + FAN4_EEPROM_PROTECT, + FAN1_POWER_ENABLE, + FAN2_POWER_ENABLE, + FAN3_POWER_ENABLE, + FAN4_POWER_ENABLE, + FAN_TACH_SPEED_CLOCK, + FAN_TACH_SPEED_COUNTER, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN_VERSION +}; + +/*********************************************************************** + * Define attributes + ***********************************************************************/ +/*fan present*/ +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +/*eeprom protect*/ +#define DECLARE_FAN_EEPROM_PROTECT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_eeprom, S_IWUSR | S_IRUGO, fan_show_value, set_eeprom_protect, FAN##index##_EEPROM_PROTECT) +#define DECLARE_FAN_EEPROM_PROTECT_ATTR(index) &sensor_dev_attr_fan##index##_eeprom.dev_attr.attr + +/*power enable*/ +#define DECLARE_FAN_POWER_ENABLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_power, S_IWUSR | S_IRUGO, fan_show_value, set_power_enable, FAN##index##_POWER_ENABLE) +#define DECLARE_FAN_POWER_ENABLE_ATTR(index) &sensor_dev_attr_fan##index##_power.dev_attr.attr + +/*fan duty cycle percentage*/ +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +/*fan speed(RPM)*/ +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/*fan fault*/ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +/*********************************************************************** + * Extend attributes + ***********************************************************************/ +static SENSOR_DEVICE_ATTR(version, S_IRUGO, fan_show_value, NULL, FAN_VERSION); +static SENSOR_DEVICE_ATTR(board_info, S_IRUGO, fan_show_value, NULL, FAN_BOARD_INFO_REG); +static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, fan_show_value, NULL, FAN_CPLD_REVISION_REG); +static SENSOR_DEVICE_ATTR(hw_ver, S_IRUGO, fan_show_value, NULL, FAN_HW_REVISION_REG); +static SENSOR_DEVICE_ATTR(watch_dog, S_IWUSR | S_IRUGO, fan_show_value, set_watch_dog, FAN_WATCHDOG_REG); +static SENSOR_DEVICE_ATTR(fan_tach_speed_clk, S_IRUGO, fan_show_value, NULL, FAN_TACH_SPEED_CLOCK); +static SENSOR_DEVICE_ATTR(fan_tach_speed_cnt, S_IRUGO, fan_show_value, NULL, FAN_TACH_SPEED_COUNTER); +/* 4 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +/* 4 fan eeprom protect attributes in this platform */ +DECLARE_FAN_EEPROM_PROTECT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_EEPROM_PROTECT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_EEPROM_PROTECT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_EEPROM_PROTECT_SENSOR_DEV_ATTR(4); +/* 4 fan power enable attributes in this platform */ +DECLARE_FAN_POWER_ENABLE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_POWER_ENABLE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_POWER_ENABLE_SENSOR_DEV_ATTR(3); +DECLARE_FAN_POWER_ENABLE_SENSOR_DEV_ATTR(4); +/* 4 fan duty cycle percentage attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(4); +/* 4 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +/* 4 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); + +/*********************************************************************** + * Define sysfs + ***********************************************************************/ +static struct attribute *as9736_64d_fan_attributes[] = { + /* fan related attributes */ + &sensor_dev_attr_board_info.dev_attr.attr, + &sensor_dev_attr_cpld_ver.dev_attr.attr, + &sensor_dev_attr_hw_ver.dev_attr.attr, + &sensor_dev_attr_watch_dog.dev_attr.attr, + &sensor_dev_attr_fan_tach_speed_clk.dev_attr.attr, + &sensor_dev_attr_fan_tach_speed_cnt.dev_attr.attr, + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_EEPROM_PROTECT_ATTR(1), + DECLARE_FAN_EEPROM_PROTECT_ATTR(2), + DECLARE_FAN_EEPROM_PROTECT_ATTR(3), + DECLARE_FAN_EEPROM_PROTECT_ATTR(4), + DECLARE_FAN_POWER_ENABLE_ATTR(1), + DECLARE_FAN_POWER_ENABLE_ATTR(2), + DECLARE_FAN_POWER_ENABLE_ATTR(3), + DECLARE_FAN_POWER_ENABLE_ATTR(4), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_DUTY_CYCLE_ATTR(2), + DECLARE_FAN_DUTY_CYCLE_ATTR(3), + DECLARE_FAN_DUTY_CYCLE_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + &sensor_dev_attr_version.dev_attr.attr, + NULL +}; + + +static int as9736_64d_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as9736_64d_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + u32 duty_cycle = 0; + + switch(reg_val) + { + case 0: + duty_cycle = 0; + break; + case 25: /*0x19*/ + duty_cycle = 10; + break; + case 51: /*0x33*/ + duty_cycle = 20; + break; + case 76: /*0x4c*/ + duty_cycle = 30; + break; + case 102: /*0x66*/ + duty_cycle = 40; + break; + case 127: /*0x7F*/ + duty_cycle = 50; + break; + case 153: /*0x99*/ + duty_cycle = 60; + break; + case 179: /*0xB3*/ + duty_cycle = 70; + break; + case 204: /*0xCC*/ + duty_cycle = 80; + break; + case 229: /*0xE5*/ + duty_cycle = 90; + break; + default: /*0xFF*/ + duty_cycle = 100; + break; + } + + return duty_cycle; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val, u8 tach_speed) +{ + int fan_tach_clk_index = (tach_speed >> 6) & 0x3; + int fan_tach_cnt = tach_speed & 0x3F; + /* + Coculation formula = reg_val/(fan_clk*can_cnt)*1000/2*60 = [(reg_val)*30000] / fan_clk*can_cnt + */ + return (u32)( (reg_val * 30000 * 100) / (fan_tach_clock[fan_tach_clk_index] * fan_tach_cnt) ); +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << (id) ); + + reg_val &= mask; /*reg: 0 is present, 1 is not present*/ + + return reg_val ? 0 : 1; /*turn to : 0 is not present, 1 is present*/ +} + +static u8 is_fan_fault(struct as9736_64d_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = id + 11; /*fan1=11, fan2=12, fan3=13, fan4=14*/ + int rear_fan_index = front_fan_index + 4; /*fan1=15, fan2=16, fan3=17, fan4=18*/ + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index], data->reg_val[FAN_TACH_SPEED_REG]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index], data->reg_val[FAN_TACH_SPEED_REG]) ) { + ret = 0; + } + + return ret; +} + +static u8 reg_val_to_is_eeprom_protect(u8 reg_val, enum fan_id id) +{ + u8 mask = 0x1; + reg_val = reg_val >> (id); + reg_val &= mask; /*reg: 0 is unprotect, 1 is protect*/ + + return reg_val; +} + +static u8 reg_val_to_is_power_enable(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << (3 - id) ); + + reg_val &= mask; /*reg: 0 is enable, 1 is disable*/ + + return reg_val ? 0 : 1; /*turn to : 0 is disable, 1 is enable*/ +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 duty_cycle = 0; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + switch(value) + { + case 0: + duty_cycle = 0; + break; + case 1 ... 10: + duty_cycle = 25; + break; + case 11 ... 20: + duty_cycle = 51; + break; + case 21 ... 30: + duty_cycle = 76; + break; + case 31 ... 40: + duty_cycle = 102; + break; + case 41 ... 50: + duty_cycle = 127; + break; + case 51 ... 60: + duty_cycle = 153; + break; + case 61 ... 70: + duty_cycle = 179; + break; + case 71 ... 80: + duty_cycle = 204; + break; + case 81 ... 90: + duty_cycle = 229; + break; + default: + duty_cycle = 255; + break; + } + + switch (attr->index) { + case FAN1_DUTY_CYCLE_PERCENTAGE: + as9736_64d_fan_write_value(client, fan_reg[FAN1_DUTY_CYCLE_PERCENTAGE], duty_cycle); + break; + case FAN2_DUTY_CYCLE_PERCENTAGE: + as9736_64d_fan_write_value(client, fan_reg[FAN2_DUTY_CYCLE_PERCENTAGE], duty_cycle); + break; + case FAN3_DUTY_CYCLE_PERCENTAGE: + as9736_64d_fan_write_value(client, fan_reg[FAN3_DUTY_CYCLE_PERCENTAGE], duty_cycle); + break; + default: + as9736_64d_fan_write_value(client, fan_reg[FAN4_DUTY_CYCLE_PERCENTAGE], duty_cycle); + break; + } + + return count; +} + +static u8 set_reg_bit(u8 reg_val, u8 number_bit, u8 value) +{ + int chk_bit, i; + u8 high_bytes, lower_bytes; + u8 mask = 0x0; + chk_bit = (reg_val >> number_bit) & 0x1; + + if( chk_bit==value ) { + return reg_val; + } else { + for( i = 1 ; i <= number_bit ; i++ ) { + mask |= 1 << (i-1); + } + lower_bytes = reg_val & mask; + high_bytes = reg_val & ( (~mask << 1) ); + + return (u8)( high_bytes | (value << number_bit) | lower_bytes ); + } +} + +static ssize_t set_eeprom_protect(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int reg_val, port_bit; + int error, value; + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_fan_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + reg_val = as9736_64d_fan_read_value(client, fan_reg[FAN_EEPROM_PROTECT_REG]); + port_bit = (3 - (attr->index - FAN1_EEPROM_PROTECT) ); + + mutex_lock(&data->update_lock); + as9736_64d_fan_write_value(client, fan_reg[FAN_EEPROM_PROTECT_REG], set_reg_bit(reg_val, port_bit, value)); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t set_power_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int reg_val, port_bit; + int error, value; + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_fan_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + reg_val = as9736_64d_fan_read_value(client, fan_reg[FAN_POWER_ENABLE_REG]); + port_bit = (3 - (attr->index - FAN1_POWER_ENABLE) ); + + mutex_lock(&data->update_lock); + as9736_64d_fan_write_value(client, fan_reg[FAN_POWER_ENABLE_REG], set_reg_bit(reg_val, port_bit, value ? 0 : 1)); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t set_watch_dog(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_fan_data *data = i2c_get_clientdata(client); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + mutex_lock(&data->update_lock); + as9736_64d_fan_write_value(client, fan_reg[FAN_WATCHDOG_REG], value); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9736_64d_fan_data *data = as9736_64d_fan_update_device(dev); + ssize_t ret = 0; + u32 duty_cycle = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_VERSION: + ret = sprintf(buf, "%d.%d\n", (data->reg_val[FAN_CPLD_REVISION_REG]) & 0x7F, (data->reg_val[FAN_BOARD_INFO_REG]) & 0xFF); + break; + case FAN_BOARD_INFO_REG: + ret = sprintf(buf, "0x%x\n", (data->reg_val[FAN_BOARD_INFO_REG]) & 0xF); + break; + case FAN_CPLD_REVISION_REG: + ret = sprintf(buf, "0x%x\n", (data->reg_val[FAN_CPLD_REVISION_REG]) & 0xF); + break; + case FAN_HW_REVISION_REG: + ret = sprintf(buf, "0x%x\n", (data->reg_val[FAN_HW_REVISION_REG]) & 0xFF); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + ret = sprintf(buf, "%d\n", reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT) ); + break; + case FAN1_EEPROM_PROTECT: + case FAN2_EEPROM_PROTECT: + case FAN3_EEPROM_PROTECT: + case FAN4_EEPROM_PROTECT: + ret = sprintf(buf, "%d\n", reg_val_to_is_eeprom_protect(data->reg_val[FAN_EEPROM_PROTECT_REG], + attr->index - FAN1_EEPROM_PROTECT) ); + break; + case FAN1_POWER_ENABLE: + case FAN2_POWER_ENABLE: + case FAN3_POWER_ENABLE: + case FAN4_POWER_ENABLE: + ret = sprintf(buf, "%d\n", + reg_val_to_is_power_enable(data->reg_val[FAN_POWER_ENABLE_REG], + attr->index - FAN1_POWER_ENABLE) ); + break; + case FAN_WATCHDOG_REG: + ret = sprintf(buf, "%x\n", (data->reg_val[FAN_WATCHDOG_REG]) & 0x1); + break; + case FAN1_DUTY_CYCLE_PERCENTAGE: + duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN1_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + case FAN2_DUTY_CYCLE_PERCENTAGE: + duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN2_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + case FAN3_DUTY_CYCLE_PERCENTAGE: + duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN3_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + case FAN4_DUTY_CYCLE_PERCENTAGE: + { + duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN4_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index], data->reg_val[FAN_TACH_SPEED_REG])); + break; + case FAN_TACH_SPEED_CLOCK: + ret = sprintf(buf, "%d\n", ((data->reg_val[FAN_TACH_SPEED_REG]) >> 6) & 0x3); /*reg: 0x90, upper 2 bits*/ + break; + case FAN_TACH_SPEED_COUNTER: + ret = sprintf(buf, "%d\n", (data->reg_val[FAN_TACH_SPEED_REG]) & 0x3F); /*reg: 0x90, lower 6 bits*/ + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as9736_64d_fan_group = { + .attrs = as9736_64d_fan_attributes, +}; + +static struct as9736_64d_fan_data *as9736_64d_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as9736_64d_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as9736_64d_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as9736_64d_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9736_64d_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9736_64d_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9736_64d_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9736_64d_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9736_64d_fan_remove(struct i2c_client *client) +{ + struct as9736_64d_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9736_64d_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as9736_64d_fan_id[] = { + { "as9736_64d_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9736_64d_fan_id); + +static struct i2c_driver as9736_64d_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as9736_64d_fan_probe, + .remove = as9736_64d_fan_remove, + .id_table = as9736_64d_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as9736_64d_fan_driver); + +MODULE_AUTHOR("Michael Shih "); +MODULE_DESCRIPTION("as9736_64d_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_fpga.c b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_fpga.c new file mode 100755 index 000000000000..dac99a5cad95 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_fpga.c @@ -0,0 +1,2513 @@ +/* + * Copyright (C) Michael Shih + * + * This module supports the accton fpga via pcie that read/write reg + * mechanism to get QSFP/SFP status, eeprom info...etc. + * This includes the: + * Accton as9736_64d UDB/LDB + * + * Based on: + * optoe.c fromDON BOLLINGER + * 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 + +/*********************************************** + * variable define + * *********************************************/ +#define DRVNAME "as9736_64d_fpga" +/* + * PCIE BAR0 address of UDB and LDB + */ +#define BAR0_NUM 0 +#define PCI_VENDOR_ID_ACCTON 0x1113 +#define PCI_DEVICE_ID_ACCTON 0x8664 +#define PCI_SUBSYSTEM_ID_UDB 0x0000 +#define PCI_SUBSYSTEM_ID_LDB 0x0001 +#define PCI_SUBSYSTEM_ID_SMB 0x0002 + +#define QSFP_PRESENT_REG_OFFSET 0x1500 +#define QSFP_LPMODE_REG_OFFSET 0x1550 +#define QSFP_RESET_REG_OFFSET 0x1560 + +#define SFP_LDB_GPIO1_DATA_EN 0x1000 +#define SFP_LDB_GPIO1_DATA_OUT 0x1004 +#define SFP_LDB_GPIO1_DATA_IN 0x1008 + +#define ASLPC_DEV_UDB_CPLD1_PCIE_START_OFFST 0x400 +#define ASLPC_DEV_UDB_CPLD2_PCIE_START_OFFST 0x500 +#define ASLPC_DEV_LDB_CPLD1_PCIE_START_OFFST 0x400 +#define ASLPC_DEV_LDB_CPLD2_PCIE_START_OFFST 0x500 +#define ASLPC_DEV_SMB_CPLD_PCIE_START_OFFST 0x200 + +#define REG_SET_ALL_32_BITS 32 +#define REG_SET_32_BITS_TO_0 0x00000000 +#define REG_SET_32_BITS_TO_1 0xFFFFFFFF +#define BIT(x) x +#define SFP_PORT0_TXDIS(x) ((x) >> (11)) +#define SFP_PORT0_ABS(x) ((x) >> (10)) +#define SFP_PORT0_TXFLT(x) ((x) >> (9)) +#define SFP_PORT0_RXLOS(x) ((x) >> (8)) +#define SFP_PORT1_TXDIS(x) ((x) >> (3)) +#define SFP_PORT1_ABS(x) ((x) >> (2)) +#define SFP_PORT1_TXFLT(x) ((x) >> (1)) +#define SFP_PORT1_RXLOS(x) ((x) >> (0)) + +#define QSFP_NUM_OF_PORT 64 +#define SFP_NUM_OF_PORT 2 +#define FPGA_NUM 3 + +#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 + +/* + *PCIE port dev define + */ +#define EEPROM_SYSFS_NAME "eeprom" + +#define FPGA_UDB_QSFP_PORT_NUM 32 +#define FPGA_LDB_QSFP_PORT_NUM 32 +#define FPGA_QSFP_PORT_NUM (FPGA_UDB_QSFP_PORT_NUM + FPGA_LDB_QSFP_PORT_NUM) +#define FPGA_LDB_SFP_PORT1_NO 65 +#define FPGA_LDB_SFP_PORT2_NO 66 +#define FPGA_LDB_SFP_PORT_NUM 2 + +#define QSFPDD_TYPE 0x18 +/* fundamental unit of addressing for EEPROM */ +#define OPTOE_PAGE_SIZE 128 +/* + * Single address devices (eg QSFP, CMIS) have 256 pages, plus the unpaged + * low 128 bytes. If the device does not support paging, it is + * only 2 'pages' long. + */ +#define OPTOE_ARCH_PAGES 256 +#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) +#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) +/* + * Dual address devices (eg SFP) have 256 pages, plus the unpaged + * low 128 bytes, plus 256 bytes at 0x50. If the device does not + * support paging, it is 4 'pages' long. + */ +#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) +#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) +#define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define OPTOE_PAGE_SELECT_REG 0x7F +#define ONE_ADDR_PAGEABLE_REG 0x02 +#define QSFP_NOT_PAGEABLE (1<<2) +#define CMIS_NOT_PAGEABLE (1<<7) +#define TWO_ADDR_PAGEABLE_REG 0x40 +#define TWO_ADDR_PAGEABLE (1<<4) +#define TWO_ADDR_0X51_REG 92 +#define TWO_ADDR_0X51_SUPP (1<<6) +#define OPTOE_READ_OP 0 +#define OPTOE_WRITE_OP 1 +#define OPTOE_EOF 0 /* used for access beyond end of device */ +#define TWO_ADDR_0X51 0x51 +#define EEPROM_ALLOW_SET_LEN 1 + +/* + * flags to distinguish one-address (QSFP family) from two-address (SFP family) + * and one-address Common Management Interface Specification (CMIS family) + */ +#define ONE_ADDR 1 +#define TWO_ADDR 2 +#define CMIS_ADDR 3 + +/* I2C Controller Management Registers */ +#define PCIE_FPGA_I2C_MGMT_RTC0_PROFILE_0 0x2008 + +/* I2C Real Time Control Registers */ +#define PCIE_FPGA_I2C_CONTROL_RTC0_CONFIG_0 0x2050 +#define PCIE_FPGA_I2C_CONTROL_RTC0_CONFIG_1 0x2054 +#define PCIE_FPGA_I2C_CONTROL_RTC0_STATUS_0 0x2060 + +/* I2C RTC Data Block */ +#define PCIE_FPGA_I2C_RTC_WRITE_DATA_REG_0 0x5000 +#define PCIE_FPGA_I2C_RTC_READ_DATA_REG_0 0xA000 + +#define PCIE_FPGA_I2C_MAX_LEN 128 +#define PCIE_FPGA_I2C_NEW_TRIGGER_VALUE 0x80000000 + +/* Show system date time */ +#define DATETIME_LEN 50 +char g_datetime[DATETIME_LEN]; + +/* System LED: */ +#define UDB_CPLD2_SYSTEM_LED_OFFSET_CTRL_REG_1 0x10 +#define UDB_CPLD2_SYSTEM_LED_OFFSET_CTRL_REG_2 0x11 + +#define LED_TYPE_LOC_REG_MASK (0xC0) +#define LED_MODE_LOC_OFF_VALUE (0x00) +#define LED_MODE_LOC_BLUE_VALUE (0x80) +#define LED_MODE_LOC_BLUE_BLINK_VALUE (0x40) + +#define LED_TYPE_STAT_REG_MASK (0x0F) +#define LED_MODE_STAT_GREEN_VALUE (0x08) +#define LED_MODE_STAT_BLUE_VALUE (0x04) +#define LED_MODE_STAT_GREEN_BLINK_VALUE (0x02) +#define LED_MODE_STAT_AMBER_VALUE (0x01) +#define LED_MODE_STAT_OFF_VALUE (0x00) + +/*********************************************** + * structure & variable declare + * *********************************************/ +static char FPGA_NAME[FPGA_NUM][10] = {"UDB FPGA", "LDB FPGA", "SMB FPGA"}; + +typedef struct pci_fpga_device_s { + struct pci_dev *fpga_pdev; + void __iomem *data_base_addr; + resource_size_t data_mmio_start; + resource_size_t data_mmio_len; + u16 id; + u32 qsfp_present; + u32 qsfp_lpmode; + u32 qsfp_reset; + u32 sfp_input_data; + u32 sfp_output_data; + u16 aslpc_cpld1_offset; + u16 aslpc_cpld2_offset; +} pci_fpga_device_t; + +/*fpga port status*/ +struct as9736_64d_fpga_data { + struct platform_device *pdev; + struct pci_dev *pci_dev_addr[FPGA_NUM]; /*UDB, LDB and SMB*/ + pci_fpga_device_t pci_fpga_dev[FPGA_NUM]; /*UDB, LDB and SMB*/ + u32 udb_version; + u32 ldb_version; + u32 smb_version; + unsigned long last_updated; /* In jiffies */ +}; + +static struct as9736_64d_fpga_data *fpga_ctl = NULL; + +struct mutex update_lock; + +struct eeprom_bin_private_data { + int port_num; + int fpga_type; + int pageable; + int sfp_support_a2; + int i2c_slave_addr; + int i2c_mgmt_rtc0_profile; + int i2c_contrl_rtc0_config_0; + int i2c_contrl_rtc0_config_1; + int i2c_contrl_rtc0_stats; + int i2c_rtc_read_data; + int i2c_rtc_write_data; + void __iomem *data_base_addr; +}; + +struct pcie_fpga_dev_platform_data { + int port_num; + char name[10]; /*ex: port1*/ + char dev_name[10]; /*ex: optoe1*/ + int dev_class; + int fpga_type; + struct bin_attribute eeprom_bin; +}; + +/*********************************************** + * macro define + * *********************************************/ +#define pcie_err(fmt, args...) \ + printk(KERN_ERR "[accton_pcie_fpga_driver]: " fmt " ", ##args) + +#define pcie_info(fmt, args...) \ + printk(KERN_INFO "[accton_pcie_fpga_driver]: " fmt " ", ##args) + +/* UDB */ + /*c from 0 to 31*/ +#define pcie_udb_qsfp_device_port(c){ \ + .name = "pcie_udb_fpga_device", \ + .id = c, \ + .dev = { \ + .platform_data = &pcie_udb_dev_platform_data[c], \ + .release = device_release, \ + }, \ +} + /*c from 1*/ +#define pcie_udb_qsfp_platform_data_init(c){ \ + .port_num = c, \ + .dev_name = "optoe1", \ + .dev_class = 1, \ + .fpga_type = PCIE_FPGA_TYPE_UDB, \ + .eeprom_bin = { \ + .private = &pcie_udb_eeprom_bin_private_data[c-1], \ + }, \ +} + /*c from 1*/ +#define eeprom_udb_private_data_port_init(c){ \ + .port_num = c, \ + .fpga_type = PCIE_FPGA_TYPE_UDB, \ + .i2c_slave_addr = 0x50, \ + .i2c_mgmt_rtc0_profile = PCIE_FPGA_I2C_MGMT_RTC0_PROFILE_0 + 0x100*(c-1), \ + .i2c_contrl_rtc0_config_0 = PCIE_FPGA_I2C_CONTROL_RTC0_CONFIG_0 + 0x100*(c-1), \ + .i2c_contrl_rtc0_config_1 = PCIE_FPGA_I2C_CONTROL_RTC0_CONFIG_1 + 0x100*(c-1), \ + .i2c_contrl_rtc0_stats = PCIE_FPGA_I2C_CONTROL_RTC0_STATUS_0 + 0x100*(c-1), \ + .i2c_rtc_read_data = PCIE_FPGA_I2C_RTC_READ_DATA_REG_0 + 0x200*(c-1), \ + .i2c_rtc_write_data = PCIE_FPGA_I2C_RTC_WRITE_DATA_REG_0 + 0x200*(c-1), \ +} + +/* LDB */ + /*c from 0 to 31*/ +#define pcie_ldb_qsfp_device_port(c){ \ + .name = "pcie_ldb_fpga_device", \ + .id = c, \ + .dev = { \ + .platform_data = &pcie_ldb_dev_platform_data[c], \ + .release = device_release, \ + }, \ +} + /*c from 32 to 33*/ +#define pcie_ldb_sfp_device_port(c){ \ + .name = "pcie_ldb_fpga_device", \ + .id = c, \ + .dev = { \ + .platform_data = &pcie_ldb_dev_platform_data[c], \ + .release = device_release, \ + }, \ +} + +/*c from 1 to 32*/ +#define pcie_ldb_qsfp_platform_data_init(c){ \ + .port_num = c, \ + .dev_name = "optoe1", \ + .dev_class = 1, \ + .fpga_type = PCIE_FPGA_TYPE_LDB, \ + .eeprom_bin = { \ + .private = &pcie_ldb_eeprom_bin_private_data[c-1], \ + }, \ +} +/*c = 33, 34*/ +#define pcie_ldb_sfp_platform_data_init(c){ \ + .port_num = c, \ + .dev_name = "optoe2", \ + .dev_class = 2, \ + .fpga_type = PCIE_FPGA_TYPE_LDB, \ + .eeprom_bin = { \ + .private = &pcie_ldb_eeprom_bin_private_data[c-1], \ + }, \ +} +/*c from 1 to 32, 33, 34*/ +#define eeprom_ldb_private_data_port_init(c){ \ + .port_num = c + 32, \ + .fpga_type = PCIE_FPGA_TYPE_LDB, \ + .i2c_slave_addr = 0x50, \ + .i2c_mgmt_rtc0_profile = PCIE_FPGA_I2C_MGMT_RTC0_PROFILE_0 + 0x100*(c-1), \ + .i2c_contrl_rtc0_config_0 = PCIE_FPGA_I2C_CONTROL_RTC0_CONFIG_0 + 0x100*(c-1), \ + .i2c_contrl_rtc0_config_1 = PCIE_FPGA_I2C_CONTROL_RTC0_CONFIG_1 + 0x100*(c-1), \ + .i2c_contrl_rtc0_stats = PCIE_FPGA_I2C_CONTROL_RTC0_STATUS_0 + 0x100*(c-1), \ + .i2c_rtc_read_data = PCIE_FPGA_I2C_RTC_READ_DATA_REG_0 + 0x200*(c-1), \ + .i2c_rtc_write_data = PCIE_FPGA_I2C_RTC_WRITE_DATA_REG_0 + 0x200*(c-1), \ +} + +/*********************************************** + * enum define + * *********************************************/ +enum fpga_type_t { + PCIE_FPGA_UDB = 0, + PCIE_FPGA_LDB, + PCIE_FPGA_SMB +}; + +enum fpga_set_function_type_t { + PCIE_FPGA_SET_LPMODE, + PCIE_FPGA_SET_RESET, + PCIE_FPGA_SET_TX_DISABLE +}; + +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, + PCIE_FPGA_UDB_VERSION, + PCIE_FPGA_LDB_VERSION, + PCIE_FPGA_SMB_VERSION, +}; + +enum pcie_type_e { + PCIE_FPGA_TYPE_UDB = 0, + PCIE_FPGA_TYPE_LDB +}; + +enum eeprom_page_type_e { + EEPROM_LOWER_PAGE = -1, + EEPROM_UPPER_PAGE +}; + +enum port_sysfs_attributes { + PORT_SYSFS_NAME_ID = 1, + PORT_SYSFS_PORT_NAME_ID, + PORT_SYSFS_DEV_CLASS_ID +}; + +/* System LED: */ +enum led_type { + LED_SYSFS_LOC = 0, + LED_SYSFS_STAT, + LED_SYSFS_FAN, + LED_SYSFS_PSU1, + LED_SYSFS_PSU2 +}; + +enum led_light_mode { + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_AMBER = 12, + LED_MODE_AMBER_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 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {LED_SYSFS_LOC, UDB_CPLD2_SYSTEM_LED_OFFSET_CTRL_REG_1}, + {LED_SYSFS_STAT, UDB_CPLD2_SYSTEM_LED_OFFSET_CTRL_REG_2}, +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + u8 reg_bit_mask; + u8 mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_SYSFS_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_SYSFS_LOC, LED_MODE_BLUE, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_BLUE_VALUE}, +{LED_SYSFS_LOC, LED_MODE_BLUE_BLINKING, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_BLUE_BLINK_VALUE}, +{LED_SYSFS_STAT, LED_MODE_OFF, LED_TYPE_STAT_REG_MASK, LED_MODE_STAT_OFF_VALUE}, +{LED_SYSFS_STAT, LED_MODE_GREEN, LED_TYPE_STAT_REG_MASK, LED_MODE_STAT_GREEN_VALUE}, +{LED_SYSFS_STAT, LED_MODE_BLUE, LED_TYPE_STAT_REG_MASK, LED_MODE_STAT_BLUE_VALUE}, +{LED_SYSFS_STAT, LED_MODE_GREEN_BLINKING, LED_TYPE_STAT_REG_MASK, LED_MODE_STAT_GREEN_BLINK_VALUE}, +{LED_SYSFS_STAT, LED_MODE_AMBER, LED_TYPE_STAT_REG_MASK, LED_MODE_STAT_AMBER_VALUE} +}; + +/*********************************************** + * function declare + * *********************************************/ +static ssize_t port_status_read(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t port_status_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static ssize_t port_read(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t port_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static ssize_t led_status_read(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t led_status_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static int fpga_i2c_ready_to_read(struct bin_attribute *attr, int page_type, int i2c_slave_addr); + +/* UDB */ +/*init eeprom private data*/ +static struct eeprom_bin_private_data pcie_udb_eeprom_bin_private_data[] = { + eeprom_udb_private_data_port_init(1), + eeprom_udb_private_data_port_init(2), + eeprom_udb_private_data_port_init(3), + eeprom_udb_private_data_port_init(4), + eeprom_udb_private_data_port_init(5), + eeprom_udb_private_data_port_init(6), + eeprom_udb_private_data_port_init(7), + eeprom_udb_private_data_port_init(8), + eeprom_udb_private_data_port_init(9), + eeprom_udb_private_data_port_init(10), + eeprom_udb_private_data_port_init(11), + eeprom_udb_private_data_port_init(12), + eeprom_udb_private_data_port_init(13), + eeprom_udb_private_data_port_init(14), + eeprom_udb_private_data_port_init(15), + eeprom_udb_private_data_port_init(16), + eeprom_udb_private_data_port_init(17), + eeprom_udb_private_data_port_init(18), + eeprom_udb_private_data_port_init(19), + eeprom_udb_private_data_port_init(20), + eeprom_udb_private_data_port_init(21), + eeprom_udb_private_data_port_init(22), + eeprom_udb_private_data_port_init(23), + eeprom_udb_private_data_port_init(24), + eeprom_udb_private_data_port_init(25), + eeprom_udb_private_data_port_init(26), + eeprom_udb_private_data_port_init(27), + eeprom_udb_private_data_port_init(28), + eeprom_udb_private_data_port_init(29), + eeprom_udb_private_data_port_init(30), + eeprom_udb_private_data_port_init(31), + eeprom_udb_private_data_port_init(32), +}; + +/*init device platform data*/ +static struct pcie_fpga_dev_platform_data pcie_udb_dev_platform_data[] = { + pcie_udb_qsfp_platform_data_init(1), + pcie_udb_qsfp_platform_data_init(2), + pcie_udb_qsfp_platform_data_init(3), + pcie_udb_qsfp_platform_data_init(4), + pcie_udb_qsfp_platform_data_init(5), + pcie_udb_qsfp_platform_data_init(6), + pcie_udb_qsfp_platform_data_init(7), + pcie_udb_qsfp_platform_data_init(8), + pcie_udb_qsfp_platform_data_init(9), + pcie_udb_qsfp_platform_data_init(10), + pcie_udb_qsfp_platform_data_init(11), + pcie_udb_qsfp_platform_data_init(12), + pcie_udb_qsfp_platform_data_init(13), + pcie_udb_qsfp_platform_data_init(14), + pcie_udb_qsfp_platform_data_init(15), + pcie_udb_qsfp_platform_data_init(16), + pcie_udb_qsfp_platform_data_init(17), + pcie_udb_qsfp_platform_data_init(18), + pcie_udb_qsfp_platform_data_init(19), + pcie_udb_qsfp_platform_data_init(20), + pcie_udb_qsfp_platform_data_init(21), + pcie_udb_qsfp_platform_data_init(22), + pcie_udb_qsfp_platform_data_init(23), + pcie_udb_qsfp_platform_data_init(24), + pcie_udb_qsfp_platform_data_init(25), + pcie_udb_qsfp_platform_data_init(26), + pcie_udb_qsfp_platform_data_init(27), + pcie_udb_qsfp_platform_data_init(28), + pcie_udb_qsfp_platform_data_init(29), + pcie_udb_qsfp_platform_data_init(30), + pcie_udb_qsfp_platform_data_init(31), + pcie_udb_qsfp_platform_data_init(32), +}; + +/* LDB */ +/*init eeprom private data*/ +static struct eeprom_bin_private_data pcie_ldb_eeprom_bin_private_data[] = { + eeprom_ldb_private_data_port_init(1), + eeprom_ldb_private_data_port_init(2), + eeprom_ldb_private_data_port_init(3), + eeprom_ldb_private_data_port_init(4), + eeprom_ldb_private_data_port_init(5), + eeprom_ldb_private_data_port_init(6), + eeprom_ldb_private_data_port_init(7), + eeprom_ldb_private_data_port_init(8), + eeprom_ldb_private_data_port_init(9), + eeprom_ldb_private_data_port_init(10), + eeprom_ldb_private_data_port_init(11), + eeprom_ldb_private_data_port_init(12), + eeprom_ldb_private_data_port_init(13), + eeprom_ldb_private_data_port_init(14), + eeprom_ldb_private_data_port_init(15), + eeprom_ldb_private_data_port_init(16), + eeprom_ldb_private_data_port_init(17), + eeprom_ldb_private_data_port_init(18), + eeprom_ldb_private_data_port_init(19), + eeprom_ldb_private_data_port_init(20), + eeprom_ldb_private_data_port_init(21), + eeprom_ldb_private_data_port_init(22), + eeprom_ldb_private_data_port_init(23), + eeprom_ldb_private_data_port_init(24), + eeprom_ldb_private_data_port_init(25), + eeprom_ldb_private_data_port_init(26), + eeprom_ldb_private_data_port_init(27), + eeprom_ldb_private_data_port_init(28), + eeprom_ldb_private_data_port_init(29), + eeprom_ldb_private_data_port_init(30), + eeprom_ldb_private_data_port_init(31), + eeprom_ldb_private_data_port_init(32), + eeprom_ldb_private_data_port_init(33), /*sfp: port65*/ + eeprom_ldb_private_data_port_init(34), /*sfp: port66*/ +}; + +/*init device platform data*/ +static struct pcie_fpga_dev_platform_data pcie_ldb_dev_platform_data[] = { + pcie_ldb_qsfp_platform_data_init(1), + pcie_ldb_qsfp_platform_data_init(2), + pcie_ldb_qsfp_platform_data_init(3), + pcie_ldb_qsfp_platform_data_init(4), + pcie_ldb_qsfp_platform_data_init(5), + pcie_ldb_qsfp_platform_data_init(6), + pcie_ldb_qsfp_platform_data_init(7), + pcie_ldb_qsfp_platform_data_init(8), + pcie_ldb_qsfp_platform_data_init(9), + pcie_ldb_qsfp_platform_data_init(10), + pcie_ldb_qsfp_platform_data_init(11), + pcie_ldb_qsfp_platform_data_init(12), + pcie_ldb_qsfp_platform_data_init(13), + pcie_ldb_qsfp_platform_data_init(14), + pcie_ldb_qsfp_platform_data_init(15), + pcie_ldb_qsfp_platform_data_init(16), + pcie_ldb_qsfp_platform_data_init(17), + pcie_ldb_qsfp_platform_data_init(18), + pcie_ldb_qsfp_platform_data_init(19), + pcie_ldb_qsfp_platform_data_init(20), + pcie_ldb_qsfp_platform_data_init(21), + pcie_ldb_qsfp_platform_data_init(22), + pcie_ldb_qsfp_platform_data_init(23), + pcie_ldb_qsfp_platform_data_init(24), + pcie_ldb_qsfp_platform_data_init(25), + pcie_ldb_qsfp_platform_data_init(26), + pcie_ldb_qsfp_platform_data_init(27), + pcie_ldb_qsfp_platform_data_init(28), + pcie_ldb_qsfp_platform_data_init(29), + pcie_ldb_qsfp_platform_data_init(30), + pcie_ldb_qsfp_platform_data_init(31), + pcie_ldb_qsfp_platform_data_init(32), + pcie_ldb_sfp_platform_data_init(33), /*sfp: port65*/ + pcie_ldb_sfp_platform_data_init(34), /*sfp: port66*/ +}; + +static void device_release(struct device *dev) +{ + return; +} + +/*UDB platform device*/ +static struct platform_device pcie_udb_qsfp_device[] = { + pcie_udb_qsfp_device_port(0), + pcie_udb_qsfp_device_port(1), + pcie_udb_qsfp_device_port(2), + pcie_udb_qsfp_device_port(3), + pcie_udb_qsfp_device_port(4), + pcie_udb_qsfp_device_port(5), + pcie_udb_qsfp_device_port(6), + pcie_udb_qsfp_device_port(7), + pcie_udb_qsfp_device_port(8), + pcie_udb_qsfp_device_port(9), + pcie_udb_qsfp_device_port(10), + pcie_udb_qsfp_device_port(11), + pcie_udb_qsfp_device_port(12), + pcie_udb_qsfp_device_port(13), + pcie_udb_qsfp_device_port(14), + pcie_udb_qsfp_device_port(15), + pcie_udb_qsfp_device_port(16), + pcie_udb_qsfp_device_port(17), + pcie_udb_qsfp_device_port(18), + pcie_udb_qsfp_device_port(19), + pcie_udb_qsfp_device_port(20), + pcie_udb_qsfp_device_port(21), + pcie_udb_qsfp_device_port(22), + pcie_udb_qsfp_device_port(23), + pcie_udb_qsfp_device_port(24), + pcie_udb_qsfp_device_port(25), + pcie_udb_qsfp_device_port(26), + pcie_udb_qsfp_device_port(27), + pcie_udb_qsfp_device_port(28), + pcie_udb_qsfp_device_port(29), + pcie_udb_qsfp_device_port(30), + pcie_udb_qsfp_device_port(31), +}; + +/*LDB platform device*/ +static struct platform_device pcie_ldb_qsfp_device[] = { + pcie_ldb_qsfp_device_port(0), + pcie_ldb_qsfp_device_port(1), + pcie_ldb_qsfp_device_port(2), + pcie_ldb_qsfp_device_port(3), + pcie_ldb_qsfp_device_port(4), + pcie_ldb_qsfp_device_port(5), + pcie_ldb_qsfp_device_port(6), + pcie_ldb_qsfp_device_port(7), + pcie_ldb_qsfp_device_port(8), + pcie_ldb_qsfp_device_port(9), + pcie_ldb_qsfp_device_port(10), + pcie_ldb_qsfp_device_port(11), + pcie_ldb_qsfp_device_port(12), + pcie_ldb_qsfp_device_port(13), + pcie_ldb_qsfp_device_port(14), + pcie_ldb_qsfp_device_port(15), + pcie_ldb_qsfp_device_port(16), + pcie_ldb_qsfp_device_port(17), + pcie_ldb_qsfp_device_port(18), + pcie_ldb_qsfp_device_port(19), + pcie_ldb_qsfp_device_port(20), + pcie_ldb_qsfp_device_port(21), + pcie_ldb_qsfp_device_port(22), + pcie_ldb_qsfp_device_port(23), + pcie_ldb_qsfp_device_port(24), + pcie_ldb_qsfp_device_port(25), + pcie_ldb_qsfp_device_port(26), + pcie_ldb_qsfp_device_port(27), + pcie_ldb_qsfp_device_port(28), + pcie_ldb_qsfp_device_port(29), + pcie_ldb_qsfp_device_port(30), + pcie_ldb_qsfp_device_port(31), + pcie_ldb_sfp_device_port(32), /*sfp port65*/ + pcie_ldb_sfp_device_port(33), /*sfp port66*/ +}; + +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, port_status_read, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR|S_IRUGO, port_status_read, port_status_write, MODULE_RESET_##index); \ + static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO | S_IWUSR, port_status_read, port_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, port_status_read, NULL, MODULE_PRESENT_65); +static SENSOR_DEVICE_ATTR(module_present_66, S_IRUGO, port_status_read, NULL, MODULE_PRESENT_66); +static SENSOR_DEVICE_ATTR(module_reset_all, S_IWUSR, NULL, port_status_write, MODULE_RESET_ALL); +static SENSOR_DEVICE_ATTR(module_tx_disable_65, S_IRUGO | S_IWUSR, port_status_read, port_status_write, MODULE_TX_DISABLE_65); +static SENSOR_DEVICE_ATTR(module_tx_disable_66, S_IRUGO | S_IWUSR, port_status_read, port_status_write, MODULE_TX_DISABLE_66); +static SENSOR_DEVICE_ATTR(module_tx_fault_65, S_IRUGO, port_status_read, NULL, MODULE_TX_FAULT_65); +static SENSOR_DEVICE_ATTR(module_tx_fault_66, S_IRUGO, port_status_read, NULL, MODULE_TX_FAULT_66); +static SENSOR_DEVICE_ATTR(module_rx_los_65, S_IRUGO, port_status_read, NULL, MODULE_RX_LOS_65); +static SENSOR_DEVICE_ATTR(module_rx_los_66, S_IRUGO, port_status_read, NULL, MODULE_RX_LOS_66); +static SENSOR_DEVICE_ATTR(udb_version, S_IRUGO, port_status_read, NULL, PCIE_FPGA_UDB_VERSION); +static SENSOR_DEVICE_ATTR(ldb_version, S_IRUGO, port_status_read, NULL, PCIE_FPGA_LDB_VERSION); +static SENSOR_DEVICE_ATTR(smb_version, S_IRUGO, port_status_read, NULL, PCIE_FPGA_SMB_VERSION); +/* led attribute */ +static SENSOR_DEVICE_ATTR(led_loc , S_IRUGO|S_IWUSR, led_status_read, led_status_write, LED_SYSFS_LOC); +static SENSOR_DEVICE_ATTR(led_stat, S_IRUGO|S_IWUSR, led_status_read, led_status_write, LED_SYSFS_STAT); +static SENSOR_DEVICE_ATTR(led_fan, S_IRUGO|S_IWUSR, led_status_read, led_status_write, LED_SYSFS_FAN); +static SENSOR_DEVICE_ATTR(led_psu1, S_IRUGO|S_IWUSR, led_status_read, led_status_write, LED_SYSFS_PSU1); +static SENSOR_DEVICE_ATTR(led_psu2, S_IRUGO|S_IWUSR, led_status_read, led_status_write, LED_SYSFS_PSU2); + +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_udb_version.dev_attr.attr, + &sensor_dev_attr_ldb_version.dev_attr.attr, + &sensor_dev_attr_smb_version.dev_attr.attr, + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_stat.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 +}; + +/* eeprom attribute */ +static SENSOR_DEVICE_ATTR(name, S_IRUGO, port_read, NULL, PORT_SYSFS_NAME_ID); /* optoe{1, 2, 3} */ +static SENSOR_DEVICE_ATTR(port_name, S_IRUGO, port_read, NULL, PORT_SYSFS_PORT_NAME_ID); /* port{1~64} */ +static SENSOR_DEVICE_ATTR(dev_class, S_IRUGO|S_IWUSR, port_read, port_write, PORT_SYSFS_DEV_CLASS_ID); /* 1 or 2 or 3 */ + +static struct attribute *fpga_eeprom_attributes[] = { + &sensor_dev_attr_name.dev_attr.attr, + &sensor_dev_attr_port_name.dev_attr.attr, + &sensor_dev_attr_dev_class.dev_attr.attr, + NULL +}; + +static const struct attribute_group fpga_port_stat_group = { + .attrs = fpga_transceiver_attributes, +}; + +static const struct attribute_group fpga_eeprom_group = { + .attrs = fpga_eeprom_attributes, +}; + +static char *show_date_time(void) +{ + struct timespec64 tv; + struct tm tm_val; + + memset(g_datetime, 0, DATETIME_LEN); + + ktime_get_real_ts64(&tv); + time64_to_tm(tv.tv_sec, 0, &tm_val); + sprintf(g_datetime, "[%04d/%02d/%02d-%02d:%02d:%02d.%06ld]", + 1900 + tm_val.tm_year, + tm_val.tm_mon + 1, + tm_val.tm_mday, + tm_val.tm_hour, + tm_val.tm_min, + tm_val.tm_sec, + tv.tv_nsec/1000); /*usec*/ + + return g_datetime; +} + +static ssize_t fpga_read_sfp_ddm_status_value(struct bin_attribute *eeprom) +{ + u32 reg_val = 0; + u16 pageable = 0; + u16 ddm_support = 0; + struct eeprom_bin_private_data *pdata = NULL; + + if(eeprom == NULL) { + return -1; + } + + pdata = eeprom->private; /*assign private sturct value*/ + + if(pdata->port_num > FPGA_QSFP_PORT_NUM) + { + /*get sfp pagable status*/ + if( fpga_i2c_ready_to_read(eeprom, EEPROM_LOWER_PAGE, pdata->i2c_slave_addr) != 1) { + return 0; + } + + reg_val = ioread32(pdata->data_base_addr + (pdata->i2c_rtc_read_data + TWO_ADDR_PAGEABLE_REG)); + pageable = (reg_val) & 0xff; /*check on bit4*/ + + /*get sfp support a2 status*/ + if( fpga_i2c_ready_to_read(eeprom, EEPROM_LOWER_PAGE, pdata->i2c_slave_addr) != 1) { + return 0; + } + + reg_val = ioread32(pdata->data_base_addr + (pdata->i2c_rtc_read_data + TWO_ADDR_0X51_REG )); + ddm_support = (reg_val) & 0xff; /*check on bit6*/ + + pdata->pageable = (pageable & TWO_ADDR_PAGEABLE ) ? 1 : 0; + pdata->sfp_support_a2 = (ddm_support & TWO_ADDR_0X51_SUPP) ? 1 : 0; + } + + return 0; +} + +static ssize_t fpga_read_port_status_value(struct bin_attribute *eeprom) +{ + int i = 0; + + if ( time_before(jiffies, fpga_ctl->last_updated + HZ / 2) ) { + return 0; + } + + for (i = 0; i < ARRAY_SIZE(fpga_ctl->pci_fpga_dev) -1; i++) + { + /*Update present*/ + fpga_ctl->pci_fpga_dev[i].qsfp_present = ioread32(fpga_ctl->pci_fpga_dev[i].data_base_addr + QSFP_PRESENT_REG_OFFSET); + + if(i==PCI_SUBSYSTEM_ID_LDB) + { + /*Read output data*/ + fpga_ctl->pci_fpga_dev[i].sfp_output_data = ioread32(fpga_ctl->pci_fpga_dev[i].data_base_addr + SFP_LDB_GPIO1_DATA_OUT); + /*Read input data*/ + fpga_ctl->pci_fpga_dev[i].sfp_input_data = ioread32(fpga_ctl->pci_fpga_dev[i].data_base_addr + SFP_LDB_GPIO1_DATA_IN); + } + /*Update lpmode*/ + fpga_ctl->pci_fpga_dev[i].qsfp_lpmode = ioread32(fpga_ctl->pci_fpga_dev[i].data_base_addr + QSFP_LPMODE_REG_OFFSET); + /*Update reset*/ + fpga_ctl->pci_fpga_dev[i].qsfp_reset = ioread32(fpga_ctl->pci_fpga_dev[i].data_base_addr + QSFP_RESET_REG_OFFSET); + } + + /*get version*/ + fpga_ctl->udb_version = ioread32(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_base_addr); + fpga_ctl->ldb_version = ioread32(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_base_addr); + fpga_ctl->smb_version = ioread32(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].data_base_addr); + + fpga_ctl->last_updated = jiffies; + + return 0; +} + +static ssize_t fpga_write_port_value(int fpga_type, int set_type, int bit_num, long val) +{ + long val_set = 0; + u32 reg_val = 0; + + if(set_type == PCIE_FPGA_SET_LPMODE) { + reg_val = ioread32(fpga_ctl->pci_fpga_dev[fpga_type].data_base_addr + QSFP_LPMODE_REG_OFFSET); + } else if(set_type == PCIE_FPGA_SET_RESET) { + reg_val = ioread32(fpga_ctl->pci_fpga_dev[fpga_type].data_base_addr + QSFP_RESET_REG_OFFSET); + } else { + reg_val = ioread32(fpga_ctl->pci_fpga_dev[fpga_type].data_base_addr + SFP_LDB_GPIO1_DATA_OUT); + } + + if(val){ + val_set = (bit_num == REG_SET_ALL_32_BITS) ? REG_SET_32_BITS_TO_1 : (reg_val | (1<pci_fpga_dev[fpga_type].data_base_addr + QSFP_LPMODE_REG_OFFSET); + break; + case PCIE_FPGA_SET_RESET: + iowrite32(val_set, fpga_ctl->pci_fpga_dev[fpga_type].data_base_addr + QSFP_RESET_REG_OFFSET); + break; + case PCIE_FPGA_SET_TX_DISABLE: + iowrite32(val_set, fpga_ctl->pci_fpga_dev[fpga_type].data_base_addr + SFP_LDB_GPIO1_DATA_OUT); + break; + default: + break; + } + + return 0; +} + +static int get_present_by_attr_index(int attr_index) +{ + int present = 0; + int index_mapping = 0; + + switch(attr_index) + { + case MODULE_PRESENT_1 ... MODULE_PRESENT_32: + case MODULE_PRESENT_33 ... MODULE_PRESENT_64: + case MODULE_PRESENT_65: /*sfp port*/ + case MODULE_PRESENT_66: /*sfp port*/ + index_mapping = attr_index; + break; + case MODULE_LPMODE_1 ... MODULE_LPMODE_32: + index_mapping = attr_index - MODULE_LPMODE_1; + break; + case MODULE_LPMODE_33 ... MODULE_LPMODE_64: + index_mapping = attr_index - MODULE_LPMODE_33; + break; + case MODULE_RESET_1 ... MODULE_RESET_32: + index_mapping = attr_index - MODULE_RESET_1; + break; + case MODULE_RESET_33 ... MODULE_RESET_64: + index_mapping = attr_index - MODULE_RESET_33; + break; + case MODULE_TX_DISABLE_65: + case MODULE_TX_FAULT_65: + case MODULE_RX_LOS_65: + index_mapping = MODULE_PRESENT_65; + break; + case MODULE_TX_DISABLE_66: + case MODULE_TX_FAULT_66: + case MODULE_RX_LOS_66: + index_mapping = MODULE_PRESENT_66; + break; + default: + index_mapping = -EINVAL; + break; + } + + if( (index_mapping >= MODULE_PRESENT_1) && (index_mapping <= MODULE_PRESENT_32) ) + { + present =((fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].qsfp_present>>(index_mapping - MODULE_PRESENT_1)) & 0x1)?0:1; + } + else if( (index_mapping >= MODULE_PRESENT_33) && (index_mapping <= MODULE_PRESENT_64) ) + { + present = ((fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].qsfp_present>>(index_mapping - MODULE_PRESENT_33)) & 0x1)?0:1; + } + else if( index_mapping == MODULE_PRESENT_65 ) + { + present = ((SFP_PORT0_ABS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1)?0:1; + } + else if( index_mapping == MODULE_PRESENT_66 ) + { + present = ((SFP_PORT1_ABS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1)?0:1; + } + else { + present = 0; /*unpresent*/ + } + + return present; +} + +static ssize_t port_status_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present = 0; + ssize_t ret = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct bin_attribute *eeprom = NULL; + + mutex_lock(&update_lock); + fpga_read_port_status_value(eeprom); + + present = get_present_by_attr_index(attr->index); + + switch(attr->index) + { + case MODULE_PRESENT_1 ... MODULE_PRESENT_32: + case MODULE_PRESENT_33 ... MODULE_PRESENT_64: + case MODULE_PRESENT_65: /*sfp port*/ + case MODULE_PRESENT_66: /*sfp port*/ + ret = sprintf(buf, "%d\n", present); + break; + case MODULE_LPMODE_1 ... MODULE_LPMODE_32: + if(present){ + ret = sprintf(buf, "%d\n", ((fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].qsfp_lpmode >> (attr->index - MODULE_LPMODE_1)) & 0x1)); + } else { + ret = sprintf(buf, "%d\n", 0); /*unpresent: default value*/ + } + break; + case MODULE_LPMODE_33 ... MODULE_LPMODE_64: + if(present){ + ret = sprintf(buf, "%d\n", ((fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].qsfp_lpmode >> (attr->index - MODULE_LPMODE_33)) & 0x1)); + } else { + ret = sprintf(buf, "%d\n", 0); /*unpresent: default value*/ + } + break; + case MODULE_RESET_1 ... MODULE_RESET_32: + if(present){ + ret = sprintf(buf, "%d\n", ((fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].qsfp_reset >>(attr->index - MODULE_RESET_1)) & 0x1)?0:1); + } else { + ret = sprintf(buf, "%d\n", 0); /*unpresent: default value*/ + } + break; + case MODULE_RESET_33 ... MODULE_RESET_64: + if(present){ + ret = sprintf(buf, "%d\n", ((fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].qsfp_reset >> (attr->index - MODULE_RESET_33)) & 0x1)?0:1); + } else { + ret = sprintf(buf, "%d\n", 0); /*unpresent: default value*/ + } + break; + case MODULE_TX_DISABLE_65: + if(present){ + ret = sprintf(buf, "%d\n", (SFP_PORT0_TXDIS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } else { + ret = sprintf(buf, "%d\n", 0); /*unpresent: default value*/ + } + break; + case MODULE_TX_DISABLE_66: + if(present){ + ret = sprintf(buf, "%d\n", (SFP_PORT1_TXDIS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } else { + ret = sprintf(buf, "%d\n", 0); /*unpresent: default value*/ + } + break; + case MODULE_TX_FAULT_65: + if(present){ + ret = sprintf(buf, "%d\n", (SFP_PORT0_TXFLT(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } else { + ret = sprintf(buf, "%d\n", 1); /*unpresent: tx_fault is true*/ + } + break; + case MODULE_TX_FAULT_66: + if(present){ + ret = sprintf(buf, "%d\n", (SFP_PORT1_TXFLT(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } else { + ret = sprintf(buf, "%d\n", 1); /*unpresent: tx_fault is true*/ + } + break; + case MODULE_RX_LOS_65: + if(present){ + ret = sprintf(buf, "%d\n", (SFP_PORT0_RXLOS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } else { + ret = sprintf(buf, "%d\n", 1); /*unpresent: rx_los is true*/ + } + break; + case MODULE_RX_LOS_66: + if(present){ + ret = sprintf(buf, "%d\n", (SFP_PORT1_RXLOS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } else { + ret = sprintf(buf, "%d\n", 1); /*unpresent: rx_los is true*/ + } + break; + case PCIE_FPGA_UDB_VERSION: + ret = sprintf(buf, "%d.%d\n", (fpga_ctl->udb_version>>8) & 0x7f, fpga_ctl->udb_version & 0xff); + break; + case PCIE_FPGA_LDB_VERSION: + ret = sprintf(buf, "%d.%d\n", (fpga_ctl->ldb_version>>8) & 0x7f, fpga_ctl->ldb_version & 0xff); + break; + case PCIE_FPGA_SMB_VERSION: + ret = sprintf(buf, "%d.%d\n", (fpga_ctl->smb_version>>8) & 0x7f, fpga_ctl->smb_version & 0xff); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&update_lock); + + return ret; +} + +static ssize_t port_status_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long value; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct bin_attribute *eeprom = NULL; + + status = kstrtol(buf, 16, &value); + if (status) { + return status; + } + + mutex_lock(&update_lock); + + switch(attr->index) + { + case MODULE_LPMODE_1 ... MODULE_LPMODE_32: + fpga_write_port_value(PCIE_FPGA_UDB, PCIE_FPGA_SET_LPMODE, (attr->index - MODULE_LPMODE_1), !!value); + break; + case MODULE_LPMODE_33 ... MODULE_LPMODE_64: + fpga_write_port_value(PCIE_FPGA_LDB, PCIE_FPGA_SET_LPMODE, (attr->index - MODULE_LPMODE_1), !!value); + break; + case MODULE_RESET_1 ... MODULE_RESET_32: + fpga_write_port_value(PCIE_FPGA_UDB, PCIE_FPGA_SET_RESET, (attr->index - MODULE_RESET_1), !value); + break; + case MODULE_RESET_33 ... MODULE_RESET_64: + fpga_write_port_value(PCIE_FPGA_LDB, PCIE_FPGA_SET_RESET, (attr->index - MODULE_RESET_1), !value); + break; + case MODULE_RESET_ALL: + fpga_write_port_value(PCIE_FPGA_UDB, PCIE_FPGA_SET_RESET, REG_SET_ALL_32_BITS, !value); /*port 1~32*/ + fpga_write_port_value(PCIE_FPGA_LDB, PCIE_FPGA_SET_RESET, REG_SET_ALL_32_BITS, !value); /*port 33~64*/ + break; + case MODULE_TX_DISABLE_65 ... MODULE_TX_DISABLE_66: + fpga_write_port_value(PCIE_FPGA_LDB, PCIE_FPGA_SET_TX_DISABLE, ((attr->index - MODULE_TX_DISABLE_65) ? BIT(3) : BIT(11) ), !!value); /*bit3 and bit11*/ + break; + default: + mutex_unlock(&update_lock); + return -EINVAL; + } + + mutex_unlock(&update_lock); + + return count; +} + +static ssize_t port_read(struct device *dev, struct device_attribute *da, char *buf) +{ + ssize_t ret = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct platform_device *pdev = to_platform_device(dev); + struct pcie_fpga_dev_platform_data *pdata = NULL; + + pdata = pdev->dev.platform_data; + + mutex_lock(&update_lock); + switch(attr->index) + { + case PORT_SYSFS_PORT_NAME_ID: + ret = sprintf(buf, "%s\n", pdata->name); + break; + case PORT_SYSFS_NAME_ID: + ret = sprintf(buf, "%s\n", pdata->dev_name); + break; + case PORT_SYSFS_DEV_CLASS_ID: + ret = sprintf(buf, "%d\n", pdata->dev_class); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&update_lock); + + return ret; +} + +static ssize_t port_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int value; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct platform_device *pdev = to_platform_device(dev); + struct pcie_fpga_dev_platform_data *pdata = NULL; + + pdata = pdev->dev.platform_data; + + status = kstrtoint(buf, 10, &value); + if (status) { + return status; + } + + mutex_lock(&update_lock); + switch(attr->index) + { + case PORT_SYSFS_DEV_CLASS_ID: + pdata->dev_class = value; + break; + default: + mutex_unlock(&update_lock); + return -EINVAL; + } + mutex_unlock(&update_lock); + return count; +} + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].reg_bit_mask & reg_val) == + led_type_mode_data[i].mode_value) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_set_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + u8 set_val; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if (mode != led_type_mode_data[i].mode) { + continue; + } + set_val = led_type_mode_data[i].mode_value | + (reg_val & (~led_type_mode_data[i].reg_bit_mask)); + + break; + } + + return set_val; +} + +static ssize_t led_status_read(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 reg_val = 0; + int led_type = 0; + ssize_t ret = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + led_type = attr->index; + + mutex_lock(&update_lock); + + reg_val = ioread8(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_base_addr + + ASLPC_DEV_UDB_CPLD2_PCIE_START_OFFST + led_reg_map[led_type].reg_addr); + + mutex_unlock(&update_lock); + + switch(led_type) + { + case LED_SYSFS_LOC: + case LED_SYSFS_STAT: + ret = sprintf(buf, "%d\n", led_reg_val_to_light_mode(led_type, reg_val)); + break; + case LED_SYSFS_FAN: + case LED_SYSFS_PSU2: + case LED_SYSFS_PSU1: + ret = sprintf(buf, "%d\n", LED_MODE_AUTO); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static ssize_t led_status_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + int value; + int led_type = 0; + u8 reg_val, set_value; + + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + led_type = attr->index; + + status = kstrtoint(buf, 10, &value); + if (status) { + return status; + } + + mutex_lock(&update_lock); + + reg_val = ioread8(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_base_addr + + ASLPC_DEV_UDB_CPLD2_PCIE_START_OFFST + led_reg_map[led_type].reg_addr); + + switch(led_type) + { + case LED_SYSFS_LOC: + case LED_SYSFS_STAT: + set_value = led_light_mode_to_set_reg_val(led_type, value, reg_val); + iowrite8(set_value, fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_base_addr + + ASLPC_DEV_UDB_CPLD2_PCIE_START_OFFST + led_reg_map[led_type].reg_addr); + break; + case LED_SYSFS_FAN: + case LED_SYSFS_PSU2: + case LED_SYSFS_PSU1: + break; + default: + count = -EINVAL; + break; + } + + mutex_unlock(&update_lock); + + return count; +} + +/* + * eeprom read fumction + */ +static int fpga_i2c_ready_to_read(struct bin_attribute *attr, int page_type, int i2c_slave_addr) +{ + int cnt = 0; + int chk_state_cnt = 0; + u32 i2c_new_trigger_val = 0; + u32 flag = 0; + struct eeprom_bin_private_data *pdata = NULL; + + pdata = attr->private; + + /*Select i2c protocol profile*/ + iowrite32(0x0, pdata->data_base_addr + pdata->i2c_mgmt_rtc0_profile); + + /*clean read data*/ + for(cnt = 0 ; cnt < 32; cnt++) + { + iowrite32(0x0, pdata->data_base_addr + ( pdata->i2c_rtc_read_data + (4 * cnt) )); + } + + /*clean done status*/ + iowrite32(0x3, pdata->data_base_addr + pdata->i2c_contrl_rtc0_stats); + + /*set read slave addr*/ + iowrite32( 0x10000080|(i2c_slave_addr << 8), pdata->data_base_addr + pdata->i2c_contrl_rtc0_config_0); + + /*triger*/ + if(page_type == EEPROM_LOWER_PAGE) { + i2c_new_trigger_val = PCIE_FPGA_I2C_NEW_TRIGGER_VALUE; + } else { + i2c_new_trigger_val = PCIE_FPGA_I2C_NEW_TRIGGER_VALUE + 0x80; + } + iowrite32(i2c_new_trigger_val, pdata->data_base_addr + pdata->i2c_contrl_rtc0_config_1); + + /*read done status*/ + while( 1 ) { + flag = ioread32(pdata->data_base_addr + pdata->i2c_contrl_rtc0_stats); + if(flag == 0) { + /*In normal case: + observed chk_state_cnt(10~120) times can get i2c rtc0 done status. */ + if( chk_state_cnt > 500 ) { + flag = -EAGAIN; + break; + } + usleep_range(50, 100); + chk_state_cnt++; + continue; + } + else { + break; + } + } + msleep(1); + + return flag; +} + +static int fpga_i2c_set_data(struct bin_attribute *attr, loff_t offset, char *data, int i2c_slave_addr) +{ + int cnt = 0; + int chk_state_cnt = 0; + struct eeprom_bin_private_data *pdata = NULL; + u32 flag = 0; + u32 i2c_new_trigger_val = 0; + + pdata = attr->private; + + /*Select i2c protocol profile*/ + iowrite32(0x0, pdata->data_base_addr + pdata->i2c_mgmt_rtc0_profile); + + /*clean read data*/ + for( cnt=0 ; cnt < (PCIE_FPGA_I2C_MAX_LEN/4); cnt++) + { + iowrite32(0x0, pdata->data_base_addr + ( pdata->i2c_rtc_write_data + (4 * cnt) )); + } + + /* Prepare date to set into data registor*/ + iowrite32(data[0], pdata->data_base_addr + pdata->i2c_rtc_write_data); + + /*clean done status*/ + iowrite32(0x3, pdata->data_base_addr + pdata->i2c_contrl_rtc0_stats); + + /*set write slave addr*/ + iowrite32( EEPROM_ALLOW_SET_LEN | (i2c_slave_addr << 8), pdata->data_base_addr + pdata->i2c_contrl_rtc0_config_0); + + /*triger*/ + i2c_new_trigger_val = PCIE_FPGA_I2C_NEW_TRIGGER_VALUE + offset; + iowrite32(i2c_new_trigger_val, pdata->data_base_addr + pdata->i2c_contrl_rtc0_config_1); + + /*read done status*/ + while( 1 ) { + flag = ioread32(pdata->data_base_addr + pdata->i2c_contrl_rtc0_stats); + if(flag == 0) { + /*In normal case: + observed chk_state_cnt(10~120) times can get i2c rtc0 done status. */ + if( chk_state_cnt > 500 ) { + flag = -EAGAIN; + break; + } + usleep_range(50, 100); + chk_state_cnt++; + continue; + } else { + break; + } + } + msleep(1); + + return flag; +} + +static ssize_t fpga_i2c_read_data(struct bin_attribute *attr, u8 *data) +{ + int cnt = 0; + u32 read_status = 0; + ssize_t byte_size = 0; + struct eeprom_bin_private_data *pdata = NULL; + + pdata = attr->private; + + for( cnt=0 ; cnt < (PCIE_FPGA_I2C_MAX_LEN/4); cnt++) + { + read_status = ioread32(pdata->data_base_addr + (pdata->i2c_rtc_read_data + cnt*4)); + + *(data + cnt*4) = read_status & 0xff; + *(data + cnt*4 + 1) = (read_status >> 8) & 0xff; + *(data + cnt*4 + 2) = (read_status >> 16) & 0xff; + *(data + cnt*4 + 3) = (read_status >> 24) & 0xff; + + byte_size = cnt*4 + 3; + } + + return byte_size + 1; +} + +static int get_port_present_status(struct bin_attribute *attr) +{ + int present = 0; + struct eeprom_bin_private_data *pdata = NULL; + + fpga_read_port_status_value(attr); + + pdata = attr->private; + /* + * get present status: + * regval:0 is present, convert + * regval:1 is unpresent, convert + */ + if(pdata->port_num == FPGA_LDB_SFP_PORT1_NO) /*sfp:65*/ + { + present = !((SFP_PORT0_ABS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } + else if(pdata->port_num == FPGA_LDB_SFP_PORT2_NO) /*sfp:66*/ + { + present = !((SFP_PORT1_ABS(fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].sfp_input_data)) & 0x1); + } + else + { + if(pdata->port_num <= FPGA_LDB_QSFP_PORT_NUM) { /*qsfp:1~32*/ + present = !((fpga_ctl->pci_fpga_dev[pdata->fpga_type].qsfp_present>>(pdata->port_num - 1)) & 0x1); + } else { /*qsfp:33~64*/ + present = !((fpga_ctl->pci_fpga_dev[pdata->fpga_type].qsfp_present>>(pdata->port_num - 33)) & 0x1); + } + } + + return present; +} + +static ssize_t +sfp_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count, int *page) +{ + int state = 0; + int page_num, slice; + char set_page_num[1] = {0}; + struct eeprom_bin_private_data *pdata = NULL; + pdata = attr->private; + + ssize_t byte_cnt; + + u8 data[128] = {0}; + + slice = off / OPTOE_PAGE_SIZE; + /*Cross page case, calculate number of count in current page*/ + if ((off + count) > (slice * OPTOE_PAGE_SIZE + OPTOE_PAGE_SIZE)) { + count = slice * OPTOE_PAGE_SIZE + OPTOE_PAGE_SIZE - off; + } + + if( slice == 0 ) + { + if( (state = fpga_i2c_ready_to_read(attr, EEPROM_LOWER_PAGE, pdata->i2c_slave_addr)) != 1) { + goto exit_err; + } + byte_cnt = fpga_i2c_read_data(attr, &data[0]); + } + else if( slice == 1 ) + { + if( (state = fpga_i2c_ready_to_read(attr, EEPROM_UPPER_PAGE, pdata->i2c_slave_addr)) != 1) { + goto exit_err; + } + byte_cnt = fpga_i2c_read_data(attr, &data[0]); + } + else + { + page_num = slice - 1; + if( pdata->port_num <= FPGA_QSFP_PORT_NUM) /*qsfp page1~0xff*/ + { + set_page_num[0] = page_num; + if( (state = fpga_i2c_set_data(attr, OPTOE_PAGE_SELECT_REG, set_page_num, pdata->i2c_slave_addr)) != 1) { + goto exit_err; + } + + if( (state = fpga_i2c_ready_to_read(attr, EEPROM_UPPER_PAGE, pdata->i2c_slave_addr)) != 1 ) { + goto exit_err; + } + byte_cnt = fpga_i2c_read_data(attr, &data[byte_cnt]); + *page = page_num; + } + else /*sfp support a2(0x51), cat behind a0(0x50)*/ + { + if(page_num == 1) /*a2 lower page*/ + { + if( (state = fpga_i2c_ready_to_read(attr, EEPROM_LOWER_PAGE, TWO_ADDR_0X51)) != 1) { + goto exit_err; + } + byte_cnt = fpga_i2c_read_data(attr, &data[0]); + } + else if (page_num == 2) /*a2 page0*/ + { + set_page_num[0] = 0; + if( (state = fpga_i2c_set_data(attr, OPTOE_PAGE_SELECT_REG, set_page_num, TWO_ADDR_0X51))!=1) { + goto exit_err; + } + + if( (state = fpga_i2c_ready_to_read(attr, EEPROM_UPPER_PAGE, TWO_ADDR_0X51)) != 1) { + goto exit_err; + } + byte_cnt = fpga_i2c_read_data(attr, &data[0]); + } + else + { + set_page_num[0] = page_num - 2; + if( (state = fpga_i2c_set_data(attr, OPTOE_PAGE_SELECT_REG, set_page_num, TWO_ADDR_0X51) != 1)) { /*set page from 1*/ + goto exit_err; + } + + if( (state = fpga_i2c_ready_to_read(attr, EEPROM_UPPER_PAGE, TWO_ADDR_0X51)) != 1 ) { + goto exit_err; + } + byte_cnt = fpga_i2c_read_data(attr, &data[byte_cnt]); + *page = page_num-2; + } + } + } + memcpy(buf, &data[off%128], count); + + return count; + +exit_err: + pcie_err("%s ERROR(%d): Port%d pcie get done status failed!!", show_date_time(), state, pdata->port_num); + + return -EBUSY; +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + int page = 0; + int state = 0; + int i2c_slave_addr; + char set_page_num[1] ={0}; + ssize_t retval = 0; + struct eeprom_bin_private_data *pdata = NULL; + pdata = attr->private; + + if (unlikely(!count)) { + return count; + } + + mutex_lock(&update_lock); + + present = get_port_present_status(attr); + if( !present ) { /*unpresent*/ + mutex_unlock(&update_lock); + return -ENODEV; + } + mutex_unlock(&update_lock); + + /* + * Read data from chip, protecting against concurrent updates + * from this host + */ + mutex_lock(&update_lock); + while (count) { + ssize_t status; + + status = sfp_eeprom_read(filp, kobj, attr, buf, off, count, &page); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + /* + * return the page register to page 0 - why? + * We either have to set the page register to 0 on every access + * to it, or restore it to 0 whenever we change it. Otherwise, + * accesses to page 0 would actually go to whatever the last page + * was. Assume more accesses to page 0 than all other pages + * combined, so less total accesses if we always leave it at page 0 + */ + if( (page > 0) && (pdata->pageable)) + { + i2c_slave_addr = + ( pdata->port_num > FPGA_QSFP_PORT_NUM) ? TWO_ADDR_0X51 : pdata->i2c_slave_addr; + + if( (state = fpga_i2c_set_data(attr, OPTOE_PAGE_SELECT_REG, set_page_num, i2c_slave_addr)) != 1) { /*set page to 0*/ + mutex_unlock(&update_lock); + goto exit_err; + } + } + mutex_unlock(&update_lock); + + return retval; + +exit_err: + pcie_err("%s ERROR(%d): Port%d pcie get done status failed!!", show_date_time(), state, pdata->port_num); + + return -EBUSY; +} + +static ssize_t +sfp_eeprom_write(struct bin_attribute *attr, char *buf, loff_t off, size_t count) +{ + int state = 0; + int page_num, slice, offset; + char set_page_num[1] = {0}; + struct eeprom_bin_private_data *pdata = NULL; + pdata = attr->private; + + slice = off / OPTOE_PAGE_SIZE; + page_num = slice - 1; + offset = off; + + if( page_num > 0) + { + set_page_num[0] = page_num; + if( (state = fpga_i2c_set_data(attr, OPTOE_PAGE_SELECT_REG, set_page_num, pdata->i2c_slave_addr)) != 1) { + goto exit_err; + } + offset = OPTOE_PAGE_SIZE + (off % OPTOE_PAGE_SIZE); + } + + if( (state = fpga_i2c_set_data(attr, offset, buf, pdata->i2c_slave_addr)) != 1) { + goto exit_err; + } + + /* + * If change page, we either have to set the page register to 0 on every access + * to it, or restore it to 0 whenever we change it. + */ + if( page_num > 0) + { + set_page_num[0] = 0; + if( (state = fpga_i2c_set_data(attr, OPTOE_PAGE_SELECT_REG, set_page_num, pdata->i2c_slave_addr)) != 1) { + goto exit_err; + } + } + + return count; + +exit_err: + pcie_err("%s ERROR(%d): Port%d pcie set failed!!", show_date_time(), state, pdata->port_num); + + return -EBUSY; +} + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + ssize_t status = 0; + + if (unlikely(!count) || + likely(count > EEPROM_ALLOW_SET_LEN)) { //only allow count = 1 + return count; + } + + mutex_lock(&update_lock); + + present = get_port_present_status(attr); + if( !present ) { /*unpresent*/ + mutex_unlock(&update_lock); + return -ENODEV; + } + mutex_unlock(&update_lock); + + /* + * Write data to chip, protecting against concurrent updates + * from this host. + */ + mutex_lock(&update_lock); + + status = sfp_eeprom_write(attr, buf, off, count); + + mutex_unlock(&update_lock); + + return status; +} + +static int check_qsfp_eeprom_pageable(struct bin_attribute *eeprom) +{ + int ret = 0; + int not_pageable; + u8 identifier_reg; + u8 pageable_reg; + u32 read_status = 0; + + struct eeprom_bin_private_data *pdata = NULL; + + pdata = eeprom->private; + + if( fpga_i2c_ready_to_read(eeprom, EEPROM_LOWER_PAGE, pdata->i2c_slave_addr) != 1) { + return ret; + } + + read_status = ioread32(pdata->data_base_addr + (pdata->i2c_rtc_read_data)); + + identifier_reg = read_status & 0xff; + pageable_reg = (read_status >> 16) & 0xff; /*check on bit2*/ + + if(identifier_reg == QSFPDD_TYPE) { + not_pageable = CMIS_NOT_PAGEABLE; + } else { + not_pageable = QSFP_NOT_PAGEABLE; + } + + if(pageable_reg & not_pageable) { /*not support*/ + pdata->pageable = 0; + } else { + pdata->pageable = 1; + } + + return pdata->pageable; +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + int ret; + int present = 0; + struct eeprom_bin_private_data *pdata = NULL; + + pdata = eeprom->private; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_SYSFS_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + + mutex_lock(&update_lock); + + present = get_port_present_status(eeprom); + + if(pdata->port_num > FPGA_QSFP_PORT_NUM) /*sfp*/ + { + if( !present ) { /*unpresent*/ + eeprom->size = TWO_ADDR_NO_0X51_SIZE; + } + else + { + ret = fpga_read_sfp_ddm_status_value(eeprom); /*check support_a2 and pageable*/ + if(ret < 0) { + pcie_err("Err: PCIE device port eeprom is empty"); + mutex_unlock(&update_lock); + return ret; + } + + if( !(pdata->sfp_support_a2) ) { /*no A2(0x51)*/ + eeprom->size = TWO_ADDR_NO_0X51_SIZE; + } + else { + eeprom->size = ( (pdata->sfp_support_a2) && (!pdata->pageable) ) ? TWO_ADDR_EEPROM_UNPAGED_SIZE : TWO_ADDR_EEPROM_SIZE; + } + } + } + else /*qsfp*/ + { + if( !present ) { /*unpresent*/ + eeprom->size = OPTOE_ARCH_PAGES; + } else { + eeprom->size = ( check_qsfp_eeprom_pageable(eeprom) ) ? ONE_ADDR_EEPROM_SIZE : ONE_ADDR_EEPROM_UNPAGED_SIZE; + } + } + + mutex_unlock(&update_lock); + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int as9736_64d_pcie_fpga_stat_probe (struct platform_device *pdev) +{ + int cnt = 0, status = 0, port_index = 0; + int err_cnt, disable_cnt, release_cnt; + int find_flag = 0; /*UDB and LDB*/ + int err = 0; + int fpga_no = 0; + struct pci_dev *pcidev, *pcidev_from; + + u16 id16 = 0; + + /* Find Accton register memory space */ + for(cnt = 0 ; cnt < FPGA_NUM ; cnt++) + { + pcidev = pci_get_device(PCI_VENDOR_ID_ACCTON, PCI_DEVICE_ID_ACCTON, (cnt == 0) ? NULL : pcidev_from); + + /*Init*/ + fpga_ctl->pci_dev_addr[cnt] = NULL; + + if (!pcidev && !cnt ) { /*Failed at first time*/ + return -ENODEV; + } + fpga_ctl->pci_dev_addr[cnt] = pcidev; + + /* Enable device: Ask low-level code to enable I/O and memory */ + err = pci_enable_device(pcidev); + if (err != 0) { + pcie_err("Cannot enable PCI(%d) device\n", cnt); + disable_cnt = cnt - 1; + status = -ENODEV; + goto exit_pci_disable; + } + + if ( pci_read_config_word(pcidev, PCI_SUBSYSTEM_ID, &id16) ) + { + disable_cnt = cnt; + status = -ENODEV; + goto exit_pci_disable; + } + pcie_info("Found PCI Device: %s", FPGA_NAME[id16]); + + err = pci_request_regions(pcidev, FPGA_NAME[id16]); + if (err != 0) { + pcie_err("[%s] cannot request regions\n", FPGA_NAME[id16]); + release_cnt = cnt - 1; + disable_cnt = cnt; + goto exit_pci_release; + } + + switch(id16) + { + case PCI_SUBSYSTEM_ID_UDB: + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].fpga_pdev = pcidev; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].id = PCI_SUBSYSTEM_ID_UDB; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].aslpc_cpld1_offset = ASLPC_DEV_UDB_CPLD1_PCIE_START_OFFST; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].aslpc_cpld2_offset = ASLPC_DEV_UDB_CPLD2_PCIE_START_OFFST; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_base_addr = pci_iomap(pcidev, BAR0_NUM, 0); /*0: means access to the complete BAR*/ + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_mmio_start = pci_resource_start(pcidev, BAR0_NUM); + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_mmio_len = pci_resource_len(pcidev, BAR0_NUM); + + /*Init eeprom (UDB)private data: I/O base address*/ + for(port_index = 0 ; port_index < FPGA_UDB_QSFP_PORT_NUM ; port_index++) { + pcie_udb_eeprom_bin_private_data[port_index].data_base_addr = fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_base_addr; + } + + pcie_info("(BAR%d resource: Start=0x%lx, Length=%lx)", BAR0_NUM, + (unsigned long)fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_mmio_start, + (unsigned long)fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_UDB].data_mmio_len); + + find_flag++; + break; + case PCI_SUBSYSTEM_ID_LDB: + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].fpga_pdev = pcidev; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].id = PCI_SUBSYSTEM_ID_LDB; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].aslpc_cpld1_offset = ASLPC_DEV_LDB_CPLD1_PCIE_START_OFFST; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].aslpc_cpld2_offset = ASLPC_DEV_LDB_CPLD2_PCIE_START_OFFST; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_base_addr = pci_iomap(pcidev, BAR0_NUM, 0); /*0: means access to the complete BAR*/ + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_mmio_start = pci_resource_start(pcidev, BAR0_NUM); + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_mmio_len = pci_resource_len(pcidev, BAR0_NUM); + + /*Init eeprom (LDB)private data: I/O base address*/ + for(port_index = 0 ; port_index < (FPGA_LDB_QSFP_PORT_NUM + FPGA_LDB_SFP_PORT_NUM) ; port_index++) { + pcie_ldb_eeprom_bin_private_data[port_index].data_base_addr = fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_base_addr; + } + + pcie_info("(BAR%d resource: Start=0x%lx, Length=%lx)", BAR0_NUM, + (unsigned long)fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_mmio_start, + (unsigned long)fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_mmio_len); + + find_flag++; + break; + case PCI_SUBSYSTEM_ID_SMB: + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].fpga_pdev = pcidev; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].id = PCI_SUBSYSTEM_ID_SMB; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].aslpc_cpld1_offset = ASLPC_DEV_SMB_CPLD_PCIE_START_OFFST; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].aslpc_cpld2_offset = 0; + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].data_base_addr = pci_iomap(pcidev, BAR0_NUM, 0); /*0: means access to the complete BAR*/ + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].data_mmio_start = pci_resource_start(pcidev, BAR0_NUM); + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].data_mmio_len = pci_resource_len(pcidev, BAR0_NUM); + + pcie_info("(BAR%d resource: Start=0x%lx, Length=%lx)", BAR0_NUM, + (unsigned long)fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].data_mmio_start, + (unsigned long)fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_SMB].data_mmio_len); + break; + default: + status = -ENODEV; + break; + } + pcidev_from = pcidev; + } + release_cnt = cnt; + disable_cnt = cnt; + + if ( find_flag != (FPGA_NUM-1) ) { + dev_err(&pdev->dev, "Failed found UDB/LDB FPAG device!!\n"); + status = -ENODEV; + goto exit_pci_iounmap; + } + + status = sysfs_create_group(&pdev->dev.kobj, &fpga_port_stat_group); + if (status) { + goto exit_pci_iounmap; + } + + mutex_lock(&update_lock); + + /*set gpio input/output*/ + iowrite32(0x707, fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_base_addr + SFP_LDB_GPIO1_DATA_EN); + + /* QSFP Port LED: Init port Enable >> LDB/UDB (0 >> 1) */ + for(fpga_no = PCI_SUBSYSTEM_ID_LDB; fpga_no >= PCI_SUBSYSTEM_ID_UDB; fpga_no--) + { + for(cnt = 0; cnt <= 1; cnt++) { + iowrite8(0xff, fpga_ctl->pci_fpga_dev[fpga_no].data_base_addr + + fpga_ctl->pci_fpga_dev[fpga_no].aslpc_cpld1_offset + 0xb0 + cnt); + } + for(cnt = 0; cnt <= 1; cnt++) { + iowrite8(0xff, fpga_ctl->pci_fpga_dev[fpga_no].data_base_addr + + fpga_ctl->pci_fpga_dev[fpga_no].aslpc_cpld2_offset + 0xb0 + cnt); + } + } + /* QSFP Port LED: Init present >> LDB/UDB (1 >> 0) */ + for(fpga_no = PCI_SUBSYSTEM_ID_LDB; fpga_no >= PCI_SUBSYSTEM_ID_UDB; fpga_no--) + { + for(cnt = 0; cnt <= 1; cnt++) { + iowrite8(0x0, fpga_ctl->pci_fpga_dev[fpga_no].data_base_addr + + fpga_ctl->pci_fpga_dev[fpga_no].aslpc_cpld1_offset + 0xb8 + cnt); + } + for(cnt = 0; cnt <= 1; cnt++) { + iowrite8(0x0, fpga_ctl->pci_fpga_dev[fpga_no].data_base_addr + + fpga_ctl->pci_fpga_dev[fpga_no].aslpc_cpld2_offset + 0xb8 + cnt); + } + } + /* SFP Port LED: Init 2XSFP Port Eanble & Present */ + iowrite8(0x3, fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].data_base_addr + + fpga_ctl->pci_fpga_dev[PCI_SUBSYSTEM_ID_LDB].aslpc_cpld1_offset + 0xbd); + + mutex_unlock(&update_lock); + + return 0; + +exit_pci_iounmap: + for(err_cnt = (FPGA_NUM-1); err_cnt >=0; err_cnt--) { + pci_iounmap(fpga_ctl->pci_dev_addr[err_cnt], fpga_ctl->pci_fpga_dev[err_cnt].data_base_addr); + } +exit_pci_release: + for(err_cnt = release_cnt; err_cnt >=0; err_cnt--) { + pci_release_regions(fpga_ctl->pci_dev_addr[err_cnt]); + } +exit_pci_disable: + for(err_cnt = disable_cnt; err_cnt >=0; err_cnt--) { + pci_disable_device(fpga_ctl->pci_dev_addr[err_cnt]); + } + + return status; +} + +static int as9736_64d_pcie_fpga_stat_remove(struct platform_device *pdev) +{ + int cnt = 0; + sysfs_remove_group(&pdev->dev.kobj, &fpga_port_stat_group); + + for(cnt = (FPGA_NUM - 1); cnt >= 0; cnt--) { + pci_iounmap(fpga_ctl->pci_dev_addr[cnt], fpga_ctl->pci_fpga_dev[cnt].data_base_addr); + pci_release_regions(fpga_ctl->pci_dev_addr[cnt]); + pci_disable_device(fpga_ctl->pci_dev_addr[cnt]); + } + + return 0; +} + +static int as9736_64d_pcie_fpga_sfp_probe (struct platform_device *pdev) +{ + int status = 0; + + struct pcie_fpga_dev_platform_data *pdata = NULL; + + pdata = pdev->dev.platform_data; + + if (!pdata) { + status = -ENOMEM; + pcie_err("kzalloc failed\n"); + goto exit; + } + + /*assign port num*/ + if(pdata->fpga_type==PCIE_FPGA_TYPE_LDB) { + sprintf(pdata->name, "port%d", pdata->port_num + 32); + } else { + sprintf(pdata->name, "port%d", pdata->port_num); + } + + status = sysfs_create_group(&pdev->dev.kobj, &fpga_eeprom_group); + if (status) { + pcie_err("sysfs_create_group failed\n"); + goto exit; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&pdev->dev.kobj, &pdata->eeprom_bin); + if (status) { + pcie_err("sfp_sysfs_eeprom_init failed\n"); + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &fpga_eeprom_group); +exit: + return status; +} + +static int __exit as9736_64d_pcie_fpga_sfp_remove(struct platform_device *pdev) +{ + struct pcie_fpga_dev_platform_data *pdata = NULL; + + pdata = pdev->dev.platform_data; + + sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->eeprom_bin); + sysfs_remove_group(&pdev->dev.kobj, &fpga_eeprom_group); + + return 0; +} + +static struct platform_driver pcie_fpga_port_stat_driver = { + .probe = as9736_64d_pcie_fpga_stat_probe, + .remove = as9736_64d_pcie_fpga_stat_remove, + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, +}; + +static struct platform_driver pcie_udb_fpga_driver = { + .probe = as9736_64d_pcie_fpga_sfp_probe, + .remove = __exit_p(as9736_64d_pcie_fpga_sfp_remove), + .driver = { + .owner = THIS_MODULE, + .name = "pcie_udb_fpga_device", + } +}; + +static struct platform_driver pcie_ldb_fpga_driver = { + .probe = as9736_64d_pcie_fpga_sfp_probe, + .remove = __exit_p(as9736_64d_pcie_fpga_sfp_remove), + .driver = { + .owner = THIS_MODULE, + .name = "pcie_ldb_fpga_device", + } +}; + +static int __init as9736_64d_pcie_fpga_init(void) +{ + int status = 0; + int err_cnt; + + int udb_fpga_cnt = 0, ldb_fpga_cnt = 0, ldb_fpga_sfp_ddm_cnt = 0; + + /*Step1. + *Init UDB, LDB port status driver*/ + mutex_init(&update_lock); + + fpga_ctl = kzalloc(sizeof(struct as9736_64d_fpga_data), GFP_KERNEL); + if (!fpga_ctl) { + status = -ENOMEM; + platform_driver_unregister(&pcie_fpga_port_stat_driver); + goto exit; + } + + status = platform_driver_register(&pcie_fpga_port_stat_driver); + if (status < 0) { + goto exit; + } + + fpga_ctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fpga_ctl->pdev)) { + status = PTR_ERR(fpga_ctl->pdev); + goto exit_pci; + } + + /*Step2. Init port device driver*/ + + /*UDB driver*/ + status = platform_driver_register(&pcie_udb_fpga_driver); + if (status < 0) { + pcie_err("Fail to register udb_fpga driver\n"); + goto exit_pci; + } + + /*UDB port1-32 qsfp device*/ + for (udb_fpga_cnt = 0; udb_fpga_cnt < ARRAY_SIZE(pcie_udb_qsfp_device); udb_fpga_cnt++) + { + status = platform_device_register(&pcie_udb_qsfp_device[udb_fpga_cnt]); + if (status) { + pcie_err("Fail to register (UDB)port%d device.\n", (udb_fpga_cnt + 1) ); + goto exit_udb_fpga; + } + } + pcie_info("Init UDB_FPGA driver and device."); + + /*LDB driver*/ + status = platform_driver_register(&pcie_ldb_fpga_driver); + if (status < 0) { + pcie_err("Fail to register ldb_fpga driver.\n"); + goto exit_udb_fpga; + } + /*LDB port33-64, 65-66 qsfp and sfp device*/ + for (ldb_fpga_cnt = 0; ldb_fpga_cnt < ARRAY_SIZE(pcie_ldb_qsfp_device); ldb_fpga_cnt++) + { + status = platform_device_register(&pcie_ldb_qsfp_device[ldb_fpga_cnt]); + if (status) { + pcie_err("Fail to register (LDB)port%d device.\n", (ldb_fpga_cnt + 33) ); + goto exit_ldb_fpga; + } + } + pcie_info("Init LDB_FPGA driver and device."); + + return 0; + +exit_ldb_fpga: + for(err_cnt=(ldb_fpga_cnt-1);err_cnt>=0;err_cnt--){ + platform_device_unregister(&pcie_ldb_qsfp_device[err_cnt]); + } + platform_driver_unregister(&pcie_ldb_fpga_driver); +exit_udb_fpga: + for(err_cnt=(udb_fpga_cnt-1);err_cnt>=0;err_cnt--){ + platform_device_unregister(&pcie_udb_qsfp_device[err_cnt]); + } + platform_driver_unregister(&pcie_udb_fpga_driver); +exit_pci: + platform_driver_unregister(&pcie_fpga_port_stat_driver); + kfree(fpga_ctl); +exit: + return status; +} + +static void __exit as9736_64d_pcie_fpga_exit(void) +{ + int i = 0; + + /*LDB qsfp port33-64, sfp port65-66*/ + for ( i = 0; i < ARRAY_SIZE(pcie_ldb_qsfp_device); i++ ) { + platform_device_unregister(&pcie_ldb_qsfp_device[i]); + } + platform_driver_unregister(&pcie_ldb_fpga_driver); + pcie_info("Remove LDB_FPGA driver and device."); + + /*UDB qsfp port1-32 */ + for ( i = 0; i < ARRAY_SIZE(pcie_udb_qsfp_device); i++ ) { + platform_device_unregister(&pcie_udb_qsfp_device[i]); + } + platform_driver_unregister(&pcie_udb_fpga_driver); + pcie_info("Remove UDB_FPGA driver and device."); + + /*UDB and LDB get port status*/ + platform_device_unregister(fpga_ctl->pdev); + platform_driver_unregister(&pcie_fpga_port_stat_driver); + pcie_info("Remove FPGA status driver."); + kfree(fpga_ctl); +} + + +module_init(as9736_64d_pcie_fpga_init); +module_exit(as9736_64d_pcie_fpga_exit); + +MODULE_AUTHOR("Michael Shih "); +MODULE_DESCRIPTION("AS9734-64D READ EEPROM From FPGA via PCIE"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_psu.c new file mode 100755 index 000000000000..0b673d1cd629 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_as9736_64d_psu.c @@ -0,0 +1,316 @@ +/* + * An hwmon driver for accton as9736_64d Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Michael Shih + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 12 +#define MAX_SERIAL_NUMBER 11 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as9736_64d_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as9736_64d_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as9736_64d_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status_present; /* Status(present) register read from CPLD */ + u8 status_pwr_good; /* Status(power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME+1]; /* Model name, read from eeprom */ + char serial_number[MAX_SERIAL_NUMBER+1]; +}; + +static struct as9736_64d_psu_data *as9736_64d_psu_update_device(struct device *dev); + +enum as9736_64d_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + + +static struct attribute *as9736_64d_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9736_64d_psu_data *data = as9736_64d_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status_present >> data->index & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status_pwr_good >> (1-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9736_64d_psu_data *data = as9736_64d_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as9736_64d_psu_group = { + .attrs = as9736_64d_psu_attributes, +}; + +static int as9736_64d_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9736_64d_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9736_64d_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9736_64d_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9736_64d_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9736_64d_psu_remove(struct i2c_client *client) +{ + struct as9736_64d_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9736_64d_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as9736_64d_psu1, + as9736_64d_psu2 +}; + +static const struct i2c_device_id as9736_64d_psu_id[] = { + { "as9736_64d_psu1", as9736_64d_psu1 }, + { "as9736_64d_psu2", as9736_64d_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9736_64d_psu_id); + +static struct i2c_driver as9736_64d_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as9736_64d_psu", + }, + .probe = as9736_64d_psu_probe, + .remove = as9736_64d_psu_remove, + .id_table = as9736_64d_psu_id, + .address_list = normal_i2c, +}; + +static int as9736_64d_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as9736_64d_psu_data *as9736_64d_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9736_64d_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int status_present, status_pwr_good; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as9736_64d update\n"); + + /* Read psu status */ + status_present = as9736_64d_cpld_read(0x60, 0x14); + status_pwr_good = as9736_64d_cpld_read(0x60, 0x90); + + if ( (status_present < 0) || (status_pwr_good < 0) ) { + dev_dbg(&client->dev, "cpld reg 0x60 offse 0x14 is %d\n", status_present); + dev_dbg(&client->dev, "cpld reg 0x60 offset 0x90 is %d\n", status_pwr_good); + } + else { + data->status_present = status_present; + data->status_pwr_good = status_pwr_good; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial_number, 0, sizeof(data->serial_number)); + power_good = (data->status_pwr_good >> (1-data->index) & 0x1); + + if (power_good) { + status = as9736_64d_psu_read_block(client, 0x12, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + } + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as9736_64d_psu_read_block(client, 0x3f, data->serial_number, MAX_SERIAL_NUMBER); + if (status < 0) + { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + } + data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as9736_64d_psu_driver); + +MODULE_AUTHOR("Michael Shih "); +MODULE_DESCRIPTION("as9736_64d_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_i2c_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_i2c_psu.c new file mode 100755 index 000000000000..39adbb0690df --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/modules/accton_i2c_psu.c @@ -0,0 +1,689 @@ +/* + * An hwmon driver for the Accton Redundant Power Module + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESCRIPTION_NAME "accton i2c psu driver" +/* PMBus Protocol. */ +#define PMBUS_LITERAL_DATA_MULTIPLIER 1000 +#define PMBUS_REGISTER_VOUT_MODE 0x20 +#define PMBUS_REGISTER_STATUS_BYTE 0x78 +#define PMBUS_REGISTER_STATUS_WORD 0x79 +#define PMBUS_REGISTER_STATUS_FAN 0x81 +#define PMBUS_REGISTER_READ_VIN 0x88 +#define PMBUS_REGISTER_READ_IIN 0x89 +#define PMBUS_REGISTER_READ_VOUT 0x8B +#define PMBUS_REGISTER_READ_IOUT 0x8C +#define PMBUS_REGISTER_READ_TEMPERATURE_1 0x8D +#define PMBUS_REGISTER_READ_TEMPERATURE_2 0x8E +#define PMBUS_REGISTER_READ_TEMPERATURE_3 0x8F +#define PMBUS_REGISTER_READ_FAN_SPEED_1 0x90 +#define PMBUS_REGISTER_READ_FAN_SPEED_2 0x91 + +#define PMBUS_REGISTER_READ_FAN_CONFIG_1 0x3A +#define PMBUS_REGISTER_FAN_COMMAND_1 0x3B + +#define PMBUS_REGISTER_READ_POUT 0x96 +#define PMBUS_REGISTER_READ_PIN 0x97 +#define PMBUS_REGISTER_MFR_ID 0x99 +#define PMBUS_REGISTER_MFR_MODEL 0x9A +#define PMBUS_REGISTER_MFR_REVISION 0x9B +#define PMBUS_REGISTER_MFR_SERIAL 0x9E + +#define PMBUS_REGISTER_READ_VIN_MIN 0xa0 +#define PMBUS_REGISTER_READ_VIN_MAX 0xa1 +#define PMBUS_REGISTER_READ_IIN_MAX 0xa2 +#define PMBUS_REGISTER_READ_PIN_MAX 0xa3 +#define PMBUS_REGISTER_READ_VOUT_MIN 0xa4 +#define PMBUS_REGISTER_READ_VOUT_MAX 0xa5 +#define PMBUS_REGISTER_READ_IOUT_MAX 0xa6 +#define PMBUS_REGISTER_READ_POUT_MAX 0xa7 +#define PMBUS_REGISTER_READ_TEMP_MAX 0xa8 + +#define MAX_FAN_DUTY_CYCLE 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct accton_i2c_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[16]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[8]; /* Register value */ + u8 mfr_serial[16]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ + u16 mfr_tambient_max; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev); + +enum accton_i2c_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT_UV, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_SERIAL, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX, + PSU_MFR_TAMBIENT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_vout, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_vout, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); +static SENSOR_DEVICE_ATTR(psu_temp1_max, S_IRUGO, show_linear, NULL, PSU_MFR_TAMBIENT_MAX); + + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +//static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + + +static struct attribute *accton_i2c_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + &sensor_dev_attr_psu_temp1_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + //&sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + accton_i2c_psu_write_word(client, PMBUS_REGISTER_FAN_COMMAND_1 + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 0; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT_UV: + multiplier=1; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_MFR_TAMBIENT_MAX: + value = data->mfr_tambient_max; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + if(!multiplier) + multiplier = PMBUS_LITERAL_DATA_MULTIPLIER; + if(attr->index==PSU_P_OUT_UV) + multiplier = 1000000; + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + int exponent, mantissa; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + switch (attr->index) { + case PSU_MFR_VOUT_MIN: + mantissa = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + mantissa = data->mfr_vout_max; + break; + case PSU_V_OUT: + mantissa = data->v_out; + break; + default: + return 0; + } + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * PMBUS_LITERAL_DATA_MULTIPLIER) : + sprintf(buf, "%d\n", (mantissa * PMBUS_LITERAL_DATA_MULTIPLIER) / (1 << -exponent)); +} + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + switch (attr->index) { + + case PSU_MFR_ID: + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: + ptr = data->mfr_revsion; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + + +static const struct attribute_group accton_i2c_psu_group = { + .attrs = accton_i2c_psu_attributes, +}; + +static int accton_i2c_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct accton_i2c_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct accton_i2c_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &accton_i2c_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int accton_i2c_psu_remove(struct i2c_client *client) +{ + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); + kfree(data); + + return 0; +} +/* Support psu moduel + */ +static const struct i2c_device_id accton_i2c_psu_id[] = { + { "delta_dps2400", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_psu_id); + +static struct i2c_driver accton_i2c_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_psu", + }, + .probe = accton_i2c_psu_probe, + .remove = accton_i2c_psu_remove, + .id_table = accton_i2c_psu_id, + .address_list = normal_i2c, +}; + +static int accton_i2c_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int accton_i2c_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int accton_i2c_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +static int accton_i2c_psu_read_block_data(struct i2c_client *client, u8 command, u8 *data, int data_length) +{ + int status = -EIO; + int length; + u8 buffer[128] = {0}, *ptr = buffer; + + status = accton_i2c_psu_read_byte(client, command); + if (status < 0) + { + dev_dbg(&client->dev, "Unable to get data from offset 0x%02X\r\n", command); + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + + status = (status & 0xFF) + 1; + if ( status > 128) + { + dev_dbg(&client->dev, "Unable to get big data from offset 0x%02X\r\n", command); + status = -EINVAL; + goto EXIT_READ_BLOCK_DATA; + } + + length = status; + status = accton_i2c_psu_read_block(client, command, buffer, length); + if (unlikely(status < 0)) + goto EXIT_READ_BLOCK_DATA; + if (unlikely(status != length)) { + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + /* The first byte is the count byte of string. */ + ptr++; + status--; + + length=status>(data_length-1)?(data_length-1):status; + memcpy(data, ptr, length); + data[length] = 0; + +EXIT_READ_BLOCK_DATA: + + return status; +} + + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + //u8 command, buf; + struct reg_data_byte regs_byte[] = { {PMBUS_REGISTER_VOUT_MODE, &data->vout_mode}, + {PMBUS_REGISTER_STATUS_FAN, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {PMBUS_REGISTER_READ_VIN, &data->v_in}, + {PMBUS_REGISTER_READ_VOUT, &data->v_out}, + {PMBUS_REGISTER_READ_IIN, &data->i_in}, + {PMBUS_REGISTER_READ_IOUT, &data->i_out}, + {PMBUS_REGISTER_READ_POUT, &data->p_out}, + {PMBUS_REGISTER_READ_PIN, &data->p_in}, + {PMBUS_REGISTER_READ_TEMPERATURE_1, &(data->temp_input[0])}, + {PMBUS_REGISTER_READ_TEMPERATURE_2, &(data->temp_input[1])}, + {PMBUS_REGISTER_FAN_COMMAND_1, &(data->fan_duty_cycle[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_1, &(data->fan_speed[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_2, &(data->fan_speed[1])}, + {PMBUS_REGISTER_READ_VIN_MIN, &data->mfr_vin_min}, + {PMBUS_REGISTER_READ_VIN_MAX, &data->mfr_vin_max}, + {PMBUS_REGISTER_READ_IIN_MAX, &data->mfr_iin_max}, + {PMBUS_REGISTER_READ_PIN_MAX, &data->mfr_pin_max}, + {PMBUS_REGISTER_READ_VOUT_MIN, &data->mfr_vout_min}, + {PMBUS_REGISTER_READ_VOUT_MAX, &data->mfr_vout_max}, + {PMBUS_REGISTER_READ_IOUT_MAX, &data->mfr_iout_max}, + {PMBUS_REGISTER_READ_POUT_MAX, &data->mfr_pout_max}, + {PMBUS_REGISTER_READ_TEMP_MAX, &data->mfr_tambient_max}, + }; + + dev_dbg(&client->dev, "Starting accton_i2c_psu update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = accton_i2c_psu_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = accton_i2c_psu_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + + } + /* Read mfr_id */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_ID, data->mfr_id, + ARRAY_SIZE(data->mfr_id)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_ID, status); + goto exit; + } + /* Read mfr_model */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_MODEL, data->mfr_model, + ARRAY_SIZE(data->mfr_model)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_MODEL, status); + goto exit; + } + /* Read mfr_revsion */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_REVISION, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_REVISION, status); + goto exit; + } + /* Read mfr_serial */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_SERIAL, data->mfr_serial, + ARRAY_SIZE(data->mfr_serial)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_SERIAL, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init accton_i2c_psu_init(void) +{ + return i2c_add_driver(&accton_i2c_psu_driver); +} + +static void __exit accton_i2c_psu_exit(void) +{ + i2c_del_driver(&accton_i2c_psu_driver); +} + +MODULE_AUTHOR("Michael Shih "); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION_NAME); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_psu_init); +module_exit(accton_i2c_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor-fan.service new file mode 100644 index 000000000000..4b1d2fd1c9d9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor-fan.service @@ -0,0 +1,14 @@ +[Unit] +Description=Accton AS9736_64D Platform Monitoring FAN service +Before=pmon.service +After=as9736-64d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9736_64d_monitor_fan.py + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor-psu.service new file mode 100644 index 000000000000..ec1d8ca9c4bb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor-psu.service @@ -0,0 +1,14 @@ +[Unit] +Description=Accton AS9736_64D Platform Monitoring PSU service +Before=pmon.service +After=as9736-64d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9736_64d_monitor_psu.py + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor.service new file mode 100644 index 000000000000..657a849ca3aa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/service/as9736-64d-platform-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description=Accton AS9736_64D Platform Monitoring service +Before=pmon.service system-health.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as9736_64d_util.py install +ExecStart=/usr/local/bin/accton_as9736_64d_monitor.py + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/setup.py new file mode 100755 index 000000000000..2df8b1d0e99f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='as9736_64d', + version='1.0', + description='Module to initialize Accton AS9736_64D platforms', + + packages=['as9736_64d'], + package_dir={'as9736_64d': 'as9736-64d/classes'}, +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/__init__.py new file mode 100644 index 000000000000..706e2313249c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ['chassis', 'eeprom', 'platform', 'psu', 'sfp', 'thermal', 'fan', 'fan_drawer'] +from . import platform diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/chassis.py new file mode 100644 index 000000000000..2f2ecb382ab9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/chassis.py @@ -0,0 +1,269 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys +import os + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_py_common.logger import Logger + 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_FAN = 2 +NUM_PSU = 2 +NUM_THERMAL = 12 +NUM_QSFP = 64 +PORT_START = 1 +PORT_END = 66 +QSFP_PORT_START = 0 +QSFP_PORT_END = 63 +NUM_COMPONENT = 8 +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" +HOST_CHK_CMD = "docker > /dev/null 2>&1" +SYSLED_FNODE= "/sys/bus/platform/devices/as9736_64d_fpga/led_stat" + +SYSLED_MODES = { + "12" : "STATUS_LED_COLOR_AMBER", + "16" : "STATUS_LED_COLOR_GREEN", + "17" : "STATUS_LED_COLOR_GREEN_BLINKING" +} + +SFP_STATUS_INSERTED = '1' + +# Global logger class instance +logger = Logger() + +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 + + self.QSFP_PORT_START = QSFP_PORT_START + self.QSFP_PORT_END = QSFP_PORT_END + for index in range(0, PORT_END): + if index in range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1): + sfp_module = Sfp(index, 'QSFP') + else: + sfp_module = Sfp(index, 'SFP') + self._sfp_list.append(sfp_module) + + 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(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Tlv + self._eeprom = Tlv() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def __initialize_watchdog(self): + from sonic_platform.watchdog import Watchdog + self._watchdog = Watchdog() + + + def __is_host(self): + return os.system(HOST_CHK_CMD) == 0 + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + + return self._api_helper.hwsku + + def get_presence(self): + """ + Retrieves the presence of the Chassis + Returns: + bool: True if Chassis is present, False if not + """ + return True + + def get_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 chassis + Returns: + string: Model/part number of chassis + """ + 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_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. + """ + + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) + sw_reboot_cause = self._api_helper.read_txt_file( + reboot_cause_path) or "Unknown" + + + return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) + + 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_change_event(self, timeout=0): + # SFP event + if not self.sfp_module_initialized: + self.__initialize_sfp() + + status, sfp_event = self._sfpevent.get_sfp_event(timeout) + + return status, sfp_event + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + 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 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/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/component.py new file mode 100644 index 000000000000..42770acd75dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/component.py @@ -0,0 +1,207 @@ +############################################################################# +# Accton +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import shlex +import subprocess + + +try: + from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CPLD_ADDR_MAPPING = { + "SYSTEM CPLD": "6-0060", + "FCM CPLD": "25-0033", + "PSU CPLD": "36-0060", + "SCM CPLD": "51-0035" +} + +FPGA_VERSION_MAPPING = { + "UDB FPGA": "udb_version", + "LDB FPGA": "ldb_version", + "SMB FPGA": "smb_version" +} + +SYSFS_PATH = "/sys/bus/i2c/devices/" +FPGA_PATH = "/sys/devices/platform/as9736_64d_fpga/" +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + +COMPONENT_LIST= [ + ("SYSTEM CPLD", "SYSTEM CPLD"), + ("FCM CPLD", "Fan Control Module CPLD"), + ("PSU CPLD", "Power Supply Unit CPLD"), + ("SCM CPLD", "Switch Control Module CPLD"), + ("UDB FPGA", "Upper Daughter Board FPGA"), + ("LDB FPGA", "Lower Daughter Board FPGA"), + ("SMB FPGA", "Switch Main Board FPGA"), + ("BIOS", "Basic Input/Output System") +] + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index=0): + self._api_helper=APIHelper() + ComponentBase.__init__(self) + self.index = component_index + self.name = self.get_name() + + def __run_command(self, command): + # Run bash command and print output to stdout + try: + process = subprocess.Popen( + shlex.split(command), stdout=subprocess.PIPE) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + rc = process.poll() + if rc != 0: + return False + except Exception: + return False + return True + + 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): + # Retrieves the CPLD firmware version + cpld_version = dict() + for cpld_name in CPLD_ADDR_MAPPING: + try: + cpld_path = "{}{}{}".format(SYSFS_PATH, CPLD_ADDR_MAPPING[cpld_name], '/version') + cpld_version_raw= self._api_helper.read_txt_file(cpld_path) + cpld_version[cpld_name] = "{}".format(cpld_version_raw) + except Exception as e: + print('Get exception when read cpld') + cpld_version[cpld_name] = 'None' + + return cpld_version + + def __get_fpga_version(self): + # Retrieves the FPGA firmware version + fpga_version = dict() + for fpga_name in FPGA_VERSION_MAPPING: + try: + fpga_path = "{}{}".format(FPGA_PATH, FPGA_VERSION_MAPPING[fpga_name]) + fpga_version_raw= self._api_helper.read_txt_file(fpga_path) + fpga_version[fpga_name] = "{}".format(fpga_version_raw) + except Exception as e: + print('Get exception when read fpga') + fpga_version[fpga_name] = 'None' + + return fpga_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: + cpld_version = self.__get_cpld_version() + fw_version = cpld_version.get(self.name) + elif "FPGA" in self.name: + fpga_version = self.__get_fpga_version() + fw_version = fpga_version.get(self.name) + + 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 + """ + raise NotImplementedError + + 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/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/eeprom.py new file mode 100644 index 000000000000..3e7cbd134a46 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/eeprom.py @@ -0,0 +1,140 @@ +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' +TLV_PRODUCT_NAME='0x21' +TLV_PART_NUMBER='0x22' +TLV_SERIAL_NUMBER='0x23' +TLV_BASE_MAC_ADDRESS='0x24' + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + + self._eeprom_path = "/sys/bus/i2c/devices/20-0051/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(TLV_PART_NUMBER, NULL) + + def get_serial(self): + return self._eeprom.get(TLV_SERIAL_NUMBER, NULL) + + def get_mac(self): + return self._eeprom.get(TLV_BASE_MAC_ADDRESS, NULL) + + def get_modelstr(self): + return self._eeprom.get(TLV_PRODUCT_NAME, NULL) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/event.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/event.py new file mode 100644 index 000000000000..fb28c38839a2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/event.py @@ -0,0 +1,66 @@ +try: + import time + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(repr(e) + " - required module not found") + +POLL_INTERVAL_IN_SEC = 1 + +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: + # clear bitmap if refresh_optoe_dev_class() failed + if sfp._refresh_optoe_dev_class() is False: + bitmap = bitmap & ~(1 << i) + continue + + 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 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/fan.py new file mode 100644 index 000000000000..4eb806aa4cd3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/fan.py @@ -0,0 +1,287 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.fan_base import FanBase + from .helper import APIHelper + import os.path +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SPEED_TOLERANCE = 30 +TARGET_SPEED_PATH = "/tmp/fan_target_speed" +CPLD_FAN_I2C_PATH = "/sys/bus/i2c/devices/25-0033/fan" +I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/" +PSU_HWMON_I2C_MAPPING = { + 0: { + "num": 41, + "addr": "59" + }, + 1: { + "num": 33, + "addr": "58" + }, +} + +PSU_CPLD_I2C_MAPPING = { + 0: { + "num": 41, + "addr": "51" + }, + 1: { + "num": 33, + "addr": "50" + }, +} + +FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", + "FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R"] + +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 + + if self.is_psu_fan: + self.psu_index = psu_index + self.psu_i2c_num = PSU_HWMON_I2C_MAPPING[self.psu_index]['num'] + self.psu_i2c_addr = PSU_HWMON_I2C_MAPPING[self.psu_index]['addr'] + self.psu_hwmon_path = I2C_PATH.format( + self.psu_i2c_num, self.psu_i2c_addr) + + self.psu_i2c_num = PSU_CPLD_I2C_MAPPING[self.psu_index]['num'] + self.psu_i2c_addr = PSU_CPLD_I2C_MAPPING[self.psu_index]['addr'] + self.psu_cpld_path = I2C_PATH.format( + self.psu_i2c_num, self.psu_i2c_addr) + + 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 + """ + if not self.is_psu_fan: + dir_str = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_direction') + val=self._api_helper.read_txt_file(dir_str) + if val is not None: #F2B is FAN_DIRECTION_EXHAUST + direction = self.FAN_DIRECTION_EXHAUST if ( + val == "0") else self.FAN_DIRECTION_INTAKE + else: + direction=self.FAN_DIRECTION_EXHAUST + + else: #For PSU + direction=self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + """ + speed = 0 + if self.is_psu_fan: + psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_speed_rpm') + fan_speed_rpm = self._api_helper.read_txt_file(psu_fan_path) + if fan_speed_rpm is not None: + speed = (int(fan_speed_rpm,10))*100/26688 + if speed > 100: + speed=100 + 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_path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_duty_cycle_percentage') + speed=self._api_helper.read_txt_file(speed_path) + if speed is None: + return 0 + 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 + """ + return self.get_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 SPEED_TOLERANCE + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + + """ + + if not self.is_psu_fan and self.get_presence(): + speed_path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_duty_cycle_percentage') + ret = self._api_helper.write_txt_file(speed_path, int(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: + status_ps=self.get_presence() #present + status=self.get_status() #power good + + if status is None or status_ps is False: + return self.STATUS_LED_COLOR_OFF + + else: + status=self.get_presence() + if status is None: + return self.STATUS_LED_COLOR_OFF + + return { + 1: self.STATUS_LED_COLOR_GREEN, + 0: self.STATUS_LED_COLOR_AMBER + }.get(status, self.STATUS_LED_COLOR_OFF) + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] \ + if not self.is_psu_fan \ + else "PSU-{} FAN-{}".format(self.psu_index+1, self.fan_index+1) + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + present_path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_present') + val=self._api_helper.read_txt_file(present_path) + if not self.is_psu_fan: + if val is not None: + return int(val, 10)==1 + else: + return False + else: + presence_path="{}{}".format(self.psu_cpld_path, 'psu_present') + val=self._api_helper.read_txt_file(presence_path) + 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: + psu_fan_path= "{}{}".format(self.psu_cpld_path, 'psu_power_good') + val=self._api_helper.read_txt_file(psu_fan_path) + if val is not None: + return int(val, 10)==1 + else: + return False + else: + path = "{}{}{}".format(CPLD_FAN_I2C_PATH, self.fan_tray_index+1, '_fault') + val=self._api_helper.read_txt_file(path) + if val is not None: + return int(val, 10)==0 + else: + return False + + + 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/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..58f0bd17f763 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/fan_drawer.py @@ -0,0 +1,83 @@ +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 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/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/helper.py new file mode 100644 index 000000000000..6653ab163dac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/helper.py @@ -0,0 +1,384 @@ +import os +import struct +import subprocess +import json +import fcntl +from mmap import * +from sonic_py_common import device_info +from sonic_py_common import logger +from threading import Lock +from typing import cast + +HOST_CHK_CMD = "which systemctl > /dev/null 2>&1" +EMPTY_STRING = "" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + return os.system(HOST_CHK_CMD) == 0 + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def run_command(self, cmd): + status = True + result = "" + try: + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + except Exception: + status = False + return status, result + + def run_interactive_command(self, cmd): + try: + os.system(cmd) + except Exception: + return False + return True + + def read_txt_file(self, file_path): + try: + with open(file_path, encoding='unicode_escape', errors='replace') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + fd.flush() + except IOError: + return False + return True + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + try: + cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd)) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + 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: + cmd = "ipmitool fru print {}".format(str( + id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key)) + + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + 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: + cmd = "ipmitool sensor thresh '{}' {} {}".format(str(id), str(threshold_key), str(value)) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + +class 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" +HIGH_THRESHOLD_FIELD = 'high_threshold' +LOW_THRESHOLD_FIELD = 'low_threshold' +HIGH_CRIT_THRESHOLD_FIELD = 'high_critical_threshold' +LOW_CRIT_THRESHOLD_FIELD = 'low_critical_threshold' +NOT_AVAILABLE = 'N/A' + +class DeviceThreshold: + + 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 = {} + try: + with self.flock: + with open(DEVICE_THRESHOLD_JSON_PATH, "r") as db_file: + self.__db_data = json.load(db_file) + except Exception as e: + self.__log.log_warning('{}'.format(str(e))) + + @property + def HIGH_THRESHOLD_FIELD(self): + return HIGH_THRESHOLD_FIELD + + @property + def LOW_THRESHOLD_FIELD(self): + return LOW_THRESHOLD_FIELD + + @property + def HIGH_CRIT_THRESHOLD_FIELD(self): + return HIGH_CRIT_THRESHOLD_FIELD + + @property + def LOW_CRIT_THRESHOLD_FIELD(self): + return LOW_CRIT_THRESHOLD_FIELD + + @property + def NOT_AVAILABLE(self): + return NOT_AVAILABLE + + 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 self.name not in self.__db_data.keys(): + return NOT_AVAILABLE + + if field not in self.__db_data[self.name].keys(): + return 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 = "w+" + if os.path.exists(DEVICE_THRESHOLD_JSON_PATH): + mode = "r+" + 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) + 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(HIGH_THRESHOLD_FIELD) + + 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 != NOT_AVAILABLE: + tmp = float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(HIGH_THRESHOLD_FIELD, 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(LOW_THRESHOLD_FIELD) + + 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 != NOT_AVAILABLE: + tmp = float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(LOW_THRESHOLD_FIELD, 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(HIGH_CRIT_THRESHOLD_FIELD) + + 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 != NOT_AVAILABLE: + tmp = float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(HIGH_CRIT_THRESHOLD_FIELD, 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(LOW_CRIT_THRESHOLD_FIELD) + + 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 != NOT_AVAILABLE: + tmp = float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(LOW_CRIT_THRESHOLD_FIELD, temperature) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/pcie.py new file mode 100644 index 000000000000..e4da32adf9f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/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) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/platform.py new file mode 100644 index 000000000000..b6bc56b5cc67 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/platform.py @@ -0,0 +1,21 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/psu.py new file mode 100644 index 000000000000..c2e2d11b4208 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/psu.py @@ -0,0 +1,281 @@ +############################################################################# +# Accton +# +# 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 sonic_platform.thermal import Thermal + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +I2C_PATH ="/sys/bus/i2c/devices/{0}-00{1}/" + +PSU_NAME_LIST = ["PSU-1", "PSU-2"] +PSU_NUM_FAN = [1, 1] +PSU_HWMON_I2C_MAPPING = { + 0: { + "num": 41, + "addr": "59" + }, + 1: { + "num": 33, + "addr": "58" + }, +} + +PSU_CPLD_I2C_MAPPING = { + 0: { + "num": 41, + "addr": "51" + }, + 1: { + "num": 33, + "addr": "50" + }, +} + +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.i2c_num = PSU_HWMON_I2C_MAPPING[self.index]["num"] + self.i2c_addr = PSU_HWMON_I2C_MAPPING[self.index]["addr"] + self.hwmon_path = I2C_PATH.format(self.i2c_num, self.i2c_addr) + + self.i2c_num = PSU_CPLD_I2C_MAPPING[self.index]["num"] + self.i2c_addr = PSU_CPLD_I2C_MAPPING[self.index]["addr"] + self.cpld_path = I2C_PATH.format(self.i2c_num, self.i2c_addr) + self.__initialize_fan() + ''' + for fan_index in range(0, PSU_NUM_FAN[self.index]): + #def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): + #fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) + fan = Fan(fan_index, 0, True, self.index) + self._fan_list.append(fan) + ''' + + 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, 0, is_psu_fan=True, psu_index=self.index) + self._fan_list.append(fan) + + self._thermal_list.append(Thermal(is_psu=True, psu_index=self.index)) + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + vout_path = "{}{}".format(self.hwmon_path, 'psu_v_out') + vout_val=self._api_helper.read_txt_file(vout_path) + if vout_val is not None: + return float(vout_val)/ 1000 + else: + return 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 + """ + iout_path = "{}{}".format(self.hwmon_path, 'psu_i_out') + val=self._api_helper.read_txt_file(iout_path) + if val is not None: + return float(val)/1000 + else: + return 0 + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + pout_path = "{}{}".format(self.hwmon_path, 'psu_p_out') + val=self._api_helper.read_txt_file(pout_path) + if val is not None: + return float(val)/1000 + else: + return 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 HW + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + status_ps=self.get_presence() #present + status=self.get_status() #power good + + if status is None or status_ps is False: + return self.STATUS_LED_COLOR_OFF + + return { + 1: self.STATUS_LED_COLOR_GREEN, + 0: self.STATUS_LED_COLOR_AMBER + }.get(status, self.STATUS_LED_COLOR_OFF) + + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_path = "{}{}".format(self.hwmon_path, 'psu_temp1_input') + val=self._api_helper.read_txt_file(temp_path) + if val is not None: + return float(val)/1000 + else: + return 0 + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return self._thermal_list[0].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 + """ + vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_max') + vout_val=self._api_helper.read_txt_file(vout_path) + if vout_val is not None: + return float(vout_val)/ 1000 + else: + return 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 + """ + vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_min') + vout_val=self._api_helper.read_txt_file(vout_path) + if vout_val is not None: + return float(vout_val)/ 1000 + else: + return 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 + """ + presence_path="{}{}".format(self.cpld_path, 'psu_present') + val=self._api_helper.read_txt_file(presence_path) + if val is not None: + return int(val, 10) == 1 + else: + return 0 + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + power_path="{}{}".format(self.cpld_path, 'psu_power_good') + val=self._api_helper.read_txt_file(power_path) + if val is not None: + return int(val, 10) == 1 + else: + return 0 + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + model_path="{}{}".format(self.cpld_path, 'psu_model_name') + model=self._api_helper.read_txt_file(model_path) + + 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_path="{}{}".format(self.cpld_path, 'psu_serial_number') + serial=self._api_helper.read_txt_file(serial_path) + + if serial is None: + return "N/A" + return serial + + 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/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/sfp.py new file mode 100644 index 000000000000..a03719ce91b6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/sfp.py @@ -0,0 +1,473 @@ +############################################################################# +# Accton +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import sys +import time +import struct + +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +#Edge-core definitions +FPGA_PCIE_PATH = "/sys/devices/platform/as9736_64d_fpga/" + +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 + +QSFP_CONTROL_WIDTH = 8 +QSFP_CONTROL_OFFSET = 86 +QSFP_POWEROVERRIDE_OFFSET = 93 + +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 +] + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" +QSFP_DD_TYPE = "QSFP_DD" + +NULL_VAL = 'N/A' + + +SFP_I2C_START = 17 +PCIE_UDB_EEPROM_PATH = '/sys/devices/platform/pcie_udb_fpga_device.{0}/eeprom' +PCIE_LDB_EEPROM_PATH = '/sys/devices/platform/pcie_ldb_fpga_device.{0}/eeprom' +PCIE_UDB_OPTOE_DEV_CLASS_PATH = '/sys/devices/platform/pcie_udb_fpga_device.{0}/dev_class' +PCIE_LDB_OPTOE_DEV_CLASS_PATH = '/sys/devices/platform/pcie_ldb_fpga_device.{0}/dev_class' + +PCIE_UDB_BIND_PATH = "/sys/bus/platform/drivers/pcie_udb_fpga_device/{0}" +PCIE_LDB_BIND_PATH = "/sys/bus/platform/drivers/pcie_ldb_fpga_device/{0}" + +class Sfp(SfpOptoeBase): + """Platform-specific Sfp class""" + HOST_CHK_CMD = "which systemctl > /dev/null 2>&1" + PLATFORM = "x86_64-accton_as9736_64d-r0" + HWSKU = "Accton-AS9736-64D" + PORT_START = 1 + PORT_END = 66 + QSFP_PORT_START = 1 + QSFP_PORT_END = 64 + + # Path to sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + + UDB_QSFP_PORT_START = 1 + UDB_QSFP_PORT_END = 32 + LDB_QSFP_PORT_START = 33 + LDB_QSFP_PORT_END = 64 + LDB_SFP_PORT_START = 65 + LDB_SFP_PORT_END = 66 + + def __init__(self, sfp_index=0, sfp_name=None): + SfpOptoeBase.__init__(self) + + self.index = sfp_index + self.port_num = self.index + 1 + self._api_helper = APIHelper() + self._name = sfp_name + + self._refresh_optoe_dev_class() + + def __write_txt_file(self, file_path, value): + try: + reg_file = open(file_path, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_file.write(str(value)) + reg_file.close() + + return True + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def get_eeprom_path(self): + if self.index < 32: + port_eeprom_path = PCIE_UDB_EEPROM_PATH.format(self.index) + else: + port_eeprom_path = PCIE_LDB_EEPROM_PATH.format(self.index - 32) + + return port_eeprom_path + + def read_eeprom(self, offset, num_bytes): + port_eeprom_path = self.get_eeprom_path() + + #Try to solved IOError + tries = 15 + for i in range(tries): + try: + eeprom = open(port_eeprom_path, mode='rb', buffering=0) + except (IOError): + if i < tries - 1: + time.sleep(0.02) + continue + else: + return None + break + try: + eeprom.seek(offset) + eeprom_raw = bytearray(eeprom.read(num_bytes)) + eeprom.close() + return eeprom_raw + except (OSError, IOError): + return None + + def _detect_sfp_type(self): + sfp_type = QSFP_TYPE + eeprom_raw = [] + eeprom_raw = self.read_eeprom(XCVR_TYPE_OFFSET, XCVR_TYPE_WIDTH) + if eeprom_raw: + if eeprom_raw[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + elif eeprom_raw[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + elif eeprom_raw[0] in QSFP_DD_TYPE_CODE_LIST: + self.sfp_type = QSFP_DD_TYPE + else: + self.sfp_type = sfp_type + else: + self.sfp_type = sfp_type + + def _refresh_optoe_dev_class(self): + self._detect_sfp_type() + + if self.index < 32: + port = "pcie_udb_fpga_device.{}".format(self.index) + port_dev_unbind = PCIE_UDB_BIND_PATH.format("unbind") + port_dev_bind = PCIE_UDB_BIND_PATH.format("bind") + else: + port = "pcie_ldb_fpga_device.{}".format(self.index-32) + port_dev_unbind = PCIE_LDB_BIND_PATH.format("unbind") + port_dev_bind = PCIE_LDB_BIND_PATH.format("bind") + + if self.sfp_type == QSFP_TYPE: + self._api_helper.write_txt_file(port_dev_unbind, port) + self._api_helper.write_txt_file(port_dev_bind, port) + elif self.sfp_type == SFP_TYPE: + self._api_helper.write_txt_file(port_dev_unbind, port) + self._api_helper.write_txt_file(port_dev_bind, port) + elif self.sfp_type == QSFP_DD_TYPE: + self._api_helper.write_txt_file(port_dev_unbind, port) + self._api_helper.write_txt_file(port_dev_bind, port) + else: + return False + + 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 + else: + return False + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.port_num > 64: + # SFP doesn't support this feature + return False + + 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 + else: + 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 + """ + # Check for invalid port_num + + if self.port_num > 64: + return False # SFP doesn't support this feature + else: + if not self.get_presence(): + return False + reset_path = "{}{}{}".format(FPGA_PCIE_PATH, 'module_reset_', self.port_num) + + ret = self.__write_txt_file(reset_path, 1) #sysfs 1: enable reset + if ret is not True: + return ret + + time.sleep(0.2) + ret = self.__write_txt_file(reset_path, 0) #sysfs 0: disable reset + time.sleep(0.2) + + 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 self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + tx_disable_value = 0xf if tx_disable else 0x0 + # Write to eeprom + sysfsfile_eeprom = open(self._eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.port_num > 64: + return False # SFP doesn't support this feature + else: + if not self.get_presence(): + return False + + lpmode_path = "{}{}{}".format(FPGA_PCIE_PATH, 'module_lp_mode_', self.port_num) + + if lpmode is True: + ret = self.__write_txt_file(lpmode_path, 1) #enable lpmode + else: + ret = self.__write_txt_file(lpmode_path, 0) #disable lpmode + + return ret + + def _convert_raw_to_byte(self, raw, num_bytes): + """ + Convert raw to the sytle that can parsing by sfpd_obj function + Returns: + A Array, hex value convert with no prefix of 0x + """ + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + if isinstance(raw, str): + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + else: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + + except BaseException: + return None + + return eeprom_raw + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + power_override = False + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._convert_raw_to_byte( + self.read_eeprom(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH), QSFP_CONTROL_WIDTH) if self.get_presence() else None + + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ( + 'On' == dom_control_data['data']['PowerOverride']['value']) + + return power_override + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + + if not self.get_presence(): + return False + try: + power_override_bit = (1 << 0) if power_override else 0 + power_set_bit = (1 << 1) if power_set else (1 << 3) + + buffer = create_string_buffer(1) + if sys.version_info[0] >= 3: + buffer[0] = (power_override_bit | power_set_bit) + else: + buffer[0] = chr(power_override_bit | power_set_bit) + + port_eeprom_path = self.get_eeprom_path() + + fd = open(port_eeprom_path, mode="rb+", buffering=0) + fd.seek(QSFP_POWEROVERRIDE_OFFSET) + fd.write(buffer[0]) + time.sleep(0.01) + fd.close() + + except Exception as e: + print ('Error: unable to open file: ', str(e)) + return False + + return True + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the 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 + 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 + """ + return self.get_presence() and not self.get_reset_status() + + def get_position_in_parent(self): + """ + Returns: + Temp return 0 + """ + return self.port_num + + def is_replaceable(self): + """ + Retrieves if replaceable + Returns: + A boolean value, True if replaceable + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/thermal.py new file mode 100644 index 000000000000..e9d9d88872e6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform/thermal.py @@ -0,0 +1,403 @@ +############################################################################# +# Accton +# +# 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 +import glob + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .helper import DeviceThreshold +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/" + +PSU_HWMON_I2C_MAPPING = { + 0: { + "num": 41, + "addr": "59" + }, + 1: { + "num": 33, + "addr": "58" + } +} + +PSU_CPLD_I2C_MAPPING = { + 0: { + "num": 41, + "addr": "51" + }, + 1: { + "num": 33, + "addr": "50" + } +} + +THERMAL_NAME_LIST = ["Temp sensor 1", "Temp sensor 2", "Temp sensor 3", + "Temp sensor 4", "Temp sensor 5", "Temp sensor 6", + "Temp sensor 7", "Temp sensor 8", "Temp sensor 9", + "Temp sensor 10", "Temp sensor 11", "CPU Temp"] + +PSU_THERMAL_NAME_LIST = ["PSU-1 temp sensor 1", "PSU-2 temp sensor 1"] + +SYSFS_PATH = "/sys/bus/i2c/devices" +CPU_SYSFS_PATH = "/sys/devices/platform" + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index=0, is_psu=False, psu_index=0): + global psu_temp_max + self.index = thermal_index + self.is_psu = is_psu + self.psu_index = psu_index + + if self.is_psu: + psu_i2c_bus = PSU_HWMON_I2C_MAPPING[psu_index]["num"] + psu_i2c_addr = PSU_HWMON_I2C_MAPPING[psu_index]["addr"] + self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus, + psu_i2c_addr) + psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["num"] + psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"] + self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr) + + self.conf = DeviceThreshold(self.get_name()) + if self.is_psu: + temp_file_path = self.psu_hwmon_path + "psu_temp1_max" + psu_temp_max = self.__get_temp(temp_file_path) + # Default thresholds + self.default_threshold = { + THERMAL_NAME_LIST[0] : { + self.conf.HIGH_THRESHOLD_FIELD : '71.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '76.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[1] : { + self.conf.HIGH_THRESHOLD_FIELD : '55.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '60.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[2] : { + self.conf.HIGH_THRESHOLD_FIELD : '58.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '63.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[3] : { + self.conf.HIGH_THRESHOLD_FIELD : '49.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '54.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[4] : { + self.conf.HIGH_THRESHOLD_FIELD : '50.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '55.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[5] : { + self.conf.HIGH_THRESHOLD_FIELD : '45.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '50.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[6] : { + self.conf.HIGH_THRESHOLD_FIELD : '41.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '46.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[7] : { + self.conf.HIGH_THRESHOLD_FIELD : '65.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '70.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[8] : { + self.conf.HIGH_THRESHOLD_FIELD : '56.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '61.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[9] : { + self.conf.HIGH_THRESHOLD_FIELD : '52.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '57.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[10] : { + self.conf.HIGH_THRESHOLD_FIELD : '62.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '67.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + THERMAL_NAME_LIST[11] : { + self.conf.HIGH_THRESHOLD_FIELD : '99.0', + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : '107.0', + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + PSU_THERMAL_NAME_LIST[0] : { + self.conf.HIGH_THRESHOLD_FIELD : str(float(psu_temp_max)), + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + }, + PSU_THERMAL_NAME_LIST[1] : { + self.conf.HIGH_THRESHOLD_FIELD : str(float(psu_temp_max)), + self.conf.LOW_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.HIGH_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE, + self.conf.LOW_CRIT_THRESHOLD_FIELD : self.conf.NOT_AVAILABLE + } + } + + # Set hwmon path + i2c_path = { + 0: "2-0048/hwmon/hwmon*/", + 1: "2-0049/hwmon/hwmon*/", + 2: "14-004c/hwmon/hwmon*/", + 3: "27-0048/hwmon/hwmon*/", + 4: "27-0049/hwmon/hwmon*/", + 5: "34-0048/hwmon/hwmon*/", + 6: "42-0049/hwmon/hwmon*/", + 7: "57-0048/hwmon/hwmon*/", + 8: "58-004c/hwmon/hwmon*/", + 9: "65-004c/hwmon/hwmon*/", + 10: "66-004d/hwmon/hwmon*/", + 11: "coretemp.0/hwmon/hwmon*/" + }.get(self.index, None) + + self.is_cpu = False + if self.index == 11: + self.is_cpu = True + self.hwmon_path = "{}/{}".format(CPU_SYSFS_PATH, i2c_path) + else: + self.hwmon_path = "{}/{}".format(SYSFS_PATH, i2c_path) + self.ss_key = THERMAL_NAME_LIST[self.index] + self.ss_index = 1 + + def __read_txt_file(self, file_path): + for filename in glob.glob(file_path): + try: + with open(filename, 'r') as fd: + data =fd.readline().rstrip() + return data + except IOError as e: + pass + + return None + + 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.__read_txt_file(temp_file_path) + if raw_temp is not None: + return float(raw_temp)/1000 + else: + return 80.0 + + def __set_threshold(self, file_name, temperature): + if self.is_psu: + return True + temp_file_path = os.path.join(self.hwmon_path, file_name) + for filename in glob.glob(temp_file_path): + try: + with open(filename, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError as e: + print("IOError") + + + 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.psu_hwmon_path + "psu_temp1_input" + return self.__get_temp(temp_file) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + value = self.conf.get_high_threshold() + if value != self.conf.NOT_AVAILABLE: + return float(value) + + default_value = self.default_threshold[self.get_name()][self.conf.HIGH_THRESHOLD_FIELD] + if default_value != self.conf.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: + return False + + try: + self.conf.set_high_threshold(str(value)) + except: + 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 PSU_THERMAL_NAME_LIST[self.psu_index] + else: + return THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the Thermal + Returns: + bool: True if Thermal is present, False if not + """ + if self.is_cpu: + return True + + if self.is_psu: + val = self.__read_txt_file(self.cpld_path + "psu_present") + return int(val, 10) == 1 + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_txt = self.__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.psu_hwmon_path + "psu_temp1_input" + return self.get_presence() and (int( + self.__read_txt_file(temp_file))) + + file_str = "temp{}_input".format(self.ss_index) + file_path = os.path.join(self.hwmon_path, file_str) + raw_txt = self.__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_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 != self.conf.NOT_AVAILABLE: + return float(value) + + default_value = self.default_threshold[self.get_name()][self.conf.HIGH_CRIT_THRESHOLD_FIELD] + if default_value != self.conf.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: + return False + + try: + self.conf.set_high_critical_threshold(str(value)) + except: + return False + + return True diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform_setup.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform_setup.py new file mode 100644 index 000000000000..22bd354ea686 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/sonic_platform_setup.py @@ -0,0 +1,25 @@ +from setuptools import setup + +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', + packages=['sonic_platform'], + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Plugins', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/README b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/README new file mode 100755 index 000000000000..78a5ce662b90 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/README @@ -0,0 +1,65 @@ +Copyright (C) 2019 Accton Networks, Inc. + +This program is free software: you can redistribute it and/or modify +It under the terms of the GNU General Public License as published by +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 . + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS9736-64D has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are at module dir. +2. A operational script, accton_as9736_64d_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + Run "accton_as9736_64d_util.py install" to install drivers. + +To initialize the system, run "accton_as9736_64d_util.py install". +To clean up the drivers & devices, run "accton_as9736_64d_util.py clean". +To dump information of sensors, run "accton_as9736_64d_util.py show". +To dump SFP EEPROM, run "accton_as9736_64d_util.py sff". +To set fan speed, run "accton_as9736_64d_util.py set fan". +To enable/disable SFP emission, run "accton_as9736_64d_util.py set sfp". +To set system LEDs' color, run "accton_as9736_64d_util.py set led" +For more information, run "accton_as9736_64d_util.py --help". + +==================================================================== +Besides applying accton_as9736_64d_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, psu1, psu2 and fan. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + But not all colors are available for each LED. + +Fan Control: + There are 12 fans inside 6 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 6 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 32 QSFP56-DD and 2 SFP+ modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor.py new file mode 100755 index 000000000000..49f543257161 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor.py @@ -0,0 +1,414 @@ +#!/usr/bin/env python +# -*- 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.)# +# 07/12/2022: Michael_Shih create for as9736_64d thermal plan +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import signal + import time # this is only being used as part of the example + from as9736_64d.fanutil import FanUtil + from as9736_64d.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9736_64d_monitor' + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +# Thermal policy(AFO-Front to back): +# +# Fan Speed Level: +# Fan Level 1 (Fan speed: 50%, RPM +/- 10%: 6800) +# Fan Level 2 (Fan speed: 70%, RPM +/- 10%: 9520) +# Fan Level 3 (Fan speed: 100%, RPM +/- 10%: 13600) +# +# Using Thermal sensors as below: +# - SMB TMP75 (0x49) +# - UDB TMP75 (0x48) +# - UDB TMP422(0x4c) +# - LDB TMP422(0x4d) +# - TH4 TMP422(0x4c) +# - CPU core_1~9 +# - MAC Use TMP422(0x4c) +# +# Raise to Fan Level 2 from Level 1 condition: +# - SMB TMP75 (0x49) >= 59 +# or +# - UDB TMP75 (0x49) >= 58 +# or +# - UDB TMP422(0x48) >= 51 +# or +# - LDB TMP422(0x4d) >= 54 +# or +# - TH4 TMP422(0x4c) >= 92 +# +# Slow down to Fan Level 1 from Level 2 condition: +# - SMB TMP75 (0x49) <= 54 +# and +# - UDB TMP75 (0x49) <= 53 +# and +# - UDB TMP422(0x48) <= 44 +# and +# - LDB TMP422(0x4d) <= 47 +# and +# - TH4 TMP422(0x4c) <= 83 +# +# Raise to Fan Level 3 conditions: +# - Fan failed +# - CPU core temp between 80 and 99 degree C +# - MAC Use TH4 TMP422(0x4c) temp between 85 and 105 degree C +# +# Slow down to Fan Level 1(Normal state) from Level 3 condition: +# - CPU core temp cool down to 80 degree C +# - MAC Use TH4 TMP422(0x4c) temp cool down to 85 degree C +# + +fan_policy_state = 0 +fan_fail = 0 +count_check = 0 + +board_thermal_min_to_mid = 0 +board_thermal_mid_to_min = 0 +cpu_fan_policy_state = 0 + +exit_by_sigterm=0 + +def power_off_dut(): + # Need to implement!! + return True + +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + init_duty_cycle = 0 + new_duty_cycle = 0 + ori_duty_cycle = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + + self.thermal = ThermalUtil() + self.fan = FanUtil() + + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def set_fan_duty_cycle(self, fan_level, duty_cycle_percentage): + logging.debug("- [Fan]: fan_policy_state = %d, set new_duty_cycle = %d", fan_level, duty_cycle_percentage) + self.fan.set_fan_duty_cycle(duty_cycle_percentage) + + def manage_fans(self): + + global fan_policy_state + global fan_fail + global count_check + global board_thermal_min_to_mid + global board_thermal_mid_to_min + global thermal_fan_policy_state + global cpu_fan_policy_state + global mac_fan_policy_state + + LEVEL_FAN_INIT=0 + FAN_LEVEL_1 = 1 + FAN_LEVEL_2 = 2 + FAN_LEVEL_3 = 3 + POLICY_NEED_SHUTDOWN = 4 + + fan_speed_policy = { + FAN_LEVEL_1: [50], + FAN_LEVEL_2: [70], + FAN_LEVEL_3: [100] + } + + thermal_spec={ + "min_to_mid_temp" : [59000, 58000, 51000, 54000, 92000], + "mid_to_min_temp" : [54000, 53000, 44000, 47000, 83000], + "cpu_temp" : [ 80000, 99000], + "mac_temp" : [ 85000, 105000] + } + + board_thermal_val = [0, 0, 0, 0, 0] + board_thermal_or_chk_min_to_mid = [0, 0, 0, 0, 0] + board_thermal_and_chk_mid_to_min = [0, 0, 0, 0, 0] + cpucore_thermal_val = [0, 0, 0, 0, 0, 0, 0, 0] + mactemp_thermal_val = [0] + + fan = self.fan + thermal = self.thermal + + # Get duty_cycle at init: + if fan_policy_state == LEVEL_FAN_INIT: + self.init_duty_cycle = fan.get_fan_duty_cycle() + for i in range (FAN_LEVEL_1, FAN_LEVEL_3 + 1): + if self.init_duty_cycle == fan_speed_policy[i][0]: + fan_policy_state = i + else: + continue + logging.debug("- [Init]: fan_policy_state = %d, get duty_cycle = %d", fan_policy_state, self.init_duty_cycle) + # Fan duty_cycle is not in FAN_LEVEL_1~3 case + if fan_policy_state == LEVEL_FAN_INIT: + if (self.init_duty_cycle > fan_speed_policy[FAN_LEVEL_2][0] and + self.init_duty_cycle < fan_speed_policy[FAN_LEVEL_3][0]): + fan_policy_state = FAN_LEVEL_2 + else: + fan_policy_state = FAN_LEVEL_1 + + self.set_fan_duty_cycle(fan_policy_state, fan_speed_policy[fan_policy_state][0]) + + return + + self.ori_duty_cycle = fan.get_fan_duty_cycle() + self.new_duty_cycle = 0 + + board_thermal_min_to_mid = 0 #use for | operation + board_thermal_mid_to_min = 1 #use for & operation + thermal_fan_policy_state = LEVEL_FAN_INIT + cpu_fan_policy_state = LEVEL_FAN_INIT + mac_fan_policy_state = LEVEL_FAN_INIT + + #1 Check fan: Unpresent or fan_fault status + fan_fail = 0 + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_present(i) == 0: + fan_fail = 1 + logging.debug('- fan_%d absent, set duty_cycle to 100%', i) + elif fan.get_fan_fault(i) == 1: + fan_fail = 1 + logging.debug('- fan_%d fail, set duty_cycle to 100%', i) + else: + if fan_fail == 1: + continue + + ori_state = fan_policy_state + current_state = fan_policy_state + + if fan_fail == 1: + if ori_state == FAN_LEVEL_2 or ori_state == FAN_LEVEL_3: + current_state = FAN_LEVEL_3 + elif ori_state == FAN_LEVEL_1: + current_state = FAN_LEVEL_2 + + if current_state != ori_state: + fan_policy_state = current_state + self.new_duty_cycle = fan_speed_policy[fan_policy_state][0] + + if self.new_duty_cycle != self.ori_duty_cycle: + self.set_fan_duty_cycle(fan_policy_state, fan_speed_policy[fan_policy_state][0]) + return True + + #2-1 Board Sensors get value: + for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_5_IDX+1): + board_thermal_val[i-1] = thermal._get_thermal_val(i) + + if board_thermal_val[i-1] >= thermal_spec["min_to_mid_temp"][i-1]: + board_thermal_or_chk_min_to_mid[i-1] = 1 + else: + board_thermal_or_chk_min_to_mid[i-1] = 0 + + if board_thermal_val[i-1] <= thermal_spec["mid_to_min_temp"][i-1]: + board_thermal_and_chk_mid_to_min[i-1] = 1 + else: + board_thermal_and_chk_mid_to_min[i-1] = 0 + #2-2 CPU Sensors get value: + for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_CPU_CORE+1): + cpucore_thermal_val[i-1] = thermal._get_thermal_val(i + thermal.THERMAL_NUM_BD_SENSOR) + + #2-3 MAC Sensors get value: + mactemp_thermal_val[0] = board_thermal_val[thermal.THERMAL_NUM_5_IDX-1] + + #3-1 Decide the board thermal policy: + for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_5_IDX+1): + board_thermal_min_to_mid |= board_thermal_or_chk_min_to_mid[i-1] + board_thermal_mid_to_min &= board_thermal_and_chk_mid_to_min[i-1] + + if board_thermal_min_to_mid == 0 and board_thermal_mid_to_min == 1: + thermal_fan_policy_state = FAN_LEVEL_1 + elif board_thermal_min_to_mid == 1 and board_thermal_mid_to_min == 0: + thermal_fan_policy_state = FAN_LEVEL_2 + else: + if ori_state == FAN_LEVEL_1: + thermal_fan_policy_state = FAN_LEVEL_1 + else: + thermal_fan_policy_state = FAN_LEVEL_2 + + #3-2 Decide the CPU thermal policy: + for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_CPU_CORE+1): + + if cpucore_thermal_val[i-1] < thermal_spec["cpu_temp"][0]: #Case of duty_cycle = 50% + + if cpu_fan_policy_state <= FAN_LEVEL_1: + # One of cpu-core is level_3, policy is level_3 + cpu_fan_policy_state = FAN_LEVEL_1 + + elif cpucore_thermal_val[i-1] >= thermal_spec["cpu_temp"][0] and cpucore_thermal_val[i-1] < thermal_spec["cpu_temp"][1]: + + if cpu_fan_policy_state <= FAN_LEVEL_3: + cpu_fan_policy_state = FAN_LEVEL_3 #Case of duty_cycle = 100% + + elif cpucore_thermal_val[i-1] >= thermal_spec["cpu_temp"][1] : #Case of shutdown + + logging.debug('CPU core%d, temperature is %d. Warning!!! Temperature is over %d', i-1, cpucore_thermal_val[i-1]/1000, thermal_spec["cpu_temp"][1]/1000) + cpu_fan_policy_state = POLICY_NEED_SHUTDOWN + + #3-3 Decide the MAC thermal policy: + if mactemp_thermal_val[0] < thermal_spec["mac_temp"][0]: + mac_fan_policy_state = FAN_LEVEL_1 + elif mactemp_thermal_val[0] >= thermal_spec["mac_temp"][0] and mactemp_thermal_val[0] < thermal_spec["mac_temp"][1]: + mac_fan_policy_state = FAN_LEVEL_3 + elif mactemp_thermal_val[0] >= thermal_spec["mac_temp"][1] : #Case of shutdown + logging.debug('Monitor MAC, temperature is %d. Warning!!! Temperature is over %d', mactemp_thermal_val[0]/1000, thermal_spec["mac_temp"][1]/1000) + mac_fan_policy_state = POLICY_NEED_SHUTDOWN + + #4 Condition of change fan speed by sensors policy: + if ori_state == FAN_LEVEL_3: + if cpu_fan_policy_state == POLICY_NEED_SHUTDOWN or mac_fan_policy_state == POLICY_NEED_SHUTDOWN: + # Need to implement Shutdown!!!!!!!!!!!!! + print("shutdown happen!!") + return False + + elif cpu_fan_policy_state == FAN_LEVEL_3 or mac_fan_policy_state == FAN_LEVEL_3: + current_state = FAN_LEVEL_3 + + else: + current_state = FAN_LEVEL_2 + + elif ori_state == FAN_LEVEL_2: + if cpu_fan_policy_state == POLICY_NEED_SHUTDOWN or mac_fan_policy_state == POLICY_NEED_SHUTDOWN: # + current_state = FAN_LEVEL_3 + + elif cpu_fan_policy_state == FAN_LEVEL_3 or mac_fan_policy_state == FAN_LEVEL_3: + current_state = FAN_LEVEL_3 + + elif thermal_fan_policy_state == FAN_LEVEL_1: + current_state = FAN_LEVEL_1 + + else: + current_state = FAN_LEVEL_2 + + elif ori_state == FAN_LEVEL_1: + if cpu_fan_policy_state == POLICY_NEED_SHUTDOWN or mac_fan_policy_state == POLICY_NEED_SHUTDOWN: + current_state = FAN_LEVEL_2 + + elif cpu_fan_policy_state == FAN_LEVEL_3 or mac_fan_policy_state == FAN_LEVEL_3: + current_state = FAN_LEVEL_2 + + elif thermal_fan_policy_state == FAN_LEVEL_2: + current_state = FAN_LEVEL_2 + + else: + current_state = FAN_LEVEL_1 + + #4 Setting new duty-cyle: + if current_state != ori_state: + fan_policy_state = current_state + + self.new_duty_cycle = fan_speed_policy[fan_policy_state][0] + + if self.new_duty_cycle != self.ori_duty_cycle: + self.set_fan_duty_cycle(fan_policy_state, fan_speed_policy[fan_policy_state][0]) + return True + + if self.new_duty_cycle == 0 : + self.set_fan_duty_cycle(FAN_LEVEL_3, fan_speed_policy[FAN_LEVEL_3][0]) + + return True + +def signal_handler(sig, frame): + global exit_by_sigterm + if sig == signal.SIGTERM: + print("Caught SIGTERM - exiting...") + exit_by_sigterm = 1 + else: + pass + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + global exit_by_sigterm + signal.signal(signal.SIGTERM, signal_handler) + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + for opt, arg in opts: + if opt == '-h': + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(5) + if exit_by_sigterm == 1: + break + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor_fan.py new file mode 100755 index 000000000000..d307f93e92f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor_fan.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 04/23/2021: Michael_Shih create for as9736-64d +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import signal + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9736_64d_monitor_fan' + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2] #init state=2, fault=1, normal=0 + +exit_by_sigterm=0 + +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 4 + self.fan_path = "/sys/bus/i2c/devices/25-0033/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + } + + """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(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def signal_handler(sig, frame): + global exit_by_sigterm + if sig == signal.SIGTERM: + print("Caught SIGTERM - exiting...") + exit_by_sigterm = 1 + else: + pass + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global exit_by_sigterm + signal.signal(signal.SIGTERM, signal_handler) + + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + for opt, arg in opts: + if opt == '-h': + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + if exit_by_sigterm == 1: + break + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor_psu.py new file mode 100755 index 000000000000..e9112076caf9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_monitor_psu.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 04/23/2021: Michael_shih create for as9736-64d +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import signal + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9736_64d_monitor_psu' + +psu_state=[2, 2] +psu_status_state=[2, 2] + +exit_by_sigterm=0 + +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "41-0051", + 1: "33-0050", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def signal_handler(sig, frame): + global exit_by_sigterm + if sig == signal.SIGTERM: + print("Caught SIGTERM - exiting...") + exit_by_sigterm = 1 + else: + pass + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global exit_by_sigterm + signal.signal(signal.SIGTERM, signal_handler) + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + for opt, arg in opts: + if opt == '-h': + print('Usage: %s [-d] [-l ]' % sys.argv[0]) + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + if exit_by_sigterm == 1: + break + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_util.py b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_util.py new file mode 100755 index 000000000000..27c76bf3967f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/accton_as9736_64d_util.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import subprocess +import getopt +import sys +import logging +import time +import os + +PROJECT_NAME = 'as9736_64d' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] + +i2c_prefix = '/sys/bus/i2c/devices/' +xcvr_set_no_reset = 'echo 0 > /sys/bus/platform/devices/as9736_64d_fpga/module_reset_all' + +mknod = [ + # i2c-mux + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-9/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-12/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-18/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-19/new_device', + + # CPLD + 'echo as9736_64d_cpld_cpu 0x60 > /sys/bus/i2c/devices/i2c-6/new_device', + # PDB-L + 'echo as9736_64d_cpld_pdb 0x60 > /sys/bus/i2c/devices/i2c-36/new_device', + # PDB-R + 'echo as9736_64d_cpld_pdb 0x60 > /sys/bus/i2c/devices/i2c-44/new_device', + 'echo as9736_64d_cpld_scm 0x35 > /sys/bus/i2c/devices/i2c-51/new_device', + + # FAN + 'echo as9736_64d_fan 0x33 > /sys/bus/i2c/devices/i2c-25/new_device', + + # LM75 + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-14/new_device', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-27/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-27/new_device', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-34/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-42/new_device', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-57/new_device', + 'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-58/new_device', + 'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-65/new_device', + 'echo lm75 0x4d > /sys/bus/i2c/devices/i2c-66/new_device', + + # PSU-1 + 'echo delta_dps2400 0x59 > /sys/bus/i2c/devices/i2c-41/new_device', + 'echo as9736_64d_psu1 0x51 > /sys/bus/i2c/devices/i2c-41/new_device', + + # PSU-2 + 'echo delta_dps2400 0x58 > /sys/bus/i2c/devices/i2c-33/new_device', + 'echo as9736_64d_psu2 0x50 > /sys/bus/i2c/devices/i2c-33/new_device', + + # EERPOM + 'echo 24c256 0x51 > /sys/bus/i2c/devices/i2c-20/new_device', +] + +FORCE = 0 + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv) < 2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG: + print(options) + print(args) + print(len(sys.argv)) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + do_mux_setting("fp") + elif arg == 'clean': + do_uninstall() + elif arg == 'api': + do_sonic_platform_install() + elif arg == 'api_clean': + do_sonic_platform_clean() + else: + show_help() + + return 0 + +def do_mux_setting(select_mode): + print("LDB 10G MUX setting select: mac to "+ select_mode) + status, output = log_os_system("ldb_mux_setting.sh " + select_mode, 0) + + if status: + print('Error: Failed to do MUX setting.') + return status + +def show_help(): + print(__doc__ % {'scriptName': sys.argv[0].split("/")[-1]}) + sys.exit(0) + + +def my_log(txt): + if DEBUG: + print("[ACCTON DBG]: " + txt) + return + +def log_os_system(cmd, show): + logging.info('Run :' + cmd) + output = "" + status, output = subprocess.getstatusoutput(cmd) + my_log(cmd + "with result:" + str(status)) + my_log("cmd:" + cmd) + 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 + +kos = [ + 'depmod', + 'modprobe i2c_i801', + 'modprobe i2c_ismt', + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x', + 'modprobe accton_as9736_64d_cpld', + 'modprobe accton_as9736_64d_fan', + 'modprobe accton_i2c_psu', + 'modprobe accton_as9736_64d_psu', + 'modprobe accton_as9736_64d_fpga', + 'modprobe optoe', + 'modprobe tmp421', + 'modprobe lm75'] + +def driver_install(): + global FORCE + + for i in range(0, len(kos)): + status, output = log_os_system(kos[i], 1) + + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0, len(kos)): + rm = kos[-(i + 1)].replace("modprobe", "modprobe -rq") + 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 + +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(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print(output) + if FORCE == 0: + return status + + # set all pca954x idle_disconnect + cmd = 'echo -2 | tee /sys/bus/i2c/drivers/pca954x/*-00*/idle_state' + status, output = log_os_system(cmd, 1) + if status: + print(output) + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i + 1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print(output) + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +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(): + 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....") + + do_sonic_platform_install() + # Init QSFP release reset mode: + # (FPGA default change to reset mode after v.12) + print("Release reset mode") + status, output = log_os_system(xcvr_set_no_reset, 1) + if status: + if FORCE == 0: + return status + + return + +def do_uninstall(): + 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 + "*0072", 0) + ret2, log = log_os_system("ls " + i2c_prefix + "i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/ldb_mux_setting.sh b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/ldb_mux_setting.sh new file mode 100755 index 000000000000..0a8a679b85ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9736-64d/utils/ldb_mux_setting.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +i2cget -y 72 0x58 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device DS100(0x58) not found\n" + i2cdetect -y 0 + exit 1 +else + printf "Device DS100(0x58) exits\n" +fi + +# Mux setting +i2cset -y 72 0x58 0x06 0x18 +i2cset -y 72 0x58 0x0F 0x00 +i2cset -y 72 0x58 0x16 0x00 +i2cset -y 72 0x58 0x17 0xAA +i2cset -y 72 0x58 0x18 0x00 +i2cset -y 72 0x58 0x1D 0x00 +i2cset -y 72 0x58 0x24 0x00 +i2cset -y 72 0x58 0x25 0xA8 +i2cset -y 72 0x58 0x26 0x00 +i2cset -y 72 0x58 0x2C 0x00 +i2cset -y 72 0x58 0x2D 0xAA +i2cset -y 72 0x58 0x2E 0x00 +i2cset -y 72 0x58 0x34 0xAA +i2cset -y 72 0x58 0x35 0x00 +i2cset -y 72 0x58 0x3A 0x00 +i2cset -y 72 0x58 0x3B 0xAA +i2cset -y 72 0x58 0x3C 0x00 +i2cset -y 72 0x58 0x41 0x00 +i2cset -y 72 0x58 0x42 0xAA +i2cset -y 72 0x58 0x43 0x00 + +if [ "$1" = "cpu" ];then + #/* Select MAC to CPU */ + i2cset -y 72 0x58 0x5E 0x06 + i2cset -y 72 0x58 0x5F 0xF0 + echo "Select MAC to CPU" +elif [ "$1" = "fp" ];then + #/* Select MAC to Front Port */ + i2cset -y 72 0x58 0x5E 0x06 + i2cset -y 72 0x58 0x5F 0x00 + echo "Select MAC to Front Port" +else + echo "format: ldb_mux_setting.sh {fp | cpu}" +fi + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control old mode 100755 new mode 100644 index 4410a2f07796..6844f266f819 --- a/platform/broadcom/sonic-platform-modules-accton/debian/control +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -73,6 +73,10 @@ Package: sonic-platform-accton-as9726-32d Architecture: amd64 Description: kernel modules for platform devices such as fan, led, sfp +Package: sonic-platform-accton-as9736-64d +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + Package: sonic-platform-accton-as5835-54t 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 8cd7611bb6e3..8be9a3267f58 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -21,7 +21,7 @@ KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) MODULE_DIRS := as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x MODULE_DIRS += as7326-56x as6712-32x as7726-32x as4630-54pe as4630-54te minipack as5812-54x -MODULE_DIRS += as5835-54x as9716-32d as9726-32d as5835-54t as7312-54xs as7315-27xb as5812-54t +MODULE_DIRS += as5835-54x as9716-32d as9726-32d as9736-64d as5835-54t as7312-54xs as7315-27xb as5812-54t MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9736-64d.install b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9736-64d.install new file mode 100644 index 000000000000..02f948bcaf64 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as9736-64d.install @@ -0,0 +1,2 @@ +as9736-64d/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-accton_as9736_64d-r0 +