[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:
Jonathan Tsai 2019-08-15 15:43:34 +08:00 committed by lguohan
parent f65c7969b6
commit ee31e3b8bb
23 changed files with 1881 additions and 1 deletions

View File

@ -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

View File

@ -0,0 +1 @@
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-ix9-32x400G.config.bcm

View File

@ -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

View File

@ -0,0 +1 @@
Quanta-IX9-32X t1

View File

@ -0,0 +1,3 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200

View File

@ -0,0 +1,2 @@
sleep 10
led auto on

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -45,6 +45,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(QUANTA_IX7_32X_PLATFORM_MODULE) \ $(QUANTA_IX7_32X_PLATFORM_MODULE) \
$(QUANTA_IX8_56X_PLATFORM_MODULE) \ $(QUANTA_IX8_56X_PLATFORM_MODULE) \
$(QUANTA_IX8C_56X_PLATFORM_MODULE) \ $(QUANTA_IX8C_56X_PLATFORM_MODULE) \
$(QUANTA_IX9_32X_PLATFORM_MODULE) \
$(MITAC_LY1200_32X_PLATFORM_MODULE) \ $(MITAC_LY1200_32X_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \ $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \ $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \

View File

@ -4,11 +4,13 @@ QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION = 1.0
QUANTA_IX7_32X_PLATFORM_MODULE_VERSION = 1.0 QUANTA_IX7_32X_PLATFORM_MODULE_VERSION = 1.0
QUANTA_IX8_56X_PLATFORM_MODULE_VERSION = 1.0 QUANTA_IX8_56X_PLATFORM_MODULE_VERSION = 1.0
QUANTA_IX8C_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_IX1B_32X_PLATFORM_MODULE_VERSION
export QUANTA_IX7_32X_PLATFORM_MODULE_VERSION export QUANTA_IX7_32X_PLATFORM_MODULE_VERSION
export QUANTA_IX8_56X_PLATFORM_MODULE_VERSION export QUANTA_IX8_56X_PLATFORM_MODULE_VERSION
export QUANTA_IX8C_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 = 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 $(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 $(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))) $(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) SONIC_STRETCH_DEBS += $(QUANTA_IX1B_32X_PLATFORM_MODULE)

View File

@ -25,3 +25,10 @@ sonic-quanta-platform-modules (1.0) unstable; urgency=low
* Initial release * Initial release
-- Chih-Pei Chang <Chih-Pei.Chang@qct.io> Jonathan Tsai <jonathan.tsai@quantatw.com> Thu, 4 Jan 2018 13:50:01 +0800 -- 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

View File

@ -20,3 +20,7 @@ Description: kernel modules for platform devices such as psu, led, sfp
Package: sonic-platform-quanta-ix8c-56x Package: sonic-platform-quanta-ix8c-56x
Architecture: amd64 Architecture: amd64
Description: kernel modules for platform devices such as psu, led, sfp 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

View File

@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-quanta
KVERSION ?= $(shell uname -r) KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION) KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd) 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 MODULE_DIR := modules
UTILS_DIR := utils UTILS_DIR := utils
SERVICE_DIR := service SERVICE_DIR := service

View File

@ -0,0 +1,3 @@
obj-m:=qci_cpld_qsfpdd.o qci_cpld_led.o qci_platform_ix9.o

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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

View File

@ -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'},
)

View 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()

View File

@ -153,3 +153,8 @@ ifp_inports_support_enable
port_flex_enable port_flex_enable
pdma_descriptor_prefetch_enable pdma_descriptor_prefetch_enable
pktdma_poll_mode_channel_bitmap pktdma_poll_mode_channel_bitmap
ccm_dma_enable
ccmdma_intr_enable
phy_enable
init_all_modules
port_fec