diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini new file mode 100644 index 0000000000..745cc69428 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36 Ethernet1/0/1 0 100000 +Ethernet4 37,38,39,40 Ethernet1/0/5 1 100000 +Ethernet8 41,42,43,44 Ethernet1/0/9 2 100000 +Ethernet12 45,46,47,48 Ethernet1/0/13 3 100000 +Ethernet16 49,50,51,52 Ethernet1/0/17 4 100000 +Ethernet20 53,54,55,56 Ethernet1/0/21 5 100000 +Ethernet24 57,58,59,60 Ethernet1/0/25 6 100000 +Ethernet28 61,62,63,64 Ethernet1/0/29 7 100000 +Ethernet32 65,66,67,68 Ethernet1/0/33 8 100000 +Ethernet36 69,70,71,72 Ethernet1/0/37 9 100000 +Ethernet40 73,74,75,76 Ethernet1/0/41 10 100000 +Ethernet44 77,78,79,80 Ethernet1/0/45 11 100000 +Ethernet48 81,82,83,84 Ethernet1/0/49 12 100000 +Ethernet52 85,86,87,88 Ethernet1/0/53 13 100000 +Ethernet56 89,90,91,92 Ethernet1/0/57 14 100000 +Ethernet60 93,94,95,96 Ethernet1/0/61 15 100000 +Ethernet64 97,98,99,100 Ethernet1/0/65 16 100000 +Ethernet68 101,102,103,104 Ethernet1/0/69 17 100000 +Ethernet72 105,106,107,108 Ethernet1/0/73 18 100000 +Ethernet76 109,110,111,112 Ethernet1/0/77 19 100000 +Ethernet80 113,114,115,116 Ethernet1/0/81 20 100000 +Ethernet84 117,118,119,120 Ethernet1/0/85 21 100000 +Ethernet88 121,122,123,124 Ethernet1/0/89 22 100000 +Ethernet92 125,126,127,128 Ethernet1/0/93 23 100000 +Ethernet96 1,2,3,4 Ethernet1/0/97 24 100000 +Ethernet100 5,6,7,8 Ethernet1/0/101 25 100000 +Ethernet104 9,10,11,12 Ethernet1/0/105 26 100000 +Ethernet108 13,14,15,16 Ethernet1/0/109 27 100000 +Ethernet112 17,18,19,20 Ethernet1/0/113 28 100000 +Ethernet116 21,22,23,24 Ethernet1/0/117 29 100000 +Ethernet120 25,26,27,28 Ethernet1/0/121 30 100000 +Ethernet124 29,30,31,32 Ethernet1/0/125 31 100000 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile new file mode 100644 index 0000000000..b6e792ad0a --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-snh60a0-32x100G.config.bcm diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm new file mode 100644 index 0000000000..395827122e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm @@ -0,0 +1,163 @@ +# This property file is for ZION-320F 100G mode only. +# Zion-320F uses Tomahawk BCM56960 as its mac. Besides, it is phyless. +# Note: The settings in this file are not verified yet. + + + +# Set stat collection interval in microseconds. +# Setting this to 0 will prevent counters from being started. +bcm_stat_interval.0=1000000 + +# Linkscan interval in microseconds. +# If non-zero, bcm_init() will start linkscan +bcm_linkscan_interval.0=450000 + + + +# BCM56960 : MMU Cell Buffer Allocation Profile to support ASF (cut-thru) Forwarding +# 0: No cut-through support +# 1: Similar speed profile (Default) +# 2: Extreme speed profile + +os=unix + + + +# EagleCore ports +#portmap_66=129:10 +#portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +#FalconCore[0 - 7] must map to logical port[1 - 32] +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +#FalconCore[8 - 15] must map to logical port[34 - 65] +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +#FalconCore[16 - 23] must map to logical port[68 - 99] +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +#FalconCore[24 - 31] must map to logical port[102 - 133] +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe +pbmp_oversubscribe=0x0000000000000000000000000000000000003fc000000ff0000003fc000001fe + + + +#core-0 +xgxs_rx_lane_map_ce0=0x3012 +xgxs_rx_lane_map_ce1=0x1230 +xgxs_rx_lane_map_ce2=0x3012 +xgxs_rx_lane_map_ce3=0x1230 +xgxs_rx_lane_map_ce4=0x1230 +xgxs_rx_lane_map_ce5=0x1230 +xgxs_rx_lane_map_ce6=0x1230 +xgxs_rx_lane_map_ce7=0x1230 + +#core-8 +xgxs_rx_lane_map_ce8=0x1032 +xgxs_rx_lane_map_ce9=0x1230 +xgxs_rx_lane_map_ce10=0x1032 +xgxs_rx_lane_map_ce11=0x1230 +xgxs_rx_lane_map_ce12=0x1230 +xgxs_rx_lane_map_ce13=0x3012 +xgxs_rx_lane_map_ce14=0x1230 +xgxs_rx_lane_map_ce15=0x3012 + +#core-16 +xgxs_rx_lane_map_ce16=0x3012 +xgxs_rx_lane_map_ce17=0x3012 +xgxs_rx_lane_map_ce18=0x1230 +xgxs_rx_lane_map_ce19=0x3012 +xgxs_rx_lane_map_ce20=0x3012 +xgxs_rx_lane_map_ce21=0x3012 +xgxs_rx_lane_map_ce22=0x3012 +xgxs_rx_lane_map_ce23=0x3012 + +#core-24 +xgxs_rx_lane_map_ce24=0x3210 +xgxs_rx_lane_map_ce25=0x3012 +xgxs_rx_lane_map_ce26=0x3210 +xgxs_rx_lane_map_ce27=0x3012 +xgxs_rx_lane_map_ce28=0x3012 +xgxs_rx_lane_map_ce29=0x1230 +xgxs_rx_lane_map_ce30=0x3012 +xgxs_rx_lane_map_ce31=0x3012 + +# +# Remap XGXS tx lanes to desired mapping by hardware provide. +#core-0 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce1=0x1032 +xgxs_tx_lane_map_ce2=0x3210 +xgxs_tx_lane_map_ce3=0x1032 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_tx_lane_map_ce5=0x3210 +xgxs_tx_lane_map_ce6=0x3210 +xgxs_tx_lane_map_ce7=0x1230 + +#core-8 +xgxs_tx_lane_map_ce8=0x2301 +xgxs_tx_lane_map_ce9=0x3210 +xgxs_tx_lane_map_ce10=0x2301 +xgxs_tx_lane_map_ce11=0x3210 +xgxs_tx_lane_map_ce12=0x0123 +xgxs_tx_lane_map_ce13=0x3210 +xgxs_tx_lane_map_ce14=0x0123 +xgxs_tx_lane_map_ce15=0x3210 + +#core-16 +xgxs_tx_lane_map_ce16=0x2301 +xgxs_tx_lane_map_ce17=0x3210 +xgxs_tx_lane_map_ce18=0x0123 +xgxs_tx_lane_map_ce19=0x1032 +xgxs_tx_lane_map_ce20=0x0123 +xgxs_tx_lane_map_ce21=0x1032 +xgxs_tx_lane_map_ce22=0x0123 +xgxs_tx_lane_map_ce23=0x1032 + +#core-24 +xgxs_tx_lane_map_ce24=0x1032 +xgxs_tx_lane_map_ce25=0x1032 +xgxs_tx_lane_map_ce26=0x1032 +xgxs_tx_lane_map_ce27=0x1032 +xgxs_tx_lane_map_ce28=0x1032 +xgxs_tx_lane_map_ce29=0x1032 +xgxs_tx_lane_map_ce30=0x3210 +xgxs_tx_lane_map_ce31=0x3210 + + + +ptp_ts_pll_fref=25000000 +ptp_bs_fref=25000000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku new file mode 100755 index 0000000000..588c4a951d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNH60A0-320FV2 t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol new file mode 100644 index 0000000000..24184113d2 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/4-004d/hwmon/hwmon3/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_snh60a0_320fv2-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf new file mode 100644 index 0000000000..14404194ef --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc new file mode 100644 index 0000000000..c05dbe3326 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +# LED microprocessor initialization for alphanetworks snh60a0-320fv2 + +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 REMAP_PORT_17=14 REMAP_PORT_18=13 REMAP_PORT_19=12 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 REMAP_PORT_37=58 REMAP_PORT_38=57 REMAP_PORT_39=56 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 REMAP_PORT_41=54 REMAP_PORT_42=53 REMAP_PORT_43=52 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 REMAP_PORT_45=50 REMAP_PORT_46=49 REMAP_PORT_47=48 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 REMAP_PORT_49=46 REMAP_PORT_50=45 REMAP_PORT_51=44 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 REMAP_PORT_53=42 REMAP_PORT_54=41 REMAP_PORT_55=40 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 REMAP_PORT_57=38 REMAP_PORT_58=37 REMAP_PORT_59=36 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 REMAP_PORT_61=34 REMAP_PORT_62=33 REMAP_PORT_63=32 + +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 2A 01 86 FF 06 FF C2 7F 60 FF 02 20 60 FE 67 2E 06 FE F2 04 60 FE D2 40 74 0E 70 1C 02 00 60 FE 67 2E 06 FE F2 04 60 FE D2 20 74 20 70 70 02 A0 F6 FE 04 D2 01 70 39 74 5F 06 FE 28 32 00 32 01 B7 97 71 46 75 4E 06 FF C2 04 74 4E 70 5F 67 76 67 72 67 76 67 76 67 76 67 76 67 76 67 76 57 67 76 67 76 67 76 67 76 67 76 67 76 67 76 67 76 57 3A 80 32 0E 87 57 32 0F 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 2A 01 86 FF 06 FF C2 7F 60 FF 02 00 60 FE 67 1C 06 FE F2 04 60 FE D2 40 74 0E 70 5E 02 A0 F6 FE 04 D2 01 70 27 74 4D 06 FE 28 32 00 32 01 B7 97 71 34 75 3C 06 FF C2 04 74 3C 70 4D 67 64 67 60 67 64 67 64 67 64 67 64 67 64 67 64 57 67 64 67 64 67 64 67 64 67 64 67 64 67 64 67 64 57 3A 80 32 0E 87 57 32 0F 87 57 +led 1 auto on +led 1 start diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py new file mode 100644 index 0000000000..c0122e6584 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-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_snh60a0_320fv2-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py new file mode 100644 index 0000000000..bab96d69dc --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py @@ -0,0 +1,255 @@ +#!/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.shg., "Ethernet0") + :param state: A string, the port link state (either "up" or "down") + """ + return + +### Zion 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) + +### Zion specified ### +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/1-005e/fan1_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan1_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan2_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan2_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan3_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan3_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan4_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan4_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan5_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan5_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan6_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan6_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + + + with open("/sys/bus/i2c/devices/1-005e/psu1_power_good", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu1_present", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu2_power_good", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu2_present", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + f11.write("1") + else: + f11.write("4") + + + with open("/sys/bus/i2c/devices/9-005f/swi_ctrl", "r") as f5: + is_reset_button_push = f5.read() + if str(is_reset_button_push) == "1\n": + is_reset_button_push = 1 + else: + is_reset_button_push = 0 + + with open("/sys/bus/i2c/devices/4-004d/hwmon/hwmon3/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/9-005f/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 1-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/9-005f/sys_locator", "w") as f: + f.write("0") + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/9-005f/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan4_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan5_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/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_snh60a0_320fv2-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py new file mode 100644 index 0000000000..7a3b87f24d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-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_snh60a0_320fv2-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py new file mode 100644 index 0000000000..9e502578f1 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 31 + port_num = 32 + + port_to_eeprom = {} + port_to_i2cbus_mapping = { + 1 : 14, + 2 : 15, + 3 : 16, + 4 : 17, + } + + 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" + + _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 + + 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 + + def __init__(self): + path = self.eeprom_path + for x in range(self.first_port, self.last_port + 1): + index = (x % 8) + i2c_index = (x / 8) + 1 + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + 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 + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.port_reset_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 + + # 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): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + 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 + + index = (port_num % 8) + i2c_index = (port_num / 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() + if reg_value == '1': + return True + + return False + diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf new file mode 100644 index 0000000000..90562c389f --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf @@ -0,0 +1,17 @@ +# libsensors configuration file for snh60a0_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 fan5 "Fan tray 5 front" + label fan6 "Fan tray 6 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" + label fan15 "Fan tray 5 rear" + label fan16 "Fan tray 6 rear" diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini new file mode 100644 index 0000000000..d365e18da7 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 5,6,7,8 Ethernet1/0/1 0 100000 +Ethernet4 9,10,11,12 Ethernet1/0/5 1 100000 +Ethernet8 13,14,15,16 Ethernet1/0/9 2 100000 +Ethernet12 1,2,3,4 Ethernet1/0/13 3 100000 +Ethernet16 21,22,23,24 Ethernet1/0/17 4 100000 +Ethernet20 25,26,27,28 Ethernet1/0/21 5 100000 +Ethernet24 29,30,31,32 Ethernet1/0/25 6 100000 +Ethernet28 17,18,19,20 Ethernet1/0/29 7 100000 +Ethernet32 37,38,39,40 Ethernet1/0/33 8 100000 +Ethernet36 41,42,43,44 Ethernet1/0/37 9 100000 +Ethernet40 45,46,47,48 Ethernet1/0/41 10 100000 +Ethernet44 33,34,35,36 Ethernet1/0/45 11 100000 +Ethernet48 53,54,55,56 Ethernet1/0/49 12 100000 +Ethernet52 57,58,59,60 Ethernet1/0/53 13 100000 +Ethernet56 61,62,63,64 Ethernet1/0/57 14 100000 +Ethernet60 49,50,51,52 Ethernet1/0/61 15 100000 +Ethernet64 69,70,71,72 Ethernet1/0/65 16 100000 +Ethernet68 73,74,75,76 Ethernet1/0/69 17 100000 +Ethernet72 77,78,79,80 Ethernet1/0/73 18 100000 +Ethernet76 65,66,67,68 Ethernet1/0/77 19 100000 +Ethernet80 85,86,87,88 Ethernet1/0/81 20 100000 +Ethernet84 89,90,91,92 Ethernet1/0/85 21 100000 +Ethernet88 93,94,95,96 Ethernet1/0/89 22 100000 +Ethernet92 81,82,83,84 Ethernet1/0/93 23 100000 +Ethernet96 101,102,103,104 Ethernet1/0/97 24 100000 +Ethernet100 105,106,107,108 Ethernet1/0/101 25 100000 +Ethernet104 109,110,111,112 Ethernet1/0/105 26 100000 +Ethernet108 97,98,99,100 Ethernet1/0/109 27 100000 +Ethernet112 117,118,119,120 Ethernet1/0/113 28 100000 +Ethernet116 121,122,123,124 Ethernet1/0/117 29 100000 +Ethernet120 125,126,127,128 Ethernet1/0/121 30 100000 +Ethernet124 113,114,115,116 Ethernet1/0/125 31 100000 +Ethernet128 133,134,135,136 Ethernet1/0/129 32 100000 +Ethernet132 137,138,139,140 Ethernet1/0/133 33 100000 +Ethernet136 141,142,143,144 Ethernet1/0/137 34 100000 +Ethernet140 129,130,131,132 Ethernet1/0/141 35 100000 +Ethernet144 149,150,151,152 Ethernet1/0/145 36 100000 +Ethernet148 153,154,155,156 Ethernet1/0/149 37 100000 +Ethernet152 157,158,159,160 Ethernet1/0/153 38 100000 +Ethernet156 145,146,147,148 Ethernet1/0/157 39 100000 +Ethernet160 165,166,167,168 Ethernet1/0/161 40 100000 +Ethernet164 169,170,171,172 Ethernet1/0/165 41 100000 +Ethernet168 173,174,175,176 Ethernet1/0/169 42 100000 +Ethernet172 161,162,163,164 Ethernet1/0/173 43 100000 +Ethernet176 181,182,183,184 Ethernet1/0/177 44 100000 +Ethernet180 185,186,187,188 Ethernet1/0/181 45 100000 +Ethernet184 189,190,191,192 Ethernet1/0/185 46 100000 +Ethernet188 177,178,179,180 Ethernet1/0/189 47 100000 +Ethernet192 197,198,199,200 Ethernet1/0/193 48 100000 +Ethernet196 201,202,203,204 Ethernet1/0/197 49 100000 +Ethernet200 205,206,207,208 Ethernet1/0/201 50 100000 +Ethernet204 193,194,195,196 Ethernet1/0/205 51 100000 +Ethernet208 213,214,215,216 Ethernet1/0/209 52 100000 +Ethernet212 217,218,219,220 Ethernet1/0/213 53 100000 +Ethernet216 221,222,223,224 Ethernet1/0/217 54 100000 +Ethernet220 209,210,211,212 Ethernet1/0/221 55 100000 +Ethernet224 229,230,231,232 Ethernet1/0/225 56 100000 +Ethernet228 233,234,235,236 Ethernet1/0/229 57 100000 +Ethernet232 237,238,239,240 Ethernet1/0/233 58 100000 +Ethernet236 225,226,227,228 Ethernet1/0/237 59 100000 +Ethernet240 245,246,247,248 Ethernet1/0/241 60 100000 +Ethernet244 249,250,251,252 Ethernet1/0/245 61 100000 +Ethernet248 253,254,255,256 Ethernet1/0/249 62 100000 +Ethernet252 241,242,243,244 Ethernet1/0/253 63 100000 +Ethernet256 257 Ethernet1/0/257 64 10000 +Ethernet260 259 Ethernet1/0/261 65 10000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile new file mode 100644 index 0000000000..04555733c0 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-snh60b0-64x100G.config.bcm diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm new file mode 100644 index 0000000000..60ca5053b9 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm @@ -0,0 +1,535 @@ +# This property file is for GOREME-2U 1x100G mode only. +# GOREME-2U uses Tomahawk2 BCM56970 as its mac. Besides, it is phyless. +# Note: The settings in this file are not verified yet. + +os=unix + +bcm_stat_interval.0=1000000 +bcm_linkscan_interval.0=250000 + +# Tuning MDIO_OUTPUT_DELAY as 0xf based on HW RD suggesstion and DVT result. +mdio_output_delay.0=0xf + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=40960 +l3_mem_entries=40960 + +portmap_66=257:10 +portmap_100=259:10 + +# Falcon core - front port +# FalconCore[0 - 15] must map to logical port[1-16], PIPE-0. +portmap_1=5:100 +portmap_2=9:100 +portmap_3=13:100 +portmap_4=1:100 +portmap_5=21:100 +portmap_6=25:100 +portmap_7=29:100 +portmap_8=17:100 +portmap_9=37:100 +portmap_10=41:100 +portmap_11=45:100 +portmap_12=33:100 +portmap_13=53:100 +portmap_14=57:100 +portmap_15=61:100 +portmap_16=49:100 + +# FalconCore[16 - 31] must map to logical port[34-49], PIPE-1. +portmap_34=69:100 +portmap_35=73:100 +portmap_36=77:100 +portmap_37=65:100 +portmap_38=85:100 +portmap_39=89:100 +portmap_40=93:100 +portmap_41=81:100 +portmap_42=101:100 +portmap_43=105:100 +portmap_44=109:100 +portmap_45=97:100 +portmap_46=117:100 +portmap_47=121:100 +portmap_48=125:100 +portmap_49=113:100 + +# FalconCore[32 - 47] must map to logical port[68-83], PIPE-2. +portmap_68=133:100 +portmap_69=137:100 +portmap_70=141:100 +portmap_71=129:100 +portmap_72=149:100 +portmap_73=153:100 +portmap_74=157:100 +portmap_75=145:100 +portmap_76=165:100 +portmap_77=169:100 +portmap_78=173:100 +portmap_79=161:100 +portmap_80=181:100 +portmap_81=185:100 +portmap_82=189:100 +portmap_83=177:100 + +# FalconCore[48 - 63] must map to logical port[102-117], PIPE-3. +portmap_102=197:100 +portmap_103=201:100 +portmap_104=205:100 +portmap_105=193:100 +portmap_106=213:100 +portmap_107=217:100 +portmap_108=221:100 +portmap_109=209:100 +portmap_110=229:100 +portmap_111=233:100 +portmap_112=237:100 +portmap_113=225:100 +portmap_114=245:100 +portmap_115=249:100 +portmap_116=253:100 +portmap_117=241:100 + +# Configure all front port as CE ports. +pbmp_xport_xe=0x00000000000000000000000000000000003fffd0000ffff40003fffc0001fffe + +# Oversubscription mode +# +# Refers to a switch being configured such that the I/O bandwidth is greater than the +# core bandwidth. +# BCM56970 device supports a maximum I/O bandwidth of 6,400 Gbps when the average packet size +# is greater than 250 bytes. +pbmp_oversubscribe=0x00000000000000000000000000000000003fffc0000ffff00003fffc0001fffe + + + +# core-0~7 +xgxs_rx_lane_map_ce0=0x0213 +xgxs_rx_lane_map_ce1=0x3102 +xgxs_rx_lane_map_ce2=0x1032 +xgxs_rx_lane_map_ce3=0x2103 +xgxs_rx_lane_map_ce4=0x0213 +xgxs_rx_lane_map_ce5=0x2103 +xgxs_rx_lane_map_ce6=0x1230 +xgxs_rx_lane_map_ce7=0x3120 + +# core-8~15 +xgxs_rx_lane_map_ce8=0x0123 +xgxs_rx_lane_map_ce9=0x3102 +xgxs_rx_lane_map_ce10=0x1230 +xgxs_rx_lane_map_ce11=0x0123 +xgxs_rx_lane_map_ce12=0x0123 +xgxs_rx_lane_map_ce13=0X1230 +xgxs_rx_lane_map_ce14=0x1230 +xgxs_rx_lane_map_ce15=0x0123 + +# core-16~23 +xgxs_rx_lane_map_ce16=0x0123 +xgxs_rx_lane_map_ce17=0x1230 +xgxs_rx_lane_map_ce18=0x1230 +xgxs_rx_lane_map_ce19=0x0123 +xgxs_rx_lane_map_ce20=0x0123 +xgxs_rx_lane_map_ce21=0x1230 +xgxs_rx_lane_map_ce22=0x1230 +xgxs_rx_lane_map_ce23=0x0123 + +# core-24~31 +xgxs_rx_lane_map_ce24=0x0123 +xgxs_rx_lane_map_ce25=0x0231 +xgxs_rx_lane_map_ce26=0x2130 +xgxs_rx_lane_map_ce27=0x2103 +xgxs_rx_lane_map_ce28=0x3012 +xgxs_rx_lane_map_ce29=0x3102 +xgxs_rx_lane_map_ce30=0x1032 +xgxs_rx_lane_map_ce31=0x2103 + +# core-32~39 +xgxs_rx_lane_map_ce32=0x3102 +xgxs_rx_lane_map_ce33=0x3102 +xgxs_rx_lane_map_ce34=0x0132 +xgxs_rx_lane_map_ce35=0x3021 +xgxs_rx_lane_map_ce36=0x0213 +xgxs_rx_lane_map_ce37=0x3012 +xgxs_rx_lane_map_ce38=0x2130 +xgxs_rx_lane_map_ce39=0x0123 + +# core-40~47 +xgxs_rx_lane_map_ce40=0x0312 +xgxs_rx_lane_map_ce41=0x0132 +xgxs_rx_lane_map_ce42=0x1230 +xgxs_rx_lane_map_ce43=0x0123 +xgxs_rx_lane_map_ce44=0x0312 +xgxs_rx_lane_map_ce45=0x0132 +xgxs_rx_lane_map_ce46=0x1230 +xgxs_rx_lane_map_ce47=0x0123 + +# core-48~55 +xgxs_rx_lane_map_ce48=0x0123 +xgxs_rx_lane_map_ce49=0x0132 +xgxs_rx_lane_map_ce50=0x1230 +xgxs_rx_lane_map_ce51=0x0123 +xgxs_rx_lane_map_ce52=0x0312 +xgxs_rx_lane_map_ce53=0x0132 +xgxs_rx_lane_map_ce54=0x1230 +xgxs_rx_lane_map_ce55=0x0123 + +# core-56~63 +xgxs_rx_lane_map_ce56=0x0123 +xgxs_rx_lane_map_ce57=0x0312 +xgxs_rx_lane_map_ce58=0x1032 +xgxs_rx_lane_map_ce59=0x2103 +xgxs_rx_lane_map_ce60=0x2103 +xgxs_rx_lane_map_ce61=0x3120 +xgxs_rx_lane_map_ce62=0x1032 +xgxs_rx_lane_map_ce63=0x0213 + +# Remap XGXS tx lanes to desired mapping by hardware provide. +#core-0~7 +xgxs_tx_lane_map_ce0=0x2301 +xgxs_tx_lane_map_ce1=0x2301 +xgxs_tx_lane_map_ce2=0x1302 +xgxs_tx_lane_map_ce3=0x3210 +xgxs_tx_lane_map_ce4=0x2301 +xgxs_tx_lane_map_ce5=0x2301 +xgxs_tx_lane_map_ce6=0x0213 +xgxs_tx_lane_map_ce7=0x3210 + +#core-8~15 +xgxs_tx_lane_map_ce8=0x1230 +xgxs_tx_lane_map_ce9=0x2301 +xgxs_tx_lane_map_ce10=0x0231 +xgxs_tx_lane_map_ce11=0x1230 +xgxs_tx_lane_map_ce12=0x3102 +xgxs_tx_lane_map_ce13=0x2301 +xgxs_tx_lane_map_ce14=0x0231 +xgxs_tx_lane_map_ce15=0x1230 + +#core-16~23 +xgxs_tx_lane_map_ce16=0x3102 +xgxs_tx_lane_map_ce17=0x2301 +xgxs_tx_lane_map_ce18=0x0231 +xgxs_tx_lane_map_ce19=0x1230 +xgxs_tx_lane_map_ce20=0x3102 +xgxs_tx_lane_map_ce21=0x2301 +xgxs_tx_lane_map_ce22=0x0231 +xgxs_tx_lane_map_ce23=0x1230 + +#core-24~31 +xgxs_tx_lane_map_ce24=0x3102 +xgxs_tx_lane_map_ce25=0x2301 +xgxs_tx_lane_map_ce26=0x0321 +xgxs_tx_lane_map_ce27=0x3210 +xgxs_tx_lane_map_ce28=0x1302 +xgxs_tx_lane_map_ce29=0x2031 +xgxs_tx_lane_map_ce30=0x3120 +xgxs_tx_lane_map_ce31=0x3210 + +#core-32~39 +xgxs_tx_lane_map_ce32=0x2310 +xgxs_tx_lane_map_ce33=0x2301 +xgxs_tx_lane_map_ce34=0x1203 +xgxs_tx_lane_map_ce35=0x1032 +xgxs_tx_lane_map_ce36=0x2130 +xgxs_tx_lane_map_ce37=0x2301 +xgxs_tx_lane_map_ce38=0x1302 +xgxs_tx_lane_map_ce39=0x3210 + +#core-40~47 +xgxs_tx_lane_map_ce40=0x3201 +xgxs_tx_lane_map_ce41=0x0231 +xgxs_tx_lane_map_ce42=0x1203 +xgxs_tx_lane_map_ce43=0x1230 +xgxs_tx_lane_map_ce44=0x3201 +xgxs_tx_lane_map_ce45=0x0231 +xgxs_tx_lane_map_ce46=0x1203 +xgxs_tx_lane_map_ce47=0x3210 + +#core-48~55 +xgxs_tx_lane_map_ce48=0x3201 +xgxs_tx_lane_map_ce49=0x0231 +xgxs_tx_lane_map_ce50=0x1203 +xgxs_tx_lane_map_ce51=0x3210 +xgxs_tx_lane_map_ce52=0x3201 +xgxs_tx_lane_map_ce53=0x0231 +xgxs_tx_lane_map_ce54=0x1203 +xgxs_tx_lane_map_ce55=0x3210 + +#core-56~63 +xgxs_tx_lane_map_ce56=0x1203 +xgxs_tx_lane_map_ce57=0x2301 +xgxs_tx_lane_map_ce58=0x0213 +xgxs_tx_lane_map_ce59=0x3210 +xgxs_tx_lane_map_ce60=0x0213 +xgxs_tx_lane_map_ce61=0x3021 +xgxs_tx_lane_map_ce62=0x3210 +xgxs_tx_lane_map_ce63=0x3210 + +serdes_preemphasis_lane0_ce0=0x0c5800 +serdes_preemphasis_lane1_ce0=0x0c5800 +serdes_preemphasis_lane2_ce0=0x0c5800 +serdes_preemphasis_lane3_ce0=0x0c5800 +serdes_preemphasis_lane0_ce1=0x0c5800 +serdes_preemphasis_lane1_ce1=0x0c5800 +serdes_preemphasis_lane2_ce1=0x0c5800 +serdes_preemphasis_lane3_ce1=0x0c5800 +serdes_preemphasis_lane0_ce2=0x0c5800 +serdes_preemphasis_lane1_ce2=0x0c5800 +serdes_preemphasis_lane2_ce2=0x0c5800 +serdes_preemphasis_lane3_ce2=0x0c5800 +serdes_preemphasis_lane0_ce3=0x0c5800 +serdes_preemphasis_lane1_ce3=0x0c5800 +serdes_preemphasis_lane2_ce3=0x0c5800 +serdes_preemphasis_lane3_ce3=0x0c5800 +serdes_preemphasis_lane0_ce4=0x0c5800 +serdes_preemphasis_lane1_ce4=0x0c5800 +serdes_preemphasis_lane2_ce4=0x0c5800 +serdes_preemphasis_lane3_ce4=0x0c5800 +serdes_preemphasis_lane0_ce5=0x0c5800 +serdes_preemphasis_lane1_ce5=0x0c5800 +serdes_preemphasis_lane2_ce5=0x0c5800 +serdes_preemphasis_lane3_ce5=0x0c5800 +serdes_preemphasis_lane0_ce6=0x0c5800 +serdes_preemphasis_lane1_ce6=0x0c5800 +serdes_preemphasis_lane2_ce6=0x0c5800 +serdes_preemphasis_lane3_ce6=0x0c5800 +serdes_preemphasis_lane0_ce7=0x0c5800 +serdes_preemphasis_lane1_ce7=0x0c5800 +serdes_preemphasis_lane2_ce7=0x0c5800 +serdes_preemphasis_lane3_ce7=0x0c5800 +serdes_preemphasis_lane0_ce8=0x0c5800 +serdes_preemphasis_lane1_ce8=0x0c5800 +serdes_preemphasis_lane2_ce8=0x0c5800 +serdes_preemphasis_lane3_ce8=0x0c5800 +serdes_preemphasis_lane0_ce9=0x0c5800 +serdes_preemphasis_lane1_ce9=0x0c5800 +serdes_preemphasis_lane2_ce9=0x0c5800 +serdes_preemphasis_lane3_ce9=0x0c5800 +serdes_preemphasis_lane0_ce10=0x0c5800 +serdes_preemphasis_lane1_ce10=0x0c5800 +serdes_preemphasis_lane2_ce10=0x0c5800 +serdes_preemphasis_lane3_ce10=0x0c5800 +serdes_preemphasis_lane0_ce11=0x0c5800 +serdes_preemphasis_lane1_ce11=0x0c5800 +serdes_preemphasis_lane2_ce11=0x0c5800 +serdes_preemphasis_lane3_ce11=0x0c5800 +serdes_preemphasis_lane0_ce12=0x0c5800 +serdes_preemphasis_lane1_ce12=0x0c5800 +serdes_preemphasis_lane2_ce12=0x0c5800 +serdes_preemphasis_lane3_ce12=0x0c5800 +serdes_preemphasis_lane0_ce13=0x0c5800 +serdes_preemphasis_lane1_ce13=0x0c5800 +serdes_preemphasis_lane2_ce13=0x0c5800 +serdes_preemphasis_lane3_ce13=0x0c5800 +serdes_preemphasis_lane0_ce14=0x0c5800 +serdes_preemphasis_lane1_ce14=0x0c5800 +serdes_preemphasis_lane2_ce14=0x0c5800 +serdes_preemphasis_lane3_ce14=0x0c5800 +serdes_preemphasis_lane0_ce15=0x0c5800 +serdes_preemphasis_lane1_ce15=0x0c5800 +serdes_preemphasis_lane2_ce15=0x0c5800 +serdes_preemphasis_lane3_ce15=0x0c5800 +serdes_preemphasis_lane0_ce16=0x085408 +serdes_preemphasis_lane1_ce16=0x085408 +serdes_preemphasis_lane2_ce16=0x085408 +serdes_preemphasis_lane3_ce16=0x085408 +serdes_preemphasis_lane0_ce17=0x085408 +serdes_preemphasis_lane1_ce17=0x085408 +serdes_preemphasis_lane2_ce17=0x085408 +serdes_preemphasis_lane3_ce17=0x085408 +serdes_preemphasis_lane0_ce18=0x085408 +serdes_preemphasis_lane1_ce18=0x085408 +serdes_preemphasis_lane2_ce18=0x085408 +serdes_preemphasis_lane3_ce18=0x085408 +serdes_preemphasis_lane0_ce19=0x085408 +serdes_preemphasis_lane1_ce19=0x085408 +serdes_preemphasis_lane2_ce19=0x085408 +serdes_preemphasis_lane3_ce19=0x085408 +serdes_preemphasis_lane0_ce20=0x085408 +serdes_preemphasis_lane1_ce20=0x085408 +serdes_preemphasis_lane2_ce20=0x085408 +serdes_preemphasis_lane3_ce20=0x085408 +serdes_preemphasis_lane0_ce21=0x085408 +serdes_preemphasis_lane1_ce21=0x085408 +serdes_preemphasis_lane2_ce21=0x085408 +serdes_preemphasis_lane3_ce21=0x085408 +serdes_preemphasis_lane0_ce22=0x085408 +serdes_preemphasis_lane1_ce22=0x085408 +serdes_preemphasis_lane2_ce22=0x085408 +serdes_preemphasis_lane3_ce22=0x085408 +serdes_preemphasis_lane0_ce23=0x085408 +serdes_preemphasis_lane1_ce23=0x085408 +serdes_preemphasis_lane2_ce23=0x085408 +serdes_preemphasis_lane3_ce23=0x085408 +serdes_preemphasis_lane0_ce24=0x085408 +serdes_preemphasis_lane1_ce24=0x085408 +serdes_preemphasis_lane2_ce24=0x085408 +serdes_preemphasis_lane3_ce24=0x085408 +serdes_preemphasis_lane0_ce25=0x085408 +serdes_preemphasis_lane1_ce25=0x085408 +serdes_preemphasis_lane2_ce25=0x085408 +serdes_preemphasis_lane3_ce25=0x085408 +serdes_preemphasis_lane0_ce26=0x0a500a +serdes_preemphasis_lane1_ce26=0x0a500a +serdes_preemphasis_lane2_ce26=0x0a500a +serdes_preemphasis_lane3_ce26=0x0a500a +serdes_preemphasis_lane0_ce27=0x0a500a +serdes_preemphasis_lane1_ce27=0x0a500a +serdes_preemphasis_lane2_ce27=0x0a500a +serdes_preemphasis_lane3_ce27=0x0a500a +serdes_preemphasis_lane0_ce28=0x0a500a +serdes_preemphasis_lane1_ce28=0x0a500a +serdes_preemphasis_lane2_ce28=0x0a500a +serdes_preemphasis_lane3_ce28=0x0a500a +serdes_preemphasis_lane0_ce29=0x0a500a +serdes_preemphasis_lane1_ce29=0x0a500a +serdes_preemphasis_lane2_ce29=0x0a500a +serdes_preemphasis_lane3_ce29=0x0a500a +serdes_preemphasis_lane0_ce30=0x0a500a +serdes_preemphasis_lane1_ce30=0x0a500a +serdes_preemphasis_lane2_ce30=0x0a500a +serdes_preemphasis_lane3_ce30=0x0a500a +serdes_preemphasis_lane0_ce31=0x0a500a +serdes_preemphasis_lane1_ce31=0x0a500a +serdes_preemphasis_lane2_ce31=0x0a500a +serdes_preemphasis_lane3_ce31=0x0a500a +serdes_preemphasis_lane0_ce32=0x0a500a +serdes_preemphasis_lane1_ce32=0x0a500a +serdes_preemphasis_lane2_ce32=0x0a500a +serdes_preemphasis_lane3_ce32=0x0a500a +serdes_preemphasis_lane0_ce33=0x0a500a +serdes_preemphasis_lane1_ce33=0x0a500a +serdes_preemphasis_lane2_ce33=0x0a500a +serdes_preemphasis_lane3_ce33=0x0a500a +serdes_preemphasis_lane0_ce34=0x0a500a +serdes_preemphasis_lane1_ce34=0x0a500a +serdes_preemphasis_lane2_ce34=0x0a500a +serdes_preemphasis_lane3_ce34=0x0a500a +serdes_preemphasis_lane0_ce35=0x0a500a +serdes_preemphasis_lane1_ce35=0x0a500a +serdes_preemphasis_lane2_ce35=0x0a500a +serdes_preemphasis_lane3_ce35=0x0a500a +serdes_preemphasis_lane0_ce36=0x0a500a +serdes_preemphasis_lane1_ce36=0x0a500a +serdes_preemphasis_lane2_ce36=0x0a500a +serdes_preemphasis_lane3_ce36=0x0a500a +serdes_preemphasis_lane0_ce37=0x0a500a +serdes_preemphasis_lane1_ce37=0x0a500a +serdes_preemphasis_lane2_ce37=0x0a500a +serdes_preemphasis_lane3_ce37=0x0a500a +serdes_preemphasis_lane0_ce38=0x0a500a +serdes_preemphasis_lane1_ce38=0x0a500a +serdes_preemphasis_lane2_ce38=0x0a500a +serdes_preemphasis_lane3_ce38=0x0a500a +serdes_preemphasis_lane0_ce39=0x0a500a +serdes_preemphasis_lane1_ce39=0x0a500a +serdes_preemphasis_lane2_ce39=0x0a500a +serdes_preemphasis_lane3_ce39=0x0a500a +serdes_preemphasis_lane0_ce40=0x085408 +serdes_preemphasis_lane1_ce40=0x085408 +serdes_preemphasis_lane2_ce40=0x085408 +serdes_preemphasis_lane3_ce40=0x085408 +serdes_preemphasis_lane0_ce41=0x085408 +serdes_preemphasis_lane1_ce41=0x085408 +serdes_preemphasis_lane2_ce41=0x085408 +serdes_preemphasis_lane3_ce41=0x085408 +serdes_preemphasis_lane0_ce42=0x085408 +serdes_preemphasis_lane1_ce42=0x085408 +serdes_preemphasis_lane2_ce42=0x085408 +serdes_preemphasis_lane3_ce42=0x085408 +serdes_preemphasis_lane0_ce43=0x085408 +serdes_preemphasis_lane1_ce43=0x085408 +serdes_preemphasis_lane2_ce43=0x085408 +serdes_preemphasis_lane3_ce43=0x085408 +serdes_preemphasis_lane0_ce44=0x085408 +serdes_preemphasis_lane1_ce44=0x085408 +serdes_preemphasis_lane2_ce44=0x085408 +serdes_preemphasis_lane3_ce44=0x085408 +serdes_preemphasis_lane0_ce45=0x085408 +serdes_preemphasis_lane1_ce45=0x085408 +serdes_preemphasis_lane2_ce45=0x085408 +serdes_preemphasis_lane3_ce45=0x085408 +serdes_preemphasis_lane0_ce46=0x085408 +serdes_preemphasis_lane1_ce46=0x085408 +serdes_preemphasis_lane2_ce46=0x085408 +serdes_preemphasis_lane3_ce46=0x085408 +serdes_preemphasis_lane0_ce47=0x085408 +serdes_preemphasis_lane1_ce47=0x085408 +serdes_preemphasis_lane2_ce47=0x085408 +serdes_preemphasis_lane3_ce47=0x085408 +serdes_preemphasis_lane0_ce48=0x085408 +serdes_preemphasis_lane1_ce48=0x085408 +serdes_preemphasis_lane2_ce48=0x085408 +serdes_preemphasis_lane3_ce48=0x085408 +serdes_preemphasis_lane0_ce49=0x085408 +serdes_preemphasis_lane1_ce49=0x085408 +serdes_preemphasis_lane2_ce49=0x085408 +serdes_preemphasis_lane3_ce49=0x085408 +serdes_preemphasis_lane0_ce50=0x085408 +serdes_preemphasis_lane1_ce50=0x085408 +serdes_preemphasis_lane2_ce50=0x085408 +serdes_preemphasis_lane3_ce50=0x085408 +serdes_preemphasis_lane0_ce51=0x085408 +serdes_preemphasis_lane1_ce51=0x085408 +serdes_preemphasis_lane2_ce51=0x085408 +serdes_preemphasis_lane3_ce51=0x085408 +serdes_preemphasis_lane0_ce52=0x085408 +serdes_preemphasis_lane1_ce52=0x085408 +serdes_preemphasis_lane2_ce52=0x085408 +serdes_preemphasis_lane3_ce52=0x085408 +serdes_preemphasis_lane0_ce53=0x085408 +serdes_preemphasis_lane1_ce53=0x085408 +serdes_preemphasis_lane2_ce53=0x085408 +serdes_preemphasis_lane3_ce53=0x085408 +serdes_preemphasis_lane0_ce54=0x085408 +serdes_preemphasis_lane1_ce54=0x085408 +serdes_preemphasis_lane2_ce54=0x085408 +serdes_preemphasis_lane3_ce54=0x085408 +serdes_preemphasis_lane0_ce55=0x085408 +serdes_preemphasis_lane1_ce55=0x085408 +serdes_preemphasis_lane2_ce55=0x085408 +serdes_preemphasis_lane3_ce55=0x085408 +serdes_preemphasis_lane0_ce56=0x0c5800 +serdes_preemphasis_lane1_ce56=0x0c5800 +serdes_preemphasis_lane2_ce56=0x0c5800 +serdes_preemphasis_lane3_ce56=0x0c5800 +serdes_preemphasis_lane0_ce57=0x0c5800 +serdes_preemphasis_lane1_ce57=0x0c5800 +serdes_preemphasis_lane2_ce57=0x0c5800 +serdes_preemphasis_lane3_ce57=0x0c5800 +serdes_preemphasis_lane0_ce58=0x0c5800 +serdes_preemphasis_lane1_ce58=0x0c5800 +serdes_preemphasis_lane2_ce58=0x0c5800 +serdes_preemphasis_lane3_ce58=0x0c5800 +serdes_preemphasis_lane0_ce59=0x0c5800 +serdes_preemphasis_lane1_ce59=0x0c5800 +serdes_preemphasis_lane2_ce59=0x0c5800 +serdes_preemphasis_lane3_ce59=0x0c5800 +serdes_preemphasis_lane0_ce60=0x0c5800 +serdes_preemphasis_lane1_ce60=0x0c5800 +serdes_preemphasis_lane2_ce60=0x0c5800 +serdes_preemphasis_lane3_ce60=0x0c5800 +serdes_preemphasis_lane0_ce61=0x0c5800 +serdes_preemphasis_lane1_ce61=0x0c5800 +serdes_preemphasis_lane2_ce61=0x0c5800 +serdes_preemphasis_lane3_ce61=0x0c5800 +serdes_preemphasis_lane0_ce62=0x0c5800 +serdes_preemphasis_lane1_ce62=0x0c5800 +serdes_preemphasis_lane2_ce62=0x0c5800 +serdes_preemphasis_lane3_ce62=0x0c5800 +serdes_preemphasis_lane0_ce63=0x0c5800 +serdes_preemphasis_lane1_ce63=0x0c5800 +serdes_preemphasis_lane2_ce63=0x0c5800 +serdes_preemphasis_lane3_ce63=0x0c5800 + +# # The TX and RX polarity flip variable. +# # It is affected by lane swapping, we used to debug for TE QSFP28 transceiver. +# # + +# # Used to select the reference clock for Timestamping and BroadSync/10Mhz PLL value. +# # 25MHz LVPECL to BS_PLL0_REFCLK, BS_PLL1_REFCLK, and TS_PLL_REFCLK +# ptp_ts_pll_fref=25000000 +# ptp_bs_fref=25000000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku new file mode 100755 index 0000000000..e262bc70c3 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNH60B0-640F t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol new file mode 100644 index 0000000000..9d443b3d3e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-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/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 +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_snh60b0_640f-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf new file mode 100644 index 0000000000..925a32fc0c --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc new file mode 100644 index 0000000000..3fa944a9fa --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for alphanetworks snh60b0-640f + +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=0x3e REMAP_PORT_2=0x3d REMAP_PORT_3=0x3c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3b REMAP_PORT_5=0x3a REMAP_PORT_6=0x39 REMAP_PORT_7=0x38 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x37 REMAP_PORT_9=0x36 REMAP_PORT_10=0x35 REMAP_PORT_11=0x34 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x33 REMAP_PORT_13=0x32 REMAP_PORT_14=0x31 REMAP_PORT_15=0x30 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x2f REMAP_PORT_17=0x2e REMAP_PORT_18=0x2d REMAP_PORT_19=0x2c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x2b REMAP_PORT_21=0x2a REMAP_PORT_22=0x29 REMAP_PORT_23=0x28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x27 REMAP_PORT_25=0x26 REMAP_PORT_26=0x25 REMAP_PORT_27=0x24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x23 REMAP_PORT_29=0x22 REMAP_PORT_30=0x21 REMAP_PORT_31=0x20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x1f REMAP_PORT_33=0x1e REMAP_PORT_34=0x1d REMAP_PORT_35=0x1c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x1b REMAP_PORT_37=0x1a REMAP_PORT_38=0x19 REMAP_PORT_39=0x18 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x17 REMAP_PORT_41=0x16 REMAP_PORT_42=0x15 REMAP_PORT_43=0x14 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x13 REMAP_PORT_45=0x12 REMAP_PORT_46=0x11 REMAP_PORT_47=0x10 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0xf REMAP_PORT_49=0xe REMAP_PORT_50=0xd REMAP_PORT_51=0xc +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0xb REMAP_PORT_53=0xa REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0xb REMAP_PORT_9=0xa REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0xf REMAP_PORT_13=0xe REMAP_PORT_14=0xd REMAP_PORT_15=0xc +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x13 REMAP_PORT_17=0x12 REMAP_PORT_18=0x11 REMAP_PORT_19=0x10 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x17 REMAP_PORT_21=0x16 REMAP_PORT_22=0x15 REMAP_PORT_23=0x14 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x1b REMAP_PORT_25=0x1a REMAP_PORT_26=0x19 REMAP_PORT_27=0x18 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x1f REMAP_PORT_29=0x1e REMAP_PORT_30=0x1d REMAP_PORT_31=0x1c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x23 REMAP_PORT_33=0x22 REMAP_PORT_34=0x21 REMAP_PORT_35=0x20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x27 REMAP_PORT_37=0x26 REMAP_PORT_38=0x25 REMAP_PORT_39=0x24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x2b REMAP_PORT_41=0x2a REMAP_PORT_42=0x29 REMAP_PORT_43=0x28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x2f REMAP_PORT_45=0x2e REMAP_PORT_46=0x2d REMAP_PORT_47=0x2c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x33 REMAP_PORT_49=0x32 REMAP_PORT_50=0x31 REMAP_PORT_51=0x30 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x37 REMAP_PORT_53=0x36 REMAP_PORT_54=0x35 REMAP_PORT_55=0x34 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3b REMAP_PORT_57=0x3a REMAP_PORT_58=0x39 REMAP_PORT_59=0x38 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3e REMAP_PORT_62=0x3d REMAP_PORT_63=0x3c + +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=0x3e REMAP_PORT_2=0x3d REMAP_PORT_3=0x3c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3b REMAP_PORT_5=0x3a REMAP_PORT_6=0x39 REMAP_PORT_7=0x38 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x37 REMAP_PORT_9=0x36 REMAP_PORT_10=0x35 REMAP_PORT_11=0x34 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x33 REMAP_PORT_13=0x32 REMAP_PORT_14=0x31 REMAP_PORT_15=0x30 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x2f REMAP_PORT_17=0x2e REMAP_PORT_18=0x2d REMAP_PORT_19=0x2c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x2b REMAP_PORT_21=0x2a REMAP_PORT_22=0x29 REMAP_PORT_23=0x28 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x27 REMAP_PORT_25=0x26 REMAP_PORT_26=0x25 REMAP_PORT_27=0x24 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x23 REMAP_PORT_29=0x22 REMAP_PORT_30=0x21 REMAP_PORT_31=0x20 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x1f REMAP_PORT_33=0x1e REMAP_PORT_34=0x1d REMAP_PORT_35=0x1c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x1b REMAP_PORT_37=0x1a REMAP_PORT_38=0x19 REMAP_PORT_39=0x18 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x17 REMAP_PORT_41=0x16 REMAP_PORT_42=0x15 REMAP_PORT_43=0x14 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x13 REMAP_PORT_45=0x12 REMAP_PORT_46=0x11 REMAP_PORT_47=0x10 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0xf REMAP_PORT_49=0xe REMAP_PORT_50=0xd REMAP_PORT_51=0xc +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0xb REMAP_PORT_53=0xa REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0xb REMAP_PORT_9=0xa REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0xf REMAP_PORT_13=0xe REMAP_PORT_14=0xd REMAP_PORT_15=0xc +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x13 REMAP_PORT_17=0x12 REMAP_PORT_18=0x11 REMAP_PORT_19=0x10 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x17 REMAP_PORT_21=0x16 REMAP_PORT_22=0x15 REMAP_PORT_23=0x14 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x1b REMAP_PORT_25=0x1a REMAP_PORT_26=0x19 REMAP_PORT_27=0x18 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x1f REMAP_PORT_29=0x1e REMAP_PORT_30=0x1d REMAP_PORT_31=0x1c +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x23 REMAP_PORT_33=0x22 REMAP_PORT_34=0x21 REMAP_PORT_35=0x20 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x27 REMAP_PORT_37=0x26 REMAP_PORT_38=0x25 REMAP_PORT_39=0x24 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x2b REMAP_PORT_41=0x2a REMAP_PORT_42=0x29 REMAP_PORT_43=0x28 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x2f REMAP_PORT_45=0x2e REMAP_PORT_46=0x2d REMAP_PORT_47=0x2c +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x33 REMAP_PORT_49=0x32 REMAP_PORT_50=0x31 REMAP_PORT_51=0x30 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x37 REMAP_PORT_53=0x36 REMAP_PORT_54=0x35 REMAP_PORT_55=0x34 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3b REMAP_PORT_57=0x3a REMAP_PORT_58=0x39 REMAP_PORT_59=0x38 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3e REMAP_PORT_62=0x3d REMAP_PORT_63=0x3c + +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=1 REMAP_PORT_2=0x3f REMAP_PORT_3=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3f REMAP_PORT_5=0x3f REMAP_PORT_6=0x3f REMAP_PORT_7=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x3f REMAP_PORT_9=0x3f REMAP_PORT_10=0x3f REMAP_PORT_11=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x3f REMAP_PORT_13=0x3f REMAP_PORT_14=0x3f REMAP_PORT_15=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x3f REMAP_PORT_17=0x3f REMAP_PORT_18=0x3f REMAP_PORT_19=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x3f REMAP_PORT_21=0x3f REMAP_PORT_22=0x3f REMAP_PORT_23=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x3f REMAP_PORT_25=0x3f REMAP_PORT_26=0x3f REMAP_PORT_27=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x3f REMAP_PORT_29=0x3f REMAP_PORT_30=0x3f REMAP_PORT_31=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x3f REMAP_PORT_33=0x3f REMAP_PORT_34=0x3f REMAP_PORT_35=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x3f REMAP_PORT_37=0x3f REMAP_PORT_38=0x3f REMAP_PORT_39=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x3f REMAP_PORT_41=0x3f REMAP_PORT_42=0x3f REMAP_PORT_43=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x3f REMAP_PORT_45=0x3f REMAP_PORT_46=0x3f REMAP_PORT_47=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x3f REMAP_PORT_49=0x3f REMAP_PORT_50=0x3f REMAP_PORT_51=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x3f REMAP_PORT_53=0x3f REMAP_PORT_54=0x3f REMAP_PORT_55=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3f REMAP_PORT_57=0x3f REMAP_PORT_58=0x3f REMAP_PORT_59=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3f REMAP_PORT_62=0x3f REMAP_PORT_63=0x3f + +led 0 stop +led 0 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 3 auto on +led 3 start + +led 4 stop +led 4 prog 86 FF 06 FF C2 7F 60 FF 02 02 60 FE 67 1A 06 FE E2 01 60 FE D2 00 74 0C 77 6A 02 9F F6 FE 04 D2 01 70 25 74 51 06 FE 90 28 32 03 32 04 97 75 64 97 71 58 75 5E 06 FE 90 28 32 00 32 01 B7 97 71 43 75 4B 06 FF C2 10 70 4E 74 4B 67 6C 57 67 70 57 67 70 67 70 67 70 57 67 6C 67 70 77 35 67 70 67 6C 77 35 67 70 67 70 77 35 3A 06 32 0E 87 57 32 0F 87 57 +led 4 auto on +led 4 start diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py new file mode 100644 index 0000000000..c0122e6584 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-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_snh60b0_640f-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py new file mode 100644 index 0000000000..457b1d750b --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py @@ -0,0 +1,217 @@ +#!/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/8-005f/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/8-005f/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/8-005f/swi_ctrl", "r") as f5: + is_reset_button_push = f5.read() + if str(is_reset_button_push) == "1\n": + is_reset_button_push = 1 + else: + is_reset_button_push = 0 + + 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/8-005f/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/8-005f/sys_locator", "w") as f: + f.write("0") + with open("/sys/bus/i2c/devices/8-005f/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/8-005f/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan4_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_snh60b0_640f-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py new file mode 100644 index 0000000000..7a3b87f24d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-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_snh60b0_640f-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py new file mode 100644 index 0000000000..cc3cd4e861 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 65 + port_num = 63 + + port_to_eeprom = {} + port_to_i2cbus_mapping = { + 1 : 13, + 2 : 14, + 3 : 15, + 4 : 16, + 5 : 23, + } + + 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" + + _qsfp_ports = range(first_port, port_num) + + @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 + + 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 + + def __init__(self): + for x in range(self.first_port, self.last_port + 1): + cpld_index = (x / 16) + 1 + index = (x % 16) + 1 + if cpld_index == 5: + path = self.eeprom_path_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 / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + path = self.port_reset_path_1 + 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: + if cpld_index < 5: + 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): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + 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 / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + path = self.present_path_1 + 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: + if cpld_index < 5: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf new file mode 100644 index 0000000000..0650d9da65 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file for snh60b0_640f +# ------------------------------------------------ + +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 29b0f20ef0..8f56a6cf50 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -30,6 +30,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(DELTA_AG5648_PLATFORM_MODULE) \ $(DELTA_ET6248BRB_PLATFORM_MODULE) \ $(QUANTA_IX1B_32X_PLATFORM_MODULE) \ - $(MITAC_LY1200_32X_PLATFORM_MODULE) + $(MITAC_LY1200_32X_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/broadcom/platform-modules-alphanetworks.mk b/platform/broadcom/platform-modules-alphanetworks.mk new file mode 100644 index 0000000000..425656e066 --- /dev/null +++ b/platform/broadcom/platform-modules-alphanetworks.mk @@ -0,0 +1,21 @@ +# Alphanetworks Platform modules + +ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION = 1.0 +ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION = 1.0 + +export ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION +export ALPHANETWORKS_SNH60B0_640F_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 +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snh60a0_320fv2-r0 +SONIC_DPKG_DEBS += $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) + +ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60b0-640f_$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION)_amd64.deb +$(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))) + +SONIC_STRETCH_DEBS += $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) + + diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk index c7fa0f7aa8..e0f07fec86 100755 --- a/platform/broadcom/rules.mk +++ b/platform/broadcom/rules.mk @@ -5,6 +5,7 @@ include $(PLATFORM_PATH)/platform-modules-dell.mk include $(PLATFORM_PATH)/platform-modules-arista.mk include $(PLATFORM_PATH)/platform-modules-ingrasys.mk include $(PLATFORM_PATH)/platform-modules-accton.mk +include $(PLATFORM_PATH)/platform-modules-alphanetworks.mk include $(PLATFORM_PATH)/platform-modules-inventec.mk include $(PLATFORM_PATH)/platform-modules-cel.mk include $(PLATFORM_PATH)/platform-modules-delta.mk diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore b/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore new file mode 100644 index 0000000000..7f287d5382 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/README.md b/platform/broadcom/sonic-platform-modules-alphanetworks/README.md new file mode 100644 index 0000000000..a0c7538301 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/README.md @@ -0,0 +1 @@ +platform drivers of Alphanetworks products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog new file mode 100644 index 0000000000..2742b7c6a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog @@ -0,0 +1,6 @@ +sonic-alphanetworks-platform-modules (1.0) unstable; urgency=low + + * Add support for SNH60A0-320FV2 and SNH60B0_640F. + + -- Alphanetworks Tue, 19 Dec 2017 09:35:58 +0800 + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control new file mode 100644 index 0000000000..075e86a008 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control @@ -0,0 +1,17 @@ +Source: sonic-alphanetworks-platform-modules +Section: main +Priority: extra +Maintainer: Alphanetworks , Alphanetworks +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-alphanetworks-snh60a0-320fv2 +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-alphanetworks-snh60b0-640f +Architecture: amd64 +Depends: linux-image-4.9.0-7-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules new file mode 100644 index 0000000000..0d1a588db6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +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_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # 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; \ + 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/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/classes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile new file mode 100644 index 0000000000..f9477910d3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/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:=alphanetworks_snh60a0-320fv2_sfp.o snh60a0_system_cpld.o snh60a0_power_cpld.o snh60a0_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/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c new file mode 100644 index 0000000000..af47c6521a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c @@ -0,0 +1,1669 @@ +/* + * SFP driver for alphanetworks snh60a0-320fv2 sfp + * + * Copyright (C) 2018 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 "snh60a0_320fv2_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __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_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 + +#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 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_cpld_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 +}; + +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 }, +{} +}; +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_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 */ + + 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, + PORT1_RX_LOS1, + PORT2_RX_LOS1, + PORT3_RX_LOS1, + PORT4_RX_LOS1, + PORT5_RX_LOS1, + PORT6_RX_LOS1, + PORT7_RX_LOS1, + PORT8_RX_LOS1, + PORT1_RX_LOS2, + PORT2_RX_LOS2, + PORT3_RX_LOS2, + PORT4_RX_LOS2, + PORT5_RX_LOS2, + PORT6_RX_LOS2, + PORT7_RX_LOS2, + PORT8_RX_LOS2, + PORT1_RX_LOS3, + PORT2_RX_LOS3, + PORT3_RX_LOS3, + PORT4_RX_LOS3, + PORT5_RX_LOS3, + PORT6_RX_LOS3, + PORT7_RX_LOS3, + PORT8_RX_LOS3, + PORT1_RX_LOS4, + PORT2_RX_LOS4, + PORT3_RX_LOS4, + PORT4_RX_LOS4, + PORT5_RX_LOS4, + PORT6_RX_LOS4, + PORT7_RX_LOS4, + PORT8_RX_LOS4, + PORT1_RX_LOS_ALL, + 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_MAX +}; + +enum sfp_sysfs_tx_disable_attributes { + PORT1_TX_DISABLE = PORT_RX_LOS_MAX, + PORT2_TX_DISABLE, + PORT3_TX_DISABLE, + PORT4_TX_DISABLE, + PORT5_TX_DISABLE, + PORT6_TX_DISABLE, + PORT7_TX_DISABLE, + PORT8_TX_DISABLE, + PORT1_TX_DISABLE1, + PORT2_TX_DISABLE1, + PORT3_TX_DISABLE1, + PORT4_TX_DISABLE1, + PORT5_TX_DISABLE1, + PORT6_TX_DISABLE1, + PORT7_TX_DISABLE1, + PORT8_TX_DISABLE1, + PORT1_TX_DISABLE2, + PORT2_TX_DISABLE2, + PORT3_TX_DISABLE2, + PORT4_TX_DISABLE2, + PORT5_TX_DISABLE2, + PORT6_TX_DISABLE2, + PORT7_TX_DISABLE2, + PORT8_TX_DISABLE2, + PORT1_TX_DISABLE3, + PORT2_TX_DISABLE3, + PORT3_TX_DISABLE3, + PORT4_TX_DISABLE3, + PORT5_TX_DISABLE3, + PORT6_TX_DISABLE3, + PORT7_TX_DISABLE3, + PORT8_TX_DISABLE3, + PORT1_TX_DISABLE4, + PORT2_TX_DISABLE4, + PORT3_TX_DISABLE4, + PORT4_TX_DISABLE4, + PORT5_TX_DISABLE4, + PORT6_TX_DISABLE4, + PORT7_TX_DISABLE4, + PORT8_TX_DISABLE4, + PORT1_TX_DISABLE_ALL, + 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_MAX +}; + +enum sfp_sysfs_tx_fault_attributes { + PORT1_TX_FAULT = PORT_TX_DISABLE_MAX, + PORT2_TX_FAULT, + PORT3_TX_FAULT, + PORT4_TX_FAULT, + PORT5_TX_FAULT, + PORT6_TX_FAULT, + PORT7_TX_FAULT, + PORT8_TX_FAULT, + PORT1_TX_FAULT1, + PORT2_TX_FAULT1, + PORT3_TX_FAULT1, + PORT4_TX_FAULT1, + PORT5_TX_FAULT1, + PORT6_TX_FAULT1, + PORT7_TX_FAULT1, + PORT8_TX_FAULT1, + PORT1_TX_FAULT2, + PORT2_TX_FAULT2, + PORT3_TX_FAULT2, + PORT4_TX_FAULT2, + PORT5_TX_FAULT2, + PORT6_TX_FAULT2, + PORT7_TX_FAULT2, + PORT8_TX_FAULT2, + PORT1_TX_FAULT3, + PORT2_TX_FAULT3, + PORT3_TX_FAULT3, + PORT4_TX_FAULT3, + PORT5_TX_FAULT3, + PORT6_TX_FAULT3, + PORT7_TX_FAULT3, + PORT8_TX_FAULT3, + PORT1_TX_FAULT4, + PORT2_TX_FAULT4, + PORT3_TX_FAULT4, + PORT4_TX_FAULT4, + PORT5_TX_FAULT4, + PORT6_TX_FAULT4, + PORT7_TX_FAULT4, + PORT8_TX_FAULT4, + PORT_TX_FAULT_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 +}; + +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_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x05}; + + 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(0x5f) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); + data->present |= (u64)status << (i*8); + } + + 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_QSFP_PLUS; + 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[] = {0x7}; + + 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(0x60) reg(0x%x) err %d", 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))? 0 : 1; + + 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 = 0x07; + + 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 == 0) { + data->port_reset |= BIT_INDEX(attr->index); + } + else { + data->port_reset &= ~BIT_INDEX(attr->index); + } + + alpha_i2c_cpld_write(0x5f, 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 <= PORT8_TX_FAULT4)){ + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - PORT1_TX_FAULT1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE1) && (attr->index <= PORT8_TX_DISABLE4)){ + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - PORT1_TX_DISABLE1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index <= PORT8_TX_DISABLE_ALL)){ + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + } + if ((attr->index >= PORT1_RX_LOS1) && (attr->index <= PORT8_RX_LOS4)){ + 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 <= PORT8_TX_DISABLE_ALL)){ + 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 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 <= PORT8_TX_FAULT)){ + index = 0; + } + else if ((attr->index >= PORT1_TX_DISABLE) && (attr->index <= PORT8_TX_DISABLE)){ + index = 1; + } + if ((attr->index >= PORT1_RX_LOS) && (attr->index <= PORT8_RX_LOS)){ + index = 2; + } + + 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 status, result, offset = 0xb; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = 14; + else if(strcmp(client->name, "sfpcpld9") == 0) + i2c_index = 15; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = 16; + else if(strcmp(client->name, "sfpcpld25") == 0) + i2c_index = 17; + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Set module select register */ + result = i2c_smbus_write_byte_data(client, offset, BIT_INDEX(attr->index)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data faill(%d)", result); + } + + /* 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 */ + result = i2c_smbus_write_byte_data(client, offset, 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data faill(%d)", 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_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) + +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_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; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + if (client->addr == SFP_CPLD_I2C_ADDR){ + /* Register sysfs hooks */ + 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; + + if ((client->addr != SFP_EEPROM_A0_I2C_ADDR) && (client->addr != SFP_CPLD_I2C_ADDR)){ + 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) + 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) + 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) + 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 snh60a0-320fv2 driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c new file mode 100644 index 0000000000..d8e246ec2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for alphanetworks_snh60a0_320fv2 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 alphanetworks_snh60a0_320fv2_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 *alphanetworks_snh60a0_320fv2_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_onie_group = { + .attrs = alphanetworks_snh60a0_320fv2_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, &alphanetworks_snh60a0_320fv2_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, &alphanetworks_snh60a0_320fv2_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snh60a0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60a0_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/snh60a0-320fv2/modules/snh60a0_power_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c new file mode 100644 index 0000000000..c9a9104d26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c @@ -0,0 +1,507 @@ +/* + * A hwmon driver for the alphanetworks_snh60a0_320fv2_power_cpld + * + * 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 DRIVER_NAME "snh60a0_power_cpld" +#define PSU1_STATUS_REG 0x3 +#define PSU2_STATUS_REG 0x4 +#define FAN_PWM_REG 0x23 + +#define PSU_PRESENT_BIT 0x4 +#define PSU_POWER_BIT 0x2 +#define FAN_PRESENT_BIT 0x2 + + +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 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 alphanetworks_snh60a0_320fv2_power_cpld */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct alphanetworks_snh60a0_320fv2_pwr_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_psu_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + FAN1_PRESENT=0x10, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FRONT_SPEED_RPM, + 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, +}; + +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 struct attribute *alphanetworks_snh60a0_320fv2_psu_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, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_psu_group = { + .attrs = alphanetworks_snh60a0_320fv2_psu_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, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 1 : 0 ); + 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, "cpld(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 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 alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct alphanetworks_snh60a0_320fv2_pwr_cpld_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_snh60a0_320fv2_pwr_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_psu_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_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_cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + struct alphanetworks_snh60a0_320fv2_pwr_cpld_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_psu_group); + alpha_i2c_cpld_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_read); + +int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_write); + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + +static struct dmi_system_id alphanetworks_snh60a0_320fv2_dmi_table[] = { + { + .ident = "Alpha Zion", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "Zion"), + }, + } +}; + +int platform_alphanetworks_snh60a0_320fv2(void) +{ + return dmi_check_system(alphanetworks_snh60a0_320fv2_dmi_table); +} +EXPORT_SYMBOL(platform_alphanetworks_snh60a0_320fv2); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c new file mode 100644 index 0000000000..13c302b356 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c @@ -0,0 +1,380 @@ +/* + * A hwmon driver for the alphanetworks_snh60a0_320fv2_system_cpld + * + * 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 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 SWI_CTRL_REG 0x4 + +#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 +#define REST_BUTTON_BITS 0x0 + + +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 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(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_system_cpld */ +static const unsigned short normal_i2c[] = { 0x5F, I2C_CLIENT_END }; + + +enum sysfs_sys_attributes { + SYS_LOCATOR, + SYS_PWR, + SYS_STATUS, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + FAN5_LED, + FAN6_LED, + SYS_REST1, + SWI_CTRL, +}; + +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +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_REST1); +static SENSOR_DEVICE_ATTR(swi_ctrl, (0660), sys_led_read, NULL, SWI_CTRL); + +static struct attribute *alphanetworks_snh60a0_320fv2_sys_attributes[] = { + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_sys_status.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_swi_ctrl.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_sys_group = { + .attrs = alphanetworks_snh60a0_320fv2_sys_attributes, +}; + + +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 SYS_STATUS: + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + command = SYS_RESET1_REG; + break; + case SWI_CTRL: + command = SWI_CTRL_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(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) >> 1; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 4; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + res = (val & FAN135_LED_BITS) >> 0; + break; + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + res = (val & FAN246_LED_BITS) >> 3; + break; + case SYS_REST1: + res = val; + break; + case SWI_CTRL: + res = (val & REST_BUTTON_BITS) >> 0; + 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: + if(write < 0 || write > 2) + return -EINVAL; + case SYS_PWR: + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS_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 = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + if (write < 0 || write > 15) + return -EINVAL; + command = SYS_RESET1_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "cpld(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 << 1; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 4; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + read &= ~FAN135_LED_BITS; + read |= write << 0; + break; + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + read &= ~FAN246_LED_BITS; + read |= write << 3; + break; + case SYS_REST1: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + 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 alpha_i2c_cpld_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, &alphanetworks_snh60a0_320fv2_sys_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 alpha_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_sys_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { "snh60a0_system_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60a0_system_cpld", + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_system_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service new file mode 100644 index 0000000000..564a8dcdb7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNH60A0-320F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snh60a0_util.py install +ExecStop=/usr/local/bin/alphanetworks_snh60a0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py new file mode 100644 index 0000000000..94435eef3c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snh60a0_320fv2', + version='1.0', + description='Module to initialize Alphanetworks SNH60A0-320FV2 platforms', + + packages=['snh60a0_320fv2'], + package_dir={'snh60a0_320fv2': 'snh60a0-320fv2/classes'}, +) + 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 new file mode 100755 index 0000000000..870267e31c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py @@ -0,0 +1,399 @@ +#!/usr/bin/env python +# +# 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 +# +# 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 = 'snh60a0-320fv2' +device_path = "x86_64-alphanetworks_snh60a0_320fv2-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + + +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 alphanetworks", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe snh60a0_power_cpld' , +'modprobe snh60a0_system_cpld' , +'modprobe snh60a0_onie_eeprom' , +'modprobe alphanetworks_snh60a0_320fv2_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 = [14,15,16,17] +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/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 pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60a0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60a0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60a0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/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-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 pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60a0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60a0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60a0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/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 + else: + order = 0 + + if not device_exist(): + #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 + + 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 + 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/9-005f/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, 32): + index = i / 8 + port = i % 8 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x5f > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output = log_os_system("i2cdetect -l | grep I801 | grep i2c-0", 0) + + if not output: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0, 32): + index = i / 8 + port = i % 8 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x5f > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + 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/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a 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" + 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() diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/classes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile new file mode 100644 index 0000000000..ec14f1229d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/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:=alphanetworks_snh60b0-640f_sfp.o snh60b0-640f_system_cpld.o snh60b0-640f_power_cpld.o snh60b0-640f_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/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c new file mode 100644 index 0000000000..8985790cce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c @@ -0,0 +1,2076 @@ +/* + * SFP driver for alphanetworks snh60b0-640f sfp + * + * Copyright (C) 2018 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 "snh60b0_640f_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 64 +#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_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 +#define SFP_PCA9506_I2C_ADDR 0x20 + + +#define SFPPLUS_1_PORT_NUMBER 64 +#define SFPPLUS_2_PORT_NUMBER 65 + +#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 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_cpld_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, SFP_PCA9506_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, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, +sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, +sfp49, sfp50, sfp51, sfp52, sfp53, sfp54, sfp55, sfp56, +sfp57, sfp58, sfp59, sfp60, sfp61, sfp62, sfp63, sfp64, +sfp65, sfp66 +}; + +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 }, { "sfpcpld35", sfp35 }, { "sfpcpld36", sfp36 }, +{ "sfpcpld37", sfp37 }, { "sfpcpld38", sfp38 }, { "sfpcpld39", sfp39 }, { "sfpcpld40", sfp40 }, +{ "sfpcpld41", sfp41 }, { "sfpcpld42", sfp42 }, { "sfpcpld43", sfp43 }, { "sfpcpld44", sfp44 }, +{ "sfpcpld45", sfp45 }, { "sfpcpld46", sfp46 }, { "sfpcpld47", sfp47 }, { "sfpcpld48", sfp48 }, +{ "sfpcpld49", sfp49 }, { "sfpcpld50", sfp50 }, { "sfpcpld51", sfp51 }, { "sfpcpld52", sfp52 }, +{ "sfpcpld53", sfp53 }, { "sfpcpld54", sfp54 }, { "sfpcpld55", sfp55 }, { "sfpcpld56", sfp56 }, +{ "sfpcpld57", sfp57 }, { "sfpcpld58", sfp58 }, { "sfpcpld59", sfp59 }, { "sfpcpld60", sfp60 }, +{ "sfpcpld61", sfp61 }, { "sfpcpld62", sfp62 }, { "sfpcpld63", sfp63 }, { "sfpcpld64", sfp64 }, +{ "sfpcpld65", sfp65 }, { "sfpcpld66", sfp66 }, {} +}; +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_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 */ + + 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, + PORT9_NUMBER, + PORT10_NUMBER, + PORT11_NUMBER, + PORT12_NUMBER, + PORT13_NUMBER, + PORT14_NUMBER, + PORT15_NUMBER, + PORT16_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, + PORT9_PRESENT, + PORT10_PRESENT, + PORT11_PRESENT, + PORT12_PRESENT, + PORT13_PRESENT, + PORT14_PRESENT, + PORT15_PRESENT, + PORT16_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, + PORT9_PRESENT_ALL, + PORT10_PRESENT_ALL, + PORT11_PRESENT_ALL, + PORT12_PRESENT_ALL, + PORT13_PRESENT_ALL, + PORT14_PRESENT_ALL, + PORT15_PRESENT_ALL, + PORT16_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, + PORT9_TYPE, + PORT10_TYPE, + PORT11_TYPE, + PORT12_TYPE, + PORT13_TYPE, + PORT14_TYPE, + PORT15_TYPE, + PORT16_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, + PORT9_RESET, + PORT10_RESET, + PORT11_RESET, + PORT12_RESET, + PORT13_RESET, + PORT14_RESET, + PORT15_RESET, + PORT16_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, + PORT9_RX_LOS, + PORT10_RX_LOS, + PORT11_RX_LOS, + PORT12_RX_LOS, + PORT13_RX_LOS, + PORT14_RX_LOS, + PORT15_RX_LOS, + PORT16_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, + PORT9_RX_LOS1, + PORT10_RX_LOS1, + PORT11_RX_LOS1, + PORT12_RX_LOS1, + PORT13_RX_LOS1, + PORT14_RX_LOS1, + PORT15_RX_LOS1, + PORT16_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, + PORT9_RX_LOS2, + PORT10_RX_LOS2, + PORT11_RX_LOS2, + PORT12_RX_LOS2, + PORT13_RX_LOS2, + PORT14_RX_LOS2, + PORT15_RX_LOS2, + PORT16_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, + PORT9_RX_LOS3, + PORT10_RX_LOS3, + PORT11_RX_LOS3, + PORT12_RX_LOS3, + PORT13_RX_LOS3, + PORT14_RX_LOS3, + PORT15_RX_LOS3, + PORT16_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, + PORT9_RX_LOS4, + PORT10_RX_LOS4, + PORT11_RX_LOS4, + PORT12_RX_LOS4, + PORT13_RX_LOS4, + PORT14_RX_LOS4, + PORT15_RX_LOS4, + PORT16_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, + PORT9_RX_LOS_ALL, + PORT10_RX_LOS_ALL, + PORT11_RX_LOS_ALL, + PORT12_RX_LOS_ALL, + PORT13_RX_LOS_ALL, + PORT14_RX_LOS_ALL, + PORT15_RX_LOS_ALL, + PORT16_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, + PORT9_TX_DISABLE, + PORT10_TX_DISABLE, + PORT11_TX_DISABLE, + PORT12_TX_DISABLE, + PORT13_TX_DISABLE, + PORT14_TX_DISABLE, + PORT15_TX_DISABLE, + PORT16_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, + PORT9_TX_DISABLE1, + PORT10_TX_DISABLE1, + PORT11_TX_DISABLE1, + PORT12_TX_DISABLE1, + PORT13_TX_DISABLE1, + PORT14_TX_DISABLE1, + PORT15_TX_DISABLE1, + PORT16_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, + PORT9_TX_DISABLE2, + PORT10_TX_DISABLE2, + PORT11_TX_DISABLE2, + PORT12_TX_DISABLE2, + PORT13_TX_DISABLE2, + PORT14_TX_DISABLE2, + PORT15_TX_DISABLE2, + PORT16_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, + PORT9_TX_DISABLE3, + PORT10_TX_DISABLE3, + PORT11_TX_DISABLE3, + PORT12_TX_DISABLE3, + PORT13_TX_DISABLE3, + PORT14_TX_DISABLE3, + PORT15_TX_DISABLE3, + PORT16_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, + PORT9_TX_DISABLE4, + PORT10_TX_DISABLE4, + PORT11_TX_DISABLE4, + PORT12_TX_DISABLE4, + PORT13_TX_DISABLE4, + PORT14_TX_DISABLE4, + PORT15_TX_DISABLE4, + PORT16_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, + PORT9_TX_DISABLE_ALL, + PORT10_TX_DISABLE_ALL, + PORT11_TX_DISABLE_ALL, + PORT12_TX_DISABLE_ALL, + PORT13_TX_DISABLE_ALL, + PORT14_TX_DISABLE_ALL, + PORT15_TX_DISABLE_ALL, + PORT16_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, + PORT9_TX_FAULT, + PORT10_TX_FAULT, + PORT11_TX_FAULT, + PORT12_TX_FAULT, + PORT13_TX_FAULT, + PORT14_TX_FAULT, + PORT15_TX_FAULT, + PORT16_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, + PORT9_TX_FAULT1, + PORT10_TX_FAULT1, + PORT11_TX_FAULT1, + PORT12_TX_FAULT1, + PORT13_TX_FAULT1, + PORT14_TX_FAULT1, + PORT15_TX_FAULT1, + PORT16_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, + PORT9_TX_FAULT2, + PORT10_TX_FAULT2, + PORT11_TX_FAULT2, + PORT12_TX_FAULT2, + PORT13_TX_FAULT2, + PORT14_TX_FAULT2, + PORT15_TX_FAULT2, + PORT16_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, + PORT9_TX_FAULT3, + PORT10_TX_FAULT3, + PORT11_TX_FAULT3, + PORT12_TX_FAULT3, + PORT13_TX_FAULT3, + PORT14_TX_FAULT3, + PORT15_TX_FAULT3, + PORT16_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, + PORT9_TX_FAULT4, + PORT10_TX_FAULT4, + PORT11_TX_FAULT4, + PORT12_TX_FAULT4, + PORT13_TX_FAULT4, + PORT14_TX_FAULT4, + PORT15_TX_FAULT4, + PORT16_TX_FAULT4, + PORT_TX_FAULT4_MAX +}; + +enum sfp_sysfs_eeprom_attributes { + PORT1_EEPROM, + PORT2_EEPROM, + PORT3_EEPROM, + PORT4_EEPROM, + PORT5_EEPROM, + PORT6_EEPROM, + PORT7_EEPROM, + PORT8_EEPROM, + PORT9_EEPROM, + PORT10_EEPROM, + PORT11_EEPROM, + PORT12_EEPROM, + PORT13_EEPROM, + PORT14_EEPROM, + PORT15_EEPROM, + PORT16_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, + PORT9_DDM_IMPLEMENTED, + PORT10_DDM_IMPLEMENTED, + PORT11_DDM_IMPLEMENTED, + PORT12_DDM_IMPLEMENTED, + PORT13_DDM_IMPLEMENTED, + PORT14_DDM_IMPLEMENTED, + PORT15_DDM_IMPLEMENTED, + PORT16_DDM_IMPLEMENTED, + PORT_DDM_IMPLEMENTED_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_pca9506_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x03}; + + DEBUG_PRINT("Starting pca9506 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("pca9506(0x20) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + data->present = status; + } + + 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[] = {0x05, 0x06}; + + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + return sfp_pca9506_update_present(client); + } + + 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 = alpha_i2c_cpld_read(0x5f, regs[i]); */ + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x5f) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + 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); + + if(data->port >= SFPPLUS_1_PORT_NUMBER) + return (data->present & BIT_INDEX(port)) ? 0 : 1; + else + 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_QSFP_PLUS; + 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[] = {0x07, 0x08}; + + 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(0x60) reg(0x%x) err %d", 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))? 0 : 1; + + 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 = 0x07; + + 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 == 0) { + data->port_reset |= BIT_INDEX(attr->index); + } + else { + data->port_reset &= ~BIT_INDEX(attr->index); + } + + alpha_i2c_cpld_write(0x5f, 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 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_1_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[] = {0x0b, 0x0c}; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = 13; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = 14; + else if(strcmp(client->name, "sfpcpld33") == 0) + i2c_index = 15; + else if(strcmp(client->name, "sfpcpld49") == 0) + i2c_index = 16; + else if(strcmp(client->name, "sfpcpld65") == 0){ + if(attr->index == 0) + i2c_index = 21; + else if(attr->index == 1) + i2c_index = 22; + } + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Set module select register */ + switch(i2c_index){ + case 13: + case 14: + case 15: + case 16: + if((attr->index/8) == 0){ + /* 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, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + else if((attr->index/8) == 1){ + /* Port number is 9-16 */ + result = i2c_smbus_write_byte_data(client, offset[1], BIT_INDEX((attr->index)%8)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + break; + default: + break; + } + + /* 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 */ + switch(i2c_index){ + case 13: + case 14: + case 15: + case 16: + if((attr->index/8) == 0){ + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + else if((attr->index/8) == 1){ + /* Port number is 9-16 */ + result = i2c_smbus_write_byte_data(client, offset[1], 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + break; + default: + break; + } + +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) +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#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) +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#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) +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#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) +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +/* 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(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#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(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#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(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#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) +DECLARE_PORT_EEPROMn_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) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + 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_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) + DECLARE_PORT_RX_LOSn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_EEPROMTn_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_EEPROMTn_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + 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_NUMBER_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + 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) + 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) +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#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) +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#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) +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) +static struct attribute *sfp_ddm_attributes[] = { + DECLARE_RX_LOS_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_RX_LOS_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_TX_DISABLE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_DISABLE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_TX_FAULT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_FAULT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + 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; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)){ + /* Register sysfs hooks */ + 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) || (client->addr == SFP_PCA9506_I2C_ADDR)){ + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + if(client->addr != SFP_PCA9506_I2C_ADDR){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + } + else if(client->addr != SFP_CPLD_I2C_ADDR){ + 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_PCA9506_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_PCA9506_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_PCA9506_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 snh60b0-640f driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c new file mode 100644 index 0000000000..f259abdca8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for snh60b0-640f 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 snh60b0-640f_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 *snh60b0_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group snh60b0_onie_group = { + .attrs = snh60b0_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, &snh60b0_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, &snh60b0_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snh60b0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60b0_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/snh60b0-640f/modules/snh60b0-640f_power_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c new file mode 100644 index 0000000000..00b8779ad5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c @@ -0,0 +1,501 @@ +/* + * A hwmon driver for the snh60b0-640f_power_cpld + * + * 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 DRIVER_NAME "snh60b0_power_cpld" +#define PSU1_STATUS_REG 0x3 +#define PSU2_STATUS_REG 0x4 +#define FAN_PWM_REG 0x23 + +#define PSU_PRESENT_BIT 0x4 +#define PSU_POWER_BIT 0x2 +#define FAN_PRESENT_BIT 0x2 + + +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 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 snh60b0-640f_power_cpld */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct snh60b0_pwr_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_psu_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + /* FAN5_FAULT, */ + /* FAN6_FAULT, */ + FAN1_PRESENT=0x12, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + /* FAN5_PRESENT, */ + /* FAN6_PRESENT, */ + FAN1_FRONT_SPEED_RPM=0x1A, + 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, */ +}; + +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 struct attribute *snh60b0_psu_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, */ + NULL +}; + +static const struct attribute_group snh60b0_psu_group = { + .attrs = snh60b0_psu_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, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 1 : 0 ); + 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, "cpld(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 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 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 alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct snh60b0_pwr_cpld_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 snh60b0_pwr_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_psu_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_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_cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + struct snh60b0_pwr_cpld_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &snh60b0_psu_group); + alpha_i2c_cpld_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_read); + +int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_write); + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + +static struct dmi_system_id snh60b0_dmi_table[] = { + { + .ident = "Alpha snh60b0-640f", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "snh60b0-640f"), + }, + } +}; + +int platform_alpha_snh60b0(void) +{ + return dmi_check_system(snh60b0_dmi_table); +} +EXPORT_SYMBOL(platform_alpha_snh60b0); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c new file mode 100644 index 0000000000..ddba09370c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c @@ -0,0 +1,365 @@ +/* + * A hwmon driver for the snh60b0-640f_system_cpld + * + * 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 SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define SYS_RESET1_REG 0x2 +#define SWI_CTRL_REG 0x4 + +#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 +#define REST_BUTTON_BITS 0x0 + + +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 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(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_system_cpld */ +static const unsigned short normal_i2c[] = { 0x5F, I2C_CLIENT_END }; + + +enum sysfs_sys_attributes { + SYS_LOCATOR, + SYS_PWR, + SYS_STATUS, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + SYS_REST1, + SWI_CTRL, +}; + +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +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(sys_reset1, (0660), sys_led_read, sys_led_write, SYS_REST1); +static SENSOR_DEVICE_ATTR(swi_ctrl, (0660), sys_led_read, NULL, SWI_CTRL); + +static struct attribute *snh60b0_sys_attributes[] = { + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_sys_status.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_sys_reset1.dev_attr.attr, + &sensor_dev_attr_swi_ctrl.dev_attr.attr, + NULL +}; + +static const struct attribute_group snh60b0_sys_group = { + .attrs = snh60b0_sys_attributes, +}; + + +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 SYS_STATUS: + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + command = SYS_RESET1_REG; + break; + case SWI_CTRL: + command = SWI_CTRL_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(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) >> 1; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 4; + break; + case FAN1_LED: + case FAN3_LED: + res = (val & FAN135_LED_BITS) >> 0; + break; + case FAN2_LED: + case FAN4_LED: + res = (val & FAN246_LED_BITS) >> 3; + break; + case SYS_REST1: + res = val; + break; + case SWI_CTRL: + res = (val & REST_BUTTON_BITS) >> 0; + 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: + if(write < 0 || write > 2) + return -EINVAL; + case SYS_PWR: + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + if (write < 0 || write > 7) + return -EINVAL; + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + if (write < 0 || write > 15) + return -EINVAL; + command = SYS_RESET1_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "cpld(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 << 1; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 4; + break; + case FAN1_LED: + case FAN3_LED: + read &= ~FAN135_LED_BITS; + read |= write << 0; + break; + case FAN2_LED: + case FAN4_LED: + read &= ~FAN246_LED_BITS; + read |= write << 3; + break; + case SYS_REST1: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + 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 alpha_i2c_cpld_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, &snh60b0_sys_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 alpha_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &snh60b0_sys_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { "snh60b0_system_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60b0_system_cpld", + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_system_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service new file mode 100644 index 0000000000..fa2e849c7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNH60B0-640F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snh60b0_util.py -f install +ExecStop=/usr/local/bin/alphanetworks_snh60b0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py new file mode 100644 index 0000000000..785a366601 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snh60b0_640f', + version='1.0', + description='Module to initialize Alphanetworks SNH60B0-640F platforms', + + packages=['snh60b0_640f'], + package_dir={'snh60b0_640f': 'snh60b0-640f/classes'}, +) + 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 new file mode 100755 index 0000000000..4b64a2e12a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py @@ -0,0 +1,427 @@ +#!/usr/bin/env python +# +# 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 +# +# 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 = 'snh60b0-640f' +device_path = "x86_64-alphanetworks_snh60b0_640f-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + + +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 alphanetworks", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe snh60b0-640f_power_cpld' , +'modprobe snh60b0-640f_system_cpld' , +'modprobe snh60b0-640f_onie_eeprom' , +'modprobe alphanetworks_snh60b0_640f_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,23] +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 pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo snh60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60b0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60b0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-8/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 pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60b0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60b0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/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 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + 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 = "echo 0x70 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + 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 + 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/8-005f/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, 66): + index = i / 16 + port = i % 16 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i == 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x20 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + if i < 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x5f > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if i == 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-21/new_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 65: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-22/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0, 66): + index = i / 16 + port = i % 16 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i == 64: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x20 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + if i < 64: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x5f > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if i == 64: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-21/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 65: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-22/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + 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/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a 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" + 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()