diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/port_config.ini b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/port_config.ini new file mode 100644 index 0000000000..8f77032943 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 33,34,35,36,37,38,39,40 fourhundredGigE1 0 +Ethernet4 25,26,27,28,29,30,31,32 fourhundredGigE2 1 +Ethernet8 49,50,51,52,53,54,55,56 fourhundredGigE3 2 +Ethernet12 57,58,59,60,61,62,63,64 fourhundredGigE4 3 +Ethernet16 65,66,67,68,69,70,71,72 fourhundredGigE5 4 +Ethernet20 73,74,75,76,77,78,79,80 fourhundredGigE6 5 +Ethernet24 81,82,83,84,85,86,87,88 fourhundredGigE7 6 +Ethernet28 89,90,91,92,93,94,95,96 fourhundredGigE8 7 +Ethernet32 17,18,19,20,21,22,23,24 fourhundredGigE9 8 +Ethernet36 97,98,99,100,101,102,103,104 fourhundredGigE10 9 +Ethernet40 9,10,11,12,13,14,15,16 fourhundredGigE11 10 +Ethernet44 41,42,43,44,45,46,47,48 fourhundredGigE12 11 +Ethernet48 113,114,115,116,117,118,119,120 fourhundredGigE13 12 +Ethernet52 105,106,107,108,109,110,111,112 fourhundredGigE14 13 +Ethernet56 121,122,123,124,125,126,127,128 fourhundredGigE15 14 +Ethernet60 1,2,3,4,5,6,7,8 fourhundredGigE16 15 +Ethernet64 137,138,139,140,141,142,143,144 fourhundredGigE17 16 +Ethernet68 129,130,131,132,133,134,135,136 fourhundredGigE18 17 +Ethernet72 241,242,243,244,245,246,247,248 fourhundredGigE19 18 +Ethernet76 249,250,251,252,253,254,255,256 fourhundredGigE20 19 +Ethernet80 225,226,227,228,229,230,231,232 fourhundredGigE21 20 +Ethernet84 145,146,147,148,149,150,151,152 fourhundredGigE22 21 +Ethernet88 153,154,155,156,157,158,159,160 fourhundredGigE23 22 +Ethernet92 233,234,235,236,237,238,239,240 fourhundredGigE24 23 +Ethernet96 161,162,163,164,165,166,167,168 fourhundredGigE25 24 +Ethernet100 169,170,171,172,173,174,175,176 fourhundredGigE26 25 +Ethernet104 177,178,179,180,181,182,183,184 fourhundredGigE27 26 +Ethernet108 185,186,187,188,189,190,191,192 fourhundredGigE28 27 +Ethernet112 193,194,195,196,197,198,199,200 fourhundredGigE29 28 +Ethernet116 201,202,203,204,205,206,207,208 fourhundredGigE30 29 +Ethernet120 209,210,211,212,213,214,215,216 fourhundredGigE31 30 +Ethernet124 217,218,219,220,221,222,223,224 fourhundredGigE32 31 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/sai.profile b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/sai.profile new file mode 100644 index 0000000000..54b62b1d09 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-ix9-32x400G.config.bcm diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/th3-ix9-32x400G.config.bcm b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/th3-ix9-32x400G.config.bcm new file mode 100644 index 0000000000..704183e109 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/th3-ix9-32x400G.config.bcm @@ -0,0 +1,341 @@ +ccm_dma_enable=0 +ccmdma_intr_enable=0 +ctr_evict_enable=0 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +phy_enable=0 +phy_null=1 +pll_bypass=1 + +init_all_modules=0 +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 + +load_firmware=0x2 +port_flex_enable=1 + +# portmap settings +pbmp_xport_xe=0x111101111411110111101111011114111102222 + +portmap_1=1:400 +portmap_5=9:400 +portmap_9=17:400 +portmap_13=25:400 +portmap_20=33:400 +portmap_24=41:400 +portmap_28=49:400 +portmap_32=57:400 + +portmap_40=65:400 +portmap_44=73:400 +portmap_48=81:400 +portmap_52=89:400 +portmap_60=97:400 +portmap_64=105:400 +portmap_68=113:400 +portmap_72=121:400 + +portmap_80=129:400 +portmap_84=137:400 +portmap_88=145:400 +portmap_92=153:400 +portmap_100=161:400 +portmap_104=169:400 +portmap_108=177:400 +portmap_112=185:400 + +portmap_120=193:400 +portmap_124=201:400 +portmap_128=209:400 +portmap_132=217:400 +portmap_140=225:400 +portmap_144=233:400 +portmap_148=241:400 +portmap_152=249:400 + +# datapath port +portmap_38=257:10 +portmap_118=258:10 + +# loopback port +portmap_19=260:10 +portmap_39=260:10 +portmap_59=261:10 +portmap_79=262:10 +portmap_99=263:10 +portmap_119=264:10 +portmap_139=265:10 +portmap_159=266:10 + +# port order remap +dport_map_port_20=1 +dport_map_port_13=2 +dport_map_port_28=3 +dport_map_port_32=4 +dport_map_port_40=5 +dport_map_port_44=6 +dport_map_port_48=7 +dport_map_port_52=8 +dport_map_port_9=9 +dport_map_port_60=10 +dport_map_port_5=11 +dport_map_port_24=12 +dport_map_port_68=13 +dport_map_port_64=14 +dport_map_port_72=15 +dport_map_port_1=16 + +dport_map_port_84=17 +dport_map_port_80=18 +dport_map_port_148=19 +dport_map_port_152=20 +dport_map_port_140=21 +dport_map_port_88=22 +dport_map_port_92=23 +dport_map_port_144=24 +dport_map_port_100=25 +dport_map_port_104=26 +dport_map_port_108=27 +dport_map_port_112=28 +dport_map_port_120=29 +dport_map_port_124=30 +dport_map_port_128=31 +dport_map_port_132=32 + +dport_map_port_38=33 +dport_map_port_118=34 + +### lane swap and polarity follow front port order ### +phy_chain_tx_lane_map_physical{33.0}=0x75206431 +serdes_core_tx_polarity_flip_physical{33}=0xdb +phy_chain_rx_lane_map_physical{33.0}=0x13572064 +serdes_core_rx_polarity_flip_physical{33}=0x69 + +phy_chain_tx_lane_map_physical{25.0}=0x75314206 +serdes_core_tx_polarity_flip_physical{25}=0xe8 +phy_chain_rx_lane_map_physical{25.0}=0x67103524 +serdes_core_rx_polarity_flip_physical{25}=0x7c + +phy_chain_tx_lane_map_physical{49.0}=0x57326014 +serdes_core_tx_polarity_flip_physical{49}=0x0e +phy_chain_rx_lane_map_physical{49.0}=0x21463057 +serdes_core_rx_polarity_flip_physical{49}=0xd2 + +phy_chain_tx_lane_map_physical{57.0}=0x12307564 +serdes_core_tx_polarity_flip_physical{57}=0xa6 +phy_chain_rx_lane_map_physical{57.0}=0x57460231 +serdes_core_rx_polarity_flip_physical{57}=0x99 + +phy_chain_tx_lane_map_physical{65.0}=0x60345721 +serdes_core_tx_polarity_flip_physical{65}=0xe2 +phy_chain_rx_lane_map_physical{65.0}=0x40675123 +serdes_core_rx_polarity_flip_physical{65}=0x0f + +phy_chain_tx_lane_map_physical{73.0}=0x21306574 +serdes_core_tx_polarity_flip_physical{73}=0xa4 +phy_chain_rx_lane_map_physical{73.0}=0x67451302 +serdes_core_rx_polarity_flip_physical{73}=0x06 + +phy_chain_tx_lane_map_physical{81.0}=0x65210347 +serdes_core_tx_polarity_flip_physical{81}=0xe2 +phy_chain_rx_lane_map_physical{81.0}=0x10675423 +serdes_core_rx_polarity_flip_physical{81}=0x0f + +phy_chain_tx_lane_map_physical{89.0}=0x41236570 +serdes_core_tx_polarity_flip_physical{89}=0x8d +phy_chain_rx_lane_map_physical{89.0}=0x45672031 +serdes_core_rx_polarity_flip_physical{89}=0x63 + +phy_chain_tx_lane_map_physical{17.0}=0x76312504 +serdes_core_tx_polarity_flip_physical{17}=0x8e +phy_chain_rx_lane_map_physical{17.0}=0x75126403 +serdes_core_rx_polarity_flip_physical{17}=0x2d + +phy_chain_tx_lane_map_physical{97.0}=0x31025764 +serdes_core_tx_polarity_flip_physical{97}=0x3c +phy_chain_rx_lane_map_physical{97.0}=0x52136470 +serdes_core_rx_polarity_flip_physical{97}=0x9c + +phy_chain_tx_lane_map_physical{9.0}=0x57326014 +serdes_core_tx_polarity_flip_physical{9}=0x3d +phy_chain_rx_lane_map_physical{9.0}=0x31452076 +serdes_core_rx_polarity_flip_physical{9}=0x1e + +phy_chain_tx_lane_map_physical{41.0}=0x03215764 +serdes_core_tx_polarity_flip_physical{41}=0x3c +phy_chain_rx_lane_map_physical{41.0}=0x54671302 +serdes_core_rx_polarity_flip_physical{41}=0x99 + +phy_chain_tx_lane_map_physical{113.0}=0x60175243 +serdes_core_tx_polarity_flip_physical{113}=0xcd +phy_chain_rx_lane_map_physical{113.0}=0x20473156 +serdes_core_rx_polarity_flip_physical{113}=0x87 + +phy_chain_tx_lane_map_physical{105.0}=0x65034721 +serdes_core_tx_polarity_flip_physical{105}=0xe6 +phy_chain_rx_lane_map_physical{105.0}=0x04157263 +serdes_core_rx_polarity_flip_physical{105}=0x4c + +phy_chain_tx_lane_map_physical{121.0}=0x16435072 +serdes_core_tx_polarity_flip_physical{121}=0xae +phy_chain_rx_lane_map_physical{121.0}=0x13560247 +serdes_core_rx_polarity_flip_physical{121}=0x2d + +phy_chain_tx_lane_map_physical{1.0}=0x34650172 +serdes_core_tx_polarity_flip_physical{1}=0xff +phy_chain_rx_lane_map_physical{1.0}=0x13026457 +serdes_core_rx_polarity_flip_physical{1}=0x99 + +phy_chain_tx_lane_map_physical{137.0}=0x02673451 +serdes_core_tx_polarity_flip_physical{137}=0x25 +phy_chain_rx_lane_map_physical{137.0}=0x14730562 +serdes_core_rx_polarity_flip_physical{137}=0x86 + +phy_chain_tx_lane_map_physical{129.0}=0x12304675 +serdes_core_tx_polarity_flip_physical{129}=0x49 +phy_chain_rx_lane_map_physical{129.0}=0x76453021 +serdes_core_rx_polarity_flip_physical{129}=0xc3 + +phy_chain_tx_lane_map_physical{241.0}=0x31462075 +serdes_core_tx_polarity_flip_physical{241}=0xf5 +phy_chain_rx_lane_map_physical{241.0}=0x47315602 +serdes_core_rx_polarity_flip_physical{241}=0xe1 + +phy_chain_tx_lane_map_physical{249.0}=0x13206547 +serdes_core_tx_polarity_flip_physical{249}=0x27 +phy_chain_rx_lane_map_physical{249.0}=0x64750312 +serdes_core_rx_polarity_flip_physical{249}=0xbd + +phy_chain_tx_lane_map_physical{225.0}=0x60315742 +serdes_core_tx_polarity_flip_physical{225}=0x44 +phy_chain_rx_lane_map_physical{225.0}=0x01546372 +serdes_core_rx_polarity_flip_physical{225}=0xc3 + +phy_chain_tx_lane_map_physical{145.0}=0x51374602 +serdes_core_tx_polarity_flip_physical{145}=0x5f +phy_chain_rx_lane_map_physical{145.0}=0x23106754 +serdes_core_rx_polarity_flip_physical{145}=0xbc + +phy_chain_tx_lane_map_physical{153.0}=0x05163742 +serdes_core_tx_polarity_flip_physical{153}=0x0f +phy_chain_rx_lane_map_physical{153.0}=0x67102354 +serdes_core_rx_polarity_flip_physical{153}=0xf0 + +phy_chain_tx_lane_map_physical{233.0}=0x20134576 +serdes_core_tx_polarity_flip_physical{233}=0x07 +phy_chain_rx_lane_map_physical{233.0}=0x23107465 +serdes_core_rx_polarity_flip_physical{233}=0xe6 + +phy_chain_tx_lane_map_physical{161.0}=0x53246710 +serdes_core_tx_polarity_flip_physical{161}=0x0f +phy_chain_rx_lane_map_physical{161.0}=0x03471265 +serdes_core_rx_polarity_flip_physical{161}=0xc0 + +phy_chain_tx_lane_map_physical{169.0}=0x20137654 +serdes_core_tx_polarity_flip_physical{169}=0x8a +phy_chain_rx_lane_map_physical{169.0}=0x27360415 +serdes_core_rx_polarity_flip_physical{169}=0x9c + +phy_chain_tx_lane_map_physical{177.0}=0x50346712 +serdes_core_tx_polarity_flip_physical{177}=0x4f +phy_chain_rx_lane_map_physical{177.0}=0x13460257 +serdes_core_rx_polarity_flip_physical{177}=0x5a + +phy_chain_tx_lane_map_physical{185.0}=0x12305674 +serdes_core_tx_polarity_flip_physical{185}=0xba +phy_chain_rx_lane_map_physical{185.0}=0x57460123 +serdes_core_rx_polarity_flip_physical{185}=0x9f + +phy_chain_tx_lane_map_physical{193.0}=0x50346712 +serdes_core_tx_polarity_flip_physical{193}=0x4f +phy_chain_rx_lane_map_physical{193.0}=0x13750264 +serdes_core_rx_polarity_flip_physical{193}=0x69 + +phy_chain_tx_lane_map_physical{201.0}=0x12305674 +serdes_core_tx_polarity_flip_physical{201}=0xba +phy_chain_rx_lane_map_physical{201.0}=0x57460123 +serdes_core_rx_polarity_flip_physical{201}=0x9f + +phy_chain_tx_lane_map_physical{209.0}=0x50346712 +serdes_core_tx_polarity_flip_physical{209}=0x4f +phy_chain_rx_lane_map_physical{209.0}=0x13460275 +serdes_core_rx_polarity_flip_physical{209}=0x5a + +phy_chain_tx_lane_map_physical{217.0}=0x31205674 +serdes_core_tx_polarity_flip_physical{217}=0x5a +phy_chain_rx_lane_map_physical{217.0}=0x67541203 +serdes_core_rx_polarity_flip_physical{217}=0x33 + + +port_fec_20=9 +port_fec_13=9 +port_fec_28=9 +port_fec_32=9 +port_fec_40=9 +port_fec_44=9 +port_fec_48=9 +port_fec_52=9 +port_fec_9=9 +port_fec_60=9 +port_fec_5=9 +port_fec_24=9 +port_fec_68=9 +port_fec_64=9 +port_fec_72=9 +port_fec_1=9 + +port_fec_84=9 +port_fec_80=9 +port_fec_148=9 +port_fec_152=9 +port_fec_140=9 +port_fec_88=9 +port_fec_92=9 +port_fec_144=9 +port_fec_100=9 +port_fec_104=9 +port_fec_108=9 +port_fec_112=9 +port_fec_120=9 +port_fec_124=9 +port_fec_128=9 +port_fec_132=9 + + +port_init_cl72_20=1 +port_init_cl72_13=1 +port_init_cl72_28=1 +port_init_cl72_32=1 +port_init_cl72_40=1 +port_init_cl72_44=1 +port_init_cl72_48=1 +port_init_cl72_52=1 +port_init_cl72_9=1 +port_init_cl72_60=1 +port_init_cl72_5=1 +port_init_cl72_24=1 +port_init_cl72_68=1 +port_init_cl72_64=1 +port_init_cl72_72=1 +port_init_cl72_1=1 + +port_init_cl72_84=1 +port_init_cl72_80=1 +port_init_cl72_148=1 +port_init_cl72_152=1 +port_init_cl72_140=1 +port_init_cl72_88=1 +port_init_cl72_92=1 +port_init_cl72_144=1 +port_init_cl72_100=1 +port_init_cl72_104=1 +port_init_cl72_108=1 +port_init_cl72_112=1 +port_init_cl72_120=1 +port_init_cl72_124=1 +port_init_cl72_128=1 +port_init_cl72_132=1 + + diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/default_sku b/device/quanta/x86_64-quanta_ix9_bwde-r0/default_sku new file mode 100644 index 0000000000..0ca35bb007 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX9-32X t1 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/installer.conf b/device/quanta/x86_64-quanta_ix9_bwde-r0/installer.conf new file mode 100644 index 0000000000..925a32fc0c --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix9_bwde-r0/led_proc_init.soc new file mode 100644 index 0000000000..adff95218e --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/led_proc_init.soc @@ -0,0 +1,2 @@ +sleep 10 +led auto on diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/eeprom.py new file mode 100644 index 0000000000..2a35f3a22a --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/eeprom.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/18-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/psuutil.py new file mode 100644 index 0000000000..885842bbda --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/psuutil.py @@ -0,0 +1,49 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +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) + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 1 + + return status diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/sfputil.py new file mode 100644 index 0000000000..6dc23d8195 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/sfputil.py @@ -0,0 +1,176 @@ +#!/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""" + + _port_start = 0 + _port_end = 31 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 1 : 32, + 2 : 33, + 3 : 34, + 4 : 35, + 5 : 36, + 6 : 37, + 7 : 38, + 8 : 39, + 9 : 40, + 10 : 41, + 11 : 42, + 12 : 43, + 13 : 44, + 14 : 45, + 15 : 46, + 16 : 47, + 17 : 48, + 18 : 49, + 19 : 50, + 20 : 51, + 21 : 52, + 22 : 53, + 23 : 54, + 24 : 55, + 25 : 56, + 26 : 57, + 27 : 58, + 28 : 59, + 29 : 60, + 30 : 61, + 31 : 62, + 32 : 63, + } + + _qsfp_ports = range(0, ports_in_block + 1) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(0, self._port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/reset", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/reset", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/module_present") + 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 + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return range(0, self.ports_in_block + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError + + diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 0edb6ebc4f..a850065a0f 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -45,6 +45,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(QUANTA_IX7_32X_PLATFORM_MODULE) \ $(QUANTA_IX8_56X_PLATFORM_MODULE) \ $(QUANTA_IX8C_56X_PLATFORM_MODULE) \ + $(QUANTA_IX9_32X_PLATFORM_MODULE) \ $(MITAC_LY1200_32X_PLATFORM_MODULE) \ $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \ $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-quanta.mk b/platform/broadcom/platform-modules-quanta.mk index 93cf7b4d9d..456af3019e 100644 --- a/platform/broadcom/platform-modules-quanta.mk +++ b/platform/broadcom/platform-modules-quanta.mk @@ -4,11 +4,13 @@ QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION = 1.0 QUANTA_IX7_32X_PLATFORM_MODULE_VERSION = 1.0 QUANTA_IX8_56X_PLATFORM_MODULE_VERSION = 1.0 QUANTA_IX8C_56X_PLATFORM_MODULE_VERSION = 1.0 +QUANTA_IX9_32X_PLATFORM_MODULE_VERSION = 1.0 export QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION export QUANTA_IX7_32X_PLATFORM_MODULE_VERSION export QUANTA_IX8_56X_PLATFORM_MODULE_VERSION export QUANTA_IX8C_56X_PLATFORM_MODULE_VERSION +export QUANTA_IX9_32X_PLATFORM_MODULE_VERSION QUANTA_IX1B_32X_PLATFORM_MODULE = sonic-platform-quanta-ix1b-32x_$(QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION)_amd64.deb $(QUANTA_IX1B_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-quanta @@ -28,4 +30,8 @@ QUANTA_IX8C_56X_PLATFORM_MODULE = sonic-platform-quanta-ix8c-56x_$(QUANTA_IX8C_5 $(QUANTA_IX8C_56X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix8c_bwde-r0 $(eval $(call add_extra_package,$(QUANTA_IX1B_32X_PLATFORM_MODULE),$(QUANTA_IX8C_56X_PLATFORM_MODULE))) +QUANTA_IX9_32X_PLATFORM_MODULE = sonic-platform-quanta-ix9-32x_$(QUANTA_IX9_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX9_32X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix9_bwde-r0 +$(eval $(call add_extra_package,$(QUANTA_IX1B_32X_PLATFORM_MODULE),$(QUANTA_IX9_32X_PLATFORM_MODULE))) + SONIC_STRETCH_DEBS += $(QUANTA_IX1B_32X_PLATFORM_MODULE) diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/changelog b/platform/broadcom/sonic-platform-modules-quanta/debian/changelog index 4bed63edf9..fe1cfa4549 100644 --- a/platform/broadcom/sonic-platform-modules-quanta/debian/changelog +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/changelog @@ -25,3 +25,10 @@ sonic-quanta-platform-modules (1.0) unstable; urgency=low * Initial release -- Chih-Pei Chang Jonathan Tsai Thu, 4 Jan 2018 13:50:01 +0800 + +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX9-32X + * Initial release + + -- Jonathan Tsai Thu, 31 Jan 2019 13:09:01 +0800 diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/control b/platform/broadcom/sonic-platform-modules-quanta/debian/control index aea2a39d6f..f25b0d8e3c 100644 --- a/platform/broadcom/sonic-platform-modules-quanta/debian/control +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/control @@ -20,3 +20,7 @@ Description: kernel modules for platform devices such as psu, led, sfp Package: sonic-platform-quanta-ix8c-56x Architecture: amd64 Description: kernel modules for platform devices such as psu, led, sfp + +Package: sonic-platform-quanta-ix9-32x +Architecture: amd64 +Description: kernel modules for platform devices such as psu, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/rules b/platform/broadcom/sonic-platform-modules-quanta/debian/rules index 8ceede7919..46b9607135 100644 --- a/platform/broadcom/sonic-platform-modules-quanta/debian/rules +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/rules @@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-quanta KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= ix1b-32x ix7-32x ix8-56x ix8c-56x +MODULE_DIRS:= ix1b-32x ix7-32x ix8-56x ix8c-56x ix9-32x MODULE_DIR := modules UTILS_DIR := utils SERVICE_DIR := service diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/classes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/Makefile new file mode 100644 index 0000000000..929782931a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=qci_cpld_qsfpdd.o qci_cpld_led.o qci_platform_ix9.o + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_led.c b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_led.c new file mode 100644 index 0000000000..d8f89240a8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_led.c @@ -0,0 +1,277 @@ +/* + * A LED CPLD driver for Quanta Switch Platform + * + * The CPLD is customize by Quanta for decode led bit stream, + * This driver modify from Quanta CPLD I/O driver. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * Author: Roger Chang + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_led_ida); + +enum platform_type { + IX7 = 0, + IX8C, + IX9, + NONE +}; + +static struct class *cpld_class = NULL; + +struct cpld_data { + struct i2c_client *cpld_client; + char name[8]; + u8 cpld_id; +}; + +struct cpld_led_data { + struct mutex lock; + struct device *port_dev; + struct cpld_data *cpld_data; +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_led_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_led_id[] = { + { "CPLDLED_IX7", IX7 }, + { "CPLDLED_IX8C", IX8C }, + { "CPLDLED_IX9", IX9 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_led_id); + +static struct i2c_driver cpld_led_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_led", + }, + .probe = cpld_led_probe, + .remove = cpld_led_remove, + .id_table = cpld_led_id, +// .address_list = normal_i2c, +}; + +#define CPLD_LED_ID_PREFIX "CPLDLED-" +#define CPLD_LED_ID_FORMAT CPLD_LED_ID_PREFIX "%d" + +#define CPLD_DECODER_OFFSET 0x4 +#define CPLD_DECODER_MASK 0x1 +#define CPLD_USERCODE_START_OFFSET 0x0 + +static ssize_t get_led_decode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 offset = (u8)(CPLD_DECODER_OFFSET); + s32 value; + + value = i2c_smbus_read_byte_data(client, offset); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value &= CPLD_DECODER_MASK; + + return sprintf(buf, "%d\n", (value == 0) ? 1 : 0); +} + +static ssize_t get_usercode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 i = 0; + s32 value = 0, reading = 0; + + for (i = 0; i < 4; i++) + { + reading = i2c_smbus_read_byte_data(client, CPLD_USERCODE_START_OFFSET + i); + if (reading < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led usercode reg %d value= %x\n", i, reading); + + value |= reading << (24 - 8 * i); + } + + return sprintf(buf, "%X\n", value); +} + +static ssize_t set_led_decode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + s32 value; + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_byte_data(client, CPLD_DECODER_OFFSET); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value |= CPLD_DECODER_MASK; + if (enable) + value &= ~CPLD_DECODER_MASK; + + dev_dbg(&client->dev, "write led decode value= %x\n", value); + + i2c_smbus_write_byte_data(client, CPLD_DECODER_OFFSET, (u8)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(led_decode, S_IWUSR | S_IRUGO, get_led_decode, set_led_decode); +static DEVICE_ATTR(usercode, S_IRUGO, get_usercode, NULL); + +static const struct attribute *led_attrs[] = { + &dev_attr_usercode.attr, + &dev_attr_led_decode.attr, + NULL, +}; + +static const struct attribute_group led_attr_group = { + .attrs = (struct attribute **) led_attrs, +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_led_data *data; + struct cpld_data *led_data; + struct device *port_dev; + int nr, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-led"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_led_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Test */ + nr = ida_simple_get(&cpld_led_ida, 1, 99, GFP_KERNEL); + if (nr < 0) + goto err_out; + + led_data = kzalloc(sizeof(struct cpld_led_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), led_data, CPLD_LED_ID_FORMAT, nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev = port_dev; + data->cpld_data = led_data; + + dev_info(&client->dev, "Register CPLDLED %d\n", nr); + + sprintf(led_data->name, "LED%d-data", nr); + led_data->cpld_id = nr; + dev_set_drvdata(port_dev, led_data); + port_dev->init_name = led_data->name; + led_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &led_attr_group); + // if (status) printk("err status\n"); + /* end */ + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_led_remove(struct i2c_client *client) +{ + struct cpld_led_data *data = i2c_get_clientdata(client); + + dev_info(data->port_dev, "Remove CPLDLED-%d\n", data->cpld_data->cpld_id); + device_unregister(data->port_dev); + ida_simple_remove(&cpld_led_ida, data->cpld_data->cpld_id); + kfree(data->cpld_data); + + if (cpld_idr_is_empty(&cpld_led_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_led_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_AUTHOR("Roger Chang "); +MODULE_DESCRIPTION("Quanta Switch LED CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_qsfpdd.c b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_qsfpdd.c new file mode 100644 index 0000000000..d616f887db --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_qsfpdd.c @@ -0,0 +1,411 @@ +/* + * A CPLD driver for monitor QSFPDD module I/O + * + * The CPLD is customize by Quanta for controlling QSFPDD module signals, + * they are RESET , INTERREPT , Module_Present, LPMODE + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + QSFPDD = 0, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-QSFPDD", QSFPDD }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_qsfpdd", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +#define RESET_MASK 0x08 +#define INTERRUPT_MASK 0x04 +#define MODULE_PRESENT_MASK 0x02 +#define LPMODE_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +static ssize_t get_reset(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RESET_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_interrupt(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= INTERRUPT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_module_present(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= MODULE_PRESENT_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_lpmode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= LPMODE_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(RESET_MASK << (group_port * 4)); + if (disable) + value |= (RESET_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(LPMODE_MASK << (group_port * 4)); + if (disable) + value |= (LPMODE_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(module_present, S_IRUGO, get_module_present, NULL); +static DEVICE_ATTR(interrupt, S_IRUGO, get_interrupt, NULL); + +static const struct attribute *sfp_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_lpmode.attr, + &dev_attr_module_present.attr, + &dev_attr_interrupt.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; + struct device *port_dev; + int port_nr, i, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-qsfpdd"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* register sfp port data to sysfs */ + for (i = 0; i < 16; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + return port_nr; + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + dev_info(&client->dev, "Register qsfpdd port-%d\n", port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +#if 0 +//FIXME: implement error check +exit_remove: +// sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +#endif +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i; + + for (i = 15; i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove qsfpdd port-%d\n", data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_DESCRIPTION("Quanta Switch SFP CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_platform_ix9.c b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_platform_ix9.c new file mode 100644 index 0000000000..a927e85079 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_platform_ix9.c @@ -0,0 +1,293 @@ +/* + * Quanta IX9 platform driver + * + * + * Copyright (C) 2019 Quanta Computer 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,12,0) +#include +#else +#include +#endif +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +static struct pca954x_platform_mode pca9546_1_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_1_data = { + .modes = pca9546_1_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548_1_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), +}; + +static struct pca954x_platform_data pca9548_1_data = { + .modes = pca9548_1_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca953x_platform_data tca9539_1_data = { + .gpio_base = 0x10, +}; +//CPU Linking Board at CPU's I2C Bus +static struct pca953x_platform_data pca9555_CPU_data = { + .gpio_base = 0x20, +}; + +static struct i2c_board_info ix9_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x72), + .platform_data = &pca9546_1_data, // 0 pca9546_1 + }, + { + I2C_BOARD_INFO("pca9548", 0x77), + .platform_data = &pca9548_1_data, // 1 pca9548_1 + }, + { + I2C_BOARD_INFO("tca9539", 0x74), + .platform_data = &tca9539_1_data, // 2 Board ID and QSFP-DD PW EN/PG + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 3 MB_BOARDINFO_EEPROM + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp1_data, // 4 0x77 ch0 pca9548 #1 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp2_data, // 5 0x77 ch1 pca9548 #2 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp3_data, // 6 0x77 ch2 pca9548 #3 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp4_data, // 7 0x77 ch3 pca9548 #4 + }, + { + I2C_BOARD_INFO("CPLD-QSFPDD", 0x38), // 8 0x72 ch0 CPLD-IO #2, #3 + }, + { + I2C_BOARD_INFO("CPLDLED_IX9", 0x39), // 9 0x72 ch1 CPLD-LED #4, #5 + }, + { + I2C_BOARD_INFO("optoe1", 0x50), // 10 eeprom for loopback module + }, + { + I2C_BOARD_INFO("pca9555", 0x22), // 11 CPU Linking Board at CPU's I2C Bus + .platform_data = &pca9555_CPU_data, + }, +}; + +static struct platform_driver ix9_platform_driver = { + .driver = { + .name = "qci-ix9", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *ix9_device; + +static int __init ix9_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + int ret, i; + + ret = platform_driver_register(&ix9_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix9_device = platform_device_alloc("qci-ix9", -1); + if (!ix9_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix9_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix9_i2c_devices[0]); // pca9546_1 - Address: 0x72 + client = i2c_new_device(adapter, &ix9_i2c_devices[1]); // pca9548_1 - Address: 0x77 + client = i2c_new_device(adapter, &ix9_i2c_devices[11]); // CPU Linking Board at CPU's I2C Bus - Address: 0x22 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix9_i2c_devices[8]); // CPLD-IO #2 - Address: 0x38 + client = i2c_new_device(adapter, &ix9_i2c_devices[9]); // CPLD-LED #4 - Address: 0x39 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix9_i2c_devices[8]); // CPLD-IO #3 - Address: 0x38 + client = i2c_new_device(adapter, &ix9_i2c_devices[9]); // CPLD-LED #5 - Address: 0x39 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x12); + client = i2c_new_device(adapter, &ix9_i2c_devices[3]); // MB_BOARDINFO_EEPROM - Address: 0x54 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x13); + client = i2c_new_device(adapter, &ix9_i2c_devices[2]); // tca9539_1 Board ID and QSFP-DD PW EN/PG - Address: 0x74 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix9_i2c_devices[4]); // pca9548 #1 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix9_i2c_devices[5]); // pca9548 #2 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix9_i2c_devices[6]); // pca9548 #3 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix9_i2c_devices[7]); // pca9548 #4 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + for(i = 0x20; i < 0x40; i++) + { + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix9_i2c_devices[10]); // eeprom for loopback module - Address: 0x50 + i2c_put_adapter(adapter); + } + + return 0; + +fail_platform_device: + platform_device_put(ix9_device); + +fail_platform_driver: + platform_driver_unregister(&ix9_platform_driver); + return ret; +} + +static void __exit ix9_platform_exit(void) +{ + platform_device_unregister(ix9_device); + platform_driver_unregister(&ix9_platform_driver); +} + +module_init(ix9_platform_init); +module_exit(ix9_platform_exit); + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta IX9 Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/service/ix9-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/service/ix9-platform-init.service new file mode 100755 index 0000000000..1f33cc1701 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/service/ix9-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX9-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix9_util.py install +ExecStop=/usr/local/bin/quanta_ix9_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/setup.py new file mode 100644 index 0000000000..b2f1b39fcd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix9_32x', + version='1.0', + description='Module to initialize Quanta IX9-32X platforms', + + packages=['ix9_32x'], + package_dir={'ix9_32x': 'ix9-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py new file mode 100755 index 0000000000..4c31aa8584 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer 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 + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +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': + install() + elif arg == 'clean': + 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 "[IX9-32X]"+txt + return + +def exec_cmd(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 + +instantiate =[ +#turn on module power +'echo 21 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio21/direction', +'echo 1 >/sys/class/gpio/gpio21/value', +#Reset fron-ports LED CPLD +'echo 33 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio33/direction', +'echo 0 >/sys/class/gpio/gpio33/value', +'echo 1 >/sys/class/gpio/gpio33/value', +#Enable front-ports LED decoding +'echo 1 > /sys/class/cpld-led/CPLDLED-1/led_decode', +'echo 1 > /sys/class/cpld-led/CPLDLED-2/led_decode', +#Update System LED +'echo 39 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio39/direction', +'echo 0 > /sys/class/gpio/gpio39/value', +'echo 40 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio40/direction', +'echo 1 > /sys/class/gpio/gpio40/value', +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'qci_cpld_qsfpdd', +'qci_cpld_led', +'qci_platform_ix9', +'ipmi_devintf' +] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #remove net rules for generating new net rules + status, output = exec_cmd("systemctl stop systemd-udevd.service ", 1) + status, output = exec_cmd("rm /etc/udev/rules.d/70-persistent-net.rules ", 1) + status, output = exec_cmd("rmmod ixgbe ", 1) + status, output = exec_cmd("rmmod igb ", 1) + status, output = exec_cmd("modprobe igb ", 1) + status, output = exec_cmd("modprobe ixgbe ", 1) + status, output = exec_cmd("systemctl start systemd-udevd.service ", 1) + + #instantiate devices + for i in range(0,len(instantiate)): + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + #QSFPDD for 1~32 port + for port_number in range(1,33): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + return + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " ix9 driver already installed...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"i2c-0", 0) + return ret1 + +if __name__ == "__main__": + main() + + + diff --git a/src/sonic-device-data/tests/permitted_list b/src/sonic-device-data/tests/permitted_list index 7e9adc1df3..6e5a066fff 100644 --- a/src/sonic-device-data/tests/permitted_list +++ b/src/sonic-device-data/tests/permitted_list @@ -153,3 +153,8 @@ ifp_inports_support_enable port_flex_enable pdma_descriptor_prefetch_enable pktdma_poll_mode_channel_bitmap +ccm_dma_enable +ccmdma_intr_enable +phy_enable +init_all_modules +port_fec