[Ingrasys] Add platform support for S9180-32X/S9280-64X with Barefoot ASIC on master branch (#1880)

* delete barefoot sonic-platform-modules-ingrasys

* add submodule for barefoot sonic-platform-modules-ingrasys

* add barefoot platform supports on master branch

* change the default speed from 40G to 100G

* remove barefoot sonic-platform-modules-ingrasys submodule

* add ingrasys s9180-32x, s9280-64x barefoot platform drivers

* update s9280-64x vdd core voltage

* update ingrasys barefoot platform debian rules
This commit is contained in:
Feng Lee 2018-08-02 08:02:48 +08:00 committed by lguohan
parent a8c41d9a66
commit 8e74230e86
43 changed files with 6200 additions and 269 deletions

View File

@ -93,7 +93,7 @@
<PngDec> <PngDec>
<DeviceInterfaceLinks> <DeviceInterfaceLinks>
<DeviceLinkBase i:type="DeviceInterfaceLink"> <DeviceLinkBase i:type="DeviceInterfaceLink">
<Bandwidth>40000</Bandwidth> <Bandwidth>100000</Bandwidth>
<ElementType>DeviceInterfaceLink</ElementType> <ElementType>DeviceInterfaceLink</ElementType>
<EndDevice>OCPSCH0104001MS</EndDevice> <EndDevice>OCPSCH0104001MS</EndDevice>
<EndPort>Ethernet24</EndPort> <EndPort>Ethernet24</EndPort>
@ -101,7 +101,7 @@
<StartPort>Ethernet0</StartPort> <StartPort>Ethernet0</StartPort>
</DeviceLinkBase> </DeviceLinkBase>
<DeviceLinkBase i:type="DeviceInterfaceLink"> <DeviceLinkBase i:type="DeviceInterfaceLink">
<Bandwidth>40000</Bandwidth> <Bandwidth>100000</Bandwidth>
<ElementType>DeviceInterfaceLink</ElementType> <ElementType>DeviceInterfaceLink</ElementType>
<EndDevice>OCPSCH0104002MS</EndDevice> <EndDevice>OCPSCH0104002MS</EndDevice>
<EndPort>Ethernet24</EndPort> <EndPort>Ethernet24</EndPort>

View File

@ -40,9 +40,9 @@ chip "w83795adg-*"
label in0 "0.9V" label in0 "0.9V"
set in0_max 0.927 set in0_max 0.927
set in0_min 0.873 set in0_min 0.873
label in1 "0.86V" label in1 "VDD"
set in1_max 0.877 set in1_max 0.962
set in1_min 0.843 set in1_min 0.717
ignore in2 ignore in2
ignore in3 ignore in3
ignore in4 ignore in4

View File

@ -0,0 +1,65 @@
# name lanes alias speed autoneg fec index
Ethernet0 0,1,2,3 Ethernet0 100000 0 0 0
Ethernet4 4,5,6,7 Ethernet4 100000 0 0 1
Ethernet8 8,9,10,11 Ethernet8 100000 0 0 2
Ethernet12 12,13,14,15 Ethernet12 100000 0 0 3
Ethernet16 16,17,18,19 Ethernet16 100000 0 0 4
Ethernet20 20,21,22,23 Ethernet20 100000 0 0 5
Ethernet24 24,25,26,27 Ethernet24 100000 0 0 6
Ethernet28 28,29,30,31 Ethernet28 100000 0 0 7
Ethernet32 32,33,34,35 Ethernet32 100000 0 0 8
Ethernet36 36,37,38,39 Ethernet36 100000 0 0 9
Ethernet40 40,41,42,43 Ethernet40 100000 0 0 10
Ethernet44 44,45,46,47 Ethernet44 100000 0 0 11
Ethernet48 48,49,50,51 Ethernet48 100000 0 0 12
Ethernet52 52,53,54,55 Ethernet52 100000 0 0 13
Ethernet56 56,57,58,59 Ethernet56 100000 0 0 14
Ethernet60 60,61,62,63 Ethernet60 100000 0 0 15
Ethernet64 64,65,66,67 Ethernet64 100000 0 0 16
Ethernet68 68,69,70,71 Ethernet68 100000 0 0 17
Ethernet72 72,73,74,75 Ethernet72 100000 0 0 18
Ethernet76 76,77,78,79 Ethernet76 100000 0 0 19
Ethernet80 80,81,82,83 Ethernet80 100000 0 0 20
Ethernet84 84,85,86,87 Ethernet84 100000 0 0 21
Ethernet88 88,89,90,91 Ethernet88 100000 0 0 22
Ethernet92 92,93,94,95 Ethernet92 100000 0 0 23
Ethernet96 96,97,98,99 Ethernet96 100000 0 0 24
Ethernet100 100,101,102,103 Ethernet100 100000 0 0 25
Ethernet104 104,105,106,107 Ethernet104 100000 0 0 26
Ethernet108 108,109,110,111 Ethernet108 100000 0 0 27
Ethernet112 112,113,114,115 Ethernet112 100000 0 0 28
Ethernet116 116,117,118,119 Ethernet116 100000 0 0 29
Ethernet120 120,121,122,123 Ethernet120 100000 0 0 30
Ethernet124 124,125,126,127 Ethernet124 100000 0 0 31
Ethernet128 128,129,130,131 Ethernet128 100000 0 0 32
Ethernet132 132,133,134,135 Ethernet132 100000 0 0 33
Ethernet136 136,137,138,139 Ethernet136 100000 0 0 34
Ethernet140 140,141,142,143 Ethernet140 100000 0 0 35
Ethernet144 144,145,146,147 Ethernet144 100000 0 0 36
Ethernet148 148,149,150,151 Ethernet148 100000 0 0 37
Ethernet152 152,153,154,155 Ethernet152 100000 0 0 38
Ethernet156 156,157,158,159 Ethernet156 100000 0 0 39
Ethernet160 160,161,162,163 Ethernet160 100000 0 0 40
Ethernet164 164,165,166,167 Ethernet164 100000 0 0 41
Ethernet168 168,169,170,171 Ethernet168 100000 0 0 42
Ethernet172 172,173,174,175 Ethernet172 100000 0 0 43
Ethernet176 176,177,178,179 Ethernet176 100000 0 0 44
Ethernet180 180,181,182,183 Ethernet180 100000 0 0 45
Ethernet184 184,185,186,187 Ethernet184 100000 0 0 46
Ethernet188 188,189,190,191 Ethernet188 100000 0 0 47
Ethernet192 192,193,194,195 Ethernet192 100000 0 0 48
Ethernet196 196,197,198,199 Ethernet196 100000 0 0 49
Ethernet200 200,201,202,203 Ethernet200 100000 0 0 50
Ethernet204 204,205,206,207 Ethernet204 100000 0 0 51
Ethernet208 208,209,210,211 Ethernet208 100000 0 0 52
Ethernet212 212,213,214,215 Ethernet212 100000 0 0 53
Ethernet216 216,217,218,219 Ethernet216 100000 0 0 54
Ethernet220 220,221,222,223 Ethernet220 100000 0 0 55
Ethernet224 224,225,226,227 Ethernet224 100000 0 0 56
Ethernet228 228,229,230,231 Ethernet228 100000 0 0 57
Ethernet232 232,233,234,235 Ethernet232 100000 0 0 58
Ethernet236 236,237,238,239 Ethernet236 100000 0 0 59
Ethernet240 240,241,242,243 Ethernet240 100000 0 0 60
Ethernet244 244,245,246,247 Ethernet244 100000 0 0 61
Ethernet248 248,249,250,251 Ethernet248 100000 0 0 62
Ethernet252 252,253,254,255 Ethernet252 100000 0 0 63

View File

@ -0,0 +1,33 @@
{
"chip_list": [
{
"id": "asic-0",
"chip_family": "Tofino",
"instance": 0,
"pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0",
"pcie_domain": 0,
"pcie_bus": 5,
"pcie_fn": 0,
"pcie_dev": 0,
"pcie_int_mode": 1,
"sds_fw_path": "share/tofino_sds_fw/avago/firmware"
}
],
"instance": 0,
"p4_program_list": [
{
"id": "pgm-0",
"instance": 0,
"path": "switch",
"program-name": "switch",
"pd": "lib/tofinopd/switch/libpd.so",
"pd-thrift": "lib/tofinopd/switch/libpdthrift.so",
"table-config": "share/tofinopd/switch/context.json",
"tofino-bin": "share/tofinopd/switch/tofino.bin",
"switchapi": "lib/libswitchapi.so",
"switchsai": "lib/libswitchsai.so",
"agent0": "lib/platform/x86_64-ingrasys_s9280_64x-r0/libpltfm_mgr.so",
"switchapi_port_add": false
}
]
}

View File

@ -0,0 +1,9 @@
INTERVAL=10
DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon3=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-6/6-004e
DEVNAME=hwmon1=w83795adg
FCTEMPS=hwmon1/device/pwm2=hwmon3/temp1_input
FCFANS=hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm2=hwmon1/device/fan3_input hwmon1/device/pwm2=hwmon1/device/fan1_input
MINTEMP=hwmon1/device/pwm2=20
MAXTEMP=hwmon1/device/pwm2=60
MINSTART=hwmon1/device/pwm2=75
MINSTOP=hwmon1/device/pwm2=22

View File

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

View File

@ -0,0 +1,151 @@
<DeviceMiniGraph xmlns="Microsoft.Search.Autopilot.Evolution" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CpgDec>
<IsisRouters xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
<PeeringSessions>
<BGPSession>
<StartRouter>OCPSCH0104001MS</StartRouter>
<StartPeer>10.10.1.26</StartPeer>
<EndRouter>OCPSCH01040GGLF</EndRouter>
<EndPeer>10.10.1.25</EndPeer>
<Multihop>1</Multihop>
<HoldTime>10</HoldTime>
<KeepAliveTime>3</KeepAliveTime>
</BGPSession>
<BGPSession>
<StartRouter>OCPSCH0104002MS</StartRouter>
<StartPeer>10.10.2.26</StartPeer>
<EndRouter>OCPSCH01040GGLF</EndRouter>
<EndPeer>10.10.2.25</EndPeer>
<Multihop>1</Multihop>
<HoldTime>10</HoldTime>
<KeepAliveTime>3</KeepAliveTime>
</BGPSession>
</PeeringSessions>
<Routers xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
<a:BGPRouterDeclaration>
<a:ASN>64536</a:ASN>
<a:Hostname>OCPSCH01040GGLF</a:Hostname>
<a:Peers>
<BGPPeer>
<Address>10.10.1.26</Address>
<RouteMapIn i:nil="true"/>
<RouteMapOut i:nil="true"/>
</BGPPeer>
<BGPPeer>
<Address>10.10.2.26</Address>
<RouteMapIn i:nil="true"/>
<RouteMapOut i:nil="true"/>
</BGPPeer>
</a:Peers>
<a:RouteMaps/>
</a:BGPRouterDeclaration>
<a:BGPRouterDeclaration>
<a:ASN>64542</a:ASN>
<a:Hostname>OCPSCH0104001MS</a:Hostname>
<a:RouteMaps/>
</a:BGPRouterDeclaration>
<a:BGPRouterDeclaration>
<a:ASN>64543</a:ASN>
<a:Hostname>OCPSCH0104002MS</a:Hostname>
<a:RouteMaps/>
</a:BGPRouterDeclaration>
</Routers>
</CpgDec>
<DpgDec>
<DeviceDataPlaneInfo>
<IPSecTunnels/>
<LoopbackIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
<a:LoopbackIPInterface>
<Name>HostIP</Name>
<AttachTo>Loopback0</AttachTo>
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.NetMux">
<b:IPPrefix>100.0.0.9/32</b:IPPrefix>
</a:Prefix>
<a:PrefixStr>100.0.0.9/32</a:PrefixStr>
</a:LoopbackIPInterface>
</LoopbackIPInterfaces>
<ManagementIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
</ManagementIPInterfaces>
<MplsInterfaces/>
<MplsTeInterfaces/>
<RsvpInterfaces/>
<Hostname>OCPSCH01040GGLF</Hostname>
<PortChannelInterfaces/>
<VlanInterfaces/>
<IPInterfaces>
<IPInterface>
<Name i:nil="true"/>
<AttachTo>Ethernet0</AttachTo>
<Prefix>10.10.1.25/30</Prefix>
</IPInterface>
<IPInterface>
<Name i:nil="true"/>
<AttachTo>Ethernet4</AttachTo>
<Prefix>10.10.2.25/30</Prefix>
</IPInterface>
</IPInterfaces>
<DataAcls/>
<AclInterfaces/>
<DownstreamSummaries/>
<DownstreamSummarySet xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
</DeviceDataPlaneInfo>
</DpgDec>
<PngDec>
<DeviceInterfaceLinks>
<DeviceLinkBase i:type="DeviceInterfaceLink">
<Bandwidth>100000</Bandwidth>
<ElementType>DeviceInterfaceLink</ElementType>
<EndDevice>OCPSCH0104001MS</EndDevice>
<EndPort>Ethernet24</EndPort>
<StartDevice>OCPSCH01040GGLF</StartDevice>
<StartPort>Ethernet0</StartPort>
</DeviceLinkBase>
<DeviceLinkBase i:type="DeviceInterfaceLink">
<Bandwidth>100000</Bandwidth>
<ElementType>DeviceInterfaceLink</ElementType>
<EndDevice>OCPSCH0104002MS</EndDevice>
<EndPort>Ethernet24</EndPort>
<StartDevice>OCPSCH01040GGLF</StartDevice>
<StartPort>Ethernet4</StartPort>
</DeviceLinkBase>
</DeviceInterfaceLinks>
<Devices>
<Device i:type="LeafRouter">
<Hostname>OCPSCH01040GGLF</Hostname>
<HwSku>INGRASYS-S9280-64X</HwSku>
</Device>
</Devices>
</PngDec>
<MetadataDeclaration>
<Devices xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
<a:DeviceMetadata>
<a:Name>OCPSCH01040GGLF</a:Name>
<a:Properties>
<a:DeviceProperty>
<a:Name>DhcpResources</a:Name>
<a:Reference i:nil="true"/>
<a:Value></a:Value>
</a:DeviceProperty>
<a:DeviceProperty>
<a:Name>NtpResources</a:Name>
<a:Reference i:nil="true"/>
<a:Value>0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org</a:Value>
</a:DeviceProperty>
<a:DeviceProperty>
<a:Name>SyslogResources</a:Name>
<a:Reference i:nil="true"/>
<a:Value></a:Value>
</a:DeviceProperty>
<a:DeviceProperty>
<a:Name>ErspanDestinationIpv4</a:Name>
<a:Reference i:nil="true"/>
<a:Value>2.2.2.2</a:Value>
</a:DeviceProperty>
</a:Properties>
</a:DeviceMetadata>
</Devices>
<Properties xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
</MetadataDeclaration>
<Hostname>OCPSCH01040GGLF</Hostname>
<HwSku>INGRASYS-S9280-64X</HwSku>
</DeviceMiniGraph>

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
#############################################################################
# Ingrasys S9280-64X
#
# Platform and model specific eeprom subclass, inherits from the base class,
# and provides the followings:
# - the eeprom format definition
# - specific encoder/decoder if there is special need
#############################################################################
try:
from sonic_eeprom import eeprom_tlvinfo
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,93 @@
#
# 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"""
# TODO: need to check if the patch mapping correct
SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050",
"/sys/bus/i2c/devices/i2c-17/17-0050"]
def __init__(self):
PsuBase.__init__(self)
# Get sysfs attribute
def get_attr_value(self, attr_path):
retval = 'ERR'
if (not os.path.isfile(attr_path)):
return retval
try:
with open(attr_path, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", attr_path, " file !")
retval = retval.rstrip('\r\n')
return retval
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 = 0
attr_file = 'psu_pg'
attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
if (attr_value != 'ERR'):
attr_value = int(attr_value, 16)
# Check for PSU status
if (attr_value == 1):
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 = 0
psu_absent = 0
attr_file ='psu_abs'
attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
if (attr_value != 'ERR'):
attr_value = int(attr_value, 16)
# Check for PSU presence
if (attr_value == 0):
status = 1
return status

View File

@ -0,0 +1,300 @@
# sfputil.py
#
# Platform-specific SFP transceiver interface for SONiC
#
try:
import time
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
PORT_START = 0
PORT_END = 63
PORTS_IN_BLOCK = 64
EEPROM_OFFSET = 41
CPLD1_PORTS = 12
CPLDx_PORTS = 13
#TODO: check init sequence for CPLD i2c bus
CPLD_OFFSET = 1
CPLD_PRES_BIT = 1
CPLD_RESET_BIT = 0
CPLD_LPMOD_BIT = 2
CPLDx_I2C_ADDR = "33"
EEPROM_I2C_ADDR = "50"
CPLD_PORT_STATUS_KEY = "cpld_qsfp_port_status"
CPLD_PORT_CONFIG_KEY = "cpld_qsfp_port_config"
CPLD_REG_PATH = "/sys/bus/i2c/devices/{0}-00{1}/{2}_{3}"
_port_to_eeprom_mapping = {}
#TODO: check the fp port to phy port mapping
_fp2phy_port_mapping = {
0: 0,
1: 1,
2: 4,
3: 5,
4: 8,
5: 9,
6: 12,
7: 13,
8: 16,
9: 17,
10: 20,
11: 21,
12: 24,
13: 25,
14: 28,
15: 29,
16: 32,
17: 33,
18: 36,
19: 37,
20: 40,
21: 41,
22: 44,
23: 45,
24: 48,
25: 49,
26: 52,
27: 53,
28: 56,
29: 57,
30: 60,
31: 61,
32: 2,
33: 3,
34: 6,
35: 7,
36: 10,
37: 11,
38: 14,
39: 15,
40: 18,
41: 19,
42: 22,
43: 23,
44: 26,
45: 27,
46: 30,
47: 31,
48: 34,
49: 35,
50: 38,
51: 39,
52: 42,
53: 43,
54: 46,
55: 47,
56: 50,
57: 51,
58: 54,
59: 55,
60: 58,
61: 59,
62: 62,
63: 63
}
@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 __init__(self):
# Override port_to_eeprom_mapping for class initialization
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-00{1}/eeprom"
for x in range(self.port_start, self.port_end + 1):
phy_port = self.fp2phy_port_num(x)
port_eeprom_path = eeprom_path.format(phy_port + self.EEPROM_OFFSET, self.EEPROM_I2C_ADDR)
self.port_to_eeprom_mapping[x] = port_eeprom_path
SfpUtilBase.__init__(self)
def qsfp_to_cpld_index(self, port_num):
if port_num < self.CPLD1_PORTS:
cpld_id = 0
cpld_port_index = port_num + 1
else:
cpld_id = 1 + (port_num - self.CPLD1_PORTS) / self.CPLDx_PORTS
cpld_port_index = ((port_num - self.CPLD1_PORTS) % self.CPLDx_PORTS) + 1
return cpld_id, cpld_port_index
def fp2phy_port_num(self, fp_port_num):
phy_port_num = self._fp2phy_port_mapping[fp_port_num]
return phy_port_num
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
# logic port to physical port mapping
port_num = self.fp2phy_port_num(port_num)
cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num)
i2c_id = self.CPLD_OFFSET + cpld_id
reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \
self.CPLD_PORT_STATUS_KEY, cpld_port_index)
try:
reg_file = open(reg_path)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
# content is a string containing the status register value
content = reg_file.readline().rstrip()
reg_file.close()
reg_value = int(content, 16)
# mask for presence bit (bit 1)
mask = (1 << self.CPLD_PRES_BIT)
# 0 - presence, 1 - absence
if reg_value & mask == 0:
return True
return False
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
# logic port to physical port mapping
port_num = self.fp2phy_port_num(port_num)
cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num)
i2c_id = self.CPLD_OFFSET + cpld_id
reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \
self.CPLD_PORT_CONFIG_KEY, cpld_port_index)
try:
reg_file = open(reg_path)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
# content is a string containing the status register value
content = reg_file.readline().rstrip()
reg_file.close()
reg_value = int(content, 16)
# mask for lp_mod bit (bit 2)
mask = (1 << self.CPLD_LPMOD_BIT)
# 0 - disable, 1 - low power mode
if reg_value & mask == 0:
return False
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
# logic port to physical port mapping
port_num = self.fp2phy_port_num(port_num)
cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num)
i2c_id = self.CPLD_OFFSET + cpld_id
reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \
self.CPLD_PORT_CONFIG_KEY, cpld_port_index)
try:
reg_file = open(reg_path, "r+")
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
# content is a string containing the status register value
content = reg_file.readline().rstrip()
reg_value = int(content, 16)
# mask for lp_mod bit (bit 2)
mask = (1 << self.CPLD_LPMOD_BIT)
# 1 - low power mode, 0 - high power mode
if lpmode is True:
reg_value = reg_value | mask
else:
reg_value = reg_value & ~mask
# convert value to hex string
content = hex(reg_value)
reg_file.seek(0)
reg_file.write(content)
reg_file.close()
return True
def reset(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
# logic port to physical port mapping
port_num = self.fp2phy_port_num(port_num)
cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num)
i2c_id = self.CPLD_OFFSET + cpld_id
reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, \
self.CPLD_PORT_CONFIG_KEY, cpld_port_index)
# reset the port
try:
reg_file = open(reg_path, "r+")
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
# content is a string containing the status register value
content = reg_file.readline().rstrip()
reg_value = int(content, 16)
# mask for reset bit (bit 0)
mask = (1 << self.CPLD_RESET_BIT)
# 1 - out of reset, 0 - reset
reg_value = reg_value & ~mask
reg_file.seek(0)
reg_file.write(hex(reg_value))
reg_file.close()
# Sleep 1 second to reset done
time.sleep(1)
# take the port out of reset
try:
reg_file = open(reg_path, "w")
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
reg_value = reg_value | mask
reg_file.seek(0)
reg_file.write(hex(reg_value))
reg_file.close()
return True

View File

@ -0,0 +1,85 @@
# libsensors configuration file
chip "i350bb-*"
ignore loc1
chip "jc42-*"
bus "i2c-16" "i2c-mux-1 (chan_id 7)"
chip "w83795adg-*"
ignore in0
label in1 "VDD_CORE"
set in1_min 0.717
set in1_max 0.962
ignore in2
ignore in3
label in4 "3.3V"
compute in4 @/(0.3052), (0.3052)*@
set in4_min 3.3 * 0.95
set in4_max 3.3 * 1.05
label in5 "0.9V"
set in5_min 0.90 * 0.98
set in5_max 0.90 * 1.02
ignore in6
ignore in7
ignore in8
ignore in9
ignore in10
ignore in11
ignore in12
ignore in13
ignore in14
ignore in15
ignore in16
ignore in17
ignore in18
ignore in19
label fan1 "FANTRAY 1"
ignore fan2
label fan3 "FANTRAY 2"
ignore fan4
label fan5 "FANTRAY 3"
ignore fan6
label fan7 "FANTRAY 4"
ignore fan8
ignore temp1
ignore temp2
ignore temp3
ignore temp4
ignore temp5
ignore temp6
ignore intrusion0
chip "tmp75-i2c-*-4A"
label temp1 "BMC Board Temp"
set temp1_max 50
set temp1_max_hyst 45
bus "i2c-0" "SMBus I801 adapter at f000"
chip "tmp75-i2c-*-4F"
label temp1 "x86 CPU Board Temp"
set temp1_max 50
set temp1_max_hyst 45
bus "i2c-6" "i2c-0-mux (chan_id 5)"
chip "lm75-i2c-6-4D"
label temp1 "Rear Panel Temp"
set temp1_max 50
set temp1_max_hyst 45
chip "lm75-i2c-6-4E"
label temp1 "Rear MAC Temp"
set temp1_max 50
set temp1_max_hyst 45
chip "lm86-i2c-6-4C"
label temp1 "MB Temp"
set temp1_max 50
label temp2 "MAC Temp"
set temp2_max 70
bus "i2c-7" "i2c-0-mux (chan_id 6)"
chip "lm75-i2c-7-4D"
label temp1 "Front Panel Temp"
set temp1_max 50
set temp1_max_hyst 45
chip "lm75-i2c-7-4E"
label temp1 "Front MAC Temp"
set temp1_max 50
set temp1_max_hyst 45

