[Quanta] Add a new supported device and platform, IX9-32X (#3341)
Switch Vendor: Quanta Switch SKU: IX9-32X CPU: Broadwell-DE with BMC ASIC Vendor: Broadcom Switch ASIC: Tomahawk3, BCM56980 Port Configuration: 32x400G Signed-off-by: Jonathan Tsai <jonathan.tsai@quantatw.com>
This commit is contained in:
Родитель
f65c7969b6
Коммит
ee31e3b8bb
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/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
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
Quanta-IX9-32X t1
|
|
@ -0,0 +1,3 @@
|
|||
CONSOLE_PORT=0x3f8
|
||||
CONSOLE_DEV=0
|
||||
CONSOLE_SPEED=115200
|
|
@ -0,0 +1,2 @@
|
|||
sleep 10
|
||||
led auto on
|
|
@ -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)
|
|
@ -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 <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 <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
|
|
@ -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
|
||||
|
||||
|
|
@ -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) \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -25,3 +25,10 @@ sonic-quanta-platform-modules (1.0) unstable; urgency=low
|
|||
* Initial release
|
||||
|
||||
-- Chih-Pei Chang <Chih-Pei.Chang@qct.io> Jonathan Tsai <jonathan.tsai@quantatw.com> 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 <jonathan.tsai@quantatw.com> Thu, 31 Jan 2019 13:09:01 +0800
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
obj-m:=qci_cpld_qsfpdd.o qci_cpld_led.o qci_platform_ix9.o
|
||||
|
||||
|
|
@ -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 <luffy.cheng@quantatw.com>
|
||||
* Author: Roger Chang <Roger.Chang@quantatw.com>
|
||||
*
|
||||
* 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 <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
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 <luffy.cheng@quantatw.com>");
|
||||
MODULE_AUTHOR("Roger Chang <Roger.Chang@quantatw.com>");
|
||||
MODULE_DESCRIPTION("Quanta Switch LED CPLD driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -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 <luffy.cheng@quantatw.com>
|
||||
*
|
||||
* 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 <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
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 <luffy.cheng@quantatw.com>");
|
||||
MODULE_DESCRIPTION("Quanta Switch SFP CPLD driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -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 <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sparse-keymap.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c/pca954x.h>
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,12,0)
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#else
|
||||
#include <linux/i2c/pca953x.h>
|
||||
#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 <jonathan.tsai@quantatw.com>");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_DESCRIPTION("Quanta IX9 Platform Driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -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
|
|
@ -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'},
|
||||
)
|
||||
|
217
platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py
Executable file
217
platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py
Executable file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
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()
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче