diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/platform_env.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/platform_env.conf new file mode 100755 index 00000000000..c8c09ab2d9d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/platform_env.conf @@ -0,0 +1,2 @@ +dmasize=32M +usemsi=0 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py index 9e502578f15..f27def99c73 100644 --- a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py @@ -1,11 +1,16 @@ #!/usr/bin/env python +import os.path +import time + try: - import time from sonic_sfp.sfputilbase import SfpUtilBase except ImportError, e: raise ImportError (str(e) + "- required module not found") +#from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' class SfpUtil(SfpUtilBase): """Platform specific SfpUtill class""" @@ -14,17 +19,29 @@ class SfpUtil(SfpUtilBase): last_port = 31 port_num = 32 + sfp_status = 0 + port_to_eeprom = {} - port_to_i2cbus_mapping = { + port_to_i2cbus_0 = { 1 : 14, 2 : 15, 3 : 16, 4 : 17, } + port_to_i2cbus_1 = { + 1 : 15, + 2 : 16, + 3 : 17, + 4 : 18, + } + + port_to_i2cbus_mapping = {} + eeprom_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_eeprom" port_reset_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_port_reset" present_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_is_present" + lpmode_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_lpmode" _qsfp_ports = range(first_port, port_num + 1) @property @@ -43,15 +60,75 @@ def qsfp_ports(self): def port_to_eeprom_mapping(self): return self.port_to_eeprom - def get_transceiver_change_event(self): - """ - TODO: This function need to be implemented - when decide to support monitoring SFP(Xcvrd) - on this platform. - """ - raise NotImplementedError + @property + def get_presence_all(self): + port = self.port_start + bitmap = "" + + while (port >= self.port_start) and (port <= self.port_end): + index = (port % 8) + i2c_index = (port / 8) + 1 + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + reg_file.close() + + if reg_value == '1': + bitmap += '1' + " " + else: + bitmap += '0' + " " + + port += 1 + + content = bitmap.split(" ") + content = "".join(content[::-1]) + + return int(content, 2) + + def get_transceiver_change_event(self, timeout=0): + while True: + port_dict = {} + port = self.port_start + + # Check for OIR events and return updated port_dict + reg_value = self.get_presence_all + if reg_value != self.sfp_status: + changed_ports = self.sfp_status ^ reg_value + while (port >= self.port_start) and (port <= self.port_end): + + # Mask off the bit corresponding to our port + mask = (1 << port) + + if changed_ports & mask: + # port presence is high + if (reg_value & mask) == mask: + port_dict[port] = SFP_STATUS_INSERTED + else: + port_dict[port] = SFP_STATUS_REMOVED + + port += 1 + + # Update reg value + self.sfp_status = reg_value + return True, port_dict + + time.sleep(0.5) def __init__(self): + path = self.present_path + port_path = path.format(self.port_to_i2cbus_0[1], 1) + if not os.path.exists(port_path): + self.port_to_i2cbus_mapping = self.port_to_i2cbus_1 + else: + self.port_to_i2cbus_mapping = self.port_to_i2cbus_0 + path = self.eeprom_path for x in range(self.first_port, self.last_port + 1): index = (x % 8) @@ -85,15 +162,58 @@ def reset(self, port_num): reg_file.close() return True - def set_low_power_mode(self, port_nuM, lpmode): - raise NotImplementedError + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.lpmode_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + if lpmode == True: + reg_file.write('1') + else: + reg_file.write('0') + + reg_file.close() + return True def get_low_power_mode(self, port_num): - raise NotImplementedError + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.lpmode_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + + reg_file.close() + + if reg_value == '1': + return True + + return False def get_presence(self, port_num): # Check for invalid port_num - if port_num < self.first_port or port_num > self.last_port: + if port_num < self.port_start or port_num > self.port_end: return False index = (port_num % 8) @@ -109,6 +229,9 @@ def get_presence(self, port_num): return False reg_value = reg_file.readline().rstrip() + + reg_file.close() + if reg_value == '1': return True diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/pmon_daemon_control.json b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/pmon_daemon_control.json new file mode 100755 index 00000000000..f2a407daaf6 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": false +} + diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/platform_env.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/platform_env.conf new file mode 100755 index 00000000000..c8c09ab2d9d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/platform_env.conf @@ -0,0 +1,2 @@ +dmasize=32M +usemsi=0 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py index cc3cd4e8611..407e6de8721 100644 --- a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py @@ -1,11 +1,16 @@ #!/usr/bin/env python +import os.path +import time + try: - import time from sonic_sfp.sfputilbase import SfpUtilBase except ImportError, e: raise ImportError (str(e) + "- required module not found") +#from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' class SfpUtil(SfpUtilBase): """Platform specific SfpUtill class""" @@ -14,8 +19,10 @@ class SfpUtil(SfpUtilBase): last_port = 65 port_num = 63 + sfp_status = 0 + port_to_eeprom = {} - port_to_i2cbus_mapping = { + port_to_i2cbus_0 = { 1 : 13, 2 : 14, 3 : 15, @@ -23,12 +30,23 @@ class SfpUtil(SfpUtilBase): 5 : 23, } + port_to_i2cbus_1 = { + 1 : 14, + 2 : 15, + 3 : 16, + 4 : 17, + 5 : 24, + } + + port_to_i2cbus_mapping = {} + eeprom_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_eeprom" eeprom_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_eeprom" port_reset_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_port_reset" port_reset_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_port_reset" present_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_is_present" present_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_is_present" + lpmode_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_lpmode" _qsfp_ports = range(first_port, port_num) @@ -48,15 +66,79 @@ def qsfp_ports(self): def port_to_eeprom_mapping(self): return self.port_to_eeprom - def get_transceiver_change_event(self): - """ - TODO: This function need to be implemented - when decide to support monitoring SFP(Xcvrd) - on this platform. - """ - raise NotImplementedError + @property + def get_presence_all(self): + bitmap = "" + port = self.port_start + + while (port >= self.port_start) and (port <= self.port_end): + i2c_index = (port / 16) + 1 + index = (port % 16) + 1 + if i2c_index == 5: + path = self.present_path_1 + else: + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], index) + + try: + reg_file = open(port_path) + except IOError as e: + if i2c_index < 5: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + reg_file.close() + + if reg_value == '1': + bitmap += '1' + " " + else: + bitmap += '0' + " " + + port += 1 + + content = bitmap.split(" ") + content = "".join(content[::-1]) + + return int(content, 2) + + def get_transceiver_change_event(self, timeout=0): + while True: + port_dict = {} + port = self.port_start + + # Check for OIR events and return updated port_dict + reg_value = self.get_presence_all + if reg_value != self.sfp_status: + changed_ports = self.sfp_status ^ reg_value + while (port >= self.port_start) and (port <= self.port_end): + + # Mask off the bit corresponding to our port + mask = (1 << port) + + if changed_ports & mask: + # port presence is high + if (reg_value & mask) == mask: + port_dict[port] = SFP_STATUS_INSERTED + else: + port_dict[port] = SFP_STATUS_REMOVED + + port += 1 + + # Update reg value + self.sfp_status = reg_value + return True, port_dict + + time.sleep(0.5) def __init__(self): + path = self.present_path + port_path = path.format(self.port_to_i2cbus_0[1], 1) + if not os.path.exists(port_path): + self.port_to_i2cbus_mapping = self.port_to_i2cbus_1 + else: + self.port_to_i2cbus_mapping = self.port_to_i2cbus_0 + for x in range(self.first_port, self.last_port + 1): cpld_index = (x / 16) + 1 index = (x % 16) + 1 @@ -97,15 +179,66 @@ def reset(self, port_num): reg_file.close() return True - def set_low_power_mode(self, port_nuM, lpmode): - raise NotImplementedError + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + raise NotImplementedError + else: + path = self.lpmode_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + if cpld_index < 5: + print "Error: unable to open file: %s" % str(e) + return False + + if lpmode == True: + reg_file.write('1') + else: + reg_file.write('0') + + reg_file.close() + return True def get_low_power_mode(self, port_num): - raise NotImplementedError + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + return False + else: + path = self.lpmode_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path) + except IOError as e: + if cpld_index < 5: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + + reg_file.close() + + if reg_value == '1': + return True + + return False def get_presence(self, port_num): # Check for invalid port_num - if port_num < self.first_port or port_num > self.last_port: + if port_num < self.port_start or port_num > self.port_end: return False cpld_index = (port_num / 16) + 1 @@ -125,6 +258,9 @@ def get_presence(self, port_num): return False reg_value = reg_file.readline().rstrip() + + reg_file.close() + if reg_value == '1': return True diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/pmon_daemon_control.json b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/pmon_daemon_control.json new file mode 100755 index 00000000000..f2a407daaf6 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": false +} + diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/port_config.ini new file mode 100755 index 00000000000..d3f2b0157a9 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4,5,6,7,8 Ethernet1/0/1 0 400000 +Ethernet8 9,10,11,12,13,14,15,16 Ethernet1/0/9 1 400000 +Ethernet16 17,18,19,20,21,22,23,24 Ethernet1/0/17 2 400000 +Ethernet24 25,26,27,28,29,30,31,32 Ethernet1/0/25 3 400000 +Ethernet32 33,34,35,36,37,38,39,40 Ethernet1/0/33 4 400000 +Ethernet40 41,42,43,44,45,46,47,48 Ethernet1/0/41 5 400000 +Ethernet48 49,50,51,52,53,54,55,56 Ethernet1/0/48 6 400000 +Ethernet56 57,58,59,60,61,62,63,64 Ethernet1/0/57 7 400000 +Ethernet64 65,66,67,68,69,70,71,72 Ethernet1/0/65 8 400000 +Ethernet72 73,74,75,76,77,78,79,80 Ethernet1/0/73 9 400000 +Ethernet80 81,82,83,84,85,86,87,88 Ethernet1/0/81 10 400000 +Ethernet88 89,90,91,92,93,94,95,96 Ethernet1/0/89 11 400000 +Ethernet96 97,98,99,100,101,102,103,104 Ethernet1/0/97 12 400000 +Ethernet104 105,106,107,108,109,110,111,112 Ethernet1/0/105 13 400000 +Ethernet112 113,114,115,116,117,118,119,120 Ethernet1/0/113 14 400000 +Ethernet120 121,122,123,124,125,126,127,128 Ethernet1/0/121 15 400000 +Ethernet128 129,130,131,132,133,134,135,136 Ethernet1/0/129 16 400000 +Ethernet136 137,138,139,140,141,142,143,144 Ethernet1/0/137 17 400000 +Ethernet144 145,146,147,148,149,150,151,152 Ethernet1/0/145 18 400000 +Ethernet152 153,154,155,156,157,158,159,160 Ethernet1/0/153 19 400000 +Ethernet160 161,162,163,164,165,166,167,168 Ethernet1/0/161 20 400000 +Ethernet169 169,170,171,172,173,174,175,176 Ethernet1/0/169 21 400000 +Ethernet176 177,178,179,180,181,182,183,184 Ethernet1/0/177 22 400000 +Ethernet184 185,186,187,188,189,190,191,192 Ethernet1/0/185 23 400000 +Ethernet192 193,194,195,196,197,198,199,200 Ethernet1/0/193 24 400000 +Ethernet200 201,202,203,204,205,206,207,208 Ethernet1/0/201 25 400000 +Ethernet208 209,210,211,212,213,214,215,216 Ethernet1/0/209 26 400000 +Ethernet216 217,218,219,220,221,222,223,224 Ethernet1/0/217 27 400000 +Ethernet224 225,226,227,228,229,230,231,232 Ethernet1/0/225 28 400000 +Ethernet232 233,234,235,236,237,238,239,240 Ethernet1/0/233 29 400000 +Ethernet240 241,242,243,244,245,246,247,248 Ethernet1/0/241 30 400000 +Ethernet248 249,250,251,252,253,254,255,256 Ethernet1/0/249 31 400000 +Ethernet256 257 Ethernet1/0/257 32 10000 +Ethernet257 258 Ethernet1/0/258 33 10000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/sai.profile new file mode 100755 index 00000000000..9b506d71833 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-snj60b0-32x400G.config.bcm diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/th3-snj60b0-32x400G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/th3-snj60b0-32x400G.config.bcm new file mode 100755 index 00000000000..09de3590c5e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/Alphanetworks-SNJ60B0-320F/th3-snj60b0-32x400G.config.bcm @@ -0,0 +1,298 @@ +# This property file is for JUNGFRAU 1x400Gx32 mode only. +# JUNGFRAU uses Tomahawk3 BCM56980 as its mac. Besides, it is phyless. + +os=linux +led_fw_path="/usr/share/sonic/platform/" +bcm_stat_interval.0=1000000 +bcm_linkscan_interval.0=250000 + +mdio_output_delay.0=0xf +mem_cache_enable=0 + +parity_enable=0 +core_clock_frequency=1325 + +dpr_clock_frequency=1000 + +# Blackhawk Core - 32 front ports +# BlackhawkCore[0 - 3] must map to device port[1-18], PIPE-0. +portmap_1.0=1:400 +portmap_2.0=9:400 +portmap_3.0=17:400 +portmap_4.0=25:400 + +# BlackhawkCore[4 - 7] must map to device port[20-37], PIPE-1. +portmap_20.0=33:400 +portmap_21.0=41:400 +portmap_22.0=49:400 +portmap_23.0=57:400 + +# BlackhawkCore[8 - 11] must map to logical port[40-57], PIPE-2. +portmap_40.0=65:400 +portmap_41.0=73:400 +portmap_42.0=81:400 +portmap_43.0=89:400 + +# BlackhawkCore[12 - 15] must map to logical port[60-77], PIPE-3. +portmap_60.0=97:400 +portmap_61.0=105:400 +portmap_62.0=113:400 +portmap_63.0=121:400 + +# BlackhawkCore[16 - 19] must map to logical port[80-97], PIPE-4. +portmap_80.0=129:400 +portmap_81.0=137:400 +portmap_82.0=145:400 +portmap_83.0=153:400 + +# BlackhawkCore[20 - 23] must map to logical port[100-117], PIPE-5. +portmap_100.0=161:400 +portmap_101.0=169:400 +portmap_102.0=177:400 +portmap_103.0=185:400 + +# BlackhawkCore[24 - 27] must map to logical port[120-137], PIPE-6. +portmap_120.0=193:400 +portmap_121.0=201:400 +portmap_122.0=209:400 +portmap_123.0=217:400 + +# BlackhawkCore[28 - 31] must map to logical port[140-157], PIPE-7. +portmap_140.0=225:400 +portmap_141.0=233:400 +portmap_142.0=241:400 +portmap_143.0=249:400 + +# Merlin Core - 2 management ports +portmap_38.0=257:10 +portmap_118.0=258:10 + +# Configure all front port as XE and CD ports. +pbmp_xport_xe=0xf0000f4000f0000f0000f0000f4000f0001e +pbmp_oversubscribe=0xf0000f4000f0000f0000f0000f4000f0001e + +# lane map and polarity +# BlackhawkCore0 +phy_chain_rx_lane_map_physical{1.0}=0x42735061 +serdes_core_rx_polarity_flip_physical{1}=0xe6 +phy_chain_tx_lane_map_physical{1.0}=0x71056243 +serdes_core_tx_polarity_flip_physical{1}=0xa1 + +# BlackhawkCore1 +phy_chain_rx_lane_map_physical{9.0}=0x27150634 +serdes_core_rx_polarity_flip_physical{9}=0xd8 +phy_chain_tx_lane_map_physical{9.0}=0x63520714 +serdes_core_tx_polarity_flip_physical{9}=0x2c + +# BlackhawkCore2 +phy_chain_rx_lane_map_physical{17.0}=0x43025176 +serdes_core_rx_polarity_flip_physical{17}=0xcb +phy_chain_tx_lane_map_physical{17.0}=0x21034765 +serdes_core_tx_polarity_flip_physical{17}=0x4f + +# BlackhawkCore3 +phy_chain_rx_lane_map_physical{25.0}=0x67352014 +serdes_core_rx_polarity_flip_physical{25}=0x72 +phy_chain_tx_lane_map_physical{25.0}=0x62730415 +serdes_core_tx_polarity_flip_physical{25}=0x69 + +# BlackhawkCore4 +phy_chain_rx_lane_map_physical{33.0}=0x13026754 +serdes_core_rx_polarity_flip_physical{33}=0xc3 +phy_chain_tx_lane_map_physical{33.0}=0x35274061 +serdes_core_tx_polarity_flip_physical{33}=0x8e + +# BlackhawkCore5 +phy_chain_rx_lane_map_physical{41.0}=0x35270146 +serdes_core_rx_polarity_flip_physical{41}=0x78 +phy_chain_tx_lane_map_physical{41.0}=0x73526014 +serdes_core_tx_polarity_flip_physical{41}=0xa4 + +# BlackhawkCore6 +phy_chain_rx_lane_map_physical{49.0}=0x13025647 +serdes_core_rx_polarity_flip_physical{49}=0xcc +phy_chain_tx_lane_map_physical{49.0}=0x37054162 +serdes_core_tx_polarity_flip_physical{49}=0x9b + +# BlackhawkCore7 +phy_chain_rx_lane_map_physical{57.0}=0x35270416 +serdes_core_rx_polarity_flip_physical{57}=0x78 +phy_chain_tx_lane_map_physical{57.0}=0x63720415 +serdes_core_tx_polarity_flip_physical{57}=0xb9 + +# BlackhawkCore8 +phy_chain_rx_lane_map_physical{65.0}=0x13024756 +serdes_core_rx_polarity_flip_physical{65}=0xc3 +phy_chain_tx_lane_map_physical{65.0}=0x37054162 +serdes_core_tx_polarity_flip_physical{65}=0xab + +# BlackhawkCore9 +phy_chain_rx_lane_map_physical{73.0}=0x35270146 +serdes_core_rx_polarity_flip_physical{73}=0x78 +phy_chain_tx_lane_map_physical{73.0}=0x63720514 +serdes_core_tx_polarity_flip_physical{73}=0x3c + +# BlackhawkCore10 +phy_chain_rx_lane_map_physical{81.0}=0x13024756 +serdes_core_rx_polarity_flip_physical{81}=0xc3 +phy_chain_tx_lane_map_physical{81.0}=0x35204761 +serdes_core_tx_polarity_flip_physical{81}=0x9e + +# BlackhawkCore11 +phy_chain_rx_lane_map_physical{89.0}=0x35270416 +serdes_core_rx_polarity_flip_physical{89}=0x78 +phy_chain_tx_lane_map_physical{89.0}=0x73620514 +serdes_core_tx_polarity_flip_physical{89}=0x8c + +# BlackhawkCore12 +phy_chain_rx_lane_map_physical{97.0}=0x13024756 +serdes_core_rx_polarity_flip_physical{97}=0xc3 +phy_chain_tx_lane_map_physical{97.0}=0x37154062 +serdes_core_tx_polarity_flip_physical{97}=0xaf + +# BlackhawkCore13 +phy_chain_rx_lane_map_physical{105.0}=0x45671320 +serdes_core_rx_polarity_flip_physical{105}=0x53 +phy_chain_tx_lane_map_physical{105.0}=0x62730415 +serdes_core_tx_polarity_flip_physical{105}=0x69 + +# BlackhawkCore14 +phy_chain_rx_lane_map_physical{113.0}=0x13026754 +serdes_core_rx_polarity_flip_physical{113}=0xc3 +phy_chain_tx_lane_map_physical{113.0}=0x17254063 +serdes_core_tx_polarity_flip_physical{113}=0x8e + +# BlackhawkCore15 +phy_chain_rx_lane_map_physical{121.0}=0x65471230 +serdes_core_rx_polarity_flip_physical{121}=0xaa +phy_chain_tx_lane_map_physical{121.0}=0x27351406 +serdes_core_tx_polarity_flip_physical{121}=0x3d + +# BlackhawkCore16 +phy_chain_rx_lane_map_physical{129.0}=0x62735140 +serdes_core_rx_polarity_flip_physical{129}=0x63 +phy_chain_tx_lane_map_physical{129.0}=0x52736140 +serdes_core_tx_polarity_flip_physical{129}=0xf4 + +# BlackhawkCore17 +phy_chain_rx_lane_map_physical{137.0}=0x35270416 +serdes_core_rx_polarity_flip_physical{137}=0x78 +phy_chain_tx_lane_map_physical{137.0}=0x52731604 +serdes_core_tx_polarity_flip_physical{137}=0xe2 + +# BlackhawkCore18 +phy_chain_rx_lane_map_physical{145.0}=0x02135746 +serdes_core_rx_polarity_flip_physical{145}=0x39 +phy_chain_tx_lane_map_physical{145.0}=0x15274063 +serdes_core_tx_polarity_flip_physical{145}=0x8e + +# BlackhawkCore19 +phy_chain_rx_lane_map_physical{153.0}=0x05471263 +serdes_core_rx_polarity_flip_physical{153}=0x81 +phy_chain_tx_lane_map_physical{153.0}=0x43621705 +serdes_core_tx_polarity_flip_physical{153}=0x9f + +# BlackhawkCore20 +phy_chain_rx_lane_map_physical{161.0}=0x13620475 +serdes_core_rx_polarity_flip_physical{161}=0x66 +phy_chain_tx_lane_map_physical{161.0}=0x35274061 +serdes_core_tx_polarity_flip_physical{161}=0x2f + +# BlackhawkCore21 +phy_chain_rx_lane_map_physical{169.0}=0x15074263 +serdes_core_rx_polarity_flip_physical{169}=0x71 +phy_chain_tx_lane_map_physical{169.0}=0x52731604 +serdes_core_tx_polarity_flip_physical{169}=0x62 + +# BlackhawkCore22 +phy_chain_rx_lane_map_physical{177.0}=0x13620475 +serdes_core_rx_polarity_flip_physical{177}=0xee +phy_chain_tx_lane_map_physical{177.0}=0x37254061 +serdes_core_tx_polarity_flip_physical{177}=0x8e + +# BlackhawkCore23 +phy_chain_rx_lane_map_physical{185.0}=0x15074263 +serdes_core_rx_polarity_flip_physical{185}=0x71 +phy_chain_tx_lane_map_physical{185.0}=0x52730614 +serdes_core_tx_polarity_flip_physical{185}=0x68 + +# BlackhawkCore24 +phy_chain_rx_lane_map_physical{193.0}=0x13620475 +serdes_core_rx_polarity_flip_physical{193}=0xee +phy_chain_tx_lane_map_physical{193.0}=0x37254061 +serdes_core_tx_polarity_flip_physical{193}=0x8e + +# BlackhawkCore25 +phy_chain_rx_lane_map_physical{201.0}=0x15074263 +serdes_core_rx_polarity_flip_physical{201}=0x71 +phy_chain_tx_lane_map_physical{201.0}=0x53720614 +serdes_core_tx_polarity_flip_physical{201}=0x38 + +# BlackhawkCore26 +phy_chain_rx_lane_map_physical{209.0}=0x13620745 +serdes_core_rx_polarity_flip_physical{209}=0xe8 +phy_chain_tx_lane_map_physical{209.0}=0x30156742 +serdes_core_tx_polarity_flip_physical{209}=0xa7 + +# BlackhawkCore27 +phy_chain_rx_lane_map_physical{217.0}=0x15072364 +serdes_core_rx_polarity_flip_physical{217}=0x79 +phy_chain_tx_lane_map_physical{217.0}=0x52730614 +serdes_core_tx_polarity_flip_physical{217}=0x68 + +# BlackhawkCore28 +phy_chain_rx_lane_map_physical{225.0}=0x03126574 +serdes_core_rx_polarity_flip_physical{225}=0x6c +phy_chain_tx_lane_map_physical{225.0}=0x35274061 +serdes_core_tx_polarity_flip_physical{225}=0x8e + +# BlackhawkCore29 +phy_chain_rx_lane_map_physical{233.0}=0x35472160 +serdes_core_rx_polarity_flip_physical{233}=0x26 +phy_chain_tx_lane_map_physical{233.0}=0x52630714 +serdes_core_tx_polarity_flip_physical{233}=0xcc + +# BlackhawkCore30 +phy_chain_rx_lane_map_physical{241.0}=0x03126475 +serdes_core_rx_polarity_flip_physical{241}=0x66 +phy_chain_tx_lane_map_physical{241.0}=0x37254061 +serdes_core_tx_polarity_flip_physical{241}=0x8e + +# BlackhawkCore31 +phy_chain_rx_lane_map_physical{249.0}=0x45673120 +serdes_core_rx_polarity_flip_physical{249}=0xac +phy_chain_tx_lane_map_physical{249.0}=0x37250416 +serdes_core_tx_polarity_flip_physical{249}=0x87 + +serdes_tx_taps_cd0=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd1=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd2=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd3=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd4=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd5=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd6=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd7=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd8=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd9=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd10=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd11=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd12=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd13=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd14=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd15=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd16=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd17=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd18=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd19=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd20=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd21=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd22=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd23=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd24=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd25=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd26=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd27=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd28=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd29=pam4:-24:144:0:0:0:0 +serdes_tx_taps_cd30=pam4:-20:148:0:0:0:0 +serdes_tx_taps_cd31=pam4:-24:144:0:0:0:0 diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/custom_led.bin b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/custom_led.bin new file mode 100755 index 00000000000..f0927badc56 Binary files /dev/null and b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/custom_led.bin differ diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/default_sku new file mode 100755 index 00000000000..073744ed338 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNJ60B0-320F t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/fancontrol new file mode 100755 index 00000000000..cf46c9159e0 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/3-004d/hwmon/hwmon2/temp1_input +FCFANS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan1_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan2_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan3_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan4_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan5_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan6_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan11_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan12_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan13_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan14_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan15_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan16_input +MINTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=50 +MAXTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=70 +MINSTART=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINSTOP=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MAXPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=200 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/installer.conf new file mode 100755 index 00000000000..925a32fc0c3 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/led_proc_init.soc new file mode 100755 index 00000000000..26b56884867 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +# LED microprocessor initialization for alphanetworks snj60b0-320f + +#LED FW is loaded in SAI platform_init.c +#m0 load 0 0x3800 /alpha/bcm/led/jungfrau-320f_traffic_led.bin +led start +led auto on diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/linkscan_led_fw.bin b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/linkscan_led_fw.bin new file mode 100755 index 00000000000..b1e43d4d48d Binary files /dev/null and b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/linkscan_led_fw.bin differ diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/platform_env.conf b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/platform_env.conf new file mode 100644 index 00000000000..c8c09ab2d9d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/platform_env.conf @@ -0,0 +1,2 @@ +dmasize=32M +usemsi=0 diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/eeprom.py new file mode 100755 index 00000000000..c0122e65844 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/eeprom.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + #Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/led_control.py new file mode 100755 index 00000000000..1758fe77d10 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/led_control.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +# try: +# from sonic_led.led_control_base import LedControlBase +# import swsssdk +# except ImportError, e: +# raise ImportError (str(e) + " - required module not found") + +import time + +class LedControlBase(object): +# __metaclass__ = abc.ABCMeta + +# @abc.abstractmethod + def port_link_state_change(self, port, state): + """ + Called when port link state changes. Update port link state LED here. + + :param port: A string, SONiC port name (e.g., "Ethernet0") + :param state: A string, the port link state (either "up" or "down") + """ + return + +### Goreme specified ### +read_fan_fault = 0 +is_fan_all_OK = 0 +read_power_status = 0 +is_power_all_OK = 0 +is_thermal_high = 0 +is_reset_button_push = 0 +########################## + +def sysled_task(): + while True: + system_led_check() + time.sleep(5) + +########## Goreme System LED checking +def system_led_check(): + global read_fan_fault, read_power_status, is_fan_all_OK, is_power_all_OK, is_thermal_high, is_reset_button_push + is_fan_all_OK = 1 + is_power_all_OK = 0 + is_thermal_high = 0 + is_reset_button_push = 0 + with open("/sys/bus/i2c/devices/0-005e/fan1_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan2_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan3_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan4_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan5_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan6_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + + with open("/sys/bus/i2c/devices/0-005e/fan1_led", "w") as f11: + if int(is_fan_all_OK) == 1: + f11.write("1") + else: + f11.write("4") + + + with open("/sys/bus/i2c/devices/0-005e/psu1_power_good", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) != str("1\n"): + is_power_all_OK = -10 + with open("/sys/bus/i2c/devices/0-005e/psu1_present", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + with open("/sys/bus/i2c/devices/0-005e/psu2_power_good", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) != str("1\n"): + is_power_all_OK = -10 + with open("/sys/bus/i2c/devices/0-005e/psu2_present", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + + with open("/sys/bus/i2c/devices/0-005e/sys_pwr", "w") as f11: + if int(is_power_all_OK) > 0: + f11.write("1") + else: + f11.write("4") + + with open("/sys/bus/i2c/devices/3-004d/hwmon/hwmon2/temp1_input", "r") as f3: + is_thermal_high = f3.read() + if int(is_thermal_high) >= 70000: + is_thermal_high = 1 + else: + is_thermal_high = 0 + + with open("/sys/bus/i2c/devices/0-005e/sys_status", "w") as f2: + if is_reset_button_push == 1: + f2.write("3") + elif is_fan_all_OK == 0 or is_power_all_OK == 0 or is_thermal_high == 1: + f2.write("4") + else: + f2.write("1") + + return +########## + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + PORT_TABLE_PREFIX = "PORT_TABLE:" + + SONIC_PORT_NAME_PREFIX = "Ethernet" + + LED_SYSFS_PATH_BREAKOUT_CAPABLE = "/sys/class/leds/qsfp{0}_{1}/brightness" + LED_SYSFS_PATH_NO_BREAKOUT = "/sys/class/leds/qsfp{0}/brightness" + + QSFP_BREAKOUT_START_IDX = 1 + QSFP_BREAKOUT_END_IDX = 24 + QSFP_NO_BREAKOUT_START_IDX = 25 + QSFP_NO_BREAKOUT_END_IDX = 32 + + LED_COLOR_OFF = 0 + LED_COLOR_GREEN = 1 + LED_COLOR_YELLOW = 2 + + # Helper method to map SONiC port name to Arista QSFP index + def _port_name_to_qsfp_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + sonic_port_num = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + swss = swsssdk.SonicV2Connector() + swss.connect(swss.APPL_DB) + + lanes = swss.get(swss.APPL_DB, self.PORT_TABLE_PREFIX + port_name, 'lanes') + + # SONiC port nums are 0-based and increment by 4 + # Arista QSFP indices are 1-based and increment by 1 + return (((sonic_port_num/4) + 1), sonic_port_num%4, len(lanes.split(','))) + + + + # Concrete implementation of port_link_state_change() method + def port_link_state_change_bk(self, port, state): + qsfp_index, lane_index, lanes = self._port_name_to_qsfp_index(port) + + # Ignore invalid QSFP indices + if qsfp_index <= 0 or lanes <= 0 or lanes > 4: + return + + # QSFP indices 0-24 are breakout-capable and have four LEDs, and each LED indicate one lane. + # whereas indices 25-32 are not breakout-capable, and only have one + if qsfp_index <= self.QSFP_BREAKOUT_END_IDX: + # assuming 40G, then we need to control four lanes + led_sysfs_paths = [ self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, i) for i in range(lane_index + 1, lane_index + 1 + lanes) ] + else: + led_sysfs_paths = [ self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) ] + + for led_sysfs_path in led_sysfs_paths: + led_file = open(led_sysfs_path, "w") + + if state == "up": + led_file.write("%d" % self.LED_COLOR_GREEN) + else: + led_file.write("%d" % self.LED_COLOR_OFF) + + led_file.close() + + # Constructor + def __init__(self): + # Initialize all front-panel status LEDs to green + with open("/sys/bus/i2c/devices/0-005e/sys_locator", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/0-005e/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/fan4_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/fan5_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/0-005e/fan6_led", "w") as f: + f.write("1") + sysled_task() + + # Initialize: Turn all front panel QSFP LEDs off + # # for qsfp_index in range(self.QSFP_BREAKOUT_START_IDX, self.QSFP_BREAKOUT_END_IDX + 1): + # # for lane in range(1, 5): + # # led_sysfs_path = self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, lane) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) + + # # for qsfp_index in range(self.QSFP_NO_BREAKOUT_START_IDX, self.QSFP_NO_BREAKOUT_END_IDX + 1): + # # led_sysfs_path = self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/psuutil.py new file mode 100755 index 00000000000..7a3b87f24d2 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/psuutil.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +############################################################################# +# Alphanetworks +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = { + 1: "/psu1_present", + 2: "/psu2_present", + } + self.psu_oper_status = { + 1: "/psu1_power_good", + 2: "/psu2_power_good", + } + self.psu_mapping = "0-005e" + if not os.path.exists(self.psu_path+self.psu_mapping): + self.psu_mapping = "1-005e" + + def get_num_psus(self): + return len(self.psu_presence) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping+self.psu_oper_status[index] + 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 + self.psu_presence[index] + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/sfputil.py new file mode 100755 index 00000000000..8fe5d1a1ca6 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/plugins/sfputil.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python + +import os.path +import time + +try: + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +#from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + +CPLD_PORT_NUM = 8 +SFP_PATH = "/sys/bus/i2c/devices/{0}-005f" +SFPPLUS_PATH = "/sys/bus/i2c/devices/{0}-005e" +SFPPLUS_EEPROM_PATH = "/sys/bus/i2c/devices/{0}-0050" + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 33 + port_num = 31 + + sfp_status = 0 + + port_to_eeprom = {} + + port_to_i2cbus_0 = { + 1 : 13, + 2 : 14, + 3 : 15, + 4 : 16, + 5 : 12, + 6 : 11, + } + + port_to_i2cbus_1 = { + 1 : 14, + 2 : 15, + 3 : 16, + 4 : 17, + 5 : 13, + 6 : 12, + } + + port_to_i2cbus_mapping = {} + + sfpplus_eeprom_path = SFPPLUS_EEPROM_PATH+"/sfp_eeprom" + eeprom_path = SFP_PATH+"/sfp{1}_eeprom" + port_reset_path = SFP_PATH+"/sfp{1}_port_reset" + present_path = SFP_PATH+"/sfp{1}_is_present" + sfpplus_present_path = SFPPLUS_PATH+"/sfp_present" + lpmode_path = SFP_PATH+"/sfp{1}_lpmode" + + _qsfp_ports = range(first_port, port_num + 1) + + @property + def port_start(self): + return self.first_port + + @property + def port_end(self): + return self.last_port + + @property + def qsfp_ports(self): + return range(self.first_port, self.port_num + 1) + + @property + def port_to_eeprom_mapping(self): + return self.port_to_eeprom + + @property + def get_presence_all(self): + bitmap = "" + port = self.port_start + + while (port >= self.first_port) and (port <= self.last_port): + i2c_index = (port / CPLD_PORT_NUM) + 1 + index = (port % CPLD_PORT_NUM) + 1 + if i2c_index == 5: + path = self.sfpplus_present_path + port_path = path.format(0) + else: + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], index) + + try: + reg_file = open(port_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + reg_file.close() + + if i2c_index == 5: + if index == 1: + if reg_value == '0' or reg_value == '1': + bitmap += '1' + " " + else: + bitmap += '0' + " " + else: + if reg_value == '0' or reg_value == '2': + bitmap += '1' + " " + else: + bitmap += '0' + " " + else: + if reg_value == '1': + bitmap += '1' + " " + else: + bitmap += '0' + " " + + port += 1 + + content = bitmap.split(" ") + content = "".join(content[::-1]) + + return int(content, 2) + + def get_transceiver_change_event(self, timeout=0): + while True: + port_dict = {} + port = self.port_start + + # Check for OIR events and return updated port_dict + reg_value = self.get_presence_all + if reg_value != self.sfp_status: + changed_ports = self.sfp_status ^ reg_value + while (port >= self.port_start) and (port <= self.port_end): + + # Mask off the bit corresponding to our port + mask = (1 << port) + + if changed_ports & mask: + # port presence is high + if (reg_value & mask) == mask: + port_dict[port] = SFP_STATUS_INSERTED + else: + port_dict[port] = SFP_STATUS_REMOVED + + port += 1 + + # Update reg value + self.sfp_status = reg_value + return True, port_dict + + time.sleep(0.5) + + def __init__(self): + path = self.present_path + port_path = path.format(self.port_to_i2cbus_0[1], 1) + if not os.path.exists(port_path): + self.port_to_i2cbus_mapping = self.port_to_i2cbus_1 + else: + self.port_to_i2cbus_mapping = self.port_to_i2cbus_0 + + for x in range(self.first_port, self.last_port + 1): + index = (x % CPLD_PORT_NUM) + 1 + cpld_index = (x / CPLD_PORT_NUM) + 1 + if cpld_index == 5: + path = self.sfpplus_eeprom_path + if index == 1: + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[cpld_index]) + else: + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[cpld_index+1]) + else: + path = self.eeprom_path + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / CPLD_PORT_NUM) + 1 + index = (port_num % CPLD_PORT_NUM) + 1 + if cpld_index == 5: + # Not support reset for SFP+ + return True + else: + path = self.port_reset_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + # reset + reg_file.write('1') + + time.sleep(1) + + reg_file.write('0') + + reg_file.close() + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.lpmode_path + if i2c_index == 5: + raise NotImplementedError + else: + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + if lpmode == True: + reg_file.write('1') + else: + reg_file.write('0') + + reg_file.close() + return True + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.lpmode_path + if i2c_index == 5: + return False + else: + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + + reg_file.close() + + if reg_value == '1': + return True + + return False + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / CPLD_PORT_NUM) + 1 + index = (port_num % CPLD_PORT_NUM) + 1 + if cpld_index == 5: + path = self.sfpplus_present_path + port_path = path.format(0) + else: + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + reg_file.close() + + if cpld_index == 5: + if index == 1: + if reg_value == '0' or reg_value == '1': + return True + else: + if reg_value == '0' or reg_value == '2': + return True + else: + if reg_value == '1': + return True + + return False + diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/pmon_daemon_control.json b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/pmon_daemon_control.json new file mode 100755 index 00000000000..f2a407daaf6 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": false +} + diff --git a/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/sensors.conf new file mode 100755 index 00000000000..b5d4fc07cfa --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snj60b0_320f-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file for snj60b0_320f +# ------------------------------------------------ + +bus "i2c-1" "SMBus I801 adapter at f000" +chip "goreme_power_cpld-*" + label fan1 "Fan tray 1 front" + label fan2 "Fan tray 2 front" + label fan3 "Fan tray 3 front" + label fan4 "Fan tray 4 front" + label fan11 "Fan tray 1 rear" + label fan12 "Fan tray 2 rear" + label fan13 "Fan tray 3 rear" + label fan14 "Fan tray 4 rear" diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 86ac56b750b..eeef34499a5 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -54,6 +54,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(MITAC_LY1200_32X_PLATFORM_MODULE) \ $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \ $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE) \ $(BRCM_XLR_GTS_PLATFORM_MODULE) \ $(DELTA_AG9032V2A_PLATFORM_MODULE) \ $(JUNIPER_QFX5210_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-alphanetworks.mk b/platform/broadcom/platform-modules-alphanetworks.mk index 13e5fc4ff9e..d02755e489b 100644 --- a/platform/broadcom/platform-modules-alphanetworks.mk +++ b/platform/broadcom/platform-modules-alphanetworks.mk @@ -2,9 +2,14 @@ ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION = 1.0 ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION = 1.0 +ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE_VERSION = 1.0 +ALPHANETWORKS_SNJ61D0_320F_PLATFORM_MODULE_VERSION = 1.0 + export ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION export ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION +export ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE_VERSION +export ALPHANETWORKS_SNJ61D0_320F_PLATFORM_MODULE_VERSION ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60a0-320fv2_$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION)_amd64.deb $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-alphanetworks @@ -16,5 +21,6 @@ ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60b $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snh60b0_640f-r0 $(eval $(call add_extra_package,$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE),$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE))) - - +ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE = sonic-platform-alphanetworks-snj60b0-320f_$(ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE_VERSION)_amd64.deb +$(ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snj60b0_320f-r0 +$(eval $(call add_extra_package,$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE),$(ALPHANETWORKS_SNJ60B0_320F_PLATFORM_MODULE))) diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog index 2742b7c6a41..e66424f8ab9 100644 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog @@ -1,6 +1,6 @@ sonic-alphanetworks-platform-modules (1.0) unstable; urgency=low - * Add support for SNH60A0-320FV2 and SNH60B0_640F. + * Add support for SNH60A0-320FV2 , SNH60B0_640F , SNJ60B0_320F and SNJ61D0_320F. - -- Alphanetworks Tue, 19 Dec 2017 09:35:58 +0800 + -- Alphanetworks Tue, 26 Nov 2019 09:35:58 +0800 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control index 55533f735a5..71e42d0f1bd 100644 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control @@ -15,3 +15,12 @@ Architecture: amd64 Depends: linux-image-4.19.0-6-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp +Package: sonic-platform-alphanetworks-snj60b0-320f +Architecture: amd64 +Depends: linux-image-4.19.0-6-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-alphanetworks-snj61d0-320f +Architecture: amd64 +Depends: linux-image-4.19.0-6-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules index 0d1a588db6b..f27ac01fe7e 100755 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules @@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-alphanetworks KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= snh60a0-320fv2 snh60b0-640f +MODULE_DIRS:= snh60a0-320fv2 snh60b0-640f snj60b0-320f snj61d0-320f MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service @@ -59,9 +59,9 @@ binary-indep: # Custom package commands (for mod in $(MODULE_DIRS); do \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c index af47c6521a0..6e7ec1b4d69 100644 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c @@ -54,7 +54,7 @@ #if (DEBUG_MODE == 1) #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) + printk (KERN_INFO "[%s,%d]: " fmt "\r\n", __FUNCTION__, __LINE__, ##args) #else #define DEBUG_PRINT(fmt, args...) #endif @@ -185,6 +185,7 @@ struct sfp_port_data { oom_driver_port_type_t port_type; u64 present; /* present status, bit0:port0, bit1:port1 and so on */ u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + u64 port_lpmode; /* lpmode status, bit0:port0, bit1:port1 and so on */ struct sfp_msa_data *msa; struct sfp_ddm_data *ddm; @@ -397,6 +398,18 @@ enum sfp_sysfs_tx_fault_attributes { PORT_TX_FAULT_MAX }; +enum sfp_sysfs_lpmode_attributes { + PORT1_LPMODE, + PORT2_LPMODE, + PORT3_LPMODE, + PORT4_LPMODE, + PORT5_LPMODE, + PORT6_LPMODE, + PORT7_LPMODE, + PORT8_LPMODE, + PORT_LPMODE_MAX +}; + enum sfp_sysfs_eeprom_attributes { PORT1_EEPROM, PORT2_EEPROM, @@ -621,7 +634,7 @@ static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, } sfp_update_port_reset(client); - is_reset = (data->port_reset & BIT_INDEX(attr->index))? 0 : 1; + is_reset = (data->port_reset & BIT_INDEX(attr->index)); return sprintf(buf, "%d\n", is_reset); } @@ -652,14 +665,14 @@ static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *d /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. * is_reset: 0 is not reset. 1 is reset. */ - if (is_reset == 0) { - data->port_reset |= BIT_INDEX(attr->index); + if (is_reset == 1) { + cpld_val |= BIT_INDEX(attr->index); } else { - data->port_reset &= ~BIT_INDEX(attr->index); + cpld_val &= ~BIT_INDEX(attr->index); } - alpha_i2c_cpld_write(0x5f, cpld_reg, cpld_val); + i2c_smbus_write_byte_data(client, cpld_reg, cpld_val); DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); mutex_unlock(&data->update_lock); @@ -787,6 +800,91 @@ static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute * return count; } +static struct sfp_port_data *qsfp_update_port_lpmode(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x9}; + + mutex_lock(&data->update_lock); + + /* Read lpmode status of port 1~32 */ + data->port_lpmode = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("lpmode status = 0x%x", status); + data->port_lpmode |= (u64)status << (i*8); + } + + DEBUG_PRINT("lpmode status = 0x%llx", data->port_lpmode); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t qsfp_show_port_lpmode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_lpmode = 0; + + qsfp_update_port_lpmode(client); + is_lpmode = (data->port_lpmode & BIT_INDEX(attr->index))?1:0; + + return sprintf(buf, "%d\n", is_lpmode); +} + +static ssize_t qsfp_set_port_lpmode(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 sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long is_lpmode; + int error; + + error = kstrtol(buf, 10, &is_lpmode); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x09; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update lpmode status. CPLD defined 0 is normal mode, 1 is Low Power mode. + * is_lpmode: 0 is normal mode. 1 is Low Power mode. + */ + if (is_lpmode == 1) { + cpld_val |= BIT_INDEX(attr->index); + } + else { + cpld_val &= ~BIT_INDEX(attr->index); + } + + i2c_smbus_write_byte_data(client, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf) { @@ -833,6 +931,7 @@ static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", val); } + static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, char *buf) { @@ -841,7 +940,7 @@ static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, char devfile[96]; struct file *sfd; int i2c_index = 0; - int status, result, offset = 0xb; + int result, offset = 0xb; int rdlen, rc; mm_segment_t old_fs; char buffer[256]; @@ -1087,11 +1186,32 @@ DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) &sensor_dev_attr_sfp##PORT8##_eeprom.dev_attr.attr, DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +#define DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT1##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT2##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT3##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT4##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT5##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT6##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT7##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT8##_LPMODE); +#define DECLARE_PORT_LPMODE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_lpmode.dev_attr.attr, +DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + static struct attribute *qsfp_attributes[] = { DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_LPMODE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) @@ -1128,7 +1248,8 @@ static struct attribute *sfp_msa_attributes[] = { static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); -#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ @@ -1147,7 +1268,8 @@ DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); -#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ @@ -1166,7 +1288,8 @@ DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); -#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py index 870267e31c2..fa0b6d06014 100755 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py @@ -345,9 +345,9 @@ def system_ready(): return True def do_install(): - tmp = "find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a return' > /tmp/tmp_fancontrol" + tmp = "find /var/lib/docker/overlay2 -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '492d' | sed '491a if \[ $? -ne 1 \]' | sed '488d' | sed '487a return' > /tmp/tmp_fancontrol" status, output = log_os_system(tmp, 1) - tmp = "fancontrol_tmp=`find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay2 -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" status, output = log_os_system(tmp, 1) print "Checking system...." if driver_check() == False: diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c index 8985790cce6..b7614fa54f8 100644 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c @@ -54,7 +54,7 @@ #if (DEBUG_MODE == 1) #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) + printk (KERN_INFO "[%s,%d]: " fmt "\r\n", __FUNCTION__, __LINE__, ##args) #else #define DEBUG_PRINT(fmt, args...) #endif @@ -203,6 +203,7 @@ struct sfp_port_data { oom_driver_port_type_t port_type; u64 present; /* present status, bit0:port0, bit1:port1 and so on */ u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + u64 port_lpmode; /* lpmode status, bit0:port0, bit1:port1 and so on */ struct sfp_msa_data *msa; struct sfp_ddm_data *ddm; @@ -647,6 +648,26 @@ enum sfp_sysfs_tx_fault4_attributes { PORT_TX_FAULT4_MAX }; +enum sfp_sysfs_lpmode_attributes { + PORT1_LPMODE, + PORT2_LPMODE, + PORT3_LPMODE, + PORT4_LPMODE, + PORT5_LPMODE, + PORT6_LPMODE, + PORT7_LPMODE, + PORT8_LPMODE, + PORT9_LPMODE, + PORT10_LPMODE, + PORT11_LPMODE, + PORT12_LPMODE, + PORT13_LPMODE, + PORT14_LPMODE, + PORT15_LPMODE, + PORT16_LPMODE, + PORT_LPMODE_MAX +}; + enum sfp_sysfs_eeprom_attributes { PORT1_EEPROM, PORT2_EEPROM, @@ -926,7 +947,7 @@ static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, } sfp_update_port_reset(client); - is_reset = (data->port_reset & BIT_INDEX(attr->index))? 0 : 1; + is_reset = (data->port_reset & BIT_INDEX(attr->index)); return sprintf(buf, "%d\n", is_reset); } @@ -957,14 +978,14 @@ static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *d /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. * is_reset: 0 is not reset. 1 is reset. */ - if (is_reset == 0) { - data->port_reset |= BIT_INDEX(attr->index); + if (is_reset == 1) { + cpld_val |= BIT_INDEX(attr->index); } else { - data->port_reset &= ~BIT_INDEX(attr->index); + cpld_val &= ~BIT_INDEX(attr->index); } - alpha_i2c_cpld_write(0x5f, cpld_reg, cpld_val); + i2c_smbus_write_byte_data(client, cpld_reg, cpld_val); DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); mutex_unlock(&data->update_lock); @@ -1092,6 +1113,99 @@ static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute * return count; } +static struct sfp_port_data *qsfp_update_port_lpmode(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x09, 0x0A}; + + mutex_lock(&data->update_lock); + + /* Read lpmode status of port 1~64 */ + data->port_lpmode = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("lpmode status = 0x%x", status); + data->port_lpmode |= (u64)status << (i*8); + } + + DEBUG_PRINT("lpmode status = 0x%llx", data->port_lpmode); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t qsfp_show_port_lpmode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_lpmode = 0; + + qsfp_update_port_lpmode(client); + is_lpmode = (data->port_lpmode & BIT_INDEX(attr->index))? 1 : 0; + + return sprintf(buf, "%d\n", is_lpmode); +} + +static ssize_t qsfp_set_port_lpmode(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 sfp_port_data *data = i2c_get_clientdata(client); + u8 regs[] = {0x09, 0x0A}; + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + u8 index = 0; + long is_lpmode; + int error; + + error = kstrtol(buf, 10, &is_lpmode); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + if (attr->index < 8){ + cpld_reg = regs[0]; + index = attr->index; + } + else{ + cpld_reg = regs[1]; + index = attr->index - 8; + } + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update lpmode status. CPLD defined 0 is normal mode, 1 is Low Power mode. + * is_lpmode: 0 is normal mode. 1 is Low Power mode. + */ + if (is_lpmode == 1) { + cpld_val |= BIT_INDEX(index); + } + else { + cpld_val &= ~BIT_INDEX(index); + } + + i2c_smbus_write_byte_data(client, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf) { @@ -1459,6 +1573,27 @@ DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) +#define DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT1##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT2##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT3##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT4##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT5##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT6##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT7##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT8##_LPMODE); +#define DECLARE_PORT_LPMODE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_lpmode.dev_attr.attr, +DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + static struct attribute *qsfp_attributes[] = { DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_NUMBER_ATTR(9, 10, 11, 12, 13, 14, 15, 16) @@ -1468,6 +1603,8 @@ static struct attribute *qsfp_attributes[] = { DECLARE_PORT_IS_PRESENT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_RESET_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_LPMODE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_LPMODE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) DECLARE_PORT_RX_LOSn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) @@ -1521,7 +1658,8 @@ static struct attribute *sfp_msa_attributes[] = { static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); -#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ @@ -1541,7 +1679,8 @@ DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); -#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ @@ -1561,7 +1700,8 @@ DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); -#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py index 4b64a2e12a1..1d4bf0f1aea 100755 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py @@ -373,9 +373,9 @@ def system_ready(): return True def do_install(): - tmp = "find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a return' > /tmp/tmp_fancontrol" + tmp = "find /var/lib/docker/overlay2 -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '492d' | sed '491a if \[ $? -ne 1 \]' | sed '488d' | sed '487a return' > /tmp/tmp_fancontrol" status, output = log_os_system(tmp, 1) - tmp = "fancontrol_tmp=`find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay2 -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" status, output = log_os_system(tmp, 1) print "Checking system...." if driver_check() == False: diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/classes/__init__.py new file mode 100755 index 00000000000..e69de29bb2d diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/Makefile new file mode 100755 index 00000000000..71dd25d6db1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/Makefile @@ -0,0 +1,8 @@ +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# goreme_system_cpld.o ym2651y.o optoe.o + +obj-m:=snj60b0-320f_sfp.o snj60b0-320f_fpga.o snj60b0-320f_onie_eeprom.o + + +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o optoe.o diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_fpga.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_fpga.c new file mode 100755 index 00000000000..86a746ca2c4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_fpga.c @@ -0,0 +1,845 @@ +/* + * A hwmon driver for the alphanetworks_snj60b0_320f_fpga + * + * Copyright (C) 2019 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * 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 + + +#define DRIVER_NAME "snj60b0_fpga" +#define PSU1_STATUS_REG 0x2 +#define PSU2_STATUS_REG 0x3 +#define FAN_PWM_REG 0x18 + +#define PSU_PRESENT_BIT 0x10 +#define PSU_POWER_BIT 0x20 +#define FAN_PRESENT_BIT 0x2 + +#define SYS_LED_REG 0x2D +#define SYS2_LED_REG 0x2E +#define FAN12_LED_REG 0x30 +#define FAN34_LED_REG 0x31 +#define FAN56_LED_REG 0x32 + +#define SYS_RESET1_REG 0x1C +#define SYS_RESET2_REG 0x1D +#define SYS_RESET3_REG 0x1E +//#define SWI_CTRL_REG 0x4 + +#define SYS_LOCATOR_LED_BITS 0x07 +#define SYS_PWR_LED_BITS 0x38 +#define PORT_LED_DISABLE_BITS 0x40 +#define SYS_STATUS_LED_BITS 0x07 +#define SYS_FAN_LED_BITS 0x38 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 +#define REST_BUTTON_BITS 0x0 + +#define SFP_TX_FAULT_REG 0x25 +#define SFP_TX_FAULT_MASK_REG 0x26 +#define SFP_TX_DISABLE_REG 0x27 +#define SFP_PRESENT_REG 0x28 +#define SFP_PRESENT_MASK_REG 0x29 +#define SFP_RX_LOSS_REG 0x2A +#define SFP_RX_LOSS_MASK_REG 0x2B +//#define SWI_CTRL_REG 0x34 + + + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf); + +static ssize_t sys_sfp_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t sys_sfp_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(fpga_client_list); +static struct mutex list_lock; + +struct fpga_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snj60b0_320f_fpga */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct alphanetworks_snj60b0_320f_pwr_fpga_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_fpga_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_PRESENT=0x05, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FRONT_SPEED_RPM=0x0b, + FAN1_REAR_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + SYS_STATUS, + SYS_PWR, + SYS_FAN, + SYS_LOCATOR, + SFP_TX_FAULT, + SFP_TX_FAULT_MASK, + SFP_TX_DISABLE, + SFP_PRESENT, + SFP_PRESENT_MASK, + SFP_RX_LOSS, + SFP_RX_LOSS_MASK, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + FAN5_LED, + FAN6_LED, + SYS_RESET1, + SYS_RESET2, + SYS_RESET3, + PORT_LED_DISABLE, +}; + + + + + + +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, psu_show_status, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, psu_show_status, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_power_good, S_IRUGO, psu_show_status, NULL, PSU1_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu2_power_good, S_IRUGO, psu_show_status, NULL, PSU2_POWER_GOOD); +static SENSOR_DEVICE_ATTR(fan_pwm, (0660), fan_pwm_show, set_fan_pwm, FAN_PWM); +static SENSOR_DEVICE_ATTR(fan1_present, S_IRUGO, fan_show_status, NULL, FAN1_PRESENT); +static SENSOR_DEVICE_ATTR(fan2_present, S_IRUGO, fan_show_status, NULL, FAN2_PRESENT); +static SENSOR_DEVICE_ATTR(fan3_present, S_IRUGO, fan_show_status, NULL, FAN3_PRESENT); +static SENSOR_DEVICE_ATTR(fan4_present, S_IRUGO, fan_show_status, NULL, FAN4_PRESENT); +static SENSOR_DEVICE_ATTR(fan5_present, S_IRUGO, fan_show_status, NULL, FAN5_PRESENT); +static SENSOR_DEVICE_ATTR(fan6_present, S_IRUGO, fan_show_status, NULL, FAN6_PRESENT); +static SENSOR_DEVICE_ATTR(fan1_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan1_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); + +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); static SENSOR_DEVICE_ATTR(fan13_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); static SENSOR_DEVICE_ATTR(fan14_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); +static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); static SENSOR_DEVICE_ATTR(fan15_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); +static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); static SENSOR_DEVICE_ATTR(fan16_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan13_input, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan14_input, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan15_input, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan16_input, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); + +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +static SENSOR_DEVICE_ATTR(port_led_disable, (0660), sys_led_read, sys_led_write, PORT_LED_DISABLE); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(fan1_led, (0660), sys_led_read, sys_led_write, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, (0660), sys_led_read, sys_led_write, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, (0660), sys_led_read, sys_led_write, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, (0660), sys_led_read, sys_led_write, FAN4_LED); +static SENSOR_DEVICE_ATTR(fan5_led, (0660), sys_led_read, sys_led_write, FAN5_LED); +static SENSOR_DEVICE_ATTR(fan6_led, (0660), sys_led_read, sys_led_write, FAN6_LED); +static SENSOR_DEVICE_ATTR(sys_reset1, (0660), sys_led_read, sys_led_write, SYS_RESET1); +static SENSOR_DEVICE_ATTR(sys_reset2, (0660), sys_led_read, sys_led_write, SYS_RESET2); +static SENSOR_DEVICE_ATTR(sys_reset3, (0660), sys_led_read, sys_led_write, SYS_RESET3); + +static SENSOR_DEVICE_ATTR(sfp_tx_fault, (0660), sys_sfp_read, sys_sfp_write, SFP_TX_FAULT); +static SENSOR_DEVICE_ATTR(sfp_tx_fault_mask, (0660), sys_sfp_read, sys_sfp_write, SFP_TX_FAULT_MASK); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, (0660), sys_sfp_read, sys_sfp_write, SFP_TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_present, (0660), sys_sfp_read, sys_sfp_write, SFP_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_present_mask, (0660), sys_sfp_read, sys_sfp_write, SFP_PRESENT_MASK); +static SENSOR_DEVICE_ATTR(sfp_rx_loss, (0660), sys_sfp_read, sys_sfp_write, SFP_RX_LOSS); +static SENSOR_DEVICE_ATTR(sfp_rx_loss_mask, (0660), sys_sfp_read, sys_sfp_write, SFP_RX_LOSS_MASK); + + +static struct attribute *alphanetworks_snj60b0_320f_fpga_attributes[] = { + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu1_power_good.dev_attr.attr, + &sensor_dev_attr_psu2_power_good.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan5_present.dev_attr.attr, + &sensor_dev_attr_fan6_present.dev_attr.attr, + &sensor_dev_attr_fan1_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan6_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan6_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, &sensor_dev_attr_fan12_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, &sensor_dev_attr_fan13_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, &sensor_dev_attr_fan14_fault.dev_attr.attr, + &sensor_dev_attr_fan5_fault.dev_attr.attr, &sensor_dev_attr_fan15_fault.dev_attr.attr, + &sensor_dev_attr_fan6_fault.dev_attr.attr, &sensor_dev_attr_fan16_fault.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan12_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan13_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan14_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan15_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan16_input.dev_attr.attr, + &sensor_dev_attr_sys_status.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan4_led.dev_attr.attr, + &sensor_dev_attr_fan5_led.dev_attr.attr, + &sensor_dev_attr_fan6_led.dev_attr.attr, + &sensor_dev_attr_sys_reset1.dev_attr.attr, + &sensor_dev_attr_sys_reset2.dev_attr.attr, + &sensor_dev_attr_sys_reset3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault_mask.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_present.dev_attr.attr, + &sensor_dev_attr_sfp_present_mask.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss_mask.dev_attr.attr, + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_port_led_disable.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snj60b0_320f_fpga_group = { + .attrs = alphanetworks_snj60b0_320f_fpga_attributes, +}; + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case PSU1_PRESENT: + case PSU1_POWER_GOOD: + command = PSU1_STATUS_REG; + break; + case PSU2_PRESENT: + case PSU2_POWER_GOOD: + command = PSU2_STATUS_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "fpga(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 0 : 1 ); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + res = (val & PSU_POWER_BIT ? 1 : 0 ); + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, FAN_PWM_REG); + + if (val < 0) { + dev_dbg(&client->dev, "fpga(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 0xFF) + return -EINVAL; + + i2c_smbus_write_byte_data(client, FAN_PWM_REG, value); + + return count; +} + +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + // struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + int val, val2; + + switch (sda->index) { + /* case FAN_DUTY_CYCLE_PERCENTAGE: */ + /* { */ + /* u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_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 FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", val * 150); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", (val & FAN_PRESENT_BIT) ? 1 : 0); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + val = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_FRONT_SPEED_RPM); + val2 = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_REAR_SPEED_RPM); + ret = sprintf(buf, "%d\n", (val|val2) ? 0 : 1); + break; + default: + break; + } + + return ret; +} + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case SYS_LOCATOR: + case SYS_PWR: + case PORT_LED_DISABLE: + command = SYS_LED_REG; + break; + case SYS_STATUS: + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + command = SYS2_LED_REG; + break; + case SYS_RESET1: + command = SYS_RESET1_REG; + break; + case SYS_RESET2: + command = SYS_RESET2_REG; + break; + case SYS_RESET3: + command = SYS_RESET3_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "fpga(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case SYS_LOCATOR: + res = (val & SYS_LOCATOR_LED_BITS) >> 0; + break; + case SYS_PWR: + res = (val & SYS_PWR_LED_BITS) >> 3; + case PORT_LED_DISABLE: + res = (val & PORT_LED_DISABLE_BITS) >> 6; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 0; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + res = (val & SYS_FAN_LED_BITS) >> 3; + break; + case SYS_RESET1: + res = val; + break; + case SYS_RESET2: + res = val; + break; + case SYS_RESET3: + res = val; + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + + switch(sda->index) { + case SYS_LOCATOR: + case SYS_PWR: + case PORT_LED_DISABLE: + if(write < 0 || write > 7) + return -EINVAL; + command = SYS_LED_REG; + break; + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS2_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS2_LED_REG; + break; + case SYS_RESET1: + if (write < 0 || write > 255) + return -EINVAL; + command = SYS_RESET1_REG; + break; + case SYS_RESET2: + if (write < 0 || write > 255) + return -EINVAL; + command = SYS_RESET2_REG; + break; + case SYS_RESET3: + if (write < 0 || write > 255) + return -EINVAL; + command = SYS_RESET3_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "fpga(0x%x) reg(0x1) err %d\n", client->addr, read); + } + + switch(sda->index) { + case SYS_LOCATOR: + read &= ~SYS_LOCATOR_LED_BITS; + read |= write << 0; + break; + case SYS_PWR: + read &= ~SYS_PWR_LED_BITS; + read |= write << 3; + break; + case PORT_LED_DISABLE: + read &= ~PORT_LED_DISABLE_BITS; + read |= write << 6; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 0; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + read &= ~SYS_FAN_LED_BITS; + read |= write << 3; + break; + case SYS_RESET1: + read = write; + break; + case SYS_RESET2: + read = write; + break; + case SYS_RESET3: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + return count; +} + +static ssize_t sys_sfp_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + int error, write, command; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + switch(sda->index) { + case SFP_TX_FAULT: + command = SFP_TX_FAULT_MASK_REG; + break; + case SFP_PRESENT: + command = SFP_PRESENT_MASK_REG; + case SFP_RX_LOSS: + command = SFP_RX_LOSS_MASK_REG; + break; + default: + return 0; + } + + i2c_smbus_write_byte_data(client, command, write); + + return count; + +} + +static ssize_t sys_sfp_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case SFP_TX_FAULT: + command = SFP_TX_FAULT_REG; + break; + case SFP_TX_DISABLE: + command = SFP_TX_DISABLE_REG; + break; + case SFP_PRESENT: + command = SFP_PRESENT_REG; + break; + case SFP_RX_LOSS: + command = SFP_RX_LOSS_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "fpga(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + res = val; + + return sprintf(buf, "%d\n", res); + +} + + +static void alpha_i2c_fpga_add_client(struct i2c_client *client) +{ + struct fpga_client_node *node = kzalloc(sizeof(struct fpga_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate fpga_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &fpga_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_fpga_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct fpga_client_node *fpga_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &fpga_client_list) + { + fpga_node = list_entry(list_node, struct fpga_client_node, list); + + if (fpga_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(fpga_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_fpga_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct alphanetworks_snj60b0_320f_pwr_fpga_data* data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct alphanetworks_snj60b0_320f_pwr_fpga_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snj60b0_320f_fpga_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_fpga_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit; + } + + dev_info(&client->dev, "%s: pwr_fpga '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_fpga_remove(struct i2c_client *client) +{ + struct alphanetworks_snj60b0_320f_pwr_fpga_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snj60b0_320f_fpga_group); + alpha_i2c_fpga_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_fpga_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_fpga_id); + +static struct i2c_driver alpha_i2c_fpga_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_fpga_probe, + .remove = alpha_i2c_fpga_remove, + .id_table = alpha_i2c_fpga_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_fpga_read(unsigned short fpga_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct fpga_client_node *fpga_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &fpga_client_list) + { + fpga_node = list_entry(list_node, struct fpga_client_node, list); + + if (fpga_node->client->addr == fpga_addr) { + ret = i2c_smbus_read_byte_data(fpga_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_fpga_read); + +int alpha_i2c_fpga_write(unsigned short fpga_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct fpga_client_node *fpga_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &fpga_client_list) + { + fpga_node = list_entry(list_node, struct fpga_client_node, list); + + if (fpga_node->client->addr == fpga_addr) { + ret = i2c_smbus_write_byte_data(fpga_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_fpga_write); + +static int __init alpha_i2c_fpga_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_fpga_driver); +} + +static void __exit alpha_i2c_fpga_exit(void) +{ + i2c_del_driver(&alpha_i2c_fpga_driver); +} + +static struct dmi_system_id alphanetworks_snj60b0_320f_dmi_table[] = { + { + .ident = "Alpha snj60b0-320f", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "snj60b0-320f"), + }, + } +}; + +int platform_alphanetworks_snj60b0_320f(void) +{ + return dmi_check_system(alphanetworks_snj60b0_320f_dmi_table); +} +EXPORT_SYMBOL(platform_alphanetworks_snj60b0_320f); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_fpga driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_fpga_init); +module_exit(alpha_i2c_fpga_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_onie_eeprom.c new file mode 100755 index 00000000000..f46d49726b4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for snj60b0-320f onie eeprom + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 + * 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. + * see + * + * 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 + +#define EEPROM_SIZE 256 + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snj60b0-320f_onie_eeprom */ +static const unsigned short normal_i2c[] = { 0x56, I2C_CLIENT_END }; + + +enum sysfs_onie_attributes { + ONIE_RW, +}; + +static SENSOR_DEVICE_ATTR(eeprom, (0660), onie_read, onie_write, ONIE_RW); + +static struct attribute *snj60b0_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group snj60b0_onie_group = { + .attrs = snj60b0_onie_attributes, +}; + + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + __u8 read_write; + unsigned short offset = 0; + union i2c_smbus_data temp; + char rbuf[EEPROM_SIZE]; + + for( offset=0 ; offset < EEPROM_SIZE ; ++offset ) + { + read_write = I2C_SMBUS_WRITE; + offset = offset & 0x3fff; + temp.byte = (u8)offset; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + + read_write = I2C_SMBUS_READ; + temp.byte = 0xaa; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + rbuf[offset] = (char)temp.byte; + } + + read_write = I2C_SMBUS_READ; + temp.byte = 0xbb; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + } + } + + memcpy(buf, rbuf, EEPROM_SIZE); + return EEPROM_SIZE; +} + +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + if (write < 0 || write > 255) + return -EINVAL; + + /* Not support yet */ + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int onie_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snj60b0_onie_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int onie_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &snj60b0_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snj60b0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snj60b0_onie_eeprom", + }, + .probe = onie_eeprom_probe, + .remove = onie_eeprom_remove, + .id_table = onie_eeprom_id, + .address_list = normal_i2c, +}; + + +static int __init onie_eeprom_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&onie_eeprom_driver); +} + +static void __exit onie_eeprom_exit(void) + +{ + i2c_del_driver(&onie_eeprom_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("onie eeprom driver"); +MODULE_LICENSE("GPL"); + +module_init(onie_eeprom_init); +module_exit(onie_eeprom_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_sfp.c new file mode 100644 index 00000000000..f2e75b7945a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/modules/snj60b0-320f_sfp.c @@ -0,0 +1,2043 @@ +/* + * SFP driver for alphanetworks snj60b0-320f sfp + * + * Copyright (C) 2019 Alphanetworks Technology Corporation. + * Philip Wang + * + * 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 + * 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. + * see + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "snj60b0-320f_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "[%s,%d]: " fmt "\r\n", __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 32 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_CPLD_I2C_ADDR 0x5F +//#define SFP_FPGA_I2C_ADDR 0x5E +#define SFP_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 + +#define SFPPLUS_1_PORT_NUMBER 32 +#define SFPPLUS_2_PORT_NUMBER 33 + +#define SFPPLUS_PRESENT_ADDRESS 0x28 + +#define SFP_CPLD_REG_ADDR_PRESENT 0x03 +#define SFP_CPLD_REG_ADDR_RESET 0x04 +#define SFP_CPLD_REG_ADDR_LOWPOWERMODE 0x05 +#define SFP_CPLD_REG_ADDR_MODSELECT 0x06 +#define SFP_CPLD_REG_ADDR_LED 0x07 + +u8 portCPLDID_0[]={13,14,15,16}; +u8 sfpPlusID_0[]={12,11}; +u8 portCPLDID_1[]={14,15,16,17}; +u8 sfpPlusID_1[]={13,12}; +u8 *portCPLDID; +u8 *sfpPlusID; + + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 +#define SFF8024_DEVICE_ID_QSFPDD 0x18 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +/* extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); */ +extern int alpha_i2c_fpga_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, SFP_CPLD_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32, +sfp33, sfp34 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfpcpld1", sfp1 }, { "sfpcpld2", sfp2 }, { "sfpcpld3", sfp3 }, { "sfpcpld4", sfp4 }, +{ "sfpcpld5", sfp5 }, { "sfpcpld6", sfp6 }, { "sfpcpld7", sfp7 }, { "sfpcpld8", sfp8 }, +{ "sfpcpld9", sfp9 }, { "sfpcpld10", sfp10 }, { "sfpcpld11", sfp11 }, { "sfpcpld12", sfp12 }, +{ "sfpcpld13", sfp13 }, { "sfpcpld14", sfp14 }, { "sfpcpld15", sfp15 }, { "sfpcpld16", sfp16 }, +{ "sfpcpld17", sfp17 }, { "sfpcpld18", sfp18 }, { "sfpcpld19", sfp19 }, { "sfpcpld20", sfp20 }, +{ "sfpcpld21", sfp21 }, { "sfpcpld22", sfp22 }, { "sfpcpld23", sfp23 }, { "sfpcpld24", sfp24 }, +{ "sfpcpld25", sfp25 }, { "sfpcpld26", sfp26 }, { "sfpcpld27", sfp27 }, { "sfpcpld28", sfp28 }, +{ "sfpcpld29", sfp29 }, { "sfpcpld30", sfp30 }, { "sfpcpld31", sfp31 }, { "sfpcpld32", sfp32 }, +{ "sfpcpld33", sfp33 }, { "sfpcpld34", sfp34 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28, + OOM_DRIVER_PORT_TYPE_QSFPDD +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + u64 port_lpmode; /* lpmode status, bit0:port0, bit1:port1 and so on */ + u64 port_led; /* port led status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_port_num_attributes { + PORT1_NUMBER, + PORT2_NUMBER, + PORT3_NUMBER, + PORT4_NUMBER, + PORT5_NUMBER, + PORT6_NUMBER, + PORT7_NUMBER, + PORT8_NUMBER, + PORT_NUMBER_MAX +}; + +enum sfp_sysfs_present_attributes { + PORT1_PRESENT, + PORT2_PRESENT, + PORT3_PRESENT, + PORT4_PRESENT, + PORT5_PRESENT, + PORT6_PRESENT, + PORT7_PRESENT, + PORT8_PRESENT, + PORT1_PRESENT_ALL, + PORT2_PRESENT_ALL, + PORT3_PRESENT_ALL, + PORT4_PRESENT_ALL, + PORT5_PRESENT_ALL, + PORT6_PRESENT_ALL, + PORT7_PRESENT_ALL, + PORT8_PRESENT_ALL, + PORT_PRESENT_MAX +}; + +enum sfp_sysfs_type_attributes { + PORT1_TYPE, + PORT2_TYPE, + PORT3_TYPE, + PORT4_TYPE, + PORT5_TYPE, + PORT6_TYPE, + PORT7_TYPE, + PORT8_TYPE, + PORT_TYPE_MAX +}; + +enum sfp_sysfs_reset_attributes { + PORT1_RESET, + PORT2_RESET, + PORT3_RESET, + PORT4_RESET, + PORT5_RESET, + PORT6_RESET, + PORT7_RESET, + PORT8_RESET, + PORT_RESET_MAX +}; + +enum sfp_sysfs_rx_los_attributes { + PORT1_RX_LOS, + PORT2_RX_LOS, + PORT3_RX_LOS, + PORT4_RX_LOS, + PORT5_RX_LOS, + PORT6_RX_LOS, + PORT7_RX_LOS, + PORT8_RX_LOS, + PORT_RX_LOS_MAX +}; + +enum sfp_sysfs_rx_los1_attributes { + PORT1_RX_LOS1 = PORT_RX_LOS_MAX, + PORT2_RX_LOS1, + PORT3_RX_LOS1, + PORT4_RX_LOS1, + PORT5_RX_LOS1, + PORT6_RX_LOS1, + PORT7_RX_LOS1, + PORT8_RX_LOS1, + PORT_RX_LOS1_MAX +}; + +enum sfp_sysfs_rx_los2_attributes { + PORT1_RX_LOS2 = PORT_RX_LOS1_MAX, + PORT2_RX_LOS2, + PORT3_RX_LOS2, + PORT4_RX_LOS2, + PORT5_RX_LOS2, + PORT6_RX_LOS2, + PORT7_RX_LOS2, + PORT8_RX_LOS2, + PORT_RX_LOS2_MAX +}; + +enum sfp_sysfs_rx_los3_attributes { + PORT1_RX_LOS3 = PORT_RX_LOS2_MAX, + PORT2_RX_LOS3, + PORT3_RX_LOS3, + PORT4_RX_LOS3, + PORT5_RX_LOS3, + PORT6_RX_LOS3, + PORT7_RX_LOS3, + PORT8_RX_LOS3, + PORT_RX_LOS3_MAX +}; + +enum sfp_sysfs_rx_los4_attributes { + PORT1_RX_LOS4 = PORT_RX_LOS3_MAX, + PORT2_RX_LOS4, + PORT3_RX_LOS4, + PORT4_RX_LOS4, + PORT5_RX_LOS4, + PORT6_RX_LOS4, + PORT7_RX_LOS4, + PORT8_RX_LOS4, + PORT_RX_LOS4_MAX +}; + +enum sfp_sysfs_rx_los_all_attributes { + PORT1_RX_LOS_ALL = PORT_RX_LOS4_MAX, + PORT2_RX_LOS_ALL, + PORT3_RX_LOS_ALL, + PORT4_RX_LOS_ALL, + PORT5_RX_LOS_ALL, + PORT6_RX_LOS_ALL, + PORT7_RX_LOS_ALL, + PORT8_RX_LOS_ALL, + PORT_RX_LOS_ALL_MAX +}; + +enum sfp_sysfs_tx_disable_attributes { + PORT1_TX_DISABLE = PORT_RX_LOS_ALL_MAX, + PORT2_TX_DISABLE, + PORT3_TX_DISABLE, + PORT4_TX_DISABLE, + PORT5_TX_DISABLE, + PORT6_TX_DISABLE, + PORT7_TX_DISABLE, + PORT8_TX_DISABLE, + PORT_TX_DISABLE_MAX +}; + +enum sfp_sysfs_tx_disable1_attributes { + PORT1_TX_DISABLE1 = PORT_TX_DISABLE_MAX, + PORT2_TX_DISABLE1, + PORT3_TX_DISABLE1, + PORT4_TX_DISABLE1, + PORT5_TX_DISABLE1, + PORT6_TX_DISABLE1, + PORT7_TX_DISABLE1, + PORT8_TX_DISABLE1, + PORT_TX_DISABLE1_MAX +}; + +enum sfp_sysfs_tx_disable2_attributes { + PORT1_TX_DISABLE2 = PORT_TX_DISABLE1_MAX, + PORT2_TX_DISABLE2, + PORT3_TX_DISABLE2, + PORT4_TX_DISABLE2, + PORT5_TX_DISABLE2, + PORT6_TX_DISABLE2, + PORT7_TX_DISABLE2, + PORT8_TX_DISABLE2, + PORT_TX_DISABLE2_MAX +}; + +enum sfp_sysfs_tx_disable3_attributes { + PORT1_TX_DISABLE3 = PORT_TX_DISABLE2_MAX, + PORT2_TX_DISABLE3, + PORT3_TX_DISABLE3, + PORT4_TX_DISABLE3, + PORT5_TX_DISABLE3, + PORT6_TX_DISABLE3, + PORT7_TX_DISABLE3, + PORT8_TX_DISABLE3, + PORT_TX_DISABLE3_MAX +}; + +enum sfp_sysfs_tx_disable4_attributes { + PORT1_TX_DISABLE4 = PORT_TX_DISABLE3_MAX, + PORT2_TX_DISABLE4, + PORT3_TX_DISABLE4, + PORT4_TX_DISABLE4, + PORT5_TX_DISABLE4, + PORT6_TX_DISABLE4, + PORT7_TX_DISABLE4, + PORT8_TX_DISABLE4, + PORT_TX_DISABLE4_MAX +}; + +enum sfp_sysfs_tx_disable_all_attributes { + PORT1_TX_DISABLE_ALL = PORT_TX_DISABLE4_MAX, + PORT2_TX_DISABLE_ALL, + PORT3_TX_DISABLE_ALL, + PORT4_TX_DISABLE_ALL, + PORT5_TX_DISABLE_ALL, + PORT6_TX_DISABLE_ALL, + PORT7_TX_DISABLE_ALL, + PORT8_TX_DISABLE_ALL, + PORT_TX_DISABLE_ALL_MAX +}; + +enum sfp_sysfs_tx_fault_attributes { + PORT1_TX_FAULT = PORT_TX_DISABLE_ALL_MAX, + PORT2_TX_FAULT, + PORT3_TX_FAULT, + PORT4_TX_FAULT, + PORT5_TX_FAULT, + PORT6_TX_FAULT, + PORT7_TX_FAULT, + PORT8_TX_FAULT, + PORT_TX_FAULT_MAX +}; + +enum sfp_sysfs_tx_fault1_attributes { + PORT1_TX_FAULT1 = PORT_TX_FAULT_MAX, + PORT2_TX_FAULT1, + PORT3_TX_FAULT1, + PORT4_TX_FAULT1, + PORT5_TX_FAULT1, + PORT6_TX_FAULT1, + PORT7_TX_FAULT1, + PORT8_TX_FAULT1, + PORT_TX_FAULT1_MAX +}; + +enum sfp_sysfs_tx_fault2_attributes { + PORT1_TX_FAULT2 = PORT_TX_FAULT1_MAX, + PORT2_TX_FAULT2, + PORT3_TX_FAULT2, + PORT4_TX_FAULT2, + PORT5_TX_FAULT2, + PORT6_TX_FAULT2, + PORT7_TX_FAULT2, + PORT8_TX_FAULT2, + PORT_TX_FAULT2_MAX +}; + +enum sfp_sysfs_tx_fault3_attributes { + PORT1_TX_FAULT3 = PORT_TX_FAULT2_MAX, + PORT2_TX_FAULT3, + PORT3_TX_FAULT3, + PORT4_TX_FAULT3, + PORT5_TX_FAULT3, + PORT6_TX_FAULT3, + PORT7_TX_FAULT3, + PORT8_TX_FAULT3, + PORT_TX_FAULT3_MAX +}; + +enum sfp_sysfs_tx_fault4_attributes { + PORT1_TX_FAULT4 = PORT_TX_FAULT3_MAX, + PORT2_TX_FAULT4, + PORT3_TX_FAULT4, + PORT4_TX_FAULT4, + PORT5_TX_FAULT4, + PORT6_TX_FAULT4, + PORT7_TX_FAULT4, + PORT8_TX_FAULT4, + PORT_TX_FAULT4_MAX +}; + +enum sfp_sysfs_lpmode_attributes { + PORT1_LPMODE, + PORT2_LPMODE, + PORT3_LPMODE, + PORT4_LPMODE, + PORT5_LPMODE, + PORT6_LPMODE, + PORT7_LPMODE, + PORT8_LPMODE, + PORT_LPMODE_MAX +}; + +enum sfp_sysfs_eeprom_attributes { + PORT1_EEPROM, + PORT2_EEPROM, + PORT3_EEPROM, + PORT4_EEPROM, + PORT5_EEPROM, + PORT6_EEPROM, + PORT7_EEPROM, + PORT8_EEPROM, + PORT_EEPROM_MAX +}; + +enum sfp_sysfs_ddm_implemented_attributes { + PORT1_DDM_IMPLEMENTED, + PORT2_DDM_IMPLEMENTED, + PORT3_DDM_IMPLEMENTED, + PORT4_DDM_IMPLEMENTED, + PORT5_DDM_IMPLEMENTED, + PORT6_DDM_IMPLEMENTED, + PORT7_DDM_IMPLEMENTED, + PORT8_DDM_IMPLEMENTED, + PORT_DDM_IMPLEMENTED_MAX +}; + +enum sfp_sysfs_port_led_attributes { + PORT_LED, + PORT_LED_MAX +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("show_port_number port number:%d", data->port + attr->index); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port + attr->index)); +} + +static struct sfp_port_data *sfp_plus_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {SFPPLUS_PRESENT_ADDRESS}; + + DEBUG_PRINT("Starting sfp+ present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + /* status = alpha_i2c_cpld_read(0x5f, regs[i]); */ + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("SFP+ reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Status:%d", status); + + if(data->port == SFPPLUS_1_PORT_NUMBER) + data->present = ((status & 0x2) == 0)?0x1:0; + else + data->present = ((status & 0x1) == 0)?0x2:0; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {SFP_CPLD_REG_ADDR_PRESENT}; + + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + if(client->addr == SFP_EEPROM_A0_I2C_ADDR) + return sfp_plus_update_present(client); + else{ + data->present = 0; + return data; + } + } + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(%d) reg(0x%x) err %d", SFP_CPLD_I2C_ADDR, regs[i], status); + goto exit; + } + DEBUG_PRINT("Present status = 0x%x", status); + + data->present |= (u64)status << (i*8); + DEBUG_PRINT("Present status = 0x%llx", data->present); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + return (data->present & BIT_INDEX(port)) ? 1 : 0; +} + +static ssize_t show_present(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); + + if ((attr->index >= PORT1_PRESENT_ALL) && (attr->index <= PORT8_PRESENT_ALL)) { + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, attr->index)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP28; + break; + case SFF8024_DEVICE_ID_QSFPDD: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFPDD; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {SFP_CPLD_REG_ADDR_RESET}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x%x) reg(0x%x) err %d", SFP_CPLD_REG_ADDR_RESET, regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_reset = 0; + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(attr->index)); + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_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 sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = SFP_CPLD_REG_ADDR_RESET; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 1) { + cpld_val |= BIT_INDEX(attr->index); + } + else { + cpld_val &= ~BIT_INDEX(attr->index); + } + + i2c_smbus_write_byte_data(client, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + if ((attr->index >= PORT1_TX_FAULT1) && (attr->index < PORT_TX_FAULT4_MAX)){ + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - PORT1_TX_FAULT1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE1) && (attr->index < PORT_TX_DISABLE4_MAX)){ + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - PORT1_TX_DISABLE1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index < PORT_TX_DISABLE_ALL_MAX)){ + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + } + if ((attr->index >= PORT1_RX_LOS1) && (attr->index < PORT_RX_LOS4_MAX)){ + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - PORT1_RX_LOS1)) ? 1 : 0; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + if((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index < PORT_TX_DISABLE_ALL_MAX)){ + DEBUG_PRINT ("disable:%ld %d==TX_DISABLE_ALL %u\r\n", disable, attr->index, data->qsfp->status[1]); + data->qsfp->status[1] = disable? 0xF:0; + } + else{ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - PORT1_TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - PORT1_TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static struct sfp_port_data *qsfp_update_port_led(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int status = -1; + u8 reg = SFP_CPLD_REG_ADDR_LED; + + mutex_lock(&data->update_lock); + + /* Read led status of port 1~32 */ + data->port_led = 0; + + status = i2c_smbus_read_byte_data(client, reg); + + if (status < 0) { + DEBUG_PRINT("cpld reg(0x%x) err %d", reg, status); + goto exit; + } + + data->port_led = status; + + DEBUG_PRINT("led status = %ll", data->port_led); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t qsfp_show_port_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = qsfp_update_port_led(client); + + return sprintf(buf, "%ll\n", data->port_led); +} + +static ssize_t qsfp_set_port_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long led_state; + int error; + int result; + + error = kstrtol(buf, 10, &led_state); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = SFP_CPLD_REG_ADDR_LED; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update led status. CPLD defined 0 is LED enable, 1 is LED disable. + * led_state: 0 is LED enable. 1 is LED disable. + */ + if (cpld_val != led_state){ + data->port_led = led_state; + + result = i2c_smbus_write_byte_data(client, cpld_reg, led_state); + if (result < 0) { + dev_info(&client->dev, "%s, i2c_smbus_write_byte_data fail(%d)", __FUNCTION__, result); + } + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, led_state); + } + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_port_lpmode(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {SFP_CPLD_REG_ADDR_LOWPOWERMODE}; + + mutex_lock(&data->update_lock); + + /* Read lpmode status of port 1~32 */ + data->port_lpmode = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("lpmode status = 0x%x", status); + data->port_lpmode |= (u64)status << (i*8); + } + + DEBUG_PRINT("lpmode status = 0x%llx", data->port_lpmode); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t qsfp_show_port_lpmode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_lpmode = 0; + + qsfp_update_port_lpmode(client); + is_lpmode = (data->port_lpmode & BIT_INDEX(attr->index))?1:0; + + return sprintf(buf, "%d\n", is_lpmode); +} + +static ssize_t qsfp_set_port_lpmode(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 sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; + long is_lpmode; + int error; + + error = kstrtol(buf, 10, &is_lpmode); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = SFP_CPLD_REG_ADDR_LOWPOWERMODE; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update lpmode status. CPLD defined 0 is normal mode, 1 is Low Power mode. + * is_lpmode: 0 is normal mode. 1 is Low Power mode. + */ + if (is_lpmode == 1) { + cpld_val |= BIT_INDEX(attr->index); + } + else { + cpld_val &= ~BIT_INDEX(attr->index); + } + + i2c_smbus_write_byte_data(client, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + if ((attr->index >= PORT1_TX_FAULT) && (attr->index < PORT_TX_FAULT_MAX)){ + index = 0; + } + else if ((attr->index >= PORT1_TX_DISABLE) && (attr->index < PORT_TX_DISABLE_MAX)){ + index = 1; + } + if ((attr->index >= PORT1_RX_LOS) && (attr->index < PORT_RX_LOS_MAX)){ + index = 2; + } + + if(data->port == SFPPLUS_1_PORT_NUMBER) + val = (data->ddm->status[index] & BIT_INDEX(0)) ? 1 : 0; + else if(data->port == SFPPLUS_2_PORT_NUMBER) + val = (data->ddm->status[index] & BIT_INDEX(1)) ? 1 : 0; + else + val = (data->ddm->status[index] & BIT_INDEX(attr->index)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char devfile[96]; + struct file *sfd; + int i2c_index = 0; + int result; + int offset[] = {SFP_CPLD_REG_ADDR_MODSELECT}; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", portCPLDID_0[0]); + + /* Read SFP EEPROM */ + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + dev_info(&client->dev, "Failed to open file(%s)#%d", devfile, __LINE__); + portCPLDID = portCPLDID_1; + sfpPlusID = sfpPlusID_1; + } + else{ + portCPLDID = portCPLDID_0; + sfpPlusID = sfpPlusID_0; + } + + if(strcmp(client->name, "sfpcpld33") == 0){ + if(attr->index == 0) + i2c_index = sfpPlusID[0]; + else if(attr->index == 1) + i2c_index = sfpPlusID[1]; + } + else{ + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = portCPLDID[0]; + else if(strcmp(client->name, "sfpcpld9") == 0) + i2c_index = portCPLDID[1]; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = portCPLDID[2]; + else if(strcmp(client->name, "sfpcpld25") == 0) + i2c_index = portCPLDID[3]; + + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], BIT_INDEX(attr->index)); + if (result < 0) { + dev_info(&client->dev, "%s, i2c_smbus_write_byte_data fail(%d)", __FUNCTION__, result); + } + } + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Read SFP EEPROM */ + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + dev_info(&client->dev, "Failed to open file(%s)#%d", devfile, __LINE__); + return 0; + } + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + dev_info(&client->dev, "file %s cann't readable ?\n", devfile); + return 0; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + dev_info(&client->dev, "File(%s) empty!\n", devfile); + rc = 0; + goto exit; + } + + rc = sizeof(buffer); + memcpy(buf, buffer, rc); + + /* Reset module select register */ + if(strcmp(client->name, "sfpcpld33") != 0){ + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], 0); + if (result < 0) { + dev_info(&client->dev, "%s, i2c_smbus_write_byte_data fail(%d)", __FUNCTION__, result); + } + } + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + + return rc; +} + +#if 0 +static ssize_t qsfp_set_eeprom(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("data->port:%d attr index:%d", data->port, attr->index); + return 1; +} +#endif + +/* SFP/QSFP common attributes for sysfs */ +#define DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT1##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT2##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT3##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT4##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT5##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT6##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT7##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT8##_NUMBER); +#define DECLARE_PORT_NUMBER_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_number.dev_attr.attr, +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_is_present, S_IRUGO, show_present, NULL, PORT##PORT1##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_is_present, S_IRUGO, show_present, NULL, PORT##PORT2##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_is_present, S_IRUGO, show_present, NULL, PORT##PORT3##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_is_present, S_IRUGO, show_present, NULL, PORT##PORT4##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_is_present, S_IRUGO, show_present, NULL, PORT##PORT5##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_is_present, S_IRUGO, show_present, NULL, PORT##PORT6##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_is_present, S_IRUGO, show_present, NULL, PORT##PORT7##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_is_present, S_IRUGO, show_present, NULL, PORT##PORT8##_PRESENT); +#define DECLARE_PORT_IS_PRESENT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_is_present.dev_attr.attr, +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT1##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT2##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT3##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT4##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT5##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT6##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT7##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT8##_TYPE); +#define DECLARE_PORT_TYPE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_type.dev_attr.attr, +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT1##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT2##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT3##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT4##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT5##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT6##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT7##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT8##_RESET); +#define DECLARE_PORT_RESET_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_reset.dev_attr.attr, +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +/* QSFP attributes for sysfs */ +#define DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS##INDEX); +#define DECLARE_PORT_RX_LOSn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los##INDEX.dev_attr.attr, +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT1##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT2##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT3##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT4##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT5##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT6##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT7##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT8##_TX_DISABLE##INDEX); + +#define DECLARE_PORT_TX_DISABLEn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable##INDEX.dev_attr.attr, +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT##INDEX); +#define DECLARE_PORT_TX_FAULTn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault##INDEX.dev_attr.attr, +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_LED_DEVICE_ATTR() \ + static SENSOR_DEVICE_ATTR(sfp_led_disable, S_IWUSR | S_IRUGO, qsfp_show_port_led, qsfp_set_port_led, PORT_LED); +#define DECLARE_PORT_LED_ATTR() \ + &sensor_dev_attr_sfp_led_disable.dev_attr.attr, +DECLARE_PORT_LED_DEVICE_ATTR() + +#define DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT1##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT2##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT3##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT4##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT5##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT6##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT7##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT8##_EEPROM); +#define DECLARE_PORT_EEPROMTn_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_eeprom.dev_attr.attr, +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT1##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT2##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT3##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT4##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT5##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT6##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT7##_LPMODE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_lpmode, S_IWUSR | S_IRUGO, qsfp_show_port_lpmode, qsfp_set_port_lpmode, PORT##PORT8##_LPMODE); +#define DECLARE_PORT_LPMODE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_lpmode.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_lpmode.dev_attr.attr, +DECLARE_PORT_LPMODE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +static struct attribute *qsfp_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_LPMODE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_LED_ATTR() + DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_EEPROMTn_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + + +/* SFP msa attributes for sysfs */ +static struct attribute *sfp_msa_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + +/* SFP ddm attributes for sysfs */ +#define DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los.dev_attr.attr, +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT1##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT2##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT3##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT4##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT5##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable.dev_attr.attr, +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault.dev_attr.attr, +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +static struct attribute *sfp_ddm_attributes[] = { + DECLARE_RX_LOS_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_DISABLE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_FAULT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + /* result = data_len; */ + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + dev_info(&client->dev, "sfp msa '%s' (sfp_sysfs_eeprom_init fail...)\n", client->name); + /* goto exit_remove; */ + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +/* exit_remove: */ + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + struct sfp_port_data *port_data = i2c_get_clientdata(client); + + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + if ( ((port_data->port < SFPPLUS_1_PORT_NUMBER) && (client->addr == SFP_CPLD_I2C_ADDR)) || + ((port_data->port >= SFPPLUS_1_PORT_NUMBER) && (client->addr == SFP_EEPROM_A0_I2C_ADDR)) ) + { + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + } + + if (client->addr == SFP_EEPROM_A0_I2C_ADDR){ + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + } + + /* Bring QSFPs out of reset */ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + DEBUG_PRINT("data->port:%d client->addr:0x%0x\n", data->port, client->addr); + if (client->addr == SFP_CPLD_I2C_ADDR){ + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_EEPROM_A0_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_EEPROM_A0_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_EEPROM_A0_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Philip Wang "); +MODULE_DESCRIPTION("alphanetworks snj60b0-320f driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/service/snj60b0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/service/snj60b0-platform-init.service new file mode 100755 index 00000000000..1bb09836ed9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/service/snj60b0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNJ60B0-320F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snj60b0_util.py -f install +ExecStop=/usr/local/bin/alphanetworks_snj60b0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/setup.py new file mode 100755 index 00000000000..b0bc6027c57 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snj60b0_320f', + version='1.0', + description='Module to initialize Alphanetworks SNJ60B0-320F platforms', + + packages=['snj60b0_320f'], + package_dir={'snj60b0_320f': 'snj60b0-320f/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/utils/alphanetworks_snj60b0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/utils/alphanetworks_snj60b0_util.py new file mode 100755 index 00000000000..50df4a794b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snj60b0-320f/utils/alphanetworks_snj60b0_util.py @@ -0,0 +1,521 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Alphanetworks Technology Corporation. +# Robin Chen +# 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 +# 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. +# see +# +# 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 os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'snj60b0-320f' +DRIVER_NAME = 'snj60b0_320f' +device_path = "x86_64-alphanetworks_snj60b0_320f-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + +devMaxPort = 34 +cpldPortNum = 8 + +FPGAAddr = "005e" +PortCPLD_Addr = "005f" + +portFPGAAddr = "0x5e" +portCPLDAddr = "0x5f" +portAddr = "0x50" + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print PROJECT_NAME.upper()+": "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +" with result: " + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod | grep " + DRIVER_NAME, 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe '+PROJECT_NAME+'_fpga' , +'modprobe '+PROJECT_NAME+'_onie_eeprom' , +'modprobe '+PROJECT_NAME+'_sfp' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + if kos[i].find('pca954') != -1: + status, output = log_os_system(kos[i]+ " force_deselect_on_exit=1", 1) + else: + 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") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [13,14,15,16,12,11] +sfp_map2 = [14,15,16,17,13,12] + +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo snj60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snj60b0_fpga 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-0/new_device' ] + +mknod2 =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo snj60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snj60b0_fpga 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-1/new_device' ] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + + status, output = log_os_system("i2cdetect -l | grep I801 | grep i2c-0", 0) + if not output: + order = 1 + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/plugins/led_control.py" + status, output = log_os_system(tmp, 0) + else: + order = 0 + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/plugins/led_control.py" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + global devMaxPort + global cpldPortNum + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + if mknod2[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/1-"+FPGAAddr+"/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo 4 > /sys/bus/i2c/devices/1-"+FPGAAddr+"/sys_reset2", 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + if mknod[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/0-"+FPGAAddr+"/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo 4 > /sys/bus/i2c/devices/0-"+FPGAAddr+"/sys_reset2", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, devMaxPort): + index = i / cpldPortNum + port = i % cpldPortNum + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + +# Port CPLD and FPGA device add + if reg_sfp == 1: + if i < 32: + if order: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portCPLDAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map2[index])+"/new_device", 1) + else: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portCPLDAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status +# Front port EEPROM device add + if order: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map2[index])+"/new_device", 1) + else: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + +# Port EEPROM device add + if i == 32: + if order: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map2[index])+"/new_device", 1) + else: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + + if status: + print output + if FORCE == 0: + return status + if i == 33: + if order: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map2[index+1])+"/new_device", 1) + else: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" "+portAddr+" > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index+1])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status +# Front port LED enable + if order: + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/1-"+FPGAAddr+"/port_led_disable", 1) + else: + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/0-"+FPGAAddr+"/port_led_disable", 1) + if status: + print output + if FORCE == 0: + return status + + if order: + for i in [0,1,2,3]: + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/"+str(sfp_map2[i])+"-"+PortCPLD_Addr+"/sfp_led_disable", 1) + if status: + if FORCE == 0: + return status + else: + for i in [0,1,2,3]: + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-"+PortCPLD_Addr+"/sfp_led_disable", 1) + if status: + if FORCE == 0: + return status +# end of Front port LED enable + + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + +# Front port LED disable + if I2C_ORDER: + status, output =log_os_system("echo 1 > /sys/bus/i2c/devices/1-"+FPGAAddr+"/port_led_disable", 1) + else: + status, output =log_os_system("echo 1 > /sys/bus/i2c/devices/0-"+FPGAAddr+"/port_led_disable", 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER: + for i in [0,1,2,3]: + status, output =log_os_system("echo 1 > /sys/bus/i2c/devices/"+str(sfp_map2[i])+"-"+PortCPLD_Addr+"/sfp_led_disable", 1) + if status: + if FORCE == 0: + return status + else: + for i in [0,1,2,3]: + status, output =log_os_system("echo 1 > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-"+PortCPLD_Addr+"/sfp_led_disable", 1) + if status: + if FORCE == 0: + return status +# end of Front port LED disable + + + for i in range(0, devMaxPort): + index = i / cpldPortNum + port = i % cpldPortNum + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i < 32: + if I2C_ORDER: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map2[index])+"/delete_device" + else: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo "+portCPLDAddr+" > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map2[index])+"/delete_device" + else: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo "+portAddr+" > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if i == 32: + if I2C_ORDER: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map2[index])+"/delete_device", 1) + else: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 33: + if I2C_ORDER: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map2[index+1])+"/delete_device", 1) + else: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index+1])+"/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER: + nodelist = mknod2 + else: + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + tmp = "find /var/lib/docker/overlay2 -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '492d' | sed '491a if \[ $? -ne 1 \]' | sed '488d' | sed '487a return' > /tmp/tmp_fancontrol" + status, output = log_os_system(tmp, 1) + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay2 -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + status, output = log_os_system(tmp, 1) + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main()