View File

@ -1,5 +1,5 @@
BFN_INGRASYS_PLATFORM = bfnplatform-ingrasys_1.0.0_amd64.deb BFN_INGRASYS_PLATFORM = bfnplatform-ingrasys_8.2.0_amd64.deb
$(BFN_INGRASYS_PLATFORM)_URL = "https://github.com/Ingrasys-sonic/packages/raw/master/lib/bfnplatform-ingrasys_1.0.0_amd64.deb" $(BFN_INGRASYS_PLATFORM)_URL = "https://github.com/Ingrasys-sonic/packages/raw/master/lib/bfnplatform-ingrasys_8.2.0_amd64.deb"
SONIC_ONLINE_DEBS += $(BFN_INGRASYS_PLATFORM) # $(BFN_SAI_DEV) SONIC_ONLINE_DEBS += $(BFN_INGRASYS_PLATFORM) # $(BFN_SAI_DEV)
$(BFN_SAI_DEV)_DEPENDS += $(BFN_INGRASYS_PLATFORM) $(BFN_SAI_DEV)_DEPENDS += $(BFN_INGRASYS_PLATFORM)

View File

@ -7,5 +7,6 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(BFN_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WNC_OSW1800_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WNC_OSW1800_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9180_32X_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9280_64X_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES)
SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) SONIC_INSTALLERS += $(SONIC_ONE_IMAGE)

View File

@ -1,11 +1,18 @@
# Ingrasys S9180-32X Platform modules # Ingrasys S9180-32X Platform modules
INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION = 1.1.0 INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION = 1.1.0
INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION = 1.1.0
export INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION export INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION
export INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION
INGRASYS_S9180_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9180-32x_$(INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION)_amd64.deb INGRASYS_S9180_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9180-32x_$(INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION)_amd64.deb
$(INGRASYS_S9180_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys $(INGRASYS_S9180_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys
$(INGRASYS_S9180_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) $(INGRASYS_S9180_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(INGRASYS_S9180_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9180_32x-r0 $(INGRASYS_S9180_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9180_32x-r0
SONIC_DPKG_DEBS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) SONIC_DPKG_DEBS += $(INGRASYS_S9180_32X_PLATFORM_MODULE)
INGRASYS_S9280_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9280-64x_$(INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION)_amd64.deb
$(INGRASYS_S9280_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9280_64x-r0
$(eval $(call add_extra_package,$(INGRASYS_S9180_32X_PLATFORM_MODULE),$(INGRASYS_S9280_64X_PLATFORM_MODULE)))

View File

@ -1,15 +1,9 @@
platform-driver (1.1.0) unstable; urgency=low platform-driver (1.1.0) unstable; urgency=low
* Add support for s9180-32x * Add support for s9180-32x s9280-64x
-- developer <developer@ingrasys.com> Fri, 26 May 2017 11:00:00 +0800 -- developer <developer@ingrasys.com> Fri, 26 May 2017 11:00:00 +0800
platform-driver (1.1.0) unstable; urgency=low
* Add support for s8900 series
-- developer <developer@ingrasys.com> Wed, 29 Mar 2017 11:00:00 +0800
platform-driver (1.0.0) unstable; urgency=low platform-driver (1.0.0) unstable; urgency=low
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP> * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>

View File

@ -8,3 +8,7 @@ Standards-Version: 1.0.0
Package: sonic-platform-ingrasys-s9180-32x Package: sonic-platform-ingrasys-s9180-32x
Architecture: amd64 Architecture: amd64
Description: This package contains S9180-32X platform driver utility for SONiC project. Description: This package contains S9180-32X platform driver utility for SONiC project.
Package: sonic-platform-ingrasys-s9280-64x
Architecture: amd64
Description: This package contains S9280-64X platform driver utility for SONiC project.

View File

@ -1,13 +1,4 @@
#!/usr/bin/make -f #!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
export INSTALL_MOD_DIR:=extra export INSTALL_MOD_DIR:=extra
@ -15,7 +6,7 @@ PACKAGE_PRE_NAME := sonic-platform-ingrasys
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:= s9180-32x MODULE_DIRS:= s9180-32x s9280-64x
MODULE_DIR := modules MODULE_DIR := modules
UTILS_DIR := utils UTILS_DIR := utils
SERVICE_DIR := service SERVICE_DIR := service
@ -24,58 +15,28 @@ CONF_DIR := conf
%: %:
dh $@ --with systemd dh $@ --with systemd
clean: override_dh_auto_build:
dh_testdir
dh_testroot
dh_clean
build:
#make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC)
(for mod in $(MODULE_DIRS); do \ (for mod in $(MODULE_DIRS); do \
make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
done) done)
binary: binary-arch binary-indep override_dh_auto_install:
# Nothing to do
binary-arch:
# Nothing to do
#install: build
#dh_testdir
#dh_testroot
#dh_clean -k
#dh_installdirs
binary-indep:
dh_testdir
dh_installdirs
# Custom package commands
(for mod in $(MODULE_DIRS); do \ (for mod in $(MODULE_DIRS); do \
mkdir debian/tmp/usr/sbin -p; \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \
mkdir debian/tmp/lib/systemd/system -p; \ $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
mkdir debian/tmp/etc/init.d -p; \ cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \
cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin/; \ cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \
cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/bfn debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/init\.d/; \ debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \
cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \
cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \
debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \
done) done)
# Resuming debhelper scripts
dh_testroot override_dh_clean:
dh_install dh_clean
dh_installchangelogs (for mod in $(MODULE_DIRS); do \
dh_installdocs make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \
dh_systemd_enable done)
dh_installinit
dh_systemd_start
dh_link
dh_fixperms
dh_compress
dh_strip
dh_installdeb
dh_gencontrol
dh_md5sums
dh_builddeb
.PHONY: build binary binary-arch binary-indep clean

View File

@ -1,4 +0,0 @@
usr/sbin
lib/systemd/system
etc/
etc/init.d/

View File

@ -0,0 +1,41 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: setup-board
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup S9180-32X board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
depmod -a
echo "done."
;;
stop)
i2c_utils.sh i2c_deinit
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9180-32x.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -1,4 +0,0 @@
lib/systemd/
usr/sbin/
etc/
etc/init.d/

View File

@ -1,57 +0,0 @@
# Automatically added by dh_systemd_enable
# This will only remove masks created by d-s-h on package removal.
deb-systemd-helper unmask s9180-32x-monitor.service >/dev/null || true
deb-systemd-helper unmask bfn.service >/dev/null || true
deb-systemd-helper unmask qsfp-monitor.service >/dev/null || true
# Generate kernel modules.dep and map files for add eeprom_mb.
depmod -a || true
# was-enabled defaults to true, so new installations run enable.
if deb-systemd-helper --quiet was-enabled s9180-32x-monitor.service; then
# Enables the unit on first installation, creates new
# symlinks on upgrades if the unit file has changed.
deb-systemd-helper enable s9180-32x-monitor.service >/dev/null || true
else
# Update the statefile to add new symlinks (if any), which need to be
# cleaned up on purge. Also remove old symlinks.
deb-systemd-helper update-state s9180-32x-monitor.service >/dev/null || true
fi
if deb-systemd-helper --quiet was-enabled bfn.service; then
# Enables the unit on first installation, creates new
# symlinks on upgrades if the unit file has changed.
deb-systemd-helper enable bfn.service >/dev/null || true
else
# Update the statefile to add new symlinks (if any), which need to be
# cleaned up on purge. Also remove old symlinks.
deb-systemd-helper update-state bfn.service >/dev/null || true
fi
if deb-systemd-helper --quiet was-enabled qsfp-monitor.service; then
# Enables the unit on first installation, creates new
# symlinks on upgrades if the unit file has changed.
deb-systemd-helper enable qsfp-monitor.service >/dev/null || true
else
# Update the statefile to add new symlinks (if any), which need to be
# cleaned up on purge. Also remove old symlinks.
deb-systemd-helper update-state qsfp-monitor.service >/dev/null || true
fi
# End automatically added section
# Automatically added by dh_installinit
if [ -x "/etc/init.d/s9180-32x-monitor" ]; then
update-rc.d s9180-32x-monitor defaults >/dev/null
invoke-rc.d s9180-32x-monitor start || exit $?
fi
if [ -x "/etc/init.d/qsfp-monitor" ]; then
update-rc.d qsfp-monitor defaults >/dev/null
invoke-rc.d qsfp-monitor start || exit $?
fi
if [ -x "/etc/init.d/bfn" ]; then
invoke-rc.d bfn start || exit $?
fi
# End automatically added section
# Automatically added by dh_systemd_start
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
deb-systemd-invoke start s9180-32x-monitor.service >/dev/null || true
deb-systemd-invoke start qsfp-monitor.service >/dev/null || true
deb-systemd-invoke start bfn.service >/dev/null || true
fi
# End automatically added section

View File

@ -1,42 +0,0 @@
# Automatically added by dh_systemd_start
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
fi
# End automatically added section
# Automatically added by dh_installinit
if [ "$1" = "purge" ] ; then
update-rc.d s9180-32x-monitor remove >/dev/null
update-rc.d bfn remove >/dev/null
update-rc.d qsfp-monitor remove >/dev/null
fi
# In case this system is running systemd, we make systemd reload the unit files
# to pick up changes.
if [ -d /run/systemd/system ] ; then
systemctl --system daemon-reload >/dev/null || true
fi
# End automatically added section
# Automatically added by dh_systemd_enable
if [ "$1" = "remove" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper mask s9180-32x-monitor.service >/dev/null
deb-systemd-helper mask bfn.service >/dev/null
deb-systemd-helper mask qsfp-monitor.service >/dev/null
fi
fi
if [ "$1" = "purge" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper purge s9180-32x-monitor.service >/dev/null
deb-systemd-helper unmask s9180-32x-monitor.service >/dev/null
deb-systemd-helper purge bfn.service >/dev/null
deb-systemd-helper unmask bfn.service >/dev/null
deb-systemd-helper purge qsfp-monitor.service >/dev/null
deb-systemd-helper unmask qsfp-monitor.service >/dev/null
fi
fi
# Generate kernel modules.dep and map files for remove eeprom_mb.
depmod -a || true
# End automatically added section

View File

@ -1,21 +0,0 @@
# Automatically added by dh_systemd_start
if [ -d /run/systemd/system ]; then
deb-systemd-invoke stop s9180-32x-monitor.service >/dev/null
deb-systemd-invoke stop bfn.service >/dev/null
deb-systemd-invoke stop qsfp-monitor.service >/dev/null
fi
# End automatically added section
# Automatically added by dh_installinit
if [ -x "/etc/init.d/s9180-32x-monitor" ]; then
invoke-rc.d s9180-32x-monitor stop || exit $?
fi
if [ -x "/etc/init.d/bfn" ]; then
invoke-rc.d bfn stop || exit $?
fi
if [ -x "/etc/init.d/qsfp-monitor" ]; then
invoke-rc.d qsfp-monitor stop || exit $?
fi
# Driver deinit
/usr/sbin/i2c_utils.sh i2c_deinit
# End automatically added section

View File

@ -1,7 +0,0 @@
description "SONiC platform service"
respawn
exec /usr/sbin/s9180_32x_monitor.sh
exec /usr/sbin/qsfp_monitor.sh
exec /etc/init.d/bfn start

View File

@ -0,0 +1,41 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: setup-board
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup S9280-64X board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
depmod -a
echo "done."
;;
stop)
i2c_utils i2c_deinit
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9280-64x.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -1 +1,3 @@
obj-m := eeprom_mb.o obj-m := eeprom_mb.o
obj-m+= cpld_wdt.o

View File

@ -0,0 +1,296 @@
/*
* CPLD Watchdog Driver
*
* Copyright (c) 2018 Ingrasys Corp.
*
* Author: Wade He <feng.cf.lee@ingrasys.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, see <http://www.gnu.org/licenses/>.
*/
/*
* Includes, defines, variables, module parameters, ...
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
/* Module and version information */
#define DRV_NAME "cpld_wdt"
#define DRV_VERSION "1.0"
/* Includes */
#include <linux/module.h> /* For module specific items */
#include <linux/moduleparam.h> /* For new moduleparam's */
#include <linux/types.h> /* For standard types (like size_t) */
#include <linux/errno.h> /* For the -ENODEV/... values */
#include <linux/kernel.h> /* For printk/panic/... */
#include <linux/watchdog.h> /* For the watchdog specific items */
#include <linux/init.h> /* For __init/__exit/... */
#include <linux/fs.h> /* For file operations */
#include <linux/platform_device.h> /* For platform_driver framework */
#include <linux/pci.h> /* For pci functions */
#include <linux/ioport.h> /* For io-port access */
#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
#include <linux/io.h> /* For inb/outb/... */
#include <linux/mfd/core.h>
#include <linux/mfd/lpc_ich.h>
#include <linux/kthread.h>
#include <linux/delay.h>
/* Address definitions for the CPLD */
/* CPLD base address */
#define TCOBASE 0x600
/* SMI Control and Enable Register */
#define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */
#define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */
#define TCO_DAT_IN (TCOBASE + 0x02) /* TCO Data In Register */
#define TCO_DAT_OUT (TCOBASE + 0x03) /* TCO Data Out Register */
#define TCO1_STS (TCOBASE + 0x04) /* Control Watchdog Register */
#define TCO2_STS (TCOBASE + 0x06) /* TCO2 Status Register */
#define TCO1_CNT (TCOBASE + 0x08) /* TCO1 Control Register */
#define TCO2_CNT (TCOBASE + 0x0a) /* TCO2 Control Register */
#define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */
#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINT(fmt, args...) \
printk (KERN_INFO "%s[%d]: " fmt "\r\n", \
__FUNCTION__, __LINE__, ##args)
#else
#define DEBUG_PRINT(fmt, args...)
#endif
#define ERROR_MSG(fmt, args...) \
printk(KERN_ERR "%s[%d]: " fmt "\r\n", \
__FUNCTION__, __LINE__, ##args)
/* internal variables */
static struct { /* this is private data for the cpld_wdt device */
/* the lock for io operations */
spinlock_t io_lock;
struct platform_device *dev;
} cpld_wdt_private;
static struct task_struct *cpld_wdt_tsk;
static int data;
static void device_release(struct device *dev)
{
return;
}
static struct platform_device cpld_wdt = {
.name = DRV_NAME,
.id = 0,
.dev = {
.platform_data = NULL,
.release = device_release
},
};
/* module parameters */
#define WATCHDOG_TIMEOUT 15 /* 15 sec default heartbeat */
static int heartbeat = WATCHDOG_TIMEOUT; /* in seconds */
module_param(heartbeat, int, 0);
MODULE_PARM_DESC(heartbeat, "Watchdog ping period in seconds. "
"5..20, default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static int cpld_wdt_check_timeout_range(unsigned int tmrval)
{
if (tmrval < 5 || tmrval > 20) {
DEBUG_PRINT("heartbeat out of range, using default=%d\n", WATCHDOG_TIMEOUT);
heartbeat = WATCHDOG_TIMEOUT;
} else {
DEBUG_PRINT("heartbeat using %d seconds\n", heartbeat);
}
return 0;
}
/*
* Some TCO specific functions
*/
static int cpld_wdt_stop(void *arg)
{
spin_lock(&cpld_wdt_private.io_lock);
outb(0x1, TCO1_STS);
DEBUG_PRINT("cpld_wdt_stop done");
spin_unlock(&cpld_wdt_private.io_lock);
return 0;
}
static int cpld_wdt_ping(void *arg)
{
spin_lock(&cpld_wdt_private.io_lock);
/* Reload the timer by writing to the TCO Timer Counter register */
outb(0x1, TCO1_STS); /* write 1 to clear bit */
udelay(100);
outb(0x3, TCO1_STS);
DEBUG_PRINT("cpld_wdt_ping done");
spin_unlock(&cpld_wdt_private.io_lock);
return 0;
}
static int kthread_wdt_ping_loop(void *arg)
{
int i;
set_current_state(TASK_INTERRUPTIBLE);
while(!kthread_should_stop()) {
DEBUG_PRINT("ping start");
cpld_wdt_ping(NULL);
set_current_state(TASK_INTERRUPTIBLE);
for (i=0;i<heartbeat;i++) {
msleep_interruptible(1000);
if(kthread_should_stop()) {
break;
}
}
DEBUG_PRINT("ping once.");
}
return 0;
}
/*
* Init & exit routines
*/
static void cpld_wdt_cleanup(void)
{
/* Stop the timer before we leave */
if (!nowayout) {
cpld_wdt_stop(NULL);
DEBUG_PRINT("nowayout disabled. stop CPLD WDT success.");
}
DEBUG_PRINT("cpld_wdt_cleanup done");
}
static int cpld_wdt_probe(struct platform_device *dev)
{
int ret = -ENODEV;
spin_lock_init(&cpld_wdt_private.io_lock);
/* Make sure the watchdog is not running */
cpld_wdt_stop(NULL);
cpld_wdt_check_timeout_range(heartbeat);
cpld_wdt_tsk = kthread_create(kthread_wdt_ping_loop, &data, "cpld_wdt_tsk");
if (IS_ERR(cpld_wdt_tsk)) {
ret = PTR_ERR(cpld_wdt_tsk);
cpld_wdt_tsk = NULL;
ERROR_MSG("cpld_wdt_tsk create kthread failed.");
goto out;
}
DEBUG_PRINT("wake_up_process cpld_wdt_tsk");
wake_up_process(cpld_wdt_tsk);
DEBUG_PRINT("wake_up_process done");
return 0;
out:
return ret;
}
static int cpld_wdt_remove(struct platform_device *dev)
{
cpld_wdt_cleanup();
kthread_stop(cpld_wdt_tsk);
DEBUG_PRINT("cpld_wdt_remove done");
return 0;
}
static void cpld_wdt_shutdown(struct platform_device *dev)
{
cpld_wdt_stop(NULL);
DEBUG_PRINT("cpld_wdt_shutdown done");
}
static struct platform_driver cpld_wdt_driver = {
.probe = cpld_wdt_probe,
.remove = cpld_wdt_remove,
.shutdown = cpld_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
},
};
static int __init cpld_wdt_init_module(void)
{
int err;
DEBUG_PRINT("Intel TCO WatchDog Timer Driver v%s\n", DRV_VERSION);
err = platform_driver_register(&cpld_wdt_driver);
if (err) {
ERROR_MSG("platform_driver_register error, err=%d\n", err);
return err;
}
DEBUG_PRINT("platform_driver_register done\n");
err = platform_device_register(&cpld_wdt);
if (err) {
printk(KERN_WARNING "Fail to create cpld device\n");
goto error_cpld;
}
return 0;
error_cpld:
platform_driver_unregister(&cpld_wdt_driver);
return err;
}
static void __exit cpld_wdt_cleanup_module(void)
{
platform_device_unregister(&cpld_wdt);
platform_driver_unregister(&cpld_wdt_driver);
DEBUG_PRINT("Watchdog Module Unloaded\n");
}
module_init(cpld_wdt_init_module);
module_exit(cpld_wdt_cleanup_module);
MODULE_AUTHOR("Wade He<feng.cf.lee@ingrasys.com>");
MODULE_DESCRIPTION("CPLD Watchdog Timer Kernel Driver");
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);

View File

@ -1,13 +0,0 @@
[Unit]
Description=Barefoot Kernel Module
After=local-fs.target
Before=docker.service
[Service]
Type=oneshot
ExecStart=-/etc/init.d/bfn start
ExecStop=-/etc/init.d/bfn stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -1,44 +0,0 @@
#!/bin/bash
# This script load/unload Barefoot kernel modules
### BEGIN INIT INFO
# Provides:
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Load Barefoot kernel modules
### END INIT INFO
case "$1" in
start)
echo -n "Load Barefoot kernel modules... "
modprobe bf_kdrv
modprobe bf_tun
echo "done."
;;
stop)
echo -n "Unload Barefoot kernel modules... "
rmmod bf_tun
rmmod bf_kdrv
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/bfn {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -72,6 +72,7 @@ NUM_FRU_MUX_CHAN2_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 2 )) # FAN
NUM_CPLD_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 3 )) # CPLD NUM_CPLD_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 3 )) # CPLD
NUM_SFP1_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 4 )) # CPLD NUM_SFP1_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 4 )) # CPLD
NUM_SFP2_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 5 )) # CPLD NUM_SFP2_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 5 )) # CPLD
NUM_ROV_DEVICE=${NUM_MAIN_MUX_CHAN6_DEVICE}
PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices"
PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon"
@ -89,12 +90,20 @@ PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}"
PATH_MUX7_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" PATH_MUX7_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}"
PATH_MAIN_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" PATH_MAIN_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}"
# i2c address for deviecs
CPLD_I2C_ADDR=0x33
ROV_I2C_ADDR=0x22
#Power Supply Status #Power Supply Status
PSU_DC_ON=1 PSU_DC_ON=1
PSU_DC_OFF=0 PSU_DC_OFF=0
PSU_EXIST=1 PSU_EXIST=1
PSU_NOT_EXIST=0 PSU_NOT_EXIST=0
# vdd value for mac
rov_val_array=( 0.85 0.82 0.77 0.87 0.74 0.84 0.79 0.89 )
rov_reg_array=( 0x24 0x21 0x1c 0x26 0x19 0x23 0x1e 0x28 )
# Help usage function # Help usage function
function _help { function _help {
echo "=========================================================" echo "========================================================="
@ -159,6 +168,7 @@ function _i2c_init {
modprobe i2c_i801 modprobe i2c_i801
modprobe i2c_dev modprobe i2c_dev
modprobe i2c_mux_pca954x force_deselect_on_exit=1 modprobe i2c_mux_pca954x force_deselect_on_exit=1
#modprobe cpld_wdt
if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then
_retry "echo 'pca9548 0x70' > ${PATH_I801_DEVICE}/new_device" _retry "echo 'pca9548 0x70' > ${PATH_I801_DEVICE}/new_device"
@ -227,9 +237,35 @@ function _i2c_init {
_i2c_led_fan_status_set _i2c_led_fan_status_set
_i2c_led_fan_tray_status_set _i2c_led_fan_tray_status_set
# rov for mac init
_mac_vdd_init
#SYS LED set green #SYS LED set green
COLOR_SYS_LED="green" COLOR_SYS_LED="green"
_i2c_sys_led _i2c_sys_led
}
function _mac_vdd_init {
# read mac vid register value from CPLD
val=`i2cget -y ${NUM_CPLD_DEVICE} ${CPLD_I2C_ADDR} 0x42 2>/dev/null`
# get vid form register value [0:2]
vid=$(($val & 0x7))
# get rov val and reg according to vid
rov_val=${rov_val_array[$vid]}
rov_reg=${rov_reg_array[$vid]}
echo "vid=${vid}, rov_val=${rov_val}, rov_reg=${rov_reg}"
# write the rov reg to rov
i2cset -y -r ${NUM_ROV_DEVICE} ${ROV_I2C_ADDR} 0x21 ${rov_reg} w
if [ $? -eq 0 ]; then
echo "set ROV for mac vdd done"
else
echo "set ROV for mac vdd fail"
fi
} }
#I2C Deinit #I2C Deinit
@ -290,7 +326,7 @@ function _i2c_io_exp_init {
i2cset -y -r ${NUM_I801_DEVICE} 0x26 5 0x00 i2cset -y -r ${NUM_I801_DEVICE} 0x26 5 0x00
i2cset -y -r ${NUM_I801_DEVICE} 0x26 2 0x3F i2cset -y -r ${NUM_I801_DEVICE} 0x26 2 0x3F
i2cset -y -r ${NUM_I801_DEVICE} 0x26 3 0x1F i2cset -y -r ${NUM_I801_DEVICE} 0x26 3 0x1F
i2cset -y -r ${NUM_I801_DEVICE} 0x26 6 0xC0 i2cset -y -r ${NUM_I801_DEVICE} 0x26 6 0xD0
i2cset -y -r ${NUM_I801_DEVICE} 0x26 7 0x00 i2cset -y -r ${NUM_I801_DEVICE} 0x26 7 0x00
#CPU Baord #CPU Baord
@ -914,7 +950,7 @@ function _i2c_qsfp_eeprom_init {
if [ "${action}" == "new" ] && \ if [ "${action}" == "new" ] && \
! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then
echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device
elif [ "${action}" == "delete" ] && \ elif [ "${action}" == "delete" ] && \
[ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then
echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device
@ -1006,7 +1042,7 @@ function _i2c_sfp_eeprom_init {
return return
fi fi
#Init 1-32 ports EEPROM #Init 33-34 ports EEPROM
if [ "${action}" == "new" ] && \ if [ "${action}" == "new" ] && \
! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \
! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then

View File

@ -21,6 +21,7 @@ I2C_UTILS="/usr/sbin/i2c_utils.sh"
# TBD: LED status monitor # TBD: LED status monitor
function _led_monitor { function _led_monitor {
${I2C_UTILS} i2c_led_fan_status_set >/dev/null ${I2C_UTILS} i2c_led_fan_status_set >/dev/null
${I2C_UTILS} i2c_led_psu_status_set >/dev/null
${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null
} }

View File

@ -0,0 +1,175 @@
# Ingrasys S9280-64X Platform Driver for SONiC
Copyright (C) 2016 Ingrasys, 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/>.
## Licensing terms
The Licensing terms of the files within this project is split 2 parts.
The Linux kernel is released under the GNU General Public License version 2.
All other code is released under the GNU General Public License version 3.
Please see the LICENSE file for copies of both licenses.
## Contents of this package
- service/
> Service config files for platform initialization and monitoring
- utils/
> Scripts useful during platform bringup and sysfs function
- conf/
> Platform configure files.
## Kernel modules and drivers
The driver for interacting with Ingrasys S9280-64X is contained in the I2C
kernel module and initialization script. The initialization script loads
the modules in the correct order. It has been built and tested against
the Linux 3.16 kernel.
The initialization script will modprobe the needed modules, navigate to the
module's device directory in sysfs, and write configuration data to
the kernel module.
### IGB
This is OOB Ports on front panel for management plane.
The IGB module must be loaded first on Ingrasys S9280-64X platform.
### I2C i801
The I2C i801 on Ingrasys S9280-64X can be found in
`/sys/bus/i2c/devices/i2c-0/`
This is I2C bus for Clock Gen, DIMM channel and digital potentiometers.
The i801 module must be loaded second on Ingrasys S9280-64X.
### I2C PCA9548
The PCA9548 module on S9280-64X can be found in
`/sys/bus/i2c/devices/i2c-0/` , `/sys/bus/i2c/devices/i2c-17/`,
`/sys/bus/i2c/devices/i2c-18/` , `/sys/bus/i2c/devices/i2c-19/`,
`/sys/bus/i2c/devices/i2c-20/`, `/sys/bus/i2c/devices/i2c-21/`,
`/sys/bus/i2c/devices/i2c-22/`, `/sys/bus/i2c/devices/i2c-23/`,
`/sys/bus/i2c/devices/i2c-24/`.
The pca9548 module for zQSFP module get/set functions, PSU information,
fan status and EEPROM.
## Hardware components
The hardware components are initialized in the init script on S9280-64X.
The following describes manual initialization as well as interaction.
The examples below are just for Ingrasys S9280-64X platform.
### Hardware initialization
When the sonic-platform-ingrasys-s9280 package is installed on the S9280-64X,
it is automatically initialized. If you want to manual initialization, the
utility command usage as follows:
```
i2c_utils.sh i2c_init
```
### EEPROM
The EEPROM is including the board SKU, model name, vendor name, serial number,
and other information can be accessed with the specific eeprom kernel module.
After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs.
The hexdump utility can be used to decode the raw output of the EEPROM.
For example,
```
bash# echo "mb_eeprom 0x55" > /sys/bus/i2c/devices/i2c-0/new_device
bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0055/eeprom | hexdump -C
```
### Front panel LEDs
LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`.
Utility function command usage as follows:
```
Status LED:
i2c_utils.sh i2c_sys_led green|amber on|off
Fan status LED:
i2c_utils.sh i2c_fan_led green|amber on|off
PSU1 status LED:
i2c_utils.sh i2c_psu1_led green|amber on|off
PSU2 status LED:
i2c_utils.sh i2c_psu2_led green|amber on|off
```
QSFP Module Port LEDs control by ASIC library.
### Fan speed
Fan speed are controlled by the w83795 kernel module.
It can be found in `/sys/class/hwmon/hwmon2/device/`.
If they were compiled as modules, you will need to modprobe w83795 for
their sysfs entries to show up. Each fan has an `fan<N>_input` file
for reading the fan speed. And `pwm1` setting fan1 to fan4,
`pwm2` setting fan5 to fan8.
There is docker-platform-monitor container installed fancontrol package that can
automatic control platform fan speed.
### Temperature sensors
Temperature sensors are controlled by the w83795 kernel
module. It can be found in `/sys/class/hwmon/hwmon3/device/`.
If they were compiled as modules, then you will need to modprobe w83795 for
their sysfs entries to show up.
`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC
temperature sensor.
There is docker-platform-monitor container installed lm-sensors package that can
monitor platform temperature. And `sensors` command can show each
temperature sensors status.
### Power supplies
Power supplies status and its EEPROM info can be used i2c utility
`/usr/sbin/i2c_utils.sh` to get.
The usage as follows:
```
PSU EEPROM:
i2c_utils.sh i2c_psu_eeprom_get
PSU Status:
i2c_utils.sh i2c_psu_status
```
### QSFPs
QSFP modules are managed by the pca9548 kernel driver.
The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and
module EEPROM informations.
The usage as follows:
```
QSFP EEPROM:
i2c_utils.sh i2c_qsfp_eeprom_get [1-64]
QSFP Insert Event:
i2c_utils.sh i2c_qsfp_status_get [1-64]
0 => not insert
1 => inserted
```

View File

@ -0,0 +1,3 @@
obj-m := eeprom_mb.o
obj-m += ingrasys_s9280_64x_i2c_cpld.o
obj-m += ingrasys_s9280_64x_psu.o

View File

@ -0,0 +1,267 @@
/*
* Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
* Philip Edelbrock <phil@netroedge.com>
* Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2003 IBM Corp.
* Copyright (C) 2004 Jean Delvare <jdelvare@suse.de>
*
* 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.
*/
/* enable dev_dbg print out */
//#define DEBUG
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54,
0x55, 0x56, 0x57,*/ I2C_CLIENT_END };
/* Size of EEPROM in bytes */
#define EEPROM_SIZE 512
#define SLICE_BITS (6)
#define SLICE_SIZE (1 << SLICE_BITS)
#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE)
/* Each client has this additional data */
struct eeprom_data {
struct mutex update_lock;
u8 valid; /* bitfield, bit!=0 if slice is valid */
unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */
u8 data[EEPROM_SIZE]; /* Register values */
};
static void mb_eeprom_update_client(struct i2c_client *client, u8 slice)
{
struct eeprom_data *data = i2c_get_clientdata(client);
int i, j;
int ret;
int addr;
mutex_lock(&data->update_lock);
if (!(data->valid & (1 << slice)) ||
time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
addr = slice << SLICE_BITS;
ret = i2c_smbus_write_byte_data(client, (u8)((addr >> 8) & 0xFF), (u8)(addr & 0xFF));
/* select the eeprom address */
if (ret < 0) {
dev_err(&client->dev, "address set failed\n");
goto exit;
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
goto exit;
}
for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) {
for (j = i; j < (i+SLICE_SIZE); j++) {
int res;
res = i2c_smbus_read_byte(client);
if (res < 0) {
goto exit;
}
data->data[j] = res & 0xFF;
}
}
data->last_updated[slice] = jiffies;
data->valid |= (1 << slice);
}
exit:
mutex_unlock(&data->update_lock);
}
static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
struct eeprom_data *data = i2c_get_clientdata(client);
u8 slice;
if (off > EEPROM_SIZE) {
return 0;
}
if (off + count > EEPROM_SIZE) {
count = EEPROM_SIZE - off;
}
if (count == 0) {
return 0;
}
/* Only refresh slices which contain requested bytes */
for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) {
mb_eeprom_update_client(client, slice);
}
memcpy(buf, &data->data[off], count);
return count;
}
static ssize_t mb_eeprom_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
struct eeprom_data *data = i2c_get_clientdata(client);
int ret;
int i;
u8 cmd;
u16 value16;
dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count);
if (off > EEPROM_SIZE) {
return 0;
}
if (off + count > EEPROM_SIZE) {
count = EEPROM_SIZE - off;
}
if (count == 0) {
return 0;
}
mutex_lock(&data->update_lock);
for(i=0; i < count; i++) {
/* write command */
cmd = (off >> 8) & 0xff;
value16 = off & 0xff;
value16 |= buf[i] << 8;
ret = i2c_smbus_write_word_data(client, cmd, value16);
if (ret < 0) {
dev_err(&client->dev, "write address failed at %d \n", (int)off);
goto exit;
}
off++;
/* need to wait for write complete */
udelay(10000);
}
exit:
mutex_unlock(&data->update_lock);
/* force to update client when reading */
for(i=0; i < SLICE_NUM; i++) {
data->last_updated[i] = 0;
}
return count;
}
static struct bin_attribute mb_eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO | S_IWUSR,
},
.size = EEPROM_SIZE,
.read = mb_eeprom_read,
.write = mb_eeprom_write,
};
/* Return 0 if detection is successful, -ENODEV otherwise */
static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
/* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline
attaching to addresses >= 0x56 on DDC buses */
if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) {
return -ENODEV;
}
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE)
&& !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
return -ENODEV;
}
strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
return 0;
}
static int mb_eeprom_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct eeprom_data *data;
int err;
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
memset(data->data, 0xff, EEPROM_SIZE);
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* create the sysfs eeprom file */
err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr);
if (err) {
goto exit_kfree;
}
return 0;
exit_kfree:
kfree(data);
exit:
return err;
}
static int mb_eeprom_remove(struct i2c_client *client)
{
sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr);
kfree(i2c_get_clientdata(client));
return 0;
}
static const struct i2c_device_id mb_eeprom_id[] = {
{ "mb_eeprom", 0 },
{ }
};
static struct i2c_driver mb_eeprom_driver = {
.driver = {
.name = "mb_eeprom",
},
.probe = mb_eeprom_probe,
.remove = mb_eeprom_remove,
.id_table = mb_eeprom_id,
.class = I2C_CLASS_DDC | I2C_CLASS_SPD,
.detect = mb_eeprom_detect,
.address_list = normal_i2c,
};
module_i2c_driver(mb_eeprom_driver);
MODULE_AUTHOR("Wade <wade.ce.he@@ingrasys.com>");
MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,338 @@
/* header file for i2c cpld driver of ingrasys_s9280_64x
*
* Copyright (C) 2017 Ingrasys Technology Corporation.
* Leo Lin <feng.lee.usa@ingrasys.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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef INGRASYS_S9280_64X_I2C_CPLD_H
#define INGRASYS_S9280_64X_I2C_CPLD_H
/* CPLD device index value */
enum cpld_id {
cpld1,
cpld2,
cpld3,
cpld4,
cpld5
};
enum LED_BLINK {
BLINK,
NOBLINK,
};
enum LED_YELLOW {
YELLOW_OFF,
YELLOW_ON,
};
enum LED_GREEN {
GREEN_OFF,
GREEN_ON,
};
/* port number on CPLD */
#define CPLD_1_PORT_NUM 12
#define CPLD_2_PORT_NUM 13
/* QSFP port number */
#define QSFP_MAX_PORT_NUM 64
#define QSFP_MIN_PORT_NUM 1
/* SFP+ port number */
#define SFP_MAX_PORT_NUM 2
#define SFP_MIN_PORT_NUM 1
/* CPLD registers */
#define CPLD_BOARD_TYPE_REG 0x0
#define CPLD_EXT_BOARD_TYPE_REG 0x7
#define CPLD_VERSION_REG 0x1
#define CPLD_ID_REG 0x2
#define CPLD_QSFP_PORT_STATUS_BASE_REG 0x20
#define CPLD_QSFP_PORT_CONFIG_BASE_REG 0x30
#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40
#define CPLD_SFP_PORT_STATUS_REG 0x2F
#define CPLD_SFP_PORT_CONFIG_REG 0x3F
#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40
#define CPLD_10GMUX_CONFIG_REG 0x41
#define CPLD_BMC_STATUS_REG 0x42
#define CPLD_BMC_WATCHDOG_REG 0x43
#define CPLD_USB_STATUS_REG 0x44
#define CPLD_RESET_CONTROL_REG 0x4A
#define CPLD_SFP_LED_REG 0x80
#define CPLD_SFP_LED_BLINK_REG 0x90
#define CPLD_QSFP_LED_BASE_REG 0x80
#define CPLD_QSFP_LED_BLINK_BASE_REG 0x90
#define CPLD_RTMR_RESET_REG 0x4B
#define CPLD_ROV_STATUS_REG 0x4C
/* bit definition for register value */
enum CPLD_QSFP_PORT_STATUS_BITS {
CPLD_QSFP_PORT_STATUS_INT_BIT,
CPLD_QSFP_PORT_STATUS_ABS_BIT,
};
enum CPLD_QSFP_PORT_CONFIG_BITS {
CPLD_QSFP_PORT_CONFIG_RESET_BIT,
CPLD_QSFP_PORT_CONFIG_RESERVE_BIT,
CPLD_QSFP_PORT_CONFIG_LPMODE_BIT,
};
enum CPLD_SFP_PORT_STATUS_BITS {
CPLD_SFP0_PORT_STATUS_PRESENT_BIT,
CPLD_SFP0_PORT_STATUS_TXFAULT_BIT,
CPLD_SFP0_PORT_STATUS_RXLOS_BIT,
CPLD_SFP_PORT_STATUS_DUMMY,
CPLD_SFP1_PORT_STATUS_PRESENT_BIT,
CPLD_SFP1_PORT_STATUS_TXFAULT_BIT,
CPLD_SFP1_PORT_STATUS_RXLOS_BIT,
};
enum CPLD_SFP_PORT_CONFIG_BITS {
CPLD_SFP0_PORT_CONFIG_TXDIS_BIT,
CPLD_SFP0_PORT_CONFIG_RS_BIT,
CPLD_SFP0_PORT_CONFIG_TS_BIT,
CPLD_SFP_PORT_CONFIG_DUMMY,
CPLD_SFP1_PORT_CONFIG_TXDIS_BIT,
CPLD_SFP1_PORT_CONFIG_RS_BIT,
CPLD_SFP1_PORT_CONFIG_TS_BIT,
};
enum CPLD_10GMUX_CONFIG_BITS {
CPLD_10GMUX_CONFIG_ENSMB_BIT,
CPLD_10GMUX_CONFIG_ENINPUT_BIT,
CPLD_10GMUX_CONFIG_SEL1_BIT,
CPLD_10GMUX_CONFIG_SEL0_BIT,
};
enum CPLD_BMC_WATCHDOG_BITS {
CPLD_10GMUX_CONFIG_ENTIMER_BIT,
CPLD_10GMUX_CONFIG_TIMEOUT_BIT,
};
enum CPLD_RESET_CONTROL_BITS {
CPLD_RESET_CONTROL_SWRST_BIT,
CPLD_RESET_CONTROL_CP2104RST_BIT,
CPLD_RESET_CONTROL_82P33814RST_BIT,
CPLD_RESET_CONTROL_BMCRST_BIT,
};
enum CPLD_SFP_LED_BITS {
CPLD_SFP_LED_SFP0_GREEN_BIT,
CPLD_SFP_LED_SFP0_YELLOW_BIT,
CPLD_SFP_LED_SFP1_GREEN_BIT,
CPLD_SFP_LED_SFP1_YELLOW_BIT,
};
enum CPLD_SFP_LED_BLINK_BITS {
CPLD_SFP_LED_BLINK_SFP0_BIT,
CPLD_SFP_LED_BLINK_SFP1_BIT,
};
enum CPLD_QSFP_LED_BITS {
CPLD_QSFP_LED_CHAN_0_GREEN_BIT,
CPLD_QSFP_LED_CHAN_0_YELLOW_BIT,
CPLD_QSFP_LED_CHAN_1_GREEN_BIT,
CPLD_QSFP_LED_CHAN_1_YELLOW_BIT,
CPLD_QSFP_LED_CHAN_2_GREEN_BIT,
CPLD_QSFP_LED_CHAN_2_YELLOW_BIT,
CPLD_QSFP_LED_CHAN_3_GREEN_BIT,
CPLD_QSFP_LED_CHAN_3_YELLOW_BIT,
};
enum CPLD_QSFP_LED_BLINK_BITS {
CPLD_QSFP_LED_BLINK_X_CHAN0_BIT,
CPLD_QSFP_LED_BLINK_X_CHAN1_BIT,
CPLD_QSFP_LED_BLINK_X_CHAN2_BIT,
CPLD_QSFP_LED_BLINK_X_CHAN3_BIT,
CPLD_QSFP_LED_BLINK_XPLUS_CHAN0_BIT,
CPLD_QSFP_LED_BLINK_XPLUS_CHAN1_BIT,
CPLD_QSFP_LED_BLINK_XPLUS_CHAN2_BIT,
CPLD_QSFP_LED_BLINK_XPLUS_CHAN3_BIT,
};
/* bit field structure for register value */
struct cpld_reg_board_type_t {
u8 build_rev:2;
u8 hw_rev:2;
u8 board_id:4;
};
struct cpld_reg_version_t {
u8 revision:6;
u8 release:1;
u8 reserve:1;
};
struct cpld_reg_id_t {
u8 id:3;
u8 release:5;
};
/* common manipulation */
#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u)
#define READ_BIT(val, bit) ((0u == (val & (1<<bit))) ? 0u : 1u)
#define SET_BIT(val, bit) (val |= (1 << bit))
#define CLEAR_BIT(val, bit) (val &= ~(1 << bit))
#define TOGGLE_BIT(val, bit) (val ^= (1 << bit))
#define _BIT(n) (1<<(n))
#define _BIT_MASK(len) (BIT(len)-1)
/* bitfield of register manipulation */
#define READ_BF(bf_struct, val, bf_name, bf_value) \
(bf_value = ((struct bf_struct *)&val)->bf_name)
#define READ_BF_1(bf_struct, val, bf_name, bf_value) \
bf_struct bf; \
bf.data = val; \
bf_value = bf.bf_name
#define BOARD_TYPE_BUILD_REV_GET(val, res) \
READ_BF(cpld_reg_board_type_t, val, build_rev, res)
#define BOARD_TYPE_HW_REV_GET(val, res) \
READ_BF(cpld_reg_board_type_t, val, hw_rev, res)
#define BOARD_TYPE_BOARD_ID_GET(val, res) \
READ_BF(cpld_reg_board_type_t, val, board_id, res)
#define CPLD_VERSION_REV_GET(val, res) \
READ_BF(cpld_reg_version_t, val, revision, res)
#define CPLD_VERSION_REL_GET(val, res) \
READ_BF(cpld_reg_version_t, val, release, res)
#define CPLD_ID_ID_GET(val, res) \
READ_BF(cpld_reg_id_t, val, id, res)
#define CPLD_ID_REL_GET(val, res) \
READ_BF(cpld_reg_id_t, val, release, res)
/* SFP/QSFP port led registers manipulation */
#define SFP_LED_TO_CPLD_IDX(sfp_port) cpld1
#define SFP_LED_REG(sfp_port) CPLD_SFP_LED_REG
#define SFP_LED_BLINK_REG(sfp_port) CPLD_SFP_LED_BLINK_REG
#define QSFP_LED_TO_CPLD_IDX(qsfp_port) \
((qsfp_port - 1) / 16 + 2)
#define QSFP_LED_REG(qsfp_port) \
((qsfp_port - 1) % 16 + CPLD_QSFP_LED_BASE_REG)
#define QSFP_LED_BLINK_REG(qsfp_port) \
(((qsfp_port - 1) % 16) / 2 + CPLD_QSFP_LED_BLINK_BASE_REG)
/* QSFP/SFP port status registers manipulation */
#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \
{ \
if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \
cpld_index = cpld1; \
cpld_port = qsfp_port - 1; \
} else if (CPLD_1_PORT_NUM < qsfp_port \
&& qsfp_port <= QSFP_MAX_PORT_NUM) { \
cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \
/ CPLD_2_PORT_NUM; \
cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \
CPLD_2_PORT_NUM; \
} else { \
cpld_index = 0; \
cpld_port = 0; \
} \
}
#define QSFP_PORT_STATUS_REG(cpld_port) \
(CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port)
#define QSFP_PORT_CONFIG_REG(cpld_port) \
(CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port)
#define QSFP_PORT_INT_BIT_GET(port_status_value) \
READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT)
#define QSFP_PORT_ABS_BIT_GET(port_status_value) \
READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT)
#define QSFP_PORT_RESET_BIT_GET(port_config_value) \
READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT)
#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \
READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT)
#define QSFP_PORT_RESET_BIT_SET(port_config_value) \
SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT)
#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \
CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT)
#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \
SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT)
#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \
CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT)
#define SFP_PORT_PRESENT_BIT_GET(sfp_port, port_status_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_PRESENT_BIT); \
} else { \
READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_PRESENT_BIT); \
}
#define SFP_PORT_TXFAULT_BIT_GET(sfp_port, port_status_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_TXFAULT_BIT); \
} else { \
READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_TXFAULT_BIT); \
}
#define SFP_PORT_RXLOS_BIT_GET(sfp_port, port_status_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_RXLOS_BIT); \
} else { \
READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_RXLOS_BIT); \
}
#define SFP_PORT_TXDIS_BIT_GET(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \
} else { \
READ_BIT(port_config_value, CPLD_SFP1_PORT_STATUS_RXLOS_BIT); \
}
#define SFP_PORT_RS_BIT_GET(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \
} else { \
READ_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \
}
#define SFP_PORT_TS_BIT_GET(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \
} else { \
READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \
}
#define SFP_PORT_TXDIS_BIT_SET(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \
} else { \
SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TXDIS_BIT); \
}
#define SFP_PORT_TXDIS_BIT_CLEAR(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \
} else { \
CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TXDIS_BIT); \
}
#define SFP_PORT_RS_BIT_SET(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \
} else { \
SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \
}
#define SFP_PORT_RS_BIT_CLEAR(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \
} else { \
CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \
}
#define SFP_PORT_TS_BIT_SET(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \
} else { \
SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TS_BIT); \
}
#define SFP_PORT_TS_BIT_CLEAR(sfp_port, port_config_value) \
if (sfp_port == SFP_MIN_PORT_NUM) { \
CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \
} else { \
CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TS_BIT); \
}
/* CPLD access functions */
extern int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num);
extern int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num);
extern int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val);
extern int ingrasys_i2c_cpld_get_sfp_port_status_val(void);
extern int ingrasys_i2c_cpld_get_sfp_port_config_val(void);
extern int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 reg_val);
extern u8 fp_port_to_phy_port(u8 fp_port);
#endif

View File

@ -0,0 +1,158 @@
#ifndef _S9230_64X_PLATFORM_H
#define _S9230_64X_PLATFORM_H
#include <linux/i2c.h>
// remove debug before release
#define DEBUG
enum bus_order {
I2C_BUS_MAIN,
MUX_9548_0_CH0,
MUX_9548_0_CH1,
MUX_9548_0_CH2,
MUX_9548_0_CH3,
MUX_9548_0_CH4,
MUX_9548_0_CH5,
MUX_9548_0_CH6,
MUX_9548_0_CH7,
MUX_9548_1_CH0,
MUX_9548_1_CH1,
MUX_9548_1_CH2,
MUX_9548_1_CH3,
MUX_9548_1_CH4,
MUX_9548_1_CH5,
MUX_9548_1_CH6,
MUX_9548_1_CH7,
MUX_9548_2_CH0,
MUX_9548_2_CH1,
MUX_9548_2_CH2,
MUX_9548_2_CH3,
MUX_9548_2_CH4,
MUX_9548_2_CH5,
MUX_9548_2_CH6,
MUX_9548_2_CH7,
MUX_9546_0_CH0,
MUX_9546_0_CH1,
MUX_9546_0_CH2,
MUX_9546_0_CH3,
MUX_9546_1_CH0,
MUX_9546_1_CH1,
MUX_9546_1_CH2,
MUX_9546_1_CH3,
MUX_9548_11_CH0,
MUX_9548_11_CH1,
MUX_9548_11_CH2,
MUX_9548_11_CH3,
MUX_9548_11_CH4,
MUX_9548_11_CH5,
MUX_9548_11_CH6,
MUX_9548_11_CH7,
MUX_9548_3_CH0,
MUX_9548_3_CH1,
MUX_9548_3_CH2,
MUX_9548_3_CH3,
MUX_9548_3_CH4,
MUX_9548_3_CH5,
MUX_9548_3_CH6,
MUX_9548_3_CH7,
MUX_9548_4_CH0,
MUX_9548_4_CH1,
MUX_9548_4_CH2,
MUX_9548_4_CH3,
MUX_9548_4_CH4,
MUX_9548_4_CH5,
MUX_9548_4_CH6,
MUX_9548_4_CH7,
MUX_9548_5_CH0,
MUX_9548_5_CH1,
MUX_9548_5_CH2,
MUX_9548_5_CH3,
MUX_9548_5_CH4,
MUX_9548_5_CH5,
MUX_9548_5_CH6,
MUX_9548_5_CH7,
MUX_9548_6_CH0,
MUX_9548_6_CH1,
MUX_9548_6_CH2,
MUX_9548_6_CH3,
MUX_9548_6_CH4,
MUX_9548_6_CH5,
MUX_9548_6_CH6,
MUX_9548_6_CH7,
MUX_9548_7_CH0,
MUX_9548_7_CH1,
MUX_9548_7_CH2,
MUX_9548_7_CH3,
MUX_9548_7_CH4,
MUX_9548_7_CH5,
MUX_9548_7_CH6,
MUX_9548_7_CH7,
MUX_9548_8_CH0,
MUX_9548_8_CH1,
MUX_9548_8_CH2,
MUX_9548_8_CH3,
MUX_9548_8_CH4,
MUX_9548_8_CH5,
MUX_9548_8_CH6,
MUX_9548_8_CH7,
MUX_9548_9_CH0,
MUX_9548_9_CH1,
MUX_9548_9_CH2,
MUX_9548_9_CH3,
MUX_9548_9_CH4,
MUX_9548_9_CH5,
MUX_9548_9_CH6,
MUX_9548_9_CH7,
MUX_9548_10_CH0,
MUX_9548_10_CH1,
MUX_9548_10_CH2,
MUX_9548_10_CH3,
MUX_9548_10_CH4,
MUX_9548_10_CH5,
MUX_9548_10_CH6,
MUX_9548_10_CH7,
};
#define I2C_ADDR_MUX_9555_0 (0x20)
#define I2C_ADDR_MUX_9555_1 (0x24)
#define I2C_ADDR_MUX_9555_2 (0x25)
#define I2C_ADDR_MUX_9555_3 (0x26)
#define I2C_ADDR_MUX_9539_0 (0x76)
#define I2C_ADDR_MUX_9539_1 (0x76)
#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN)
#define I2C_BUS_SYS_LED (MUX_9548_1_CH1)
#define I2C_BUS_PSU_STATUS (I2C_BUS_MAIN)
#define I2C_ADDR_PSU_STATUS (I2C_ADDR_MUX_9555_2)
#define NUM_OF_I2C_MUX (11)
#define NUM_OF_CPLD (5)
#define NUM_OF_QSFP_PORT (64)
#define NUM_OF_SFP_PORT (2)
#define QSFP_EEPROM_I2C_ADDR (0x50)
enum gpio_reg {
REG_PORT0_IN,
REG_PORT1_IN,
REG_PORT0_OUT,
REG_PORT1_OUT,
REG_PORT0_POL,
REG_PORT1_POL,
REG_PORT0_DIR,
REG_PORT1_DIR,
};
struct ing_i2c_board_info {
int ch;
int size;
struct i2c_board_info *board_info;
};
struct i2c_init_data {
__u16 ch;
__u16 addr;
__u8 reg;
__u8 value;
};
#endif

View File

@ -0,0 +1,394 @@
/*
* S9280-64x PSU driver
*
* Copyright (C) 2017 Ingrasys, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include "ingrasys_s9280_64x_platform.h"
static ssize_t show_psu_eeprom(struct device *dev,
struct device_attribute *da,
char *buf);
static struct s9280_psu_data *s9280_psu_update_status(struct device *dev);
static struct s9280_psu_data *s9280_psu_update_eeprom(struct device *dev);
static int s9280_psu_read_block(struct i2c_client *client,
u8 command,
u8 *data,
int data_len);
#define DRIVER_NAME "psu"
// Addresses scanned
static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
/* PSU EEPROM SIZE */
#define EEPROM_SZ 256
#define READ_EEPROM 1
#define NREAD_EEPROM 0
static struct i2c_client pca9555_client;
/* pca9555 gpio pin mapping */
#define PSU2_PWROK 0
#define PSU2_PRSNT_L 1
#define PSU2_PWRON_L 2
#define PSU1_PWROK 3
#define PSU1_PRSNT_L 4
#define PSU1_PWRON_L 5
#define TMP_75_INT_L 6
/* Driver Private Data */
struct s9280_psu_data {
struct mutex lock;
char valid; /* !=0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 index; /* PSU index */
s32 status; /* IO expander value */
char eeprom[EEPROM_SZ]; /* psu eeprom data */
char psuABS; /* PSU absent */
char psuPG; /* PSU power good */
};
enum psu_index
{
s9280_psu1,
s9280_psu2
};
/*
* display power good attribute
*/
static ssize_t
show_psu_pg(struct device *dev,
struct device_attribute *devattr,
char *buf)
{
struct s9280_psu_data *data = s9280_psu_update_status(dev);
unsigned int value;
mutex_lock(&data->lock);
value = data->psuPG;
mutex_unlock(&data->lock);
return sprintf(buf, "%d\n", value);
}
/*
* display power absent attribute
*/
static ssize_t
show_psu_abs(struct device *dev,
struct device_attribute *devattr,
char *buf)
{
struct s9280_psu_data *data = s9280_psu_update_status(dev);
unsigned int value;
mutex_lock(&data->lock);
value = data->psuABS;
mutex_unlock(&data->lock);
return sprintf(buf, "%d\n", value);
}
/*
* sysfs attributes for psu
*/
static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL);
static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL);
static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL);
static struct attribute *s9280_psu_attributes[] = {
&dev_attr_psu_pg.attr,
&dev_attr_psu_abs.attr,
&dev_attr_psu_eeprom.attr,
NULL
};
/*
* display psu eeprom content
*/
static ssize_t
show_psu_eeprom(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct s9280_psu_data *data = s9280_psu_update_eeprom(dev);
memcpy(buf, (char *)data->eeprom, EEPROM_SZ);
return EEPROM_SZ;
}
static const struct attribute_group s9280_psu_group = {
.attrs = s9280_psu_attributes,
};
/*
* check gpio expander is accessible
*/
static int
pca9555_detect(struct i2c_client *client)
{
if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) {
return -ENODEV;
}
return 0;
}
/*
* client init
*/
static void
i2c_devices_client_address_init(struct i2c_client *client)
{
pca9555_client = *client;
/* get i2c adapter for the target */
pca9555_client.adapter = i2c_get_adapter(I2C_BUS_PSU_STATUS);
/* get the i2c addr for the target */
pca9555_client.addr = I2C_ADDR_PSU_STATUS;
}
static int
s9280_psu_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct s9280_psu_data *data;
int status, err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct s9280_psu_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
memset(data, 0, sizeof(struct s9280_psu_data));
i2c_set_clientdata(client, data);
data->valid = 0;
data->index = dev_id->driver_data;
mutex_init(&data->lock);
i2c_devices_client_address_init(client);
err = pca9555_detect(&pca9555_client);
if (err) {
return err;
}
dev_info(&client->dev, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &s9280_psu_group);
if (status) {
goto exit_free;
}
return 0;
exit_free:
kfree(data);
exit:
return status;
}
static int
s9280_psu_remove(struct i2c_client *client)
{
struct s9280_psu_data *data = i2c_get_clientdata(client);
sysfs_remove_group(&client->dev.kobj, &s9280_psu_group);
kfree(data);
/* free i2c adapter */
i2c_put_adapter(pca9555_client.adapter);
return 0;
}
/*
* psu eeprom read utility
*/
static int
s9280_psu_read_block(struct i2c_client *client,
u8 command,
u8 *data,
int data_len)
{
int i=0, ret=0;
int blk_max = 32; //max block read size
/* read eeprom, 32 * 8 = 256 bytes */
for (i=0; i < EEPROM_SZ/blk_max; i++) {
ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max,
data + (i*blk_max));
if (ret < 0) {
return ret;
}
}
return ret;
}
/*
* update eeprom content
*/
static struct s9280_psu_data
*s9280_psu_update_eeprom(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct s9280_psu_data *data = i2c_get_clientdata(client);
s32 status = 0;
int psu_pwrok = 0;
int psu_prsnt_l = 0;
mutex_lock(&data->lock);
if (time_after(jiffies, data->last_updated + 300 * HZ)
|| !data->valid) {
/* Read psu status */
status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN);
data->status = status;
/*read psu status from io expander*/
if (data->index == s9280_psu1) {
psu_pwrok = PSU1_PWROK;
psu_prsnt_l = PSU1_PRSNT_L;
} else {
psu_pwrok = PSU2_PWROK;
psu_prsnt_l = PSU2_PRSNT_L;
}
data->psuPG = (status >> psu_pwrok) & 0x1;
data->psuABS = (status >> psu_prsnt_l) & 0x1;
/* Read eeprom */
if (!data->psuABS) {
//clear local eeprom data
memset(data->eeprom, 0, EEPROM_SZ);
//read eeprom
status = s9280_psu_read_block(client, 0, data->eeprom,
ARRAY_SIZE(data->eeprom));
if (status < 0) {
memset(data->eeprom, 0, EEPROM_SZ);
dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status);
} else {
data->valid = 1;
}
} else {
memset(data->eeprom, 0, EEPROM_SZ);
}
data->last_updated = jiffies;
}
mutex_unlock(&data->lock);
return data;
}
/*
* update psu status
*/
static struct s9280_psu_data
*s9280_psu_update_status(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct s9280_psu_data *data = i2c_get_clientdata(client);
s32 status = 0;
int psu_pwrok = 0;
int psu_prsnt_l = 0;
mutex_lock(&data->lock);
/* Read psu status */
status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN);
data->status = status;
/*read psu status from io expander*/
if (data->index == s9280_psu1) {
psu_pwrok = PSU1_PWROK;
psu_prsnt_l = PSU1_PRSNT_L;
} else {
psu_pwrok = PSU2_PWROK;
psu_prsnt_l = PSU2_PRSNT_L;
}
data->psuPG = (status >> psu_pwrok) & 0x1;
data->psuABS = (status >> psu_prsnt_l) & 0x1;
mutex_unlock(&data->lock);
return data;
}
static const struct i2c_device_id s9280_psu_id[] = {
{ "psu1", s9280_psu1 },
{ "psu2", s9280_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, s9280_psu_id);
static struct i2c_driver s9280_psu_driver = {
.driver = {
.name = DRIVER_NAME,
},
.probe = s9280_psu_probe,
.remove = s9280_psu_remove,
.id_table = s9280_psu_id,
.address_list = normal_i2c,
};
static int __init s9280_psu_init(void)
{
return i2c_add_driver(&s9280_psu_driver);
}
static void __exit s9280_psu_exit(void)
{
i2c_del_driver(&s9280_psu_driver);
}
module_init(s9280_psu_init);
module_exit(s9280_psu_exit);
MODULE_AUTHOR("Leo Lin <feng.lee.usa@ingrasys.com>");
MODULE_DESCRIPTION("S9280-64X psu driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,15 @@
[Unit]
Description= This QSFP Monitor service is to setup QSFP SI.
Requires=s9280-64x-monitor.service
After=s9280-64x-monitor.service
[Service]
ExecStart=/usr/sbin/qsfp_monitor.sh
KillSignal=SIGKILL
SuccessExitStatus=SIGKILL
# Resource Limitations
LimitCORE=infinity
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,19 @@
[Unit]
Description= This Platform Monitor service is to initialize platform and monitor platform.
Before=platform-monitor.service
After=sysinit.target
Wants=fancontrol.service
Wants=qsfp-monitor.service
DefaultDependencies=no
[Service]
ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init
ExecStart=/usr/sbin/s9280_64x_monitor.sh
KillSignal=SIGKILL
SuccessExitStatus=SIGKILL
# Resource Limitations
LimitCORE=infinity
[Install]
WantedBy=multi-user.target

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
#!/bin/bash
# Copyright (C) 2017 Ingrasys, 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/>.
INTERVAL=3
I2C_UTILS="/usr/sbin/i2c_utils.sh"
QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh"
QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
#QSFP SI monitor
function _qsfp_si_monitor {
local i
local status
for i in {0..63};
do
status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'`
if [ "${status}" == "1" ]; then
_qsfp_type_check $i
fi
done
}
#QSFP type
function _qsfp_type_check {
local port=$1
local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)`
local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'`
if [ "${identifier}" == "11" ]; then
connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'`
case ${connector} in
21|23)
#DAC
if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then
echo "Change Port $(expr $port + 1) to DAC"
QSFP_ARRAY[$port]=${connector}
${QSFP_SI_SCRIPT} dac $port >/dev/null
fi
;;
*)
#Optical
if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then
echo "Change Port $(expr $port + 1) to Optical"
QSFP_ARRAY[$port]=${connector}
${QSFP_SI_SCRIPT} optical $port >/dev/null
fi
;;
esac
fi
}
#Docker exist check
function _docker_swss_check {
while true
do
# Check if syncd starts
result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
if [ "$result" == "3" ]; then
return
fi
sleep $INTERVAL
done
}
#Docker exist check
function _qsfp_si_cfg_script_check {
if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then
echo "SI Script exists. Start monitor."
return
else
echo "SI Script not exist. Exit monitor."
exit
fi
}
# main function
function _main {
#Check SI Script
_qsfp_si_cfg_script_check
#Check docker swss is running
_docker_swss_check
while true
do
_qsfp_si_monitor
# Sleep while still handling signals
sleep $INTERVAL &
wait $!
done
}
_main

View File

@ -0,0 +1,42 @@
#!/bin/bash
# Copyright (C) 2016 Ingrasys, 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/>.
INTERVAL=5
I2C_UTILS="/usr/sbin/i2c_utils.sh"
# TBD: LED status monitor
function _led_monitor {
${I2C_UTILS} i2c_led_fan_status_set >/dev/null
${I2C_UTILS} i2c_led_psu_status_set >/dev/null
${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null
}
# main function
function _main {
while true
do
#PSU controlled by dummy board,
#but fan LED and fan tray LED must controlled by this service
_led_monitor
# Sleep while still handling signals
sleep $INTERVAL &
wait $!
done
}
_main