Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Michael Shych
2018-04-08 10:18:56 +00:00
200 changed files with 18830 additions and 7859 deletions

View File

@@ -1,107 +1,114 @@
Hardware Support
================
Because of the HTML formatting, this page may be best viewed from
<http://opennetlinux.org/hcl>
Quanta
------
<table class="table table-striped table-hover">
<thead>
<tr class="info">
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
</thead>
<tr> <td> QuantaMesh T1048-LB9 <td> 48x1G + 4x10G <td> FreeScale P2020 <td> Broadcom BCM56534 (Firebolt3) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> QuantaMesh T3048-LY2 <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56846 (Trident+) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> QuantaMesh T3048-LY8 <td> 48x10G + 6x40G <td> Intel Rangeley C2758 x86 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> QuantaMesh T5032-LY6 <td> 32x40G <td> Intel Rangeley C2758 x86 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> QuantaMesh T3048-LY9 <td> 48x10GT + 6x40G <td> Intel Rangeley C2758 x86 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
</table>
Accton/Edge-Core
------
<table class="table table-striped table-hover">
<thead>
<tr class="info">
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
</thead>
<tr> <td> Accton AS4600-54T <td> 48x1G + 4x10G <td> FreeScale P2020 <td> Broadcom BCM56540 (Apollo2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS4610-54P <td> 48x1G + 4x10G + 2x20G <td> Dual-core ARM Cortex A9 1GHz <td> Broadcom BCM56340 (Helix4) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> Accton AS5610-52X <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56846 (Trident+) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> Accton AS5710-54X <td> 48x10G + 6x40G <td> FreeScale P2041 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS6700-32X <td> 32x40G <td> FreeScale P2041 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> Accton AS5512-54X <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> MediaTek/Nephos MT3258 <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> Accton AS5712-54X <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS6712-32X <td> 32x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS5812-54T <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56864 (Trident2+) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> Accton AS5812-54X <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56864 (Trident2+) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS6812-32X <td> 32x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56864 (Trident2+) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS7712-32X <td> 32x100G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56960 (Tomahawk) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton AS7716-32X <td> 32x100G <td> Intel Xeon D-1518 x86 <td> Broadcom BCM56960 (Tomahawk) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Accton Wedge-16X <td> 16x40G <td> Intel Rangeley C2550 x86 <td> Broadcom BCM56864 (Trident2+) <td> Work In Progress** <td> Yes <td> No <td> Yes <td> No </tr>
<tr> <td> Accton (FB) Wedge 100 <td> 32x100G <td> Intel Bay Trail E3845 x86 <td> Broadcom BCM56960 (Tomahawk) <td> Work In Progress** <td> Yes <td> No <td> Yes <td> No </tr>
</table>
Device Ports CPU Forwarding In Lab
Accton AS4600-54T 48x1G + 4x10G FreeScale P2020 Broadcom BCM56540 (Apollo2) Yes
Accton AS4610-54P 48x1G + 4x10G + 2x20G Dual-core ARM Cortex A9 Broadcom BCM56340 (Helix4) Yes
Accton AS5512-54X 48x10G + 6x40G Intel C2538 MediaTek/Nephos MT3258 Yes
Accton AS5610-52X 48x10G + 4x40G FreeScale P2020 Broadcom BCM56846 (Trident+) Yes
Accton AS5710-54X 48x10G + 6x40G FreeScale P2041 Broadcom BCM56854 (Trident2) Yes
Accton AS5712-54X 48x10G + 6x40G Intel C2538 Broadcom BCM56854 (Trident2) Yes
Accton AS5812-54T 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
Accton AS5812-54X 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
Accton AS5822-32X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
Accton AS5912-54X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
Accton AS5912-54XK 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
Accton AS5916-54XM 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) No
Accton AS5916-54X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) No
Accton AS6700-32X 32x40G FreeScale P2041 Broadcom BCM56850 (Trident2) Yes
Accton AS6712-32X 32x40G Intel C2538 Broadcom BCM56850 (Trident2) Yes
Accton AS6812-32X 32x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
Accton AS7312-54X 48x25G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
Accton AS7712-32X 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
Accton AS7716-32X 32x100G Intel Xeon D-1518 Broadcom BCM56960 (Tomahawk) Yes
Accton AS7816-64X 64x100 Intel C2558 Broadcom BCM56970 (Tomahawk II) Yes
Accton Wedge-16X 16x40G Intel C2550 Broadcom BCM56864 (Trident2+) Yes
Accton Wedge 100-32X 32x100G Intel E3845 Broadcom BCM56960 (Tomahawk) Yes
Accton Wedge 100S-32X 32x100G Intel D1508 Broadcom BCM56960 (Tomahawk) Yes
Alpha Networks
---
Device Ports CPU Forwarding In Lab
SNX-60A0-486F 48x10G + 6x40G Intel C2558 Broadcom BCM56850 (Trident2) Yes
Celestica
---
Device Ports CPU Forwarding In Lab
Redstone-XP 48x10G + 6x40G Intel C2558 Broadcom BCM56854 (Trident2) Yes
Seastone 32x100G Intel C2558 Broadcom BCM56960 (Tomahawk) No
DNI/Agema
---
<table class="table table-striped table-hover">
<thead>
<tr class="info">
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
</thead>
<tr> <td> AG-7448CU <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56845 (Trident) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
</table>
Device Ports CPU Forwarding In Lab
AG-7448CU 48x10G + 4x40G FreeScale P2020 Broadcom BCM56845 (Trident) Yes
AG-5648 48x25G + 6x100G Intel D1548 Broadcom BCM56960 (Tomahawk) No
AG-5648v1 48x25G + 6x100G Intel D1548 Broadcom BCM56963 (Tomahawk+) No
AG-7648 48x10G + 6x40G Intel D1548 Broadcom BCM56854 (Trident2) Yes
AG-9032v1 32x100G Intel D1548 Broadcom BCM56960 (Tomahawk) Yes
AG-9032v2 32x100G Intel D1548 Broadcom BCM56963 (Tomahawk+) No
AG-9064 64x100G Intel D1547 Broadcom BCM56970 (Tomahawk II) No
AGC-5648S 48x25G + 6x100G Intel D1548 Broadcom BCM88680 (Jericho+) No
AGC-7648A 48x10G + 6x100G Intel D1548 Broadcom BCM88370 (Qumran MX) No
WB-2448 48x1GT + 4x10G Intel E3805 Broadcom BCM56150 (Hurricane2) No
AG-6248C 48x1GT + 2x10G ARM A9 1GHz Broadcom BCM56340 (Helix4) Yes
Dell
---
<table class="table table-striped table-hover">
<thead>
<tr class="info">
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
</thead>
<tr> <td> S4810-ON <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56845 (Trident) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> S4048-ON <td> 48x10G + 6x40G <td> Intel Atom C2338 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> S6000-ON <td> 32x40G <td> Intel Atom S1220 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
<tr> <td> Z9100-ON <td> 32x100G <td> Intel Atom C2538 <td> Broadcom BCM56960 (Tomahawk) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
</table>
Device Ports CPU Forwarding In Lab
S4000-ON 48x10G + 6x40G Intel C2338 Broadcom BCM56854 (Trident2) Yes
S4810-ON 48x10G + 4x40G FreeScale P2020 Broadcom BCM56845 (Trident) Yes
S4048-ON 48x10G + 6x40G Intel C2338 Broadcom BCM56854 (Trident2) Yes
S6000-ON 32x40G Intel S1220 Broadcom BCM56850 (Trident2) Yes
S6010-ON 32x40G Intel S1220 Broadcom BCM56850 (Trident2) Yes
S6100-ON 64x50G/128x25G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
Z9100-ON 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
Interface Masters Technologies, Inc.
HPE
---
<table class="table table-striped table-hover">
<thead>
<tr class="info">
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
</thead>
<tr> <td> Niagara 2948X12XLm <td> 48x10G + 12x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Niagara 2960X6XLm <td> 60x10G + 6x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Niagara 2972Xm <td> 72x10G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Niagara 2932XL <td> 32x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes*** <td> No </tr>
<tr> <td> Niagara 2948X6XL <td> 48x10G + 6x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes <td> No </tr>
</table>
Device Ports CPU Forwarding In Lab
Altoline 6921 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
Altoline 6921T 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
Altoline 6941 32x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
Altoline 6960 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
Ingrasys
---
Device Ports CPU Forwarding In Lab
S9100-32X 32x100G Intel Broadcom BCM56960 (Tomahawk) No
Inventec
---
Device Ports CPU Forwarding In Lab
D7032Q28B 32x100G Intel No
Mellanox
---
<table class="table table-striped table-hover">
<thead>
<tr class="info">
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> SAI </tr>
</thead>
<tr> <td> SN2100 <td> 16x100G <td> Intel Rangeley C2558 <td> Mellanox Spectrum <td> Yes <td> Yes <td> Yes </tr>
<tr> <td> SN2100B <td> 16x40G <td> Intel Rangeley C2558 <td> Mellanox Spectrum <td> Yes <td> No <td> Yes </tr>
<tr> <td> SN2410 <td> 48x25G + 8x100G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> Yes <td> Yes </tr>
<tr> <td> SN2410B <td> 48x10G + 8x100G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> No <td> Yes </tr>
<tr> <td> SN2700 <td> 32x100G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> Yes <td> Yes </tr>
<tr> <td> SN2700B <td> 32x40G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> No <td> Yes </tr>
</table>
Device Ports CPU Forwarding In Lab
SN2100 16x100G Intel C2558 Mellanox Spectrum Yes
SN2100B 16x40G Intel C2558 Mellanox Spectrum No
SN2410 48x25G + 8x100G Intel 1047UE Mellanox Spectrum Yes
SN2410B 48x10G + 8x100G Intel 1047UE Mellanox Spectrum No
SN2700 32x100G Intel 1047UE Mellanox Spectrum Yes
SN2700B 32x40G Intel 1047UE Mellanox Spectrum No
Notes:
Netberg
---
Device Ports CPU Forwarding In Lab
Aurora 620 32x100G Intel C2558 Broadcom BCM56960 (Tomahawk) Yes
Aurora 720 48x10/25G + 6x40/100G Intel C2558 Broadcom BCM56960 (Tomahawk) Yes
ONL Certified means that the system runs ONIE, is able to install a generic version of ONL and has the ONL Platform drivers necessary to manage the system.
\* Systems no longer in the lab cannot be certified post removal
\** Developing ONL Platform Drivers
\*** Vendor provided
Quanta
------
Device Ports CPU Forwarding In Lab
QuantaMesh T1048-LB9 48x1G + 4x10G FreeScale P2020 Broadcom BCM56534 (Firebolt3) Yes
QuantaMesh T3048-LY2 48x10G + 4x40G FreeScale P2020 Broadcom BCM56846 (Trident+) Yes
QuantaMesh T5032-LY6 32x40G Intel C2758 Broadcom BCM56850 (Trident2) Yes
QuantaMesh T3048-LY7 48x10G + 4x100G Intel C2558 Broadcom BCM56768 (Maverick) Yes
QuantaMesh T3048-LY8 48x10G + 6x40G Intel C2758 Broadcom BCM56854 (Trident2) Yes
QuantaMesh T3048-LY9 48x10GT + 6x40G Intel C2758 Broadcom BCM56850 (Trident2) Yes
QuantaMesh T7032-IX1 32x100G Intel C2758 Broadcom BCM56960 (Tomahawk) Yes
QuantaMesh T7032-IX1B 32x100G Intel C2758 Broadcom BCM56960 (Tomahawk) Yes
QuantaMesh T4048-IX2 48xSFP28 + 8xQSFP28 Intel C2758 Broadcom BCM56960 (Tomahawk) Yes
QuantaMesh T4048-IX8 48x10G + 8x100G Intel Broadcom BCM56870 (Trident 3) Yes

View File

@@ -21,6 +21,9 @@ if [ -f /etc/onl/abort ]; then
exit 1
fi
if [ -f /mnt/onl/boot/autoboot ]; then
. /mnt/onl/boot/autoboot
fi
#
# The maximum number of times we will retry autobooting before
@@ -118,4 +121,3 @@ else
msg_error "BOOTMODE $BOOTMODE is not implemented. Autobooting cannot continue."
exit 1
fi

View File

@@ -19,6 +19,7 @@ import zipfile
import onl.install.InstallUtils
MountContext = onl.install.InstallUtils.MountContext
BlkidParser = onl.install.InstallUtils.BlkidParser
UbinfoParser = onl.install.InstallUtils.UbinfoParser
ProcMountsParser = onl.install.InstallUtils.ProcMountsParser
import onl.mounts
@@ -247,6 +248,14 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
part = blkid[label]
except IndexError:
part = None
if part is None:
ubinfo = UbinfoParser(log=self.log)
part = {}
part = ubinfo[label]
device = "/dev/" + part['device'] + "_" + part['Volume ID']
return self.blockdevCopy(device, r, dir=mpt)
if part is not None:
return self.blockdevCopy(part.device, r, dir=mpt)

View File

@@ -11,6 +11,7 @@ import logging
import onl.install.InstallUtils
BlkidParser = onl.install.InstallUtils.BlkidParser
UbinfoParser = onl.install.InstallUtils.UbinfoParser
import onl.mounts
MountContext = onl.install.InstallUtils.MountContext
@@ -26,6 +27,7 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
self.log = log
self.blkid = BlkidParser(log=self.log)
self.ubinfo = UbinfoParser(log=self.log)
def mount(self, SWI):
@@ -125,6 +127,13 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
part = self.blkid[label]
except IndexError:
part = None
if part is None:
part = {}
part = self.ubinfo[label]
device = "/dev/" + part['device'] + "_" + part['Volume ID']
return self.blockdevMount(device, path, dir=mpt)
if part is not None:
return self.blockdevMount(part.device, path, dir=mpt)
@@ -141,7 +150,12 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
if not os.path.exists(dst):
self.log.error("missing SWI: %s", dst)
return None
self.check_call(('mount', '-o', 'rw,remount', dst,))
p = dev.find('ubi')
if p < 0:
self.check_call(('mount', '-o', 'rw,remount', dst,))
else:
self.check_call(('mount', '-t', 'ubifs', '-o', 'rw,remount', dst,))
return dst
with MountContext(device=dev, log=self.log) as ctx:
@@ -154,7 +168,12 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
# move to its proper location as per mtab
# XXX perms may not be right here
if dir is not None:
self.check_call(('mount', '-o', 'rw,remount', ctx.dir,))
p = dev.find('ubi')
if p < 0:
self.check_call(('mount', '-o', 'rw,remount', ctx.dir,))
else:
self.check_call(('mount', '-t', 'ubifs', '-o', 'rw,remount', ctx.dir,))
self.check_call(('mount', '--move', ctx.dir, dir,))
ctx.mounted = False
dst = dir

View File

@@ -15,8 +15,8 @@ if [ ! -d /mnt/onl/data ]; then
fi
# make sure it's mounted as per mtab.yml
d1=$(stat -f -c '%d' /mnt/onl)
d2=$(stat -f -c '%d' /mnt/onl/data)
d1=$(stat -f -c '%b' /mnt/onl)
d2=$(stat -f -c '%b' /mnt/onl/data)
if [ "$d1" -eq "$d2" ]; then
msg_error "Unmounted /mnt/onl/data, disk boot cannot continue"
exit 200

View File

@@ -129,6 +129,13 @@ default:
- ext2load mmc 0:1 $onl_loadaddr $onl_itb
- "bootm $onl_loadaddr#$onl_platform"
#ubifs to boot onl
flash_bootcmds: &flash_bootcmds
- ubi part open
- ubifsmount ONL-BOOT
- ubifsload $loadaddr $onl_itb
- "bootm $onl_loadaddr#$onl_platform"
nos_bootcmds: *ide_bootcmds
# Configure the fw_env.config file,

View File

@@ -17,7 +17,7 @@ import imp
import fnmatch, glob
from InstallUtils import SubprocessMixin
from InstallUtils import MountContext, BlkidParser, PartedParser
from InstallUtils import MountContext, BlkidParser, PartedParser, UbinfoParser
from InstallUtils import ProcMountsParser
from InstallUtils import GdiskParser
from InstallUtils import OnieSubprocess
@@ -83,6 +83,7 @@ class Base:
# keep track of next partition/next block
self.blkidParts = []
self.ubiParts = []
# current scan of partitions and labels
self.partedDevice = None
@@ -853,7 +854,203 @@ class GrubInstaller(SubprocessMixin, Base):
def shutdown(self):
Base.shutdown(self)
class UbootInstaller(SubprocessMixin, Base):
class UBIfsCreater(SubprocessMixin, Base):
def __init__(self, *args, **kwargs):
Base.__init__(self, *args, **kwargs)
self.log = logging.getLogger("ubinfo -a")
self.device = self.im.getDevice()
self.ubiParts = None
"""Set up an UBI file system."""
def ubifsinit(self):
UNITS = {
'GiB' : 1024 * 1024 * 1024,
'G' : 1000 * 1000 * 1000,
'MiB' : 1024 * 1024,
'M' : 1000 * 1000,
'KiB' : 1024,
'K' : 1000,
}
try:
code = 0
if not code:
mtd_num = self.device[-1]
cmd = ('ubiformat', '/dev/mtd' + mtd_num)
self.check_call(cmd, vmode=self.V2)
cmd = ('ubiattach', '-m', mtd_num, '-d', '0', '/dev/ubi_ctrl',)
self.check_call(cmd, vmode=self.V2)
for part in self.im.platformConf['installer']:
label, partData = list(part.items())[0]
if type(partData) == dict:
sz, fmt = partData['='], partData.get('format', 'ubifs')
else:
sz, fmt = partData, 'ubifs'
cnt = None
for ul, ub in UNITS.items():
if sz.endswith(ul):
cnt = int(sz[:-len(ul)], 10) * ub
break
if cnt is None:
self.log.error("invalid size (no units) for %s: %s",part, sz)
return 1
label = label.strip()
cmd = ('ubimkvol', '/dev/ubi0', '-N', label, '-s', bytes(cnt),)
self.check_call(cmd, vmode=self.V2)
except Exception:
self.log.exception("cannot create UBI file systemfrom %s",self.device)
return 0
def ubi_mount(self, dir, devpart):
if devpart is None:
self.log.error("Mount failed.no given mount device part")
return 1
if dir is None:
self.log.error("Mount failed.no given mount directory")
return 1
if self.ubiParts is None:
try:
self.ubiParts = UbinfoParser(log=self.log.getChild("ubinfo -a"))
except Exception:
self.log.exception("Mount failed.No UBIfs")
return 1
try:
dev = self.ubiParts[devpart]
except IndexError as ex:
self.log.error("Mount failed.cannot find %s partition", str(devpart))
return 1
self.makedirs(dir)
device = "/dev/" + dev['device'] + "_" + dev['Volume ID']
if dev['fsType']:
cmd = ('mount', '-t', dev['fsType'], device, dir,)
else:
cmd = ('mount', device, dir,)
code = self.check_call(cmd, vmode=self.V2)
if code:
self.log.error("Mount failed.mount command exect failed")
return 1
return 0
def ubi_unmount(self,dir=None):
if dir is None:
self.log.error("Unmount failed.no given unmount directory")
return 1
cmd = ('umount', dir)
code = self.check_call(cmd, vmode=self.V2)
if code:
self.log.error("Unmount failed.umount command exect failed")
return 1
return 0
def ubi_getinfo(self):
try:
self.ubiParts = UbinfoParser(log=self.log.getChild("ubinfo -a"))
except Exception:
self.log.exception("UBI info get failed.No UBIfs")
return 1
return 0
def ubi_installSwi(self):
files = os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist()
swis = [x for x in files if x.endswith('.swi')]
if not swis:
self.log.warn("No ONL Software Image available for ubi installation.")
self.log.warn("Post-install ZTN installation will be required.")
if len(swis) > 1:
self.log.error("Multiple SWIs found in ubi installer: %s", " ".join(swis))
return 1
base = swis[0]
self.log.info("Installing ONL Software Image (%s)...", base)
dev = "ONL-IMAGES"
dstDir = "/tmp/ubifs"
code = self.ubi_mount(dstDir,dev)
if code :
return 1
dst = os.path.join(dstDir, base)
self.installerCopy(base, dst)
self.log.info("syncing block devices(%s)...",dev)
self.check_call(('sync',))
self.ubi_unmount(dstDir)
return 0
def ubi_installLoader(self):
loaderBasename = None
for c in sysconfig.installer.fit:
if self.installerExists(c):
loaderBasename = c
break
if not loaderBasename:
self.log.error("The platform loader file is missing.")
return 1
self.log.info("Installing the ONL loader from %s...", loaderBasename)
dev = "ONL-BOOT"
dstDir = "/tmp/ubiloader"
code = self.ubi_mount(dstDir,dev)
if code :
return 1
dst = os.path.join(dstDir, "%s.itb" % self.im.installerConf.installer_platform)
self.installerCopy(loaderBasename, dst)
self.log.info("syncing block devices(%s)...",dev)
self.check_call(('sync',))
self.ubi_unmount(dstDir)
return 0
def ubi_installBootConfig(self):
basename = 'boot-config'
self.log.info("Installing boot-config to ONL-BOOT partion")
dev = "ONL-BOOT"
dstDir = "/tmp/ubibootcon"
code = self.ubi_mount(dstDir,dev)
if code :
return 1
dst = os.path.join(dstDir, basename)
self.installerCopy(basename, dst, True)
with open(dst) as fd:
buf = fd.read()
ecf = buf.encode('base64', 'strict').strip()
if self.im.grub and self.im.grubEnv is not None:
setattr(self.im.grubEnv, 'boot_config_default', ecf)
if self.im.uboot and self.im.ubootEnv is not None:
setattr(self.im.ubootEnv, 'boot-config-default', ecf)
self.log.info("syncing block devices(%s)...",dev)
self.check_call(('sync',))
self.ubi_unmount(dstDir)
return 0
def ubi_installOnlConfig(self):
self.log.info("Installing onl-config to ONL-CONFIG partion")
dev = "ONL-CONFIG"
dstDir = "/tmp/ubionlconfig"
code = self.ubi_mount(dstDir,dev)
if code :
return 1
for f in self.zf.namelist():
d = 'config/'
if f.startswith(d) and f != d:
dst = os.path.join(dstDir, os.path.basename(f))
if not os.path.exists(dst):
self.installerCopy(f, dst)
self.log.info("syncing block devices(%s)...",dev)
self.check_call(('sync',))
self.ubi_unmount(dstDir)
return 0
class UbootInstaller(SubprocessMixin, UBIfsCreater):
class installmeta(Base.installmeta):
@@ -874,13 +1071,16 @@ class UbootInstaller(SubprocessMixin, Base):
cmds.append("setenv onl_itb %s" % itb)
for item in self.platformConf['loader']['setenv']:
k, v = list(item.items())[0]
cmds.append("setenv %s %s" % (k, v,))
device = self.getDevice()
if "mtdblock" in device:
cmds.append("setenv %s %s ${platformargs} ubi.mtd=%s root=/dev/ram ethaddr=$ethaddr" % (k, v, device[-1],))
else:
cmds.append("setenv %s %s" % (k, v,))
cmds.extend(self.platformConf['loader']['nos_bootcmds'])
return "; ".join(cmds)
def __init__(self, *args, **kwargs):
Base.__init__(self, *args, **kwargs)
UBIfsCreater.__init__(self, *args, **kwargs)
self.device = self.im.getDevice()
self.rawLoaderDevice = None
@@ -1014,6 +1214,24 @@ class UbootInstaller(SubprocessMixin, Base):
code = self.assertUnmounted()
if code: return code
if "mtdblock" in self.device:
code = self.ubifsinit()
if code: return code
code = self.ubi_getinfo()
if code: return code
code = self.ubi_installSwi()
if code: return code
code = self.ubi_installLoader()
if code: return code
code = self.ubi_installBootConfig()
if code: return code
code = self.ubi_installOnlConfig()
if code: return code
code = self.runPlugins(Plugin.PLUGIN_POSTINSTALL)
if code: return code
code = self.installUbootEnv()
return code
code = self.maybeCreateLabel()
if code: return code

View File

@@ -388,6 +388,63 @@ class BlkidParser(SubprocessMixin):
def __len__(self):
return len(self.parts)
class UbinfoParser(SubprocessMixin):
def __init__(self, log=None):
self.log = log or logging.getLogger("ubinfo -a")
self.parse()
def parse(self):
self.parts = []
lines = ''
try:
cmd = ('ubinfo', '-a',)
lines = self.check_output(cmd).splitlines()
except Exception as ex:
return self
dev = None
volId = None
name = None
attrs = {}
for line in lines:
line = line.strip()
p = line.find(':')
if p < 0: continue
name, value = line[:p], line[p+1:].strip()
if 'Volume ID' in name:
p = value.find('(')
if p < 0: continue
volumeId = value[:p].strip()
attrs['Volume ID'] = volumeId
p = value.find('on')
if p < 0: continue
dev = value[p+2:-1].strip()
attrs['device'] = dev
if 'Name' in name:
dev = "/dev/" + dev + "_" + volumeId
p = line.find(':')
if p < 0: continue
attrs['Name'] = line[p+1:].strip()
attrs['fsType'] = 'ubifs'
self.parts.append(attrs)
dev = None
volId = None
name = None
attrs = {}
def __getitem__(self, idxOrName):
if type(idxOrName) == int:
return self.parts[idxOrName]
for part in self.parts:
if part['Name'] == idxOrName: return part
raise IndexError("cannot find partition %s" % repr(idxOrName))
def __len__(self):
return len(self.parts)
class ProcMtdEntry:
def __init__(self,

View File

@@ -63,7 +63,12 @@ class MountManager(object):
self.logger.debug("%s not mounted @ %s. It will be mounted %s" % (device, directory, mode))
try:
cmd = "mount -o %s %s %s" % (','.join(mountargs), device, directory)
p = device.find('ubi')
if p < 0:
cmd = "mount -o %s %s %s" % (','.join(mountargs), device, directory)
else:
cmd = "mount -o %s -t %s %s %s" % (','.join(mountargs), 'ubifs', device, directory)
self.logger.debug("+ %s" % cmd)
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError, e:
@@ -148,12 +153,39 @@ class OnlMountManager(object):
def _discover(k):
v = md[k]
lbl = v.get('label', k)
useUbiDev = False
try:
v['device'] = subprocess.check_output(('blkid', '-L', lbl,)).strip()
except subprocess.CalledProcessError:
return False
useUbiDev = True
if useUbiDev == True:
if k == 'EFI-BOOT':
return False
output = subprocess.check_output("ubinfo -d 0 -N %s" % k, shell=True).splitlines()
volumeId = None
device = None
for line in output:
line = line.strip()
p = line.find(':')
if p < 0:
self.logger.debug("Invaild ubinfo output %s" % line)
name, value = line[:p], line[p+1:].strip()
if 'Volume ID' in name:
p = value.find('(')
if p < 0:
self.logger.debug("Invalid Volume ID %s" % value)
volumeId = value[:p].strip()
p = value.find('on')
if p < 0:
self.logger.debug("Invalid ubi devicde %s" % value)
device = value[p+2:-1].strip()
if 'Name' in name:
v['device'] = "/dev/" + device + "_" + volumeId
if not os.path.isdir(v['dir']):
self.logger.debug("Make directory '%s'...", v['dir'])
os.makedirs(v['dir'])

View File

@@ -477,6 +477,10 @@ class OnlPlatformPortConfig_48x1_4x10(object):
PORT_COUNT=52
PORT_CONFIG="48x1 + 4x10"
class OnlPlatformPortConfig_48x1_2x10(object):
PORT_COUNT=50
PORT_CONFIG="48x1 + 2x10"
class OnlPlatformPortConfig_48x10_4x40(object):
PORT_COUNT=52
PORT_CONFIG="48x10 + 4x40"

View File

@@ -16,7 +16,4 @@ packages:
init: ${ONL}/packages/base/any/faultd/faultd.init
changelog: Change changes changes.,
asr: True

View File

@@ -38,6 +38,6 @@ K_COPY_DST := kernel-3.2-lts-arm-iproc-all.bin.gz
endif
export ARCH=arm
DTS_LIST := accton_as4610_54
DTS_LIST := accton_as4610_54 delta_ag6248c
include $(ONL)/make/kbuild.mk

View File

@@ -289,6 +289,7 @@ CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000
# CONFIG_MACH_GH is not set
# CONFIG_MACH_DNI_3448P is not set
CONFIG_MACH_ACCTON_AS4610_54=y
CONFIG_MACH_DELTA_AG6248C=y
# CONFIG_MACH_IPROC_EMULATION is not set
#
@@ -1938,7 +1939,8 @@ CONFIG_IPROC_QSPI_SINGLE_MODE=y
# CONFIG_IPROC_QSPI_DUAL_MODE is not set
# CONFIG_IPROC_QSPI_QUAD_MODE is not set
CONFIG_IPROC_QSPI_MAX_HZ=62500000
# CONFIG_IPROC_MTD_NAND is not set
CONFIG_IPROC_MTD_NAND=y
# CONFIG_IPROC_MTD_NAND_USE_JFFS2 is not set
# CONFIG_IPROC_PWM is not set
CONFIG_IPROC_USB2H=y
CONFIG_USB_EHCI_BCM=y

View File

@@ -0,0 +1,181 @@
diff --git a/arch/arm/boot/dts/delta_ag6248c.dts b/arch/arm/boot/dts/delta_ag6248c.dts
new file mode 100755
index 0000000..f86c35b
--- /dev/null
+++ b/arch/arm/boot/dts/delta_ag6248c.dts
@@ -0,0 +1,78 @@
+/*
+ * Delta Networks, Inc. AG6248C Device Tree Source
+ *
+ * Copyright 2015, Cumulus Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+/dts-v1/;
+/include/ "helix4.dtsi"
+
+/ {
+ model = "delta,ag6248c";
+ compatible = "delta,ag6248c";
+
+ aliases {
+ serial0 = &uart0;
+ i2c-controller0 = &i2c0;
+ i2c-controller1 = &i2c1;
+ };
+
+ memory {
+ reg = <0x61000000 0x7f000000>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ next-level-cache = <&L2>;
+ reg = <0x00>;
+ };
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ next-level-cache = <&L2>;
+ reg = <0x01>;
+ };
+ };
+
+ localbus@1e000000{
+ address-cells = <0x2>;
+ #size-cells = <0x1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x0 0x1e000000 0x02000000>;
+
+ };
+
+ i2c0: i2c@18038000 {
+ compatible = "iproc-smb";
+ reg = <0x18038000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = < 127 >;
+ clock-frequency = <400000>;
+ rtc@68 {
+ compatible = "m41st85";
+ reg = <0x68>;
+ };
+ };
+
+
+ i2c1: i2c@1803b000 {
+ compatible = "iproc-smb";
+ reg = <0x1803b000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = < 128 >;
+ clock-frequency = <100000>;
+
+ };
+};
diff --git a/arch/arm/mach-iproc/Kconfig b/arch/arm/mach-iproc/Kconfig
index c77208d..c6a87fc 100644
--- a/arch/arm/mach-iproc/Kconfig
+++ b/arch/arm/mach-iproc/Kconfig
@@ -49,6 +49,12 @@ config MACH_ACCTON_AS4610_54
help
Support for Accton AS4610-54 POE and non -POE board.
+config MACH_DELTA_AG6248C
+ select ARM_L1_CACHE_SHIFT_6
+ bool "Support Delta AG6248C board"
+ help
+ Support for Delta AG6248C board.
+
config MACH_IPROC_P7
bool "Support iProc Profile 7 architecture"
depends on MACH_GH
diff --git a/arch/arm/mach-iproc/board_bu.c b/arch/arm/mach-iproc/board_bu.c
index 7e07ed1..5479020 100644
--- a/arch/arm/mach-iproc/board_bu.c
+++ b/arch/arm/mach-iproc/board_bu.c
@@ -1083,6 +1083,7 @@ MACHINE_END
static const char * helix4_dt_board_compat[] = {
"dni,dni_3448p",
"accton,as4610_54",
+ "delta,ag6248c",
NULL
};
diff --git a/arch/arm/mach-iproc/common.c b/arch/arm/mach-iproc/common.c
index b116ffc..e911a2b 100644
--- a/arch/arm/mach-iproc/common.c
+++ b/arch/arm/mach-iproc/common.c
@@ -187,7 +187,8 @@ static struct platform_device wdt_device =
enum {
HX4_NONE = 0,
HX4_DNI_3448P,
- HX4_ACCTON_AS4610_54
+ HX4_ACCTON_AS4610_54,
+ HX4_DELTA_AG6248C,
};
/*
@@ -212,6 +213,8 @@ int brcm_get_hx4_model(void)
return HX4_DNI_3448P;
else if (!strcmp(model, "accton,as4610_54"))
return HX4_ACCTON_AS4610_54;
+ else if (!strcmp(model, "delta,ag6248c"))
+ return HX4_DELTA_AG6248C;
printk( KERN_ERR "Unknown Model %s\n", model );
return HX4_NONE;
diff --git a/arch/arm/mach-iproc/include/mach/iproc_regs.h b/arch/arm/mach-iproc/include/mach/iproc_regs.h
index 460c436..50ea557 100644
--- a/arch/arm/mach-iproc/include/mach/iproc_regs.h
+++ b/arch/arm/mach-iproc/include/mach/iproc_regs.h
@@ -364,7 +364,11 @@
#define IPROC_GMAC3_INT 182
#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \
defined(CONFIG_MACH_ACCTON_AS4610_54))
+#if defined(CONFIG_MACH_DELTA_AG6248C)
+#define IPROC_NUM_GMACS 1
+#else
#define IPROC_NUM_GMACS 2
+#endif
#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000)
#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCONTROL) //(0x18023000)
#define IPROC_GMAC2_REG_BASE (0) // n/a
diff --git a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c
index d5b400d..a823697 100644
--- a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c
+++ b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c
@@ -143,7 +143,8 @@ __setup("envaddr=", envaddr_setup);
enum {
HX4_NONE = 0,
HX4_DNI_3448P,
- HX4_ACCTON_AS4610_54
+ HX4_ACCTON_AS4610_54,
+ HX4_DELTA_AG6248C
};
static void
@@ -158,7 +159,10 @@ setup_uboot_vars(void) {
} else if (modelnum == HX4_ACCTON_AS4610_54) {
env_offset = 0x000f0000;
uboot_vars_start = CONFIG_SPI_BASE + env_offset;
- }
+ }else if (modelnum == HX4_DELTA_AG6248C) {
+ env_offset = 0x00300000;
+ uboot_vars_start = CONFIG_NAND_BASE + env_offset;
+ }
}
/*
--
2.1.4

View File

@@ -506,3 +506,4 @@ scripts_package_Makefile.patch
tools_include_tools_be_byteshift.h.patch
tools_include_tools_le_byteshift.h.patch
platform-accton-as4610-device-drivers.patch
platform-delta-ag6248c-device-drivers.patch

View File

@@ -21,5 +21,4 @@ packages:
init: ${ONL}/packages/base/any/onlp-snmpd/onlp-snmpd.init
changelog: Change changes changes.,
asr: True

View File

@@ -36,7 +36,4 @@ packages:
init: $ONL/packages/base/any/onlp/src/onlpd.init
changelog: Change changes changes.,
asr: True

View File

@@ -50,11 +50,26 @@ ds_connect__(const char* path)
return -1;
}
/*
* UDS connects must be non-blocking.
*/
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
if(connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
/*
* Set blocking with a 1 second timeout on all domain socket read/write operations.
*/
struct timeval tv;
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
return fd;
}
else {

View File

@@ -111,7 +111,7 @@ decode_tlv__(onlp_onie_info_t* info, tlvinfo_tlv_t * tlv)
} \
_info -> _member = aim_zmalloc(_tlv->length + 1); \
memcpy((void*) _info -> _member, _tlv->value, _tlv->length); \
break; \
break; \
}
CASE_TLV_STRING(info, product_name, PRODUCT_NAME, tlv);
@@ -425,6 +425,7 @@ onlp_onie_show_json(onlp_onie_info_t* info, aim_pvs_t* pvs)
cJSON_AddStringToObject(cj, "MAC", mac);
aim_free(mac);
}
_S(Manufacturer, manufacturer);
_S(Manufacture Date,manufacture_date);
_S(Vendor,vendor);
_S(Platform Name,platform_name);
@@ -522,8 +523,3 @@ onlp_onie_read_json(onlp_onie_info_t* info, const char* fname)
cJSON_Delete(cj);
return 0;
}

View File

@@ -131,8 +131,8 @@ static ssize_t fan_set_duty_cycle(struct device *dev,
static ssize_t fan_show_value(struct device *dev,
struct device_attribute *da, char *buf);
extern int as5812_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5812_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5812_54x_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5812_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
/*******************/
@@ -258,12 +258,12 @@ static const struct attribute_group accton_as5812_54x_fan_group = {
static int accton_as5812_54x_fan_read_value(u8 reg)
{
return as5812_54x_i2c_cpld_read(0x60, reg);
return as5812_54x_cpld_read(0x60, reg);
}
static int accton_as5812_54x_fan_write_value(u8 reg, u8 value)
{
return as5812_54x_i2c_cpld_write(0x60, reg, value);
return as5812_54x_cpld_write(0x60, reg, value);
}
static void accton_as5812_54x_fan_update_device(struct device *dev)
@@ -393,7 +393,7 @@ static struct platform_driver accton_as5812_54x_fan_driver = {
static int __init accton_as5812_54x_fan_init(void)
{
int ret;
ret = platform_driver_register(&accton_as5812_54x_fan_driver);
if (ret < 0) {
goto exit;

View File

@@ -29,8 +29,8 @@
#include <linux/leds.h>
#include <linux/slab.h>
extern int as5812_54x_i2c_cpld_read (unsigned short cpld_addr, u8 reg);
extern int as5812_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5812_54x_cpld_read (unsigned short cpld_addr, u8 reg);
extern int as5812_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern void led_classdev_unregister(struct led_classdev *led_cdev);
extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
@@ -220,12 +220,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type,
static int accton_as5812_54x_led_read_value(u8 reg)
{
return as5812_54x_i2c_cpld_read(0x60, reg);
return as5812_54x_cpld_read(0x60, reg);
}
static int accton_as5812_54x_led_write_value(u8 reg, u8 value)
{
return as5812_54x_i2c_cpld_write(0x60, reg, value);
return as5812_54x_cpld_write(0x60, reg, value);
}
static void accton_as5812_54x_led_update(void)

View File

@@ -44,7 +44,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, char
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_serial_number(struct device *dev, struct device_attribute *da,char *buf);
static int as5812_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int as5812_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5812_54x_cpld_read(unsigned short cpld_addr, u8 reg);
static int as5812_54x_psu_model_name_get(struct device *dev , int get_serial);
/* Addresses scanned
@@ -406,7 +406,7 @@ static struct as5812_54x_psu_data *as5812_54x_psu_update_device(struct device *d
/* Read psu status */
status = as5812_54x_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
status = as5812_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
@@ -426,20 +426,9 @@ exit:
return data;
}
static int __init as5812_54x_psu_init(void)
{
return i2c_add_driver(&as5812_54x_psu_driver);
}
static void __exit as5812_54x_psu_exit(void)
{
i2c_del_driver(&as5812_54x_psu_driver);
}
module_i2c_driver(as5812_54x_psu_driver);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("accton as5812_54x_psu driver");
MODULE_LICENSE("GPL");
module_init(as5812_54x_psu_init);
module_exit(as5812_54x_psu_exit);

View File

@@ -1,508 +0,0 @@
/*
* An hwmon driver for accton as5812_54x sfp
*
* Copyright (C) 2015 Accton Technology Corporation.
* Brandon Chuang <brandon_chuang@accton.com.tw>
*
* Based on ad7414.c
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#define NUM_OF_SFP_PORT 54
#define BIT_INDEX(i) (1ULL << (i))
/* Addresses scanned
*/
static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
/* Each client has this additional data
*/
struct as5812_54x_sfp_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* !=0 if registers are valid */
unsigned long last_updated; /* In jiffies */
int port; /* Front port index */
char eeprom[256]; /* eeprom data */
u64 status[4]; /* bit0:port0, bit1:port1 and so on */
/* index 0 => is_present
1 => tx_fail
2 => tx_disable
3 => rx_loss */
};
/* The table maps active port to cpld port.
* Array index 0 is for active port 1,
* index 1 for active port 2, and so on.
* The array content implies cpld port index.
*/
static const u8 cpld_to_front_port_table[] =
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 52, 50, 53, 51, 54};
#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port])
static struct as5812_54x_sfp_data *as5812_54x_sfp_update_device(struct device *dev, int update_eeprom);
static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
extern int as5812_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5812_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
enum as5812_54x_sfp_sysfs_attributes {
SFP_IS_PRESENT,
SFP_TX_FAULT,
SFP_TX_DISABLE,
SFP_RX_LOSS,
SFP_PORT_NUMBER,
SFP_EEPROM,
SFP_RX_LOS_ALL,
SFP_IS_PRESENT_ALL,
};
/* sysfs attributes for hwmon
*/
static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT);
static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, show_status, NULL, SFP_TX_FAULT);
static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, show_status, set_tx_disable, SFP_TX_DISABLE);
static SENSOR_DEVICE_ATTR(sfp_rx_loss, S_IRUGO, show_status,NULL, SFP_RX_LOSS);
static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER);
static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM);
static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, show_status,NULL, SFP_RX_LOS_ALL);
static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL);
static struct attribute *as5812_54x_sfp_attributes[] = {
&sensor_dev_attr_sfp_is_present.dev_attr.attr,
&sensor_dev_attr_sfp_tx_fault.dev_attr.attr,
&sensor_dev_attr_sfp_rx_loss.dev_attr.attr,
&sensor_dev_attr_sfp_tx_disable.dev_attr.attr,
&sensor_dev_attr_sfp_eeprom.dev_attr.attr,
&sensor_dev_attr_sfp_port_number.dev_attr.attr,
&sensor_dev_attr_sfp_rx_los_all.dev_attr.attr,
&sensor_dev_attr_sfp_is_present_all.dev_attr.attr,
NULL
};
static ssize_t show_port_number(struct device *dev, struct device_attribute *da,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct as5812_54x_sfp_data *data = i2c_get_clientdata(client);
return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port));
}
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5812_54x_sfp_data *data;
u8 val;
int values[7];
/* Error-check the CPLD read results. */
#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \
do { \
_rv = (_read_expr); \
if(_rv < 0) { \
return sprintf(_buf, "READ ERROR\n"); \
} \
if(_invert) { \
_rv = ~_rv; \
} \
_rv &= 0xFF; \
} while(0)
if(attr->index == SFP_RX_LOS_ALL) {
/*
* Report the RX_LOS status for all ports.
* This does not depend on the currently active SFP selector.
*/
/* RX_LOS Ports 1-8 */
VALIDATED_READ(buf, values[0], as5812_54x_i2c_cpld_read(0x61, 0x0F), 0);
/* RX_LOS Ports 9-16 */
VALIDATED_READ(buf, values[1], as5812_54x_i2c_cpld_read(0x61, 0x10), 0);
/* RX_LOS Ports 17-24 */
VALIDATED_READ(buf, values[2], as5812_54x_i2c_cpld_read(0x61, 0x11), 0);
/* RX_LOS Ports 25-32 */
VALIDATED_READ(buf, values[3], as5812_54x_i2c_cpld_read(0x62, 0x0F), 0);
/* RX_LOS Ports 33-40 */
VALIDATED_READ(buf, values[4], as5812_54x_i2c_cpld_read(0x62, 0x10), 0);
/* RX_LOS Ports 41-48 */
VALIDATED_READ(buf, values[5], as5812_54x_i2c_cpld_read(0x62, 0x11), 0);
/** Return values 1 -> 48 in order */
return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n",
values[0], values[1], values[2],
values[3], values[4], values[5]);
}
if(attr->index == SFP_IS_PRESENT_ALL) {
/*
* Report the SFP_PRESENCE status for all ports.
* This does not depend on the currently active SFP selector.
*/
/* SFP_PRESENT Ports 1-8 */
VALIDATED_READ(buf, values[0], as5812_54x_i2c_cpld_read(0x61, 0x6), 1);
/* SFP_PRESENT Ports 9-16 */
VALIDATED_READ(buf, values[1], as5812_54x_i2c_cpld_read(0x61, 0x7), 1);
/* SFP_PRESENT Ports 17-24 */
VALIDATED_READ(buf, values[2], as5812_54x_i2c_cpld_read(0x61, 0x8), 1);
/* SFP_PRESENT Ports 25-32 */
VALIDATED_READ(buf, values[3], as5812_54x_i2c_cpld_read(0x62, 0x6), 1);
/* SFP_PRESENT Ports 33-40 */
VALIDATED_READ(buf, values[4], as5812_54x_i2c_cpld_read(0x62, 0x7), 1);
/* SFP_PRESENT Ports 41-48 */
VALIDATED_READ(buf, values[5], as5812_54x_i2c_cpld_read(0x62, 0x8), 1);
/* QSFP_PRESENT Ports 49-54 */
VALIDATED_READ(buf, values[6], as5812_54x_i2c_cpld_read(0x62, 0x14), 1);
/* Return values 1 -> 54 in order */
return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
values[0], values[1], values[2],
values[3], values[4], values[5],
values[6] & 0x3F);
}
/*
* The remaining attributes are gathered on a per-selected-sfp basis.
*/
data = as5812_54x_sfp_update_device(dev, 0);
if (attr->index == SFP_IS_PRESENT) {
val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 0 : 1;
}
else {
val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 1 : 0;
}
return sprintf(buf, "%d", val);
}
static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct as5812_54x_sfp_data *data = i2c_get_clientdata(client);
unsigned short cpld_addr = 0;
u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0;
long disable;
int error;
/* Tx disable is not supported for QSFP ports(49-54) */
if (data->port >= 48) {
return -EINVAL;
}
error = kstrtol(buf, 10, &disable);
if (error) {
return error;
}
mutex_lock(&data->update_lock);
if(data->port < 24) {
cpld_addr = 0x61;
cpld_reg = 0xC + data->port / 8;
cpld_bit = 1 << (data->port % 8);
}
else {
cpld_addr = 0x62;
cpld_reg = 0xC + (data->port - 24) / 8;
cpld_bit = 1 << (data->port % 8);
}
cpld_val = as5812_54x_i2c_cpld_read(cpld_addr, cpld_reg);
/* Update tx_disable status */
if (disable) {
data->status[SFP_TX_DISABLE] |= BIT_INDEX(data->port);
cpld_val |= cpld_bit;
}
else {
data->status[SFP_TX_DISABLE] &= ~BIT_INDEX(data->port);
cpld_val &= ~cpld_bit;
}
as5812_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_eeprom(struct device *dev, struct device_attribute *da,
char *buf)
{
struct as5812_54x_sfp_data *data = as5812_54x_sfp_update_device(dev, 1);
if (!data->valid) {
return 0;
}
if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) != 0) {
return 0;
}
memcpy(buf, data->eeprom, sizeof(data->eeprom));
return sizeof(data->eeprom);
}
static const struct attribute_group as5812_54x_sfp_group = {
.attrs = as5812_54x_sfp_attributes,
};
static int as5812_54x_sfp_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct as5812_54x_sfp_data *data;
int status;
extern int platform_accton_as5812_54x(void);
if(!platform_accton_as5812_54x()) {
return -ENODEV;
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as5812_54x_sfp_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
mutex_init(&data->update_lock);
data->port = dev_id->driver_data;
i2c_set_clientdata(client, data);
dev_info(&client->dev, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &as5812_54x_sfp_group);
if (status) {
goto exit_free;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
dev_info(&client->dev, "%s: sfp '%s'\n",
dev_name(data->hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &as5812_54x_sfp_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as5812_54x_sfp_remove(struct i2c_client *client)
{
struct as5812_54x_sfp_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as5812_54x_sfp_group);
kfree(data);
return 0;
}
enum port_numbers {
as5812_54x_sfp1, as5812_54x_sfp2, as5812_54x_sfp3, as5812_54x_sfp4,
as5812_54x_sfp5, as5812_54x_sfp6, as5812_54x_sfp7, as5812_54x_sfp8,
as5812_54x_sfp9, as5812_54x_sfp10, as5812_54x_sfp11,as5812_54x_sfp12,
as5812_54x_sfp13, as5812_54x_sfp14, as5812_54x_sfp15,as5812_54x_sfp16,
as5812_54x_sfp17, as5812_54x_sfp18, as5812_54x_sfp19,as5812_54x_sfp20,
as5812_54x_sfp21, as5812_54x_sfp22, as5812_54x_sfp23,as5812_54x_sfp24,
as5812_54x_sfp25, as5812_54x_sfp26, as5812_54x_sfp27,as5812_54x_sfp28,
as5812_54x_sfp29, as5812_54x_sfp30, as5812_54x_sfp31,as5812_54x_sfp32,
as5812_54x_sfp33, as5812_54x_sfp34, as5812_54x_sfp35,as5812_54x_sfp36,
as5812_54x_sfp37, as5812_54x_sfp38, as5812_54x_sfp39,as5812_54x_sfp40,
as5812_54x_sfp41, as5812_54x_sfp42, as5812_54x_sfp43,as5812_54x_sfp44,
as5812_54x_sfp45, as5812_54x_sfp46, as5812_54x_sfp47,as5812_54x_sfp48,
as5812_54x_sfp49, as5812_54x_sfp52, as5812_54x_sfp50,as5812_54x_sfp53,
as5812_54x_sfp51, as5812_54x_sfp54
};
static const struct i2c_device_id as5812_54x_sfp_id[] = {
{ "as5812_54x_sfp1", as5812_54x_sfp1 }, { "as5812_54x_sfp2", as5812_54x_sfp2 },
{ "as5812_54x_sfp3", as5812_54x_sfp3 }, { "as5812_54x_sfp4", as5812_54x_sfp4 },
{ "as5812_54x_sfp5", as5812_54x_sfp5 }, { "as5812_54x_sfp6", as5812_54x_sfp6 },
{ "as5812_54x_sfp7", as5812_54x_sfp7 }, { "as5812_54x_sfp8", as5812_54x_sfp8 },
{ "as5812_54x_sfp9", as5812_54x_sfp9 }, { "as5812_54x_sfp10", as5812_54x_sfp10 },
{ "as5812_54x_sfp11", as5812_54x_sfp11 }, { "as5812_54x_sfp12", as5812_54x_sfp12 },
{ "as5812_54x_sfp13", as5812_54x_sfp13 }, { "as5812_54x_sfp14", as5812_54x_sfp14 },
{ "as5812_54x_sfp15", as5812_54x_sfp15 }, { "as5812_54x_sfp16", as5812_54x_sfp16 },
{ "as5812_54x_sfp17", as5812_54x_sfp17 }, { "as5812_54x_sfp18", as5812_54x_sfp18 },
{ "as5812_54x_sfp19", as5812_54x_sfp19 }, { "as5812_54x_sfp20", as5812_54x_sfp20 },
{ "as5812_54x_sfp21", as5812_54x_sfp21 }, { "as5812_54x_sfp22", as5812_54x_sfp22 },
{ "as5812_54x_sfp23", as5812_54x_sfp23 }, { "as5812_54x_sfp24", as5812_54x_sfp24 },
{ "as5812_54x_sfp25", as5812_54x_sfp25 }, { "as5812_54x_sfp26", as5812_54x_sfp26 },
{ "as5812_54x_sfp27", as5812_54x_sfp27 }, { "as5812_54x_sfp28", as5812_54x_sfp28 },
{ "as5812_54x_sfp29", as5812_54x_sfp29 }, { "as5812_54x_sfp30", as5812_54x_sfp30 },
{ "as5812_54x_sfp31", as5812_54x_sfp31 }, { "as5812_54x_sfp32", as5812_54x_sfp32 },
{ "as5812_54x_sfp33", as5812_54x_sfp33 }, { "as5812_54x_sfp34", as5812_54x_sfp34 },
{ "as5812_54x_sfp35", as5812_54x_sfp35 }, { "as5812_54x_sfp36", as5812_54x_sfp36 },
{ "as5812_54x_sfp37", as5812_54x_sfp37 }, { "as5812_54x_sfp38", as5812_54x_sfp38 },
{ "as5812_54x_sfp39", as5812_54x_sfp39 }, { "as5812_54x_sfp40", as5812_54x_sfp40 },
{ "as5812_54x_sfp41", as5812_54x_sfp41 }, { "as5812_54x_sfp42", as5812_54x_sfp42 },
{ "as5812_54x_sfp43", as5812_54x_sfp43 }, { "as5812_54x_sfp44", as5812_54x_sfp44 },
{ "as5812_54x_sfp45", as5812_54x_sfp45 }, { "as5812_54x_sfp46", as5812_54x_sfp46 },
{ "as5812_54x_sfp47", as5812_54x_sfp47 }, { "as5812_54x_sfp48", as5812_54x_sfp48 },
{ "as5812_54x_sfp49", as5812_54x_sfp49 }, { "as5812_54x_sfp50", as5812_54x_sfp50 },
{ "as5812_54x_sfp51", as5812_54x_sfp51 }, { "as5812_54x_sfp52", as5812_54x_sfp52 },
{ "as5812_54x_sfp53", as5812_54x_sfp53 }, { "as5812_54x_sfp54", as5812_54x_sfp54 },
{}
};
MODULE_DEVICE_TABLE(i2c, as5812_54x_sfp_id);
static struct i2c_driver as5812_54x_sfp_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "as5812_54x_sfp",
},
.probe = as5812_54x_sfp_probe,
.remove = as5812_54x_sfp_remove,
.id_table = as5812_54x_sfp_id,
.address_list = normal_i2c,
};
static int as5812_54x_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data)
{
int result = i2c_smbus_read_byte_data(client, command);
if (unlikely(result < 0)) {
dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result);
goto abort;
}
*data = (u8)result;
result = 0;
abort:
return result;
}
#define ALWAYS_UPDATE_DEVICE 1
static struct as5812_54x_sfp_data *as5812_54x_sfp_update_device(struct device *dev, int update_eeprom)
{
struct i2c_client *client = to_i2c_client(dev);
struct as5812_54x_sfp_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (ALWAYS_UPDATE_DEVICE || time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int status = -1;
int i = 0, j = 0;
data->valid = 0;
//dev_dbg(&client->dev, "Starting as5812_54x sfp status update\n");
memset(data->status, 0, sizeof(data->status));
/* Read status of port 1~48(SFP port) */
for (i = 0; i < 2; i++) {
for (j = 0; j < 12; j++) {
status = as5812_54x_i2c_cpld_read(0x61+i, 0x6+j);
if (status < 0) {
dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", 0x61+i, 0x6+j, status);
goto exit;
}
data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8);
}
}
/*
* Bring QSFPs out of reset,
* This is a temporary fix until the QSFP+_MOD_RST register
* can be exposed through the driver.
*/
as5812_54x_i2c_cpld_write(0x62, 0x15, 0x3F);
/* Read present status of port 49-54(QSFP port) */
status = as5812_54x_i2c_cpld_read(0x62, 0x14);
if (status < 0) {
dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", 0x61+i, 0x6+j, status);
}
else {
data->status[SFP_IS_PRESENT] |= (u64)status << 48;
}
if (update_eeprom) {
/* Read eeprom data based on port number */
memset(data->eeprom, 0, sizeof(data->eeprom));
/* Check if the port is present */
if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) {
/* read eeprom */
for (i = 0; i < sizeof(data->eeprom); i++) {
status = as5812_54x_sfp_read_byte(client, i, data->eeprom + i);
if (status < 0) {
dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n",
CPLD_PORT_TO_FRONT_PORT(data->port));
goto exit;
}
}
}
}
data->valid = 1;
data->last_updated = jiffies;
}
exit:
mutex_unlock(&data->update_lock);
return data;
}
module_i2c_driver(as5812_54x_sfp_driver);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("accton as5812_54x_sfp driver");
MODULE_LICENSE("GPL");

View File

@@ -24,20 +24,24 @@
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <fcntl.h> /* For O_RDWR && open */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <onlplib/i2c.h>
#include "platform_lib.h"
#include <onlplib/file.h>
#include "x86_64_accton_as5812_54x_int.h"
#include "x86_64_accton_as5812_54x_log.h"
#define MAX_SFP_PATH 64
static char sfp_node_path[MAX_SFP_PATH] = {0};
#define CPLD_MUX_BUS_START_INDEX 2
static int front_port_to_cpld_mux_index(int port)
#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom"
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_present_%d"
#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-00%d/module_rx_los_%d"
#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_fault_%d"
#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_disable_%d"
#define MODULE_PRESENT_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_present_all"
#define MODULE_PRESENT_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_present_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_rx_los_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_rx_los_all"
static int front_port_bus_index(int port)
{
int rport = 0;
@@ -63,38 +67,6 @@ static int front_port_to_cpld_mux_index(int port)
return (rport + CPLD_MUX_BUS_START_INDEX);
}
static int
as5812_54x_sfp_node_read_int(char *node_path, int *value, int data_len)
{
int ret = 0;
char buf[8] = {0};
*value = 0;
ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len);
if (ret == 0) {
*value = atoi(buf);
}
return ret;
}
static char*
as5812_54x_sfp_get_port_path_addr(int port, int addr, char *node_name)
{
sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s",
front_port_to_cpld_mux_index(port), addr,
node_name);
return sfp_node_path;
}
static char*
as5812_54x_sfp_get_port_path(int port, char *node_name)
{
return as5812_54x_sfp_get_port_path_addr(port, 50, node_name);
}
/************************************************************
*
* SFPI Entry Points
@@ -203,10 +175,10 @@ onlp_sfpi_is_present(int port)
* Return < 0 if error.
*/
int present;
char* path = as5812_54x_sfp_get_port_path(port, "sfp_is_present");
if (as5812_54x_sfp_node_read_int(path, &present, 1) != 0) {
AIM_LOG_INFO("Unable to read present status from port(%d)\r\n", port);
int addr = (port < 24) ? 61 : 62;
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -217,29 +189,35 @@ int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char* path;
FILE* fp;
path = as5812_54x_sfp_get_port_path(0, "sfp_is_present_all");
fp = fopen(path, "r");
/* Read present status of port 0~23 */
fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD2, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD2.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5,
bytes+6
);
int count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2);
fclose(fp);
if(count != AIM_ARRAYSIZE(bytes)) {
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD2.");
return ONLP_STATUS_E_INTERNAL;
}
/* Read present status of port 24~53 */
fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD3, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD3.");
return ONLP_STATUS_E_INTERNAL;
}
count = fscanf(fp, "%x %x %x %x", bytes+3, bytes+4, bytes+5, bytes+6);
fclose(fp);
if(count != 4) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD3.");
return ONLP_STATUS_E_INTERNAL;
}
@@ -268,33 +246,39 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char* path;
uint32_t bytes[6];
uint32_t *ptr = bytes;
FILE* fp;
path = as5812_54x_sfp_get_port_path(0, "sfp_rx_los_all");
fp = fopen(path, "r");
/* Read present status of port 0~23 */
int addr, i = 0;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5
);
fclose(fp);
if(count != 6) {
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 61; addr <= 62; addr++) {
if (addr == 61) {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r");
}
else {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD3, "r");
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
ptr += count;
}
/* Convert to 64 bit integer in port order */
int i = 0;
i = 0;
uint64_t rx_los_all = 0 ;
for(i = 5; i >= 0; i--) {
rx_los_all <<= 8;
@@ -315,18 +299,22 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
char* path = as5812_54x_sfp_get_port_path(port, "sfp_eeprom");
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
memset(data, 0, 256);
if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) {
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if (size != 256) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -336,11 +324,26 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256])
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
char* path = as5812_54x_sfp_get_port_path_addr(port, 51, "sfp_eeprom");
memset(data, 0, 256);
FILE* fp;
char file[64] = {0};
sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port));
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) {
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
if (fseek(fp, 256, SEEK_CUR) != 0) {
fclose(fp);
AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
int ret = fread(data, 1, 256, fp);
fclose(fp);
if (ret != 256) {
AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -350,28 +353,28 @@ onlp_sfpi_dom_read(int port, uint8_t data[256])
int
onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr)
{
int bus = front_port_to_cpld_mux_index(port);
int bus = front_port_bus_index(port);
return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value)
{
int bus = front_port_to_cpld_mux_index(port);
int bus = front_port_bus_index(port);
return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr)
{
int bus = front_port_to_cpld_mux_index(port);
int bus = front_port_bus_index(port);
return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value)
{
int bus = front_port_to_cpld_mux_index(port);
int bus = front_port_bus_index(port);
return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
}
@@ -384,13 +387,13 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 61 : 62;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
char* path = as5812_54x_sfp_get_port_path(port, "sfp_tx_disable");
if (deviceNodeWriteInt(path, value, 0) != 0) {
if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -412,19 +415,18 @@ int
onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
char* path = NULL;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 61 : 62;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
path = as5812_54x_sfp_get_port_path(port, "sfp_rx_loss");
if (as5812_54x_sfp_node_read_int(path, value, 1) != 0) {
if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -436,9 +438,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_FAULT:
{
path = as5812_54x_sfp_get_port_path(port, "sfp_tx_fault");
if (as5812_54x_sfp_node_read_int(path, value, 1) != 0) {
if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -450,9 +450,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_DISABLE:
{
path = as5812_54x_sfp_get_port_path(port, "sfp_tx_disable");
if (as5812_54x_sfp_node_read_int(path, value, 0) != 0) {
if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}

View File

@@ -9,9 +9,10 @@ class OnlPlatform_x86_64_accton_as5812_54x_r0(OnlPlatformAccton,
SYS_OBJECT_ID=".5812.54.1"
def baseconfig(self):
self.insmod('optoe')
self.insmod('cpr_4011_4mxx')
self.insmod("ym2651y")
for m in [ 'cpld', 'fan', 'psu', 'leds', 'sfp' ]:
for m in [ 'cpld', 'fan', 'psu', 'leds' ]:
self.insmod("x86-64-accton-as5812-54x-%s.ko" % m)
########### initialize I2C bus 0 ###########
@@ -26,16 +27,18 @@ class OnlPlatform_x86_64_accton_as5812_54x_r0(OnlPlatformAccton,
)
# initialize SFP devices
for port in range(1, 49):
self.new_i2c_device('as5812_54x_sfp%d' % port, 0x50, port+1)
self.new_i2c_device('as5812_54x_sfp%d' % port, 0x51, port+1)
self.new_i2c_device('optoe2', 0x50, port+1)
subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+1), shell=True)
# Initialize QSFP devices
self.new_i2c_device('as5812_54x_sfp49', 0x50, 50)
self.new_i2c_device('as5812_54x_sfp52', 0x50, 51)
self.new_i2c_device('as5812_54x_sfp50', 0x50, 52)
self.new_i2c_device('as5812_54x_sfp53', 0x50, 53)
self.new_i2c_device('as5812_54x_sfp51', 0x50, 54)
self.new_i2c_device('as5812_54x_sfp54', 0x50, 55)
for port in range(49, 55):
self.new_i2c_device('optoe1', 0x50, port+1)
subprocess.call('echo port49 > /sys/bus/i2c/devices/50-0050/port_name', shell=True)
subprocess.call('echo port52 > /sys/bus/i2c/devices/51-0050/port_name', shell=True)
subprocess.call('echo port50 > /sys/bus/i2c/devices/52-0050/port_name', shell=True)
subprocess.call('echo port53 > /sys/bus/i2c/devices/53-0050/port_name', shell=True)
subprocess.call('echo port51 > /sys/bus/i2c/devices/54-0050/port_name', shell=True)
subprocess.call('echo port54 > /sys/bus/i2c/devices/55-0050/port_name', shell=True)
########### initialize I2C bus 1 ###########
self.new_i2c_devices(

View File

@@ -39,8 +39,8 @@ static struct as5822_54x_fan_data *as5822_54x_fan_update_device(struct device *d
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5822_54x_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5822_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
/* fan related data, the index should match sysfs_fan_attributes
*/
@@ -199,12 +199,12 @@ static struct attribute *as5822_54x_fan_attributes[] = {
static int as5822_54x_fan_read_value(u8 reg)
{
return accton_i2c_cpld_read(FAN_STATUS_I2C_ADDR, reg);
return as5822_54x_cpld_read(FAN_STATUS_I2C_ADDR, reg);
}
static int as5822_54x_fan_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(FAN_STATUS_I2C_ADDR, reg, value);
return as5822_54x_cpld_write(FAN_STATUS_I2C_ADDR, reg, value);
}
/* fan utility functions

View File

@@ -38,8 +38,8 @@
#define DEBUG_PRINT(fmt, args...)
#endif
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5822_54x_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5822_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
struct accton_as5822_54x_led_data {
struct platform_device *pdev;
@@ -147,12 +147,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type,
static int accton_as5822_54x_led_read_value(u8 reg)
{
return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
return as5822_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
}
static int accton_as5822_54x_led_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
return as5822_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
}
static void accton_as5822_54x_led_update(void)

View File

@@ -50,7 +50,7 @@
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf);
static int as5822_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5822_54x_cpld_read(unsigned short cpld_addr, u8 reg);
/* Addresses scanned
*/
@@ -317,7 +317,7 @@ static struct as5822_54x_psu_data *as5822_54x_psu_update_device(struct device *d
data->valid = 0;
/* Read psu status */
status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
status = as5822_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
@@ -372,18 +372,7 @@ exit:
return data;
}
static int __init as5822_54x_psu_init(void)
{
return i2c_add_driver(&as5822_54x_psu_driver);
}
static void __exit as5822_54x_psu_exit(void)
{
i2c_del_driver(&as5822_54x_psu_driver);
}
module_init(as5822_54x_psu_init);
module_exit(as5822_54x_psu_exit);
module_i2c_driver(as5822_54x_psu_driver);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as5822_54x_psu driver");

View File

@@ -2,7 +2,7 @@
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2016 Accton Technology Corporation.
* Copyright 2013 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
@@ -24,29 +24,21 @@
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/i2c.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#include "x86_64_accton_as5822_54x_int.h"
#include "x86_64_accton_as5822_54x_log.h"
#define NUM_OF_SFP_PORT 54
#define MAX_SFP_PATH 64
static char sfp_node_path[MAX_SFP_PATH] = {0};
#define FRONT_PORT_BUS_INDEX(port) (port+18)
#define PORT_BUS_INDEX(port) (port+18)
static char*
sfp_get_port_path_addr(int port, int addr, char *node_name)
{
sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s",
FRONT_PORT_BUS_INDEX(port), addr, node_name);
return sfp_node_path;
}
static char*
sfp_get_port_path(int port, char *node_name)
{
return sfp_get_port_path_addr(port, 50, node_name);
}
#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom"
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d"
#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d"
#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d"
#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d"
#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/10-0061/module_rx_los_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/11-0062/module_rx_los_all"
/************************************************************
*
@@ -68,7 +60,7 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap)
*/
int p;
for(p = 0; p < NUM_OF_SFP_PORT; p++) {
for(p = 0; p < 54; p++) {
AIM_BITMAP_SET(bmap, p);
}
@@ -84,9 +76,12 @@ onlp_sfpi_is_present(int port)
* Return < 0 if error.
*/
int present;
char *path = sfp_get_port_path(port, "sfp_is_present");
int bus, addr;
if (onlp_file_read_int(&present, path) < 0) {
addr = (port < 29) ? 61 : 62;
bus = (addr == 61) ? 10 : 11;
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -97,42 +92,51 @@ onlp_sfpi_is_present(int port)
int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char* path;
uint32_t bytes[8], *ptr = NULL;
FILE* fp;
int addr;
AIM_BITMAP_CLR_ALL(dst);
ptr = bytes;
path = sfp_get_port_path(0, "sfp_is_present_all");
fp = fopen(path, "r");
for (addr = 61; addr <= 62; addr++) {
/* Read present status of port 0~53 */
char file[64] = {0};
int bus = (addr == 61) ? 10 : 11;
sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr);
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD.");
return ONLP_STATUS_E_INTERNAL;
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5,
bytes+6
);
fclose(fp);
if(count != AIM_ARRAYSIZE(bytes)) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
int count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3);
fclose(fp);
if(count != 4) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD.");
return ONLP_STATUS_E_INTERNAL;
}
ptr += count;
}
/* Mask out non-existant QSFP ports */
bytes[6] &= 0x3F;
bytes[3] &= 0x1F;
bytes[7] &= 0x1;
/* Convert to 64 bit integer in port order */
int i = 0;
uint64_t presence_all = 0 ;
for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) {
for(i = 7; i >= 4; i--) {
presence_all <<= 8;
presence_all |= bytes[i];
}
presence_all <<= 5;
presence_all |= bytes[3];
for(i = 2; i >= 0; i--) {
presence_all <<= 8;
presence_all |= bytes[i];
}
@@ -149,39 +153,68 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[6];
char* path;
uint32_t bytes[7];
uint32_t *ptr = bytes;
FILE* fp;
path = sfp_get_port_path(0, "sfp_rx_los_all");
fp = fopen(path, "r");
/* Read present status of port 0~23 */
int addr, i = 0;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5
);
fclose(fp);
if(count != 6) {
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 61; addr <= 62; addr++) {
int count;
if (addr == 61) {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r");
}
else {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD3, "r");
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
if (addr == 61) {
count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3);
fclose(fp);
if(count != 4) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
else {
count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
ptr += count;
}
/* Convert to 64 bit integer in port order */
int i = 0;
uint64_t rx_los_all = 0 ;
for(i = 5; i >= 0; i--) {
bytes[3] &= 0x1F;
bytes[6] &= 0x7;
for(i = 6; i >= 4; i--) {
rx_los_all <<= 8;
rx_los_all |= bytes[i];
}
rx_los_all <<= 5;
rx_los_all |= bytes[3];
for(i = 2; i >= 0; i--) {
rx_los_all <<= 8;
rx_los_all |= bytes[i];
}
/* Populate bitmap */
for(i = 0; rx_los_all; i++) {
AIM_BITMAP_MOD(dst, i, (rx_los_all & 1));
@@ -194,50 +227,102 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
char* path = sfp_get_port_path(port, "sfp_eeprom");
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
memset(data, 0, 256);
if (onlp_file_read_binary(path, (char*)data, 256, 256) != 0) {
if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if (size != 256) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom");
memset(data, 0, 256);
FILE* fp;
char file[64] = {0};
sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port));
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
if (onlp_file_read_binary(path, (char*)data, 256, 256) != 0) {
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
if (fseek(fp, 256, SEEK_CUR) != 0) {
fclose(fp);
AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
int ret = fread(data, 1, 256, fp);
fclose(fp);
if (ret != 256) {
AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
{
int rv;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 29) ? 61 : 62;
int bus = (addr == 61) ? 10 : 11;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
char* path = sfp_get_port_path(port, "sfp_tx_disable");
if (onlp_file_write_integer(path, value) != 0) {
if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -259,16 +344,20 @@ int
onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
char* path = NULL;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 29) ? 61 : 62;
int bus = (addr == 61) ? 10 : 11;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
path = sfp_get_port_path(port, "sfp_rx_los");
if (onlp_file_read_int(value, path) < 0) {
AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port);
if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
@@ -279,9 +368,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_FAULT:
{
path = sfp_get_port_path(port, "sfp_tx_fault");
if (onlp_file_read_int(value, path) < 0) {
if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -293,9 +380,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_DISABLE:
{
path = sfp_get_port_path(port, "sfp_tx_disable");
if (onlp_file_read_int(value, path) < 0) {
if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -312,9 +397,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
return rv;
}
int
onlp_sfpi_denit(void)
{
return ONLP_STATUS_OK;
}

View File

@@ -8,9 +8,9 @@ class OnlPlatform_x86_64_accton_as5822_54x_r0(OnlPlatformAccton,
SYS_OBJECT_ID=".5822.54"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.insmod('optoe')
self.insmod("ym2651y")
for m in [ "sfp", "psu", "fan", "leds" ]:
for m in [ 'cpld', 'fan', 'psu', 'leds' ]:
self.insmod("x86-64-accton-as5822-54x-%s" % m)
########### initialize I2C bus 0 ###########
@@ -20,7 +20,7 @@ class OnlPlatform_x86_64_accton_as5822_54x_r0(OnlPlatformAccton,
('pca9548', 0x72, 0),
# initialize CPLD
('accton_i2c_cpld', 0x60, 6),
('as5822_54x_cpld1', 0x60, 6),
# initiate PSU-1 AC Power
('as5822_54x_psu1', 0x50, 3),
@@ -45,8 +45,8 @@ class OnlPlatform_x86_64_accton_as5822_54x_r0(OnlPlatformAccton,
('pca9548', 0x70, 1),
# initialize CPLD
('accton_i2c_cpld', 0x61, 10),
('accton_i2c_cpld', 0x62, 11),
('as5822_54x_cpld2', 0x61, 10),
('as5822_54x_cpld3', 0x62, 11),
# initialize multiplexer (PCA9548)
('pca9548', 0x71, 12),
@@ -64,11 +64,13 @@ class OnlPlatform_x86_64_accton_as5822_54x_r0(OnlPlatformAccton,
# initialize SFP devices
for port in range(1, 49):
self.new_i2c_device('as5822_54x_sfp%d' % port, 0x50, port+17)
self.new_i2c_device('as5822_54x_sfp%d' % port, 0x51, port+17)
self.new_i2c_device('optoe2', 0x50, port+17)
# initialize QSFP devices
for port in range(49, 55):
self.new_i2c_device('as5822_54x_sfp%d' % port, 0x50, port+17)
self.new_i2c_device('optoe1', 0x50, port+17)
for port in range(1, 55):
subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+17), shell=True)
return True

View File

@@ -38,8 +38,8 @@
#define DEBUG_PRINT(fmt, args...)
#endif
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5912_54xk_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5912_54xk_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
struct accton_as5912_54xk_led_data {
struct platform_device *pdev;
@@ -157,12 +157,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type,
static int accton_as5912_54xk_led_read_value(u8 reg)
{
return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
return as5912_54xk_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
}
static int accton_as5912_54xk_led_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
return as5912_54xk_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
}
static void accton_as5912_54xk_led_update(void)

View File

@@ -37,7 +37,7 @@
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
static int as5912_54xk_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5912_54xk_cpld_read(unsigned short cpld_addr, u8 reg);
/* Addresses scanned
*/
@@ -234,7 +234,7 @@ static struct as5912_54xk_psu_data *as5912_54xk_psu_update_device(struct device
dev_dbg(&client->dev, "Starting as5912_54xk update\n");
/* Read psu status */
status = accton_i2c_cpld_read(0x60, 0x2);
status = as5912_54xk_cpld_read(0x60, 0x2);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);

View File

@@ -24,17 +24,21 @@
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/i2c.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#include "x86_64_accton_as5912_54xk_int.h"
#include "x86_64_accton_as5912_54xk_log.h"
#define NUM_OF_SFP_PORT 54
#define MAX_PORT_PATH 64
#define PORT_BUS_INDEX(port) (port+26)
#define SFP_PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s"
#define SFP_PORT_DOM_FORMAT "/sys/bus/i2c/devices/%d-0051/%s"
#define SFP_BUS_INDEX(port) (port+26)
#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom"
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d"
#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d"
#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d"
#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d"
#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/4-0060/module_rx_los_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/5-0062/module_rx_los_all"
/************************************************************
*
@@ -55,8 +59,8 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap)
* Ports {0, 54}
*/
int p;
for(p = 0; p < NUM_OF_SFP_PORT; p++) {
for(p = 0; p < 54; p++) {
AIM_BITMAP_SET(bmap, p);
}
@@ -72,7 +76,12 @@ onlp_sfpi_is_present(int port)
* Return < 0 if error.
*/
int present;
if (onlp_file_read_int(&present, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_is_present") < 0) {
int bus, addr;
addr = (port < 24) ? 60 : 62;
bus = (addr == 60) ? 4 : 5;
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -83,31 +92,45 @@ onlp_sfpi_is_present(int port)
int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char path[MAX_PORT_PATH] = {0};
uint32_t bytes[7], *ptr = NULL;
FILE* fp;
int addr;
sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_is_present_all");
fp = fopen(path, "r");
ptr = bytes;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5,
bytes+6
);
fclose(fp);
if(count != AIM_ARRAYSIZE(bytes)) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 60; addr <= 62; addr+=2) {
/* Read present status of port 0~53 */
int count = 0;
char file[64] = {0};
int bus = (addr == 60) ? 4 : 5;
sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr);
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
if (addr == 60) { /* CPLD1 */
count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
else { /* CPLD2 */
count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3);
fclose(fp);
if(count != 4) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
ptr += count;
}
/* Mask out non-existant QSFP ports */
@@ -130,64 +153,44 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
return ONLP_STATUS_OK;
}
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
int size = 0;
if(onlp_file_read(data, 256, &size, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) {
if(size == 256) {
return ONLP_STATUS_OK;
}
}
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
int size = 0;
if(onlp_file_read(data, 256, &size, SFP_PORT_DOM_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) {
if(size == 256) {
return ONLP_STATUS_OK;
}
}
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[6];
char path[MAX_PORT_PATH] = {0};
uint32_t *ptr = bytes;
FILE* fp;
sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_rx_los_all");
fp = fopen(path, "r");
/* Read present status of port 0~23 */
int addr, i = 0;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5
);
fclose(fp);
if(count != 6) {
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 60; addr <= 62; addr+=2) {
if (addr == 60) {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD1, "r");
}
else {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r");
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
ptr += count;
}
/* Convert to 64 bit integer in port order */
int i = 0;
i = 0;
uint64_t rx_los_all = 0 ;
for(i = 5; i >= 0; i--) {
for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) {
rx_los_all <<= 8;
rx_los_all |= bytes[i];
}
@@ -201,16 +204,77 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
return ONLP_STATUS_OK;
}
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
memset(data, 0, 256);
if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if (size != 256) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
FILE* fp;
char file[64] = {0};
sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port));
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
if (fseek(fp, 256, SEEK_CUR) != 0) {
fclose(fp);
AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
int ret = fread(data, 1, 256, fp);
fclose(fp);
if (ret != 256) {
AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
{
int rv;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 60 : 62;
int bus = (addr == 60) ? 4 : 5;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
if (onlp_file_write_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") != 0) {
if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -233,12 +297,19 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 60 : 62;
int bus = (addr == 60) ? 4 : 5;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_rx_los") < 0) {
AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port);
if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
@@ -249,7 +320,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_FAULT:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_fault") < 0) {
if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -261,7 +332,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_DISABLE:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") < 0) {
if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -278,7 +349,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
return rv;
}
int
onlp_sfpi_denit(void)
{

View File

@@ -8,9 +8,9 @@ class OnlPlatform_x86_64_accton_as5912_54xk_r0(OnlPlatformAccton,
SYS_OBJECT_ID=".5912.54"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.insmod('optoe')
self.insmod("ym2651y")
for m in [ "sfp", "psu", "fan", "leds" ]:
for m in [ "cpld", "psu", "fan", "leds" ]:
self.insmod("x86-64-accton-as5912-54xk-%s" % m)
########### initialize I2C bus 0 ###########
@@ -29,8 +29,8 @@ class OnlPlatform_x86_64_accton_as5912_54xk_r0(OnlPlatformAccton,
('lm75', 0x4b, 3),
# initialize CPLDs
('accton_i2c_cpld', 0x60, 4),
('accton_i2c_cpld', 0x62, 5),
('as5912_54xk_cpld1', 0x60, 4),
('as5912_54xk_cpld2', 0x62, 5),
]
)
@@ -69,12 +69,14 @@ class OnlPlatform_x86_64_accton_as5912_54xk_r0(OnlPlatformAccton,
# initialize SFP devices
for port in range(1, 49):
self.new_i2c_device('as5912_54xk_sfp%d' % port, 0x50, port+25)
self.new_i2c_device('as5912_54xk_sfp%d' % port, 0x51, port+25)
self.new_i2c_device('optoe2', 0x50, port+25)
# initialize QSFP devices
for port in range(49, 55):
self.new_i2c_device('as5912_54xk_sfp%d' % port, 0x50, port+25)
self.new_i2c_device('optoe1', 0x50, port+25)
for port in range(1, 55):
subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+25), shell=True)
return True

View File

@@ -38,8 +38,8 @@
#define DEBUG_PRINT(fmt, args...)
#endif
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5916_54x_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5916_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
struct accton_as5916_54x_led_data {
struct platform_device *pdev;
@@ -157,12 +157,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type,
static int accton_as5916_54x_led_read_value(u8 reg)
{
return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
return as5916_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
}
static int accton_as5916_54x_led_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
return as5916_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
}
static void accton_as5916_54x_led_update(void)

View File

@@ -37,7 +37,7 @@
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
static int as5916_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5916_54x_cpld_read(unsigned short cpld_addr, u8 reg);
/* Addresses scanned
*/
@@ -234,7 +234,7 @@ static struct as5916_54x_psu_data *as5916_54x_psu_update_device(struct device *d
dev_dbg(&client->dev, "Starting as5916_54x update\n");
/* Read psu status */
status = accton_i2c_cpld_read(0x60, 0x2);
status = as5916_54x_cpld_read(0x60, 0x2);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);

View File

@@ -24,17 +24,21 @@
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/i2c.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#include "x86_64_accton_as5916_54x_int.h"
#include "x86_64_accton_as5916_54x_log.h"
#define NUM_OF_SFP_PORT 54
#define MAX_PORT_PATH 64
#define PORT_BUS_INDEX(port) (port+33)
#define SFP_PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s"
#define SFP_PORT_DOM_FORMAT "/sys/bus/i2c/devices/%d-0051/%s"
#define SFP_BUS_INDEX(port) (port+33)
#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom"
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d"
#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d"
#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d"
#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d"
#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/11-0060/module_rx_los_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/12-0062/module_rx_los_all"
/************************************************************
*
@@ -56,7 +60,7 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap)
*/
int p;
for(p = 0; p < NUM_OF_SFP_PORT; p++) {
for(p = 0; p < 54; p++) {
AIM_BITMAP_SET(bmap, p);
}
@@ -72,7 +76,12 @@ onlp_sfpi_is_present(int port)
* Return < 0 if error.
*/
int present;
if (onlp_file_read_int(&present, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_is_present") < 0) {
int bus, addr;
addr = (port < 24) ? 60 : 62;
bus = (addr == 60) ? 11 : 12;
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -83,31 +92,45 @@ onlp_sfpi_is_present(int port)
int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char path[MAX_PORT_PATH] = {0};
uint32_t bytes[7], *ptr = NULL;
FILE* fp;
int addr;
sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_is_present_all");
fp = fopen(path, "r");
ptr = bytes;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5,
bytes+6
);
fclose(fp);
if(count != AIM_ARRAYSIZE(bytes)) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 60; addr <= 62; addr+=2) {
/* Read present status of port 0~53 */
int count = 0;
char file[64] = {0};
int bus = (addr == 60) ? 11 : 12;
sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr);
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
if (addr == 60) { /* CPLD1 */
count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
else { /* CPLD2 */
count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3);
fclose(fp);
if(count != 4) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
ptr += count;
}
/* Mask out non-existant QSFP ports */
@@ -130,64 +153,44 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
return ONLP_STATUS_OK;
}
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
int size = 0;
if(onlp_file_read(data, 256, &size, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) {
if(size == 256) {
return ONLP_STATUS_OK;
}
}
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
int size = 0;
if(onlp_file_read(data, 256, &size, SFP_PORT_DOM_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) {
if(size == 256) {
return ONLP_STATUS_OK;
}
}
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[6];
char path[MAX_PORT_PATH] = {0};
uint32_t *ptr = bytes;
FILE* fp;
sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_rx_los_all");
fp = fopen(path, "r");
/* Read present status of port 0~23 */
int addr, i = 0;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5
);
fclose(fp);
if(count != 6) {
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 60; addr <= 62; addr+=2) {
if (addr == 60) {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD1, "r");
}
else {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r");
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
ptr += count;
}
/* Convert to 64 bit integer in port order */
int i = 0;
i = 0;
uint64_t rx_los_all = 0 ;
for(i = 5; i >= 0; i--) {
for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) {
rx_los_all <<= 8;
rx_los_all |= bytes[i];
}
@@ -201,16 +204,77 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
return ONLP_STATUS_OK;
}
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
memset(data, 0, 256);
if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if (size != 256) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
FILE* fp;
char file[64] = {0};
sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port));
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
if (fseek(fp, 256, SEEK_CUR) != 0) {
fclose(fp);
AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
int ret = fread(data, 1, 256, fp);
fclose(fp);
if (ret != 256) {
AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
{
int rv;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 60 : 62;
int bus = (addr == 60) ? 11 : 12;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
if (onlp_file_write_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") != 0) {
if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -233,12 +297,19 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 60 : 62;
int bus = (addr == 60) ? 11 : 12;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_rx_los") < 0) {
AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port);
if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
@@ -249,7 +320,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_FAULT:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_fault") < 0) {
if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -261,7 +332,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_DISABLE:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") < 0) {
if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -278,7 +349,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
return rv;
}
int
onlp_sfpi_denit(void)
{

View File

@@ -8,9 +8,9 @@ class OnlPlatform_x86_64_accton_as5916_54x_r1(OnlPlatformAccton,
SYS_OBJECT_ID=".5916.54"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.insmod('optoe')
self.insmod("ym2651y")
for m in [ "sfp", "psu", "fan", "leds" ]:
for m in [ "cpld", "psu", "fan", "leds" ]:
self.insmod("x86-64-accton-as5916-54x-%s" % m)
########### initialize I2C bus 0 ###########
@@ -30,8 +30,8 @@ class OnlPlatform_x86_64_accton_as5916_54x_r1(OnlPlatformAccton,
('lm75', 0x4b, 10),
# initialize CPLDs
('accton_i2c_cpld', 0x60, 11),
('accton_i2c_cpld', 0x62, 12),
('as5916_54x_cpld1', 0x60, 11),
('as5916_54x_cpld2', 0x62, 12),
# initialize multiplexer (PCA9548)
('pca9548', 0x74, 2),
@@ -61,12 +61,14 @@ class OnlPlatform_x86_64_accton_as5916_54x_r1(OnlPlatformAccton,
# initialize SFP devices
for port in range(1, 49):
self.new_i2c_device('as5916_54x_sfp%d' % port, 0x50, port+32)
self.new_i2c_device('as5916_54x_sfp%d' % port, 0x51, port+32)
self.new_i2c_device('optoe2', 0x50, port+32)
# initialize QSFP devices
for port in range(49, 55):
self.new_i2c_device('as5916_54x_sfp%d' % port, 0x50, port+32)
self.new_i2c_device('optoe1', 0x50, port+32)
for port in range(1, 55):
subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+32), shell=True)
return True

View File

@@ -0,0 +1,2 @@
*x86*64*accton*as5916*54xk*.mk
onlpdump.mk

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as5916-54xk ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64"

View File

@@ -0,0 +1,6 @@
KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64
KMODULES := $(wildcard *.c)
VENDOR := accton
BASENAME := x86-64-accton-as5916-54xk
ARCH := x86_64
include $(ONL)/make/kmodule.mk

View File

@@ -0,0 +1,485 @@
/*
* A hwmon driver for the Accton as5916 54xk fan
*
* Copyright (C) 2016 Accton Technology Corporation.
* Brandon Chuang <brandon_chuang@accton.com.tw>
*
* 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/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#define DRVNAME "as5916_54xk_fan"
#define MAX_FAN_SPEED_RPM 25500
static struct as5916_54xk_fan_data *as5916_54xk_fan_update_device(struct device *dev);
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
/* fan related data, the index should match sysfs_fan_attributes
*/
static const u8 fan_reg[] = {
0x0F, /* fan 1-6 present status */
0x10, /* fan 1-6 direction(0:B2F 1:F2B) */
0x11, /* fan PWM(for all fan) */
0x12, /* front fan 1 speed(rpm) */
0x13, /* front fan 2 speed(rpm) */
0x14, /* front fan 3 speed(rpm) */
0x15, /* front fan 4 speed(rpm) */
0x16, /* front fan 5 speed(rpm) */
0x17, /* front fan 6 speed(rpm) */
0x22, /* rear fan 1 speed(rpm) */
0x23, /* rear fan 2 speed(rpm) */
0x24, /* rear fan 3 speed(rpm) */
0x25, /* rear fan 4 speed(rpm) */
0x26, /* rear fan 5 speed(rpm) */
0x27, /* rear fan 6 speed(rpm) */
};
/* Each client has this additional data */
struct as5916_54xk_fan_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */
};
enum fan_id {
FAN1_ID,
FAN2_ID,
FAN3_ID,
FAN4_ID,
FAN5_ID,
FAN6_ID
};
enum sysfs_fan_attributes {
FAN_PRESENT_REG,
FAN_DIRECTION_REG,
FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
FAN1_FRONT_SPEED_RPM,
FAN2_FRONT_SPEED_RPM,
FAN3_FRONT_SPEED_RPM,
FAN4_FRONT_SPEED_RPM,
FAN5_FRONT_SPEED_RPM,
FAN6_FRONT_SPEED_RPM,
FAN1_REAR_SPEED_RPM,
FAN2_REAR_SPEED_RPM,
FAN3_REAR_SPEED_RPM,
FAN4_REAR_SPEED_RPM,
FAN5_REAR_SPEED_RPM,
FAN6_REAR_SPEED_RPM,
FAN1_DIRECTION,
FAN2_DIRECTION,
FAN3_DIRECTION,
FAN4_DIRECTION,
FAN5_DIRECTION,
FAN6_DIRECTION,
FAN1_PRESENT,
FAN2_PRESENT,
FAN3_PRESENT,
FAN4_PRESENT,
FAN5_PRESENT,
FAN6_PRESENT,
FAN1_FAULT,
FAN2_FAULT,
FAN3_FAULT,
FAN4_FAULT,
FAN5_FAULT,
FAN6_FAULT,
FAN_MAX_RPM
};
/* Define attributes
*/
#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT)
#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr
#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION)
#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT)
#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM)
#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
&sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr
static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM);
#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr
/* 6 fan fault attributes in this platform */
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6);
/* 6 fan speed(rpm) attributes in this platform */
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6);
/* 6 fan present attributes in this platform */
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6);
/* 6 fan direction attribute in this platform */
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6);
/* 1 fan duty cycle attribute in this platform */
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
static struct attribute *as5916_54xk_fan_attributes[] = {
/* fan related attributes */
DECLARE_FAN_FAULT_ATTR(1),
DECLARE_FAN_FAULT_ATTR(2),
DECLARE_FAN_FAULT_ATTR(3),
DECLARE_FAN_FAULT_ATTR(4),
DECLARE_FAN_FAULT_ATTR(5),
DECLARE_FAN_FAULT_ATTR(6),
DECLARE_FAN_SPEED_RPM_ATTR(1),
DECLARE_FAN_SPEED_RPM_ATTR(2),
DECLARE_FAN_SPEED_RPM_ATTR(3),
DECLARE_FAN_SPEED_RPM_ATTR(4),
DECLARE_FAN_SPEED_RPM_ATTR(5),
DECLARE_FAN_SPEED_RPM_ATTR(6),
DECLARE_FAN_PRESENT_ATTR(1),
DECLARE_FAN_PRESENT_ATTR(2),
DECLARE_FAN_PRESENT_ATTR(3),
DECLARE_FAN_PRESENT_ATTR(4),
DECLARE_FAN_PRESENT_ATTR(5),
DECLARE_FAN_PRESENT_ATTR(6),
DECLARE_FAN_DIRECTION_ATTR(1),
DECLARE_FAN_DIRECTION_ATTR(2),
DECLARE_FAN_DIRECTION_ATTR(3),
DECLARE_FAN_DIRECTION_ATTR(4),
DECLARE_FAN_DIRECTION_ATTR(5),
DECLARE_FAN_DIRECTION_ATTR(6),
DECLARE_FAN_DUTY_CYCLE_ATTR(),
DECLARE_FAN_MAX_RPM_ATTR(),
NULL
};
#define FAN_DUTY_CYCLE_REG_MASK 0xF
#define FAN_MAX_DUTY_CYCLE 100
#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100
static int as5916_54xk_fan_read_value(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
static int as5916_54xk_fan_write_value(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
/* fan utility functions
*/
static u32 reg_val_to_duty_cycle(u8 reg_val)
{
reg_val &= FAN_DUTY_CYCLE_REG_MASK;
return ((u32)(reg_val+1) * 625 + 75)/ 100;
}
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
{
return ((u32)duty_cycle * 100 / 625) - 1;
}
static u32 reg_val_to_speed_rpm(u8 reg_val)
{
return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
}
static u8 reg_val_to_direction(u8 reg_val, enum fan_id id)
{
return !!(reg_val & BIT(id));
}
static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id)
{
return !(reg_val & BIT(id));
}
static u8 is_fan_fault(struct as5916_54xk_fan_data *data, enum fan_id id)
{
u8 ret = 1;
int front_fan_index = FAN1_FRONT_SPEED_RPM + id;
int rear_fan_index = FAN1_REAR_SPEED_RPM + id;
/* Check if the speed of front or rear fan is ZERO,
*/
if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) &&
reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) {
ret = 0;
}
return ret;
}
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value;
struct i2c_client *client = to_i2c_client(dev);
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (value < 0 || value > FAN_MAX_DUTY_CYCLE)
return -EINVAL;
as5916_54xk_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */
as5916_54xk_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
return count;
}
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xk_fan_data *data = as5916_54xk_fan_update_device(dev);
ssize_t ret = 0;
if (data->valid) {
switch (attr->index) {
case FAN_DUTY_CYCLE_PERCENTAGE:
{
u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
ret = sprintf(buf, "%u\n", duty_cycle);
break;
}
case FAN1_FRONT_SPEED_RPM:
case FAN2_FRONT_SPEED_RPM:
case FAN3_FRONT_SPEED_RPM:
case FAN4_FRONT_SPEED_RPM:
case FAN5_FRONT_SPEED_RPM:
case FAN6_FRONT_SPEED_RPM:
case FAN1_REAR_SPEED_RPM:
case FAN2_REAR_SPEED_RPM:
case FAN3_REAR_SPEED_RPM:
case FAN4_REAR_SPEED_RPM:
case FAN5_REAR_SPEED_RPM:
case FAN6_REAR_SPEED_RPM:
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
break;
case FAN1_PRESENT:
case FAN2_PRESENT:
case FAN3_PRESENT:
case FAN4_PRESENT:
case FAN5_PRESENT:
case FAN6_PRESENT:
ret = sprintf(buf, "%d\n",
reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG],
attr->index - FAN1_PRESENT));
break;
case FAN1_FAULT:
case FAN2_FAULT:
case FAN3_FAULT:
case FAN4_FAULT:
case FAN5_FAULT:
case FAN6_FAULT:
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
break;
case FAN1_DIRECTION:
case FAN2_DIRECTION:
case FAN3_DIRECTION:
case FAN4_DIRECTION:
case FAN5_DIRECTION:
case FAN6_DIRECTION:
ret = sprintf(buf, "%d\n",
reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG],
attr->index - FAN1_DIRECTION));
break;
case FAN_MAX_RPM:
ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM);
default:
break;
}
}
return ret;
}
static const struct attribute_group as5916_54xk_fan_group = {
.attrs = as5916_54xk_fan_attributes,
};
static struct as5916_54xk_fan_data *as5916_54xk_fan_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as5916_54xk_fan_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
!data->valid) {
int i;
dev_dbg(&client->dev, "Starting as5916_54xk_fan update\n");
data->valid = 0;
/* Update fan data
*/
for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
int status = as5916_54xk_fan_read_value(client, fan_reg[i]);
if (status < 0) {
data->valid = 0;
mutex_unlock(&data->update_lock);
dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status);
return data;
}
else {
data->reg_val[i] = status;
}
}
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
static int as5916_54xk_fan_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct as5916_54xk_fan_data *data;
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as5916_54xk_fan_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
dev_info(&client->dev, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &as5916_54xk_fan_group);
if (status) {
goto exit_free;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
dev_info(&client->dev, "%s: fan '%s'\n",
dev_name(data->hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &as5916_54xk_fan_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as5916_54xk_fan_remove(struct i2c_client *client)
{
struct as5916_54xk_fan_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as5916_54xk_fan_group);
return 0;
}
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END };
static const struct i2c_device_id as5916_54xk_fan_id[] = {
{ "as5916_54xk_fan", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, as5916_54xk_fan_id);
static struct i2c_driver as5916_54xk_fan_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = DRVNAME,
},
.probe = as5916_54xk_fan_probe,
.remove = as5916_54xk_fan_remove,
.id_table = as5916_54xk_fan_id,
.address_list = normal_i2c,
};
static int __init as5916_54xk_fan_init(void)
{
return i2c_add_driver(&as5916_54xk_fan_driver);
}
static void __exit as5916_54xk_fan_exit(void)
{
i2c_del_driver(&as5916_54xk_fan_driver);
}
module_init(as5916_54xk_fan_init);
module_exit(as5916_54xk_fan_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as5916_54xk_fan driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,386 @@
/*
* A LED driver for the accton_as5916_54xk_led
*
* Copyright (C) 2016 Accton Technology Corporation.
* Brandon Chuang <brandon_chuang@accton.com.tw>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/slab.h>
#define DRVNAME "accton_as5916_54xk_led"
#define DEBUG_MODE 1
#if (DEBUG_MODE == 1)
#define DEBUG_PRINT(fmt, args...) \
printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define DEBUG_PRINT(fmt, args...)
#endif
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
struct accton_as5916_54xk_led_data {
struct platform_device *pdev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED,
1 = FAN/PSU LED,
2 ~ 4 = SYSTEM LED */
};
static struct accton_as5916_54xk_led_data *ledctl = NULL;
#define LED_CNTRLER_I2C_ADDRESS (0x60)
#define LED_TYPE_DIAG_REG_MASK (0x0C)
#define LED_MODE_DIAG_GREEN_VALUE (0x04)
#define LED_MODE_DIAG_ORANGE_VALUE (0x08)
#define LED_MODE_DIAG_OFF_VALUE (0x0C)
#define LED_TYPE_LOC_REG_MASK (0x10)
#define LED_MODE_LOC_ORANGE_VALUE (0x00)
#define LED_MODE_LOC_OFF_VALUE (0x10)
static const u8 led_reg[] = {
0x65, /* LOC/DIAG/FAN LED */
0x66, /* PSU LED */
};
enum led_type {
LED_TYPE_DIAG,
LED_TYPE_LOC,
LED_TYPE_FAN,
LED_TYPE_PSU1,
LED_TYPE_PSU2
};
/* FAN/PSU/DIAG/RELEASE led mode */
enum led_light_mode {
LED_MODE_OFF,
LED_MODE_RED = 10,
LED_MODE_RED_BLINKING = 11,
LED_MODE_ORANGE = 12,
LED_MODE_ORANGE_BLINKING = 13,
LED_MODE_YELLOW = 14,
LED_MODE_YELLOW_BLINKING = 15,
LED_MODE_GREEN = 16,
LED_MODE_GREEN_BLINKING = 17,
LED_MODE_BLUE = 18,
LED_MODE_BLUE_BLINKING = 19,
LED_MODE_PURPLE = 20,
LED_MODE_PURPLE_BLINKING = 21,
LED_MODE_AUTO = 22,
LED_MODE_AUTO_BLINKING = 23,
LED_MODE_WHITE = 24,
LED_MODE_WHITE_BLINKING = 25,
LED_MODE_CYAN = 26,
LED_MODE_CYAN_BLINKING = 27,
LED_MODE_UNKNOWN = 99
};
struct led_type_mode {
enum led_type type;
enum led_light_mode mode;
int type_mask;
int mode_value;
};
static struct led_type_mode led_type_mode_data[] = {
{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
{LED_TYPE_LOC, LED_MODE_ORANGE, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ORANGE_VALUE},
{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
{LED_TYPE_DIAG, LED_MODE_ORANGE, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_ORANGE_VALUE},
};
static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type) {
continue;
}
if ((led_type_mode_data[i].type_mask & reg_val) ==
led_type_mode_data[i].mode_value) {
return led_type_mode_data[i].mode;
}
}
return LED_MODE_UNKNOWN;
}
static u8 led_light_mode_to_reg_val(enum led_type type,
enum led_light_mode mode, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
int type_mask, mode_value;
if (type != led_type_mode_data[i].type)
continue;
if (mode != led_type_mode_data[i].mode)
continue;
type_mask = led_type_mode_data[i].type_mask;
mode_value = led_type_mode_data[i].mode_value;
reg_val = (reg_val & ~type_mask) | mode_value;
}
return reg_val;
}
static int accton_as5916_54xk_led_read_value(u8 reg)
{
return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
}
static int accton_as5916_54xk_led_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
}
static void accton_as5916_54xk_led_update(void)
{
mutex_lock(&ledctl->update_lock);
if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
|| !ledctl->valid) {
int i;
dev_dbg(&ledctl->pdev->dev, "Starting accton_as5916_54xk_led update\n");
ledctl->valid = 0;
/* Update LED data
*/
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
int status = accton_as5916_54xk_led_read_value(led_reg[i]);
if (status < 0) {
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status);
goto exit;
}
else
ledctl->reg_val[i] = status;
}
ledctl->last_updated = jiffies;
ledctl->valid = 1;
}
exit:
mutex_unlock(&ledctl->update_lock);
}
static void accton_as5916_54xk_led_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode,
u8 reg, enum led_type type)
{
int reg_val;
mutex_lock(&ledctl->update_lock);
reg_val = accton_as5916_54xk_led_read_value(reg);
if (reg_val < 0) {
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val);
goto exit;
}
reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val);
accton_as5916_54xk_led_write_value(reg, reg_val);
ledctl->valid = 0;
exit:
mutex_unlock(&ledctl->update_lock);
}
static void accton_as7312_54xk_led_auto_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
}
static enum led_brightness accton_as7312_54xk_led_auto_get(struct led_classdev *cdev)
{
return LED_MODE_AUTO;
}
static void accton_as5916_54xk_led_diag_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
accton_as5916_54xk_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG);
}
static enum led_brightness accton_as5916_54xk_led_diag_get(struct led_classdev *cdev)
{
accton_as5916_54xk_led_update();
return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
}
static enum led_brightness accton_as5916_54xk_led_loc_get(struct led_classdev *cdev)
{
accton_as5916_54xk_led_update();
return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
}
static void accton_as5916_54xk_led_loc_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
accton_as5916_54xk_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC);
}
static struct led_classdev accton_as5916_54xk_leds[] = {
[LED_TYPE_LOC] = {
.name = "accton_as5916_54xk_led::loc",
.default_trigger = "unused",
.brightness_set = accton_as5916_54xk_led_loc_set,
.brightness_get = accton_as5916_54xk_led_loc_get,
.max_brightness = LED_MODE_ORANGE,
},
[LED_TYPE_DIAG] = {
.name = "accton_as5916_54xk_led::diag",
.default_trigger = "unused",
.brightness_set = accton_as5916_54xk_led_diag_set,
.brightness_get = accton_as5916_54xk_led_diag_get,
.max_brightness = LED_MODE_GREEN,
},
[LED_TYPE_PSU1] = {
.name = "accton_as5916_54xk_led::psu1",
.default_trigger = "unused",
.brightness_set = accton_as7312_54xk_led_auto_set,
.brightness_get = accton_as7312_54xk_led_auto_get,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_PSU2] = {
.name = "accton_as5916_54xk_led::psu2",
.default_trigger = "unused",
.brightness_set = accton_as7312_54xk_led_auto_set,
.brightness_get = accton_as7312_54xk_led_auto_get,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN] = {
.name = "accton_as5916_54xk_led::fan",
.default_trigger = "unused",
.brightness_set = accton_as7312_54xk_led_auto_set,
.brightness_get = accton_as7312_54xk_led_auto_get,
.max_brightness = LED_MODE_AUTO,
},
};
static int accton_as5916_54xk_led_probe(struct platform_device *pdev)
{
int ret, i;
for (i = 0; i < ARRAY_SIZE(accton_as5916_54xk_leds); i++) {
ret = led_classdev_register(&pdev->dev, &accton_as5916_54xk_leds[i]);
if (ret < 0) {
break;
}
}
/* Check if all LEDs were successfully registered */
if (i != ARRAY_SIZE(accton_as5916_54xk_leds)){
int j;
/* only unregister the LEDs that were successfully registered */
for (j = 0; j < i; j++) {
led_classdev_unregister(&accton_as5916_54xk_leds[i]);
}
}
return ret;
}
static int accton_as5916_54xk_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(accton_as5916_54xk_leds); i++) {
led_classdev_unregister(&accton_as5916_54xk_leds[i]);
}
return 0;
}
static struct platform_driver accton_as5916_54xk_led_driver = {
.probe = accton_as5916_54xk_led_probe,
.remove = accton_as5916_54xk_led_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init accton_as5916_54xk_led_init(void)
{
int ret;
ret = platform_driver_register(&accton_as5916_54xk_led_driver);
if (ret < 0) {
goto exit;
}
ledctl = kzalloc(sizeof(struct accton_as5916_54xk_led_data), GFP_KERNEL);
if (!ledctl) {
ret = -ENOMEM;
goto exit_driver;
}
mutex_init(&ledctl->update_lock);
ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(ledctl->pdev)) {
ret = PTR_ERR(ledctl->pdev);
goto exit_free;
}
return 0;
exit_free:
kfree(ledctl);
exit_driver:
platform_driver_unregister(&accton_as5916_54xk_led_driver);
exit:
return ret;
}
static void __exit accton_as5916_54xk_led_exit(void)
{
platform_device_unregister(ledctl->pdev);
platform_driver_unregister(&accton_as5916_54xk_led_driver);
kfree(ledctl);
}
late_initcall(accton_as5916_54xk_led_init);
module_exit(accton_as5916_54xk_led_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("accton_as5916_54xk_led driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,288 @@
/*
* An hwmon driver for accton as5916_54xk Power Module
*
* Copyright (C) 2014 Accton Technology Corporation.
* Brandon Chuang <brandon_chuang@accton.com.tw>
*
* Based on ad7414.c
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.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>
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
static int as5916_54xk_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
/* Addresses scanned
*/
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Each client has this additional data
*/
struct as5916_54xk_psu_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* !=0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 index; /* PSU index */
u8 status; /* Status(present/power_good) register read from CPLD */
char model_name[9]; /* Model name, read from eeprom */
};
static struct as5916_54xk_psu_data *as5916_54xk_psu_update_device(struct device *dev);
enum as5916_54xk_psu_sysfs_attributes {
PSU_PRESENT,
PSU_MODEL_NAME,
PSU_POWER_GOOD
};
/* sysfs attributes for hwmon
*/
static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME);
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
static struct attribute *as5916_54xk_psu_attributes[] = {
&sensor_dev_attr_psu_present.dev_attr.attr,
&sensor_dev_attr_psu_model_name.dev_attr.attr,
&sensor_dev_attr_psu_power_good.dev_attr.attr,
NULL
};
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xk_psu_data *data = as5916_54xk_psu_update_device(dev);
u8 status = 0;
if (attr->index == PSU_PRESENT) {
status = !(data->status & BIT(1 - data->index));;
}
else { /* PSU_POWER_GOOD */
status = !!(data->status & BIT(3 - data->index));
}
return sprintf(buf, "%d\n", status);
}
static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
char *buf)
{
struct as5916_54xk_psu_data *data = as5916_54xk_psu_update_device(dev);
return sprintf(buf, "%s\n", data->model_name);
}
static const struct attribute_group as5916_54xk_psu_group = {
.attrs = as5916_54xk_psu_attributes,
};
static int as5916_54xk_psu_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct as5916_54xk_psu_data *data;
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as5916_54xk_psu_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
data->index = dev_id->driver_data;
mutex_init(&data->update_lock);
dev_info(&client->dev, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &as5916_54xk_psu_group);
if (status) {
goto exit_free;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
dev_info(&client->dev, "%s: psu '%s'\n",
dev_name(data->hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &as5916_54xk_psu_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as5916_54xk_psu_remove(struct i2c_client *client)
{
struct as5916_54xk_psu_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as5916_54xk_psu_group);
kfree(data);
return 0;
}
enum psu_index
{
as5916_54xk_psu1,
as5916_54xk_psu2
};
static const struct i2c_device_id as5916_54xk_psu_id[] = {
{ "as5916_54xk_psu1", as5916_54xk_psu1 },
{ "as5916_54xk_psu2", as5916_54xk_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, as5916_54xk_psu_id);
static struct i2c_driver as5916_54xk_psu_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "as5916_54xk_psu",
},
.probe = as5916_54xk_psu_probe,
.remove = as5916_54xk_psu_remove,
.id_table = as5916_54xk_psu_id,
.address_list = normal_i2c,
};
static int as5916_54xk_psu_read_block(struct i2c_client *client, u8 command, u8 *data,
int data_len)
{
int result = 0;
int retry_count = 5;
while (retry_count) {
retry_count--;
result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
if (unlikely(result < 0)) {
msleep(10);
continue;
}
if (unlikely(result != data_len)) {
result = -EIO;
msleep(10);
continue;
}
result = 0;
break;
}
return result;
}
static struct as5916_54xk_psu_data *as5916_54xk_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as5916_54xk_psu_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int status;
int power_good = 0;
dev_dbg(&client->dev, "Starting as5916_54xk update\n");
/* Read psu status */
status = accton_i2c_cpld_read(0x60, 0x2);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);
}
else {
data->status = status;
}
/* Read model name */
memset(data->model_name, 0, sizeof(data->model_name));
power_good = data->status & BIT(3 - data->index);
if (power_good) {
status = as5916_54xk_psu_read_block(client, 0x20, data->model_name,
ARRAY_SIZE(data->model_name)-1);
if (status < 0) {
data->model_name[0] = '\0';
dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
}
else {
data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0';
}
}
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
static int __init as5916_54xk_psu_init(void)
{
return i2c_add_driver(&as5916_54xk_psu_driver);
}
static void __exit as5916_54xk_psu_exit(void)
{
i2c_del_driver(&as5916_54xk_psu_driver);
}
module_init(as5916_54xk_psu_init);
module_exit(as5916_54xk_psu_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as5916_54xk_psu driver");
MODULE_LICENSE("GPL");

View File

@@ -1,5 +1,5 @@
/*
* SFP driver for accton as5916_54xm sfp
* SFP driver for accton as5916_54xk sfp
*
* Copyright (C) Brandon Chuang <brandon_chuang@accton.com.tw>
*
@@ -32,7 +32,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#define DRIVER_NAME "as5916_54xm_sfp" /* Platform dependent */
#define DRIVER_NAME "as5916_54xk_sfp" /* Platform dependent */
#define DEBUG_MODE 0
@@ -181,30 +181,30 @@ static struct attribute *sfp_ddm_attributes[] = {
#define CPLD_PORT_TO_FRONT_PORT(port) (port+1)
enum port_numbers {
as5916_54xm_sfp1, as5916_54xm_sfp2, as5916_54xm_sfp3, as5916_54xm_sfp4, as5916_54xm_sfp5, as5916_54xm_sfp6, as5916_54xm_sfp7, as5916_54xm_sfp8,
as5916_54xm_sfp9, as5916_54xm_sfp10, as5916_54xm_sfp11, as5916_54xm_sfp12, as5916_54xm_sfp13, as5916_54xm_sfp14, as5916_54xm_sfp15, as5916_54xm_sfp16,
as5916_54xm_sfp17, as5916_54xm_sfp18, as5916_54xm_sfp19, as5916_54xm_sfp20, as5916_54xm_sfp21, as5916_54xm_sfp22, as5916_54xm_sfp23, as5916_54xm_sfp24,
as5916_54xm_sfp25, as5916_54xm_sfp26, as5916_54xm_sfp27, as5916_54xm_sfp28, as5916_54xm_sfp29, as5916_54xm_sfp30, as5916_54xm_sfp31, as5916_54xm_sfp32,
as5916_54xm_sfp33, as5916_54xm_sfp34, as5916_54xm_sfp35, as5916_54xm_sfp36, as5916_54xm_sfp37, as5916_54xm_sfp38, as5916_54xm_sfp39, as5916_54xm_sfp40,
as5916_54xm_sfp41, as5916_54xm_sfp42, as5916_54xm_sfp43, as5916_54xm_sfp44, as5916_54xm_sfp45, as5916_54xm_sfp46, as5916_54xm_sfp47, as5916_54xm_sfp48,
as5916_54xm_sfp49, as5916_54xm_sfp50, as5916_54xm_sfp51, as5916_54xm_sfp52, as5916_54xm_sfp53, as5916_54xm_sfp54
as5916_54xk_sfp1, as5916_54xk_sfp2, as5916_54xk_sfp3, as5916_54xk_sfp4, as5916_54xk_sfp5, as5916_54xk_sfp6, as5916_54xk_sfp7, as5916_54xk_sfp8,
as5916_54xk_sfp9, as5916_54xk_sfp10, as5916_54xk_sfp11, as5916_54xk_sfp12, as5916_54xk_sfp13, as5916_54xk_sfp14, as5916_54xk_sfp15, as5916_54xk_sfp16,
as5916_54xk_sfp17, as5916_54xk_sfp18, as5916_54xk_sfp19, as5916_54xk_sfp20, as5916_54xk_sfp21, as5916_54xk_sfp22, as5916_54xk_sfp23, as5916_54xk_sfp24,
as5916_54xk_sfp25, as5916_54xk_sfp26, as5916_54xk_sfp27, as5916_54xk_sfp28, as5916_54xk_sfp29, as5916_54xk_sfp30, as5916_54xk_sfp31, as5916_54xk_sfp32,
as5916_54xk_sfp33, as5916_54xk_sfp34, as5916_54xk_sfp35, as5916_54xk_sfp36, as5916_54xk_sfp37, as5916_54xk_sfp38, as5916_54xk_sfp39, as5916_54xk_sfp40,
as5916_54xk_sfp41, as5916_54xk_sfp42, as5916_54xk_sfp43, as5916_54xk_sfp44, as5916_54xk_sfp45, as5916_54xk_sfp46, as5916_54xk_sfp47, as5916_54xk_sfp48,
as5916_54xk_sfp49, as5916_54xk_sfp50, as5916_54xk_sfp51, as5916_54xk_sfp52, as5916_54xk_sfp53, as5916_54xk_sfp54
};
static const struct i2c_device_id sfp_device_id[] = {
{ "as5916_54xm_sfp1", as5916_54xm_sfp1 }, { "as5916_54xm_sfp2", as5916_54xm_sfp2 }, { "as5916_54xm_sfp3", as5916_54xm_sfp3 }, { "as5916_54xm_sfp4", as5916_54xm_sfp4 },
{ "as5916_54xm_sfp5", as5916_54xm_sfp5 }, { "as5916_54xm_sfp6", as5916_54xm_sfp6 }, { "as5916_54xm_sfp7", as5916_54xm_sfp7 }, { "as5916_54xm_sfp8", as5916_54xm_sfp8 },
{ "as5916_54xm_sfp9", as5916_54xm_sfp9 }, { "as5916_54xm_sfp10", as5916_54xm_sfp10 }, { "as5916_54xm_sfp11", as5916_54xm_sfp11 }, { "as5916_54xm_sfp12", as5916_54xm_sfp12 },
{ "as5916_54xm_sfp13", as5916_54xm_sfp13 }, { "as5916_54xm_sfp14", as5916_54xm_sfp14 }, { "as5916_54xm_sfp15", as5916_54xm_sfp15 }, { "as5916_54xm_sfp16", as5916_54xm_sfp16 },
{ "as5916_54xm_sfp17", as5916_54xm_sfp17 }, { "as5916_54xm_sfp18", as5916_54xm_sfp18 }, { "as5916_54xm_sfp19", as5916_54xm_sfp19 }, { "as5916_54xm_sfp20", as5916_54xm_sfp20 },
{ "as5916_54xm_sfp21", as5916_54xm_sfp21 }, { "as5916_54xm_sfp22", as5916_54xm_sfp22 }, { "as5916_54xm_sfp23", as5916_54xm_sfp23 }, { "as5916_54xm_sfp24", as5916_54xm_sfp24 },
{ "as5916_54xm_sfp25", as5916_54xm_sfp25 }, { "as5916_54xm_sfp26", as5916_54xm_sfp26 }, { "as5916_54xm_sfp27", as5916_54xm_sfp27 }, { "as5916_54xm_sfp28", as5916_54xm_sfp28 },
{ "as5916_54xm_sfp29", as5916_54xm_sfp29 }, { "as5916_54xm_sfp30", as5916_54xm_sfp30 }, { "as5916_54xm_sfp31", as5916_54xm_sfp31 }, { "as5916_54xm_sfp32", as5916_54xm_sfp32 },
{ "as5916_54xm_sfp33", as5916_54xm_sfp33 }, { "as5916_54xm_sfp34", as5916_54xm_sfp34 }, { "as5916_54xm_sfp35", as5916_54xm_sfp35 }, { "as5916_54xm_sfp36", as5916_54xm_sfp36 },
{ "as5916_54xm_sfp37", as5916_54xm_sfp37 }, { "as5916_54xm_sfp38", as5916_54xm_sfp38 }, { "as5916_54xm_sfp39", as5916_54xm_sfp39 }, { "as5916_54xm_sfp40", as5916_54xm_sfp40 },
{ "as5916_54xm_sfp41", as5916_54xm_sfp41 }, { "as5916_54xm_sfp42", as5916_54xm_sfp42 }, { "as5916_54xm_sfp43", as5916_54xm_sfp43 }, { "as5916_54xm_sfp44", as5916_54xm_sfp44 },
{ "as5916_54xm_sfp45", as5916_54xm_sfp45 }, { "as5916_54xm_sfp46", as5916_54xm_sfp46 }, { "as5916_54xm_sfp47", as5916_54xm_sfp47 }, { "as5916_54xm_sfp48", as5916_54xm_sfp48 },
{ "as5916_54xm_sfp49", as5916_54xm_sfp49 }, { "as5916_54xm_sfp50", as5916_54xm_sfp50 }, { "as5916_54xm_sfp51", as5916_54xm_sfp51 }, { "as5916_54xm_sfp52", as5916_54xm_sfp52 },
{ "as5916_54xm_sfp53", as5916_54xm_sfp53 }, { "as5916_54xm_sfp54", as5916_54xm_sfp54 },
{ "as5916_54xk_sfp1", as5916_54xk_sfp1 }, { "as5916_54xk_sfp2", as5916_54xk_sfp2 }, { "as5916_54xk_sfp3", as5916_54xk_sfp3 }, { "as5916_54xk_sfp4", as5916_54xk_sfp4 },
{ "as5916_54xk_sfp5", as5916_54xk_sfp5 }, { "as5916_54xk_sfp6", as5916_54xk_sfp6 }, { "as5916_54xk_sfp7", as5916_54xk_sfp7 }, { "as5916_54xk_sfp8", as5916_54xk_sfp8 },
{ "as5916_54xk_sfp9", as5916_54xk_sfp9 }, { "as5916_54xk_sfp10", as5916_54xk_sfp10 }, { "as5916_54xk_sfp11", as5916_54xk_sfp11 }, { "as5916_54xk_sfp12", as5916_54xk_sfp12 },
{ "as5916_54xk_sfp13", as5916_54xk_sfp13 }, { "as5916_54xk_sfp14", as5916_54xk_sfp14 }, { "as5916_54xk_sfp15", as5916_54xk_sfp15 }, { "as5916_54xk_sfp16", as5916_54xk_sfp16 },
{ "as5916_54xk_sfp17", as5916_54xk_sfp17 }, { "as5916_54xk_sfp18", as5916_54xk_sfp18 }, { "as5916_54xk_sfp19", as5916_54xk_sfp19 }, { "as5916_54xk_sfp20", as5916_54xk_sfp20 },
{ "as5916_54xk_sfp21", as5916_54xk_sfp21 }, { "as5916_54xk_sfp22", as5916_54xk_sfp22 }, { "as5916_54xk_sfp23", as5916_54xk_sfp23 }, { "as5916_54xk_sfp24", as5916_54xk_sfp24 },
{ "as5916_54xk_sfp25", as5916_54xk_sfp25 }, { "as5916_54xk_sfp26", as5916_54xk_sfp26 }, { "as5916_54xk_sfp27", as5916_54xk_sfp27 }, { "as5916_54xk_sfp28", as5916_54xk_sfp28 },
{ "as5916_54xk_sfp29", as5916_54xk_sfp29 }, { "as5916_54xk_sfp30", as5916_54xk_sfp30 }, { "as5916_54xk_sfp31", as5916_54xk_sfp31 }, { "as5916_54xk_sfp32", as5916_54xk_sfp32 },
{ "as5916_54xk_sfp33", as5916_54xk_sfp33 }, { "as5916_54xk_sfp34", as5916_54xk_sfp34 }, { "as5916_54xk_sfp35", as5916_54xk_sfp35 }, { "as5916_54xk_sfp36", as5916_54xk_sfp36 },
{ "as5916_54xk_sfp37", as5916_54xk_sfp37 }, { "as5916_54xk_sfp38", as5916_54xk_sfp38 }, { "as5916_54xk_sfp39", as5916_54xk_sfp39 }, { "as5916_54xk_sfp40", as5916_54xk_sfp40 },
{ "as5916_54xk_sfp41", as5916_54xk_sfp41 }, { "as5916_54xk_sfp42", as5916_54xk_sfp42 }, { "as5916_54xk_sfp43", as5916_54xk_sfp43 }, { "as5916_54xk_sfp44", as5916_54xk_sfp44 },
{ "as5916_54xk_sfp45", as5916_54xk_sfp45 }, { "as5916_54xk_sfp46", as5916_54xk_sfp46 }, { "as5916_54xk_sfp47", as5916_54xk_sfp47 }, { "as5916_54xk_sfp48", as5916_54xk_sfp48 },
{ "as5916_54xk_sfp49", as5916_54xk_sfp49 }, { "as5916_54xk_sfp50", as5916_54xk_sfp50 }, { "as5916_54xk_sfp51", as5916_54xk_sfp51 }, { "as5916_54xk_sfp52", as5916_54xk_sfp52 },
{ "as5916_54xk_sfp53", as5916_54xk_sfp53 }, { "as5916_54xk_sfp54", as5916_54xk_sfp54 },
{ /* LIST END */ }
};
MODULE_DEVICE_TABLE(i2c, sfp_device_id);
@@ -351,7 +351,7 @@ static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev)
return data;
}
DEBUG_PRINT("Starting as5916_54xm sfp tx rx status update");
DEBUG_PRINT("Starting as5916_54xk sfp tx rx status update");
mutex_lock(&data->update_lock);
data->msa->valid = 0;
memset(data->msa->status, 0, sizeof(data->msa->status));
@@ -1220,7 +1220,7 @@ static int sfp_device_probe(struct i2c_client *client,
data->port = dev_id->driver_data;
data->client = client;
if (dev_id->driver_data >= as5916_54xm_sfp1 && dev_id->driver_data <= as5916_54xm_sfp48) {
if (dev_id->driver_data >= as5916_54xk_sfp1 && dev_id->driver_data <= as5916_54xk_sfp48) {
if (client->addr == SFP_EEPROM_A0_I2C_ADDR) {
data->driver_type = DRIVER_TYPE_SFP_MSA;
return sfp_msa_probe(client, dev_id, &data->msa);
@@ -1230,7 +1230,7 @@ static int sfp_device_probe(struct i2c_client *client,
return sfp_ddm_probe(client, dev_id, &data->ddm);
}
}
else { /* as5916_54xm_sfp49 ~ as5916_54xm_sfp54 */
else { /* as5916_54xk_sfp49 ~ as5916_54xk_sfp54 */
if (client->addr == SFP_EEPROM_A0_I2C_ADDR) {
data->driver_type = DRIVER_TYPE_QSFP;
return qsfp_probe(client, dev_id, &data->qsfp);
@@ -1306,7 +1306,7 @@ static void __exit sfp_exit(void)
}
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("accton as5916_54xm_sfp driver");
MODULE_DESCRIPTION("accton as5916_54xk_sfp driver");
MODULE_LICENSE("GPL");
late_initcall(sfp_init);

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
!include $ONL_TEMPLATES/onlp-platform-revision.yml PLATFORM=x86-64-accton-as5916-54xk ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu REVISION=r1

View File

@@ -0,0 +1,2 @@
FILTER=src
include $(ONL)/make/subdirs.mk

View File

@@ -0,0 +1,45 @@
############################################################
# <bsn.cl fy=2014 v=onl>
#
# Copyright 2014 BigSwitch Networks, Inc.
#
# Licensed under the Eclipse Public License, Version 1.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.eclipse.org/legal/epl-v10.html
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the
# License.
#
# </bsn.cl>
############################################################
#
#
############################################################
include $(ONL)/make/config.amd64.mk
MODULE := libonlp-x86-64-accton-as5916-54xk
include $(BUILDER)/standardinit.mk
DEPENDMODULES := AIM IOF x86_64_accton_as5916_54xk onlplib
DEPENDMODULE_HEADERS := sff
include $(BUILDER)/dependmodules.mk
SHAREDLIB := libonlp-x86-64-accton-as5916-54xk.so
$(SHAREDLIB)_TARGETS := $(ALL_TARGETS)
include $(BUILDER)/so.mk
.DEFAULT_GOAL := $(SHAREDLIB)
GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc
GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1
GLOBAL_CFLAGS += -fPIC
GLOBAL_LINK_LIBS += -lpthread
include $(BUILDER)/targets.mk

View File

@@ -0,0 +1,46 @@
############################################################
# <bsn.cl fy=2014 v=onl>
#
# Copyright 2014 BigSwitch Networks, Inc.
#
# Licensed under the Eclipse Public License, Version 1.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.eclipse.org/legal/epl-v10.html
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the
# License.
#
# </bsn.cl>
############################################################
#
#
#
############################################################
include $(ONL)/make/config.amd64.mk
.DEFAULT_GOAL := onlpdump
MODULE := onlpdump
include $(BUILDER)/standardinit.mk
DEPENDMODULES := AIM IOF onlp x86_64_accton_as5916_54xk onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS
include $(BUILDER)/dependmodules.mk
BINARY := onlpdump
$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS)
include $(BUILDER)/bin.mk
GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main
GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1
GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1
GLOBAL_LINK_LIBS += -lpthread -lm
include $(BUILDER)/targets.mk

View File

@@ -0,0 +1 @@
name: x86_64_accton_as5916_54xk

View File

@@ -0,0 +1,9 @@
###############################################################################
#
#
#
###############################################################################
include ../../init.mk
MODULE := x86_64_accton_as5916_54xk
AUTOMODULE := x86_64_accton_as5916_54xk
include $(BUILDER)/definemodule.mk

View File

@@ -0,0 +1,6 @@
###############################################################################
#
# x86_64_accton_as5916_54xk README
#
###############################################################################

View File

@@ -0,0 +1,9 @@
###############################################################################
#
# x86_64_accton_as5916_54xk Autogeneration
#
###############################################################################
x86_64_accton_as5916_54xk_AUTO_DEFS := module/auto/x86_64_accton_as5916_54xk.yml
x86_64_accton_as5916_54xk_AUTO_DIRS := module/inc/x86_64_accton_as5916_54xk module/src
include $(BUILDER)/auto.mk

View File

@@ -0,0 +1,50 @@
###############################################################################
#
# x86_64_accton_as5916_54xk Autogeneration Definitions.
#
###############################################################################
cdefs: &cdefs
- X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING:
doc: "Include or exclude logging."
default: 1
- X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT:
doc: "Default enabled log options."
default: AIM_LOG_OPTIONS_DEFAULT
- X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT:
doc: "Default enabled log bits."
default: AIM_LOG_BITS_DEFAULT
- X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT:
doc: "Default enabled custom log bits."
default: 0
- X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB:
doc: "Default all porting macros to use the C standard libraries."
default: 1
- X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS:
doc: "Include standard library headers for stdlib porting macros."
default: X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB
- X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI:
doc: "Include generic uCli support."
default: 0
- X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION:
doc: "Assume chassis fan direction is the same as the PSU fan direction."
default: 0
definitions:
cdefs:
X86_64_ACCTON_AS5916_54XK_CONFIG_HEADER:
defs: *cdefs
basename: x86_64_accton_as5916_54xk_config
portingmacro:
x86_64_accton_as5916_54xk:
macros:
- malloc
- free
- memset
- memcpy
- strncpy
- vsnprintf
- snprintf
- strlen

View File

@@ -0,0 +1,14 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
/* <--auto.start.xmacro(ALL).define> */
/* <auto.end.xmacro(ALL).define> */
/* <--auto.start.xenum(ALL).define> */
/* <auto.end.xenum(ALL).define> */

View File

@@ -0,0 +1,137 @@
/**************************************************************************//**
*
* @file
* @brief x86_64_accton_as5916_54xk Configuration Header
*
* @addtogroup x86_64_accton_as5916_54xk-config
* @{
*
*****************************************************************************/
#ifndef __X86_64_ACCTON_AS5916_54XK_CONFIG_H__
#define __X86_64_ACCTON_AS5916_54XK_CONFIG_H__
#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG
#include <global_custom_config.h>
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_INCLUDE_CUSTOM_CONFIG
#include <x86_64_accton_as5916_54xk_custom_config.h>
#endif
/* <auto.start.cdefs(X86_64_ACCTON_AS5916_54XK_CONFIG_HEADER).header> */
#include <AIM/aim.h>
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING
*
* Include or exclude logging. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING
#define X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING 1
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT
*
* Default enabled log options. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT
#define X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT
*
* Default enabled log bits. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT
#define X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
*
* Default enabled custom log bits. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
#define X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB
*
* Default all porting macros to use the C standard libraries. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB
#define X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB 1
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
*
* Include standard library headers for stdlib porting macros. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
#define X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI
*
* Include generic uCli support. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI
#define X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI 0
#endif
/**
* X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
*
* Assume chassis fan direction is the same as the PSU fan direction. */
#ifndef X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
#define X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0
#endif
/**
* All compile time options can be queried or displayed
*/
/** Configuration settings structure. */
typedef struct x86_64_accton_as5916_54xk_config_settings_s {
/** name */
const char* name;
/** value */
const char* value;
} x86_64_accton_as5916_54xk_config_settings_t;
/** Configuration settings table. */
/** x86_64_accton_as5916_54xk_config_settings table. */
extern x86_64_accton_as5916_54xk_config_settings_t x86_64_accton_as5916_54xk_config_settings[];
/**
* @brief Lookup a configuration setting.
* @param setting The name of the configuration option to lookup.
*/
const char* x86_64_accton_as5916_54xk_config_lookup(const char* setting);
/**
* @brief Show the compile-time configuration.
* @param pvs The output stream.
*/
int x86_64_accton_as5916_54xk_config_show(struct aim_pvs_s* pvs);
/* <auto.end.cdefs(X86_64_ACCTON_AS5916_54XK_CONFIG_HEADER).header> */
#include "x86_64_accton_as5916_54xk_porting.h"
#endif /* __X86_64_ACCTON_AS5916_54XK_CONFIG_H__ */
/* @} */

View File

@@ -0,0 +1,26 @@
/**************************************************************************//**
*
* x86_64_accton_as5916_54xk Doxygen Header
*
*****************************************************************************/
#ifndef __X86_64_ACCTON_AS5916_54XK_DOX_H__
#define __X86_64_ACCTON_AS5916_54XK_DOX_H__
/**
* @defgroup x86_64_accton_as5916_54xk x86_64_accton_as5916_54xk - x86_64_accton_as5916_54xk Description
*
The documentation overview for this module should go here.
*
* @{
*
* @defgroup x86_64_accton_as5916_54xk-x86_64_accton_as5916_54xk Public Interface
* @defgroup x86_64_accton_as5916_54xk-config Compile Time Configuration
* @defgroup x86_64_accton_as5916_54xk-porting Porting Macros
*
* @}
*
*/
#endif /* __X86_64_ACCTON_AS5916_54XK_DOX_H__ */

View File

@@ -0,0 +1,107 @@
/**************************************************************************//**
*
* @file
* @brief x86_64_accton_as5916_54xk Porting Macros.
*
* @addtogroup x86_64_accton_as5916_54xk-porting
* @{
*
*****************************************************************************/
#ifndef __X86_64_ACCTON_AS5916_54XK_PORTING_H__
#define __X86_64_ACCTON_AS5916_54XK_PORTING_H__
/* <auto.start.portingmacro(ALL).define> */
#if X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <memory.h>
#endif
#ifndef x86_64_accton_as5916_54xk_MALLOC
#if defined(GLOBAL_MALLOC)
#define x86_64_accton_as5916_54xk_MALLOC GLOBAL_MALLOC
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_MALLOC malloc
#else
#error The macro x86_64_accton_as5916_54xk_MALLOC is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_FREE
#if defined(GLOBAL_FREE)
#define x86_64_accton_as5916_54xk_FREE GLOBAL_FREE
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_FREE free
#else
#error The macro x86_64_accton_as5916_54xk_FREE is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_MEMSET
#if defined(GLOBAL_MEMSET)
#define x86_64_accton_as5916_54xk_MEMSET GLOBAL_MEMSET
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_MEMSET memset
#else
#error The macro x86_64_accton_as5916_54xk_MEMSET is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_MEMCPY
#if defined(GLOBAL_MEMCPY)
#define x86_64_accton_as5916_54xk_MEMCPY GLOBAL_MEMCPY
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_MEMCPY memcpy
#else
#error The macro x86_64_accton_as5916_54xk_MEMCPY is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_STRNCPY
#if defined(GLOBAL_STRNCPY)
#define x86_64_accton_as5916_54xk_STRNCPY GLOBAL_STRNCPY
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_STRNCPY strncpy
#else
#error The macro x86_64_accton_as5916_54xk_STRNCPY is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_VSNPRINTF
#if defined(GLOBAL_VSNPRINTF)
#define x86_64_accton_as5916_54xk_VSNPRINTF GLOBAL_VSNPRINTF
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_VSNPRINTF vsnprintf
#else
#error The macro x86_64_accton_as5916_54xk_VSNPRINTF is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_SNPRINTF
#if defined(GLOBAL_SNPRINTF)
#define x86_64_accton_as5916_54xk_SNPRINTF GLOBAL_SNPRINTF
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_SNPRINTF snprintf
#else
#error The macro x86_64_accton_as5916_54xk_SNPRINTF is required but cannot be defined.
#endif
#endif
#ifndef x86_64_accton_as5916_54xk_STRLEN
#if defined(GLOBAL_STRLEN)
#define x86_64_accton_as5916_54xk_STRLEN GLOBAL_STRLEN
#elif X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB == 1
#define x86_64_accton_as5916_54xk_STRLEN strlen
#else
#error The macro x86_64_accton_as5916_54xk_STRLEN is required but cannot be defined.
#endif
#endif
/* <auto.end.portingmacro(ALL).define> */
#endif /* __X86_64_ACCTON_AS5916_54XK_PORTING_H__ */
/* @} */

View File

@@ -0,0 +1,10 @@
###############################################################################
#
#
#
###############################################################################
THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
x86_64_accton_as5916_54xk_INCLUDES := -I $(THIS_DIR)inc
x86_64_accton_as5916_54xk_INTERNAL_INCLUDES := -I $(THIS_DIR)src
x86_64_accton_as5916_54xk_DEPENDMODULE_ENTRIES := init:x86_64_accton_as5916_54xk ucli:x86_64_accton_as5916_54xk

View File

@@ -0,0 +1,9 @@
###############################################################################
#
# Local source generation targets.
#
###############################################################################
ucli:
@../../../../tools/uclihandlers.py x86_64_accton_as5916_54xk_ucli.c

View File

@@ -0,0 +1,303 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
* Fan Platform Implementation Defaults.
*
***********************************************************/
#include <onlplib/file.h>
#include <onlp/platformi/fani.h>
#include "platform_lib.h"
enum fan_id {
FAN_1_ON_FAN_BOARD = 1,
FAN_2_ON_FAN_BOARD,
FAN_3_ON_FAN_BOARD,
FAN_4_ON_FAN_BOARD,
FAN_5_ON_FAN_BOARD,
FAN_6_ON_FAN_BOARD,
FAN_1_ON_PSU_1,
FAN_1_ON_PSU_2,
};
#define MAX_FAN_SPEED 25500
#define MAX_PSU_FAN_SPEED 25500
#define CHASSIS_FAN_INFO(fid) \
{ \
{ ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\
0x0,\
ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\
0,\
0,\
ONLP_FAN_MODE_INVALID,\
}
#define PSU_FAN_INFO(pid, fid) \
{ \
{ ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\
0x0,\
ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\
0,\
0,\
ONLP_FAN_MODE_INVALID,\
}
/* Static fan information */
onlp_fan_info_t finfo[] = {
{ }, /* Not used */
CHASSIS_FAN_INFO(1),
CHASSIS_FAN_INFO(2),
CHASSIS_FAN_INFO(3),
CHASSIS_FAN_INFO(4),
CHASSIS_FAN_INFO(5),
CHASSIS_FAN_INFO(6),
PSU_FAN_INFO(1, 1),
PSU_FAN_INFO(2, 1)
};
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_FAN(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
static int
_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info)
{
int value, ret;
/* get fan present status
*/
ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid);
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
if (value == 0) {
return ONLP_STATUS_OK; /* fan is not present */
}
info->status |= ONLP_FAN_STATUS_PRESENT;
/* get fan fault status (turn on when any one fails)
*/
ret = onlp_file_read_int(&value, "%s""fan%d_fault", FAN_BOARD_PATH, fid);
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
if (value > 0) {
info->status |= ONLP_FAN_STATUS_FAILED;
}
/* get fan direction (both : the same)
*/
ret = onlp_file_read_int(&value, "%s""fan%d_direction", FAN_BOARD_PATH, fid);
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
info->status |= value ? ONLP_FAN_STATUS_F2B : ONLP_FAN_STATUS_B2F;
/* get front fan speed
*/
ret = onlp_file_read_int(&value, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid);
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
info->rpm = value;
/* get rear fan speed
*/
ret = onlp_file_read_int(&value, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid);
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
/* take the min value from front/rear fan speed
*/
if (info->rpm > value) {
info->rpm = value;
}
/* get speed percentage from rpm
*/
ret = onlp_file_read_int(&value, "%s""fan_max_speed_rpm", FAN_BOARD_PATH);
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
info->percentage = (info->rpm * 100)/value;
return ONLP_STATUS_OK;
}
static uint32_t
_onlp_get_fan_direction_on_psu(void)
{
/* Try to read direction from PSU1.
* If PSU1 is not valid, read from PSU2
*/
int i = 0;
for (i = PSU1_ID; i <= PSU2_ID; i++) {
psu_type_t psu_type;
psu_type = get_psu_type(i, NULL, 0);
if (psu_type == PSU_TYPE_UNKNOWN) {
continue;
}
if (PSU_TYPE_AC_F2B == psu_type) {
return ONLP_FAN_STATUS_F2B;
}
else {
return ONLP_FAN_STATUS_B2F;
}
}
return 0;
}
static int
_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info)
{
int val = 0;
info->status |= ONLP_FAN_STATUS_PRESENT;
/* get fan direction
*/
info->status |= _onlp_get_fan_direction_on_psu();
/* get fan speed
*/
if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) {
info->rpm = val;
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
info->status |= (val == 0) ? ONLP_FAN_STATUS_FAILED : 0;
}
return ONLP_STATUS_OK;
}
/*
* This function will be called prior to all of onlp_fani_* functions.
*/
int
onlp_fani_init(void)
{
return ONLP_STATUS_OK;
}
int
onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info)
{
int rc = 0;
int fid;
VALIDATE(id);
fid = ONLP_OID_ID_GET(id);
*info = finfo[fid];
switch (fid)
{
case FAN_1_ON_PSU_1:
rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info);
break;
case FAN_1_ON_PSU_2:
rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info);
break;
case FAN_1_ON_FAN_BOARD:
case FAN_2_ON_FAN_BOARD:
case FAN_3_ON_FAN_BOARD:
case FAN_4_ON_FAN_BOARD:
case FAN_5_ON_FAN_BOARD:
case FAN_6_ON_FAN_BOARD:
rc =_onlp_fani_info_get_fan(fid, info);
break;
default:
rc = ONLP_STATUS_E_INVALID;
break;
}
return rc;
}
/*
* This function sets the fan speed of the given OID as a percentage.
*
* This will only be called if the OID has the PERCENTAGE_SET
* capability.
*
* It is optional if you have no fans at all with this feature.
*/
int
onlp_fani_percentage_set(onlp_oid_t id, int p)
{
int fid;
char *path = NULL;
VALIDATE(id);
fid = ONLP_OID_ID_GET(id);
/* reject p=0 (p=0, stop fan) */
if (p == 0){
return ONLP_STATUS_E_INVALID;
}
switch (fid)
{
case FAN_1_ON_PSU_1:
return psu_ym2651y_pmbus_info_set(PSU1_ID, "psu_fan1_duty_cycle_percentage", p);
case FAN_1_ON_PSU_2:
return psu_ym2651y_pmbus_info_set(PSU2_ID, "psu_fan1_duty_cycle_percentage", p);
case FAN_1_ON_FAN_BOARD:
case FAN_2_ON_FAN_BOARD:
case FAN_3_ON_FAN_BOARD:
case FAN_4_ON_FAN_BOARD:
case FAN_5_ON_FAN_BOARD:
case FAN_6_ON_FAN_BOARD:
path = FAN_NODE(fan_duty_cycle_percentage);
break;
default:
return ONLP_STATUS_E_INVALID;
}
if (onlp_file_write_int(p, path) < 0) {
AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,247 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2013 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlplib/file.h>
#include <onlp/platformi/ledi.h>
#include "platform_lib.h"
#define LED_FORMAT "/sys/class/leds/accton_as5916_54xk_led::%s/brightness"
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_LED(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
/* LED related data
*/
enum onlp_led_id
{
LED_RESERVED = 0,
LED_LOC,
LED_DIAG,
LED_PSU1,
LED_PSU2,
LED_FAN,
};
enum led_light_mode {
LED_MODE_OFF,
LED_MODE_RED = 10,
LED_MODE_RED_BLINKING = 11,
LED_MODE_ORANGE = 12,
LED_MODE_ORANGE_BLINKING = 13,
LED_MODE_YELLOW = 14,
LED_MODE_YELLOW_BLINKING = 15,
LED_MODE_GREEN = 16,
LED_MODE_GREEN_BLINKING = 17,
LED_MODE_BLUE = 18,
LED_MODE_BLUE_BLINKING = 19,
LED_MODE_PURPLE = 20,
LED_MODE_PURPLE_BLINKING = 21,
LED_MODE_AUTO = 22,
LED_MODE_AUTO_BLINKING = 23,
LED_MODE_WHITE = 24,
LED_MODE_WHITE_BLINKING = 25,
LED_MODE_CYAN = 26,
LED_MODE_CYAN_BLINKING = 27,
LED_MODE_UNKNOWN = 99
};
typedef struct led_light_mode_map {
enum onlp_led_id id;
enum led_light_mode driver_led_mode;
enum onlp_led_mode_e onlp_led_mode;
} led_light_mode_map_t;
led_light_mode_map_t led_map[] = {
{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_LOC, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE},
{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
{LED_DIAG, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE},
{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}
};
static char *leds[] = /* must map with onlp_led_id */
{
NULL,
"loc",
"diag",
"psu1",
"psu2",
"fan"
};
/*
* Get the information for the given LED OID.
*/
static onlp_led_info_t linfo[] =
{
{ }, /* Not used */
{
{ ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE,
},
{
{ ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 2 (DIAG LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN,
},
{
{ ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 3 (PSU1 LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO,
},
{
{ ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO,
},
{
{ ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 5 (FAN LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_AUTO,
},
};
static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode)
{
int i, nsize = sizeof(led_map)/sizeof(led_map[0]);
for (i = 0; i < nsize; i++)
{
if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode)
{
return led_map[i].onlp_led_mode;
}
}
return 0;
}
static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode)
{
int i, nsize = sizeof(led_map)/sizeof(led_map[0]);
for(i = 0; i < nsize; i++)
{
if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode)
{
return led_map[i].driver_led_mode;
}
}
return 0;
}
/*
* This function will be called prior to any other onlp_ledi_* functions.
*/
int
onlp_ledi_init(void)
{
/*
* Turn off the LOCATION and DIAG LEDs at startup
*/
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_OFF);
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_LOC), ONLP_LED_MODE_OFF);
return ONLP_STATUS_OK;
}
int
onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info)
{
int lid, value;
VALIDATE(id);
lid = ONLP_OID_ID_GET(id);
/* Set the onlp_oid_hdr_t and capabilities */
*info = linfo[ONLP_OID_ID_GET(id)];
/* Get LED mode */
if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) {
DEBUG_PRINT("Unable to read status from file "LED_FORMAT, leds[lid]);
return ONLP_STATUS_E_INTERNAL;
}
info->mode = driver_to_onlp_led_mode(lid, value);
/* Set the on/off status */
if (info->mode != ONLP_LED_MODE_OFF) {
info->status |= ONLP_LED_STATUS_ON;
}
return ONLP_STATUS_OK;
}
/*
* Turn an LED on or off.
*
* This function will only be called if the LED OID supports the ONOFF
* capability.
*
* What 'on' means in terms of colors or modes for multimode LEDs is
* up to the platform to decide. This is intended as baseline toggle mechanism.
*/
int
onlp_ledi_set(onlp_oid_t id, int on_or_off)
{
VALIDATE(id);
if (!on_or_off) {
return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF);
}
return ONLP_STATUS_E_UNSUPPORTED;
}
/*
* This function puts the LED into the given mode. It is a more functional
* interface for multimode LEDs.
*
* Only modes reported in the LED's capabilities will be attempted.
*/
int
onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode)
{
int lid;
VALIDATE(id);
lid = ONLP_OID_ID_GET(id);
if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), LED_FORMAT, leds[lid]) < 0) {
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,9 @@
###############################################################################
#
#
#
###############################################################################
LIBRARY := x86_64_accton_as5916_54xk
$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(BUILDER)/lib.mk

View File

@@ -0,0 +1,124 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2013 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <unistd.h>
#include <fcntl.h>
#include <onlplib/file.h>
#include <onlp/onlp.h>
#include "platform_lib.h"
#define PSU_NODE_MAX_PATH_LEN 64
#define PSU_MODEL_NAME_LEN 9
#define PSU_FAN_DIR_LEN 3
psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
{
int ret = 0, value = 0;
char model[PSU_MODEL_NAME_LEN + 1] = {0};
char fan_dir[PSU_FAN_DIR_LEN + 1] = {0};
char *path = NULL;
if (modelname && modelname_len < PSU_MODEL_NAME_LEN) {
return PSU_TYPE_UNKNOWN;
}
/* Check AC model name */
path = (id == PSU1_ID) ? PSU1_AC_EEPROM_NODE(psu_model_name) : PSU2_AC_EEPROM_NODE(psu_model_name);
ret = onlp_file_read((uint8_t*)model, PSU_MODEL_NAME_LEN, &value, path);
if (ret != ONLP_STATUS_OK || value != PSU_MODEL_NAME_LEN) {
return PSU_TYPE_UNKNOWN;
}
if (strncmp(model, "YM-2651Y", strlen("YM-2651Y")) != 0) {
return PSU_TYPE_UNKNOWN;
}
if (modelname) {
strncpy(modelname, model, modelname_len-1);
}
path = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir);
ret = onlp_file_read((uint8_t*)fan_dir, sizeof(fan_dir), &value, path);
if (ret != ONLP_STATUS_OK) {
return PSU_TYPE_UNKNOWN;
}
if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) {
return PSU_TYPE_AC_F2B;
}
if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) {
return PSU_TYPE_AC_B2F;
}
return PSU_TYPE_UNKNOWN;
}
int psu_ym2651y_pmbus_info_get(int id, char *node, int *value)
{
int ret = 0;
char path[PSU_NODE_MAX_PATH_LEN] = {0};
*value = 0;
if (PSU1_ID == id) {
ret = onlp_file_read_int(value, "%s%s", PSU1_AC_PMBUS_PREFIX, node);
}
else {
ret = onlp_file_read_int(value, "%s%s", PSU2_AC_PMBUS_PREFIX, node);
}
if (ret < 0) {
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ret;
}
int psu_ym2651y_pmbus_info_set(int id, char *node, int value)
{
char path[PSU_NODE_MAX_PATH_LEN] = {0};
switch (id) {
case PSU1_ID:
sprintf(path, "%s%s", PSU1_AC_PMBUS_PREFIX, node);
break;
case PSU2_ID:
sprintf(path, "%s%s", PSU2_AC_PMBUS_PREFIX, node);
break;
default:
return ONLP_STATUS_E_UNSUPPORTED;
};
if (onlp_file_write_int(value, path) < 0) {
AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,89 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#ifndef __PLATFORM_LIB_H__
#define __PLATFORM_LIB_H__
#include "x86_64_accton_as5916_54xk_log.h"
#define CHASSIS_FAN_COUNT 6
#define CHASSIS_THERMAL_COUNT 5
#define CHASSIS_LED_COUNT 5
#define CHASSIS_PSU_COUNT 2
#define PSU1_ID 1
#define PSU2_ID 2
#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-005b/"
#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/17-0058/"
#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node
#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node
#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/18-0053/"
#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/17-0050/"
#define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node
#define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node
#define FAN_BOARD_PATH "/sys/bus/i2c/devices/9-0066/"
#define FAN_NODE(node) FAN_BOARD_PATH#node
#define IDPROM_PATH "/sys/bus/i2c/devices/0-0056/eeprom"
enum onlp_thermal_id
{
THERMAL_RESERVED = 0,
THERMAL_CPU_CORE,
THERMAL_1_ON_MAIN_BROAD,
THERMAL_2_ON_MAIN_BROAD,
THERMAL_3_ON_MAIN_BROAD,
THERMAL_4_ON_MAIN_BROAD,
THERMAL_1_ON_PSU1,
THERMAL_1_ON_PSU2,
};
typedef enum psu_type {
PSU_TYPE_UNKNOWN,
PSU_TYPE_AC_F2B,
PSU_TYPE_AC_B2F
} psu_type_t;
psu_type_t get_psu_type(int id, char* modelname, int modelname_len);
int psu_ym2651y_pmbus_info_get(int id, char *node, int *value);
int psu_ym2651y_pmbus_info_set(int id, char *node, int value);
#define DEBUG_MODE 0
#if (DEBUG_MODE == 1)
#define DEBUG_PRINT(fmt, args...) \
printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define DEBUG_PRINT(fmt, args...)
#endif
#endif /* __PLATFORM_LIB_H__ */

View File

@@ -0,0 +1,177 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlp/platformi/psui.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#define PSU_STATUS_PRESENT 1
#define PSU_STATUS_POWER_GOOD 1
#define PSU_NODE_MAX_PATH_LEN 64
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_PSU(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
static int
psu_status_info_get(int id, char *node, int *value)
{
char *prefix = NULL;
*value = 0;
prefix = (id == PSU1_ID) ? PSU1_AC_EEPROM_PREFIX : PSU2_AC_EEPROM_PREFIX;
if (onlp_file_read_int(value, "%s%s", prefix, node) < 0) {
AIM_LOG_ERROR("Unable to read status from file(%s%s)\r\n", prefix, node);
return ONLP_STATUS_E_INTERNAL;
}
return 0;
}
int
onlp_psui_init(void)
{
return ONLP_STATUS_OK;
}
static int
psu_ym2651y_info_get(onlp_psu_info_t* info)
{
int val = 0;
int index = ONLP_OID_ID_GET(info->hdr.id);
/* Set capability
*/
info->caps = ONLP_PSU_CAPS_AC;
if (info->status & ONLP_PSU_STATUS_FAILED) {
return ONLP_STATUS_OK;
}
/* Set the associated oid_table */
info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT);
info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT);
/* Read voltage, current and power */
if (psu_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) {
info->mvout = val;
info->caps |= ONLP_PSU_CAPS_VOUT;
}
if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) {
info->miout = val;
info->caps |= ONLP_PSU_CAPS_IOUT;
}
if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) {
info->mpout = val;
info->caps |= ONLP_PSU_CAPS_POUT;
}
return ONLP_STATUS_OK;
}
/*
* Get all information about the given PSU oid.
*/
static onlp_psu_info_t pinfo[] =
{
{ }, /* Not used */
{
{ ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 },
},
{
{ ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 },
}
};
int
onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
{
int val = 0;
int ret = ONLP_STATUS_OK;
int index = ONLP_OID_ID_GET(id);
psu_type_t psu_type;
VALIDATE(id);
memset(info, 0, sizeof(onlp_psu_info_t));
*info = pinfo[index]; /* Set the onlp_oid_hdr_t */
/* Get the present state */
if (psu_status_info_get(index, "psu_present", &val) != 0) {
printf("Unable to read PSU(%d) node(psu_present)\r\n", index);
}
if (val != PSU_STATUS_PRESENT) {
info->status &= ~ONLP_PSU_STATUS_PRESENT;
return ONLP_STATUS_OK;
}
info->status |= ONLP_PSU_STATUS_PRESENT;
/* Get power good status */
if (psu_status_info_get(index, "psu_power_good", &val) != 0) {
printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index);
}
if (val != PSU_STATUS_POWER_GOOD) {
info->status |= ONLP_PSU_STATUS_FAILED;
}
/* Get PSU type
*/
psu_type = get_psu_type(index, info->model, sizeof(info->model));
switch (psu_type) {
case PSU_TYPE_AC_F2B:
case PSU_TYPE_AC_B2F:
ret = psu_ym2651y_info_get(info);
break;
case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/
info->status |= ONLP_PSU_STATUS_UNPLUGGED;
info->status &= ~ONLP_PSU_STATUS_FAILED;
ret = ONLP_STATUS_OK;
break;
default:
ret = ONLP_STATUS_E_UNSUPPORTED;
break;
}
return ret;
}
int
onlp_psui_ioctl(onlp_oid_t pid, va_list vargs)
{
return ONLP_STATUS_E_UNSUPPORTED;
}

View File

@@ -0,0 +1,287 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2017 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#include "x86_64_accton_as5916_54xk_log.h"
#define NUM_OF_SFP_PORT 54
#define MAX_PORT_PATH 64
#define SFP_PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s"
#define SFP_PORT_DOM_FORMAT "/sys/bus/i2c/devices/%d-0051/%s"
#define SFP_BUS_INDEX(port) (port+33)
/************************************************************
*
* SFPI Entry Points
*
***********************************************************/
int
onlp_sfpi_init(void)
{
/* Called at initialization time */
return ONLP_STATUS_OK;
}
int
onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap)
{
/*
* Ports {0, 54}
*/
int p;
for(p = 0; p < NUM_OF_SFP_PORT; p++) {
AIM_BITMAP_SET(bmap, p);
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_is_present(int port)
{
/*
* Return 1 if present.
* Return 0 if not present.
* Return < 0 if error.
*/
int present;
if (onlp_file_read_int(&present, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_is_present") < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
return present;
}
int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char path[MAX_PORT_PATH] = {0};
FILE* fp;
sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_is_present_all");
fp = fopen(path, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5,
bytes+6
);
fclose(fp);
if(count != AIM_ARRAYSIZE(bytes)) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
/* Mask out non-existant QSFP ports */
bytes[6] &= 0x3F;
/* Convert to 64 bit integer in port order */
int i = 0;
uint64_t presence_all = 0 ;
for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) {
presence_all <<= 8;
presence_all |= bytes[i];
}
/* Populate bitmap */
for(i = 0; presence_all; i++) {
AIM_BITMAP_MOD(dst, i, (presence_all & 1));
presence_all >>= 1;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
int size = 0;
if(onlp_file_read(data, 256, &size, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) {
if(size == 256) {
return ONLP_STATUS_OK;
}
}
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
int size = 0;
if(onlp_file_read(data, 256, &size, SFP_PORT_DOM_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) {
if(size == 256) {
return ONLP_STATUS_OK;
}
}
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[6];
char path[MAX_PORT_PATH] = {0};
FILE* fp;
sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_rx_los_all");
fp = fopen(path, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5
);
fclose(fp);
if(count != 6) {
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
/* Convert to 64 bit integer in port order */
int i = 0;
uint64_t rx_los_all = 0 ;
for(i = 5; i >= 0; i--) {
rx_los_all <<= 8;
rx_los_all |= bytes[i];
}
/* Populate bitmap */
for(i = 0; rx_los_all; i++) {
AIM_BITMAP_MOD(dst, i, (rx_los_all & 1));
rx_los_all >>= 1;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
{
int rv;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
if (onlp_file_write_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") != 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
rv = ONLP_STATUS_OK;
}
break;
}
default:
rv = ONLP_STATUS_E_UNSUPPORTED;
break;
}
return rv;
}
int
onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_rx_los") < 0) {
AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
rv = ONLP_STATUS_OK;
}
break;
}
case ONLP_SFP_CONTROL_TX_FAULT:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_fault") < 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
rv = ONLP_STATUS_OK;
}
break;
}
case ONLP_SFP_CONTROL_TX_DISABLE:
{
if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") < 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
rv = ONLP_STATUS_OK;
}
break;
}
default:
rv = ONLP_STATUS_E_UNSUPPORTED;
}
return rv;
}
int
onlp_sfpi_denit(void)
{
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,339 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2017 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <unistd.h>
#include <fcntl.h>
#include <onlplib/file.h>
#include <onlp/platformi/sysi.h>
#include <onlp/platformi/ledi.h>
#include <onlp/platformi/thermali.h>
#include <onlp/platformi/fani.h>
#include <onlp/platformi/psui.h>
#include "platform_lib.h"
#include "x86_64_accton_as5916_54xk_int.h"
#include "x86_64_accton_as5916_54xk_log.h"
#define CPLD_VERSION_FORMAT "/sys/bus/i2c/devices/%s/version"
#define NUM_OF_CPLD 2
static char* cpld_path[NUM_OF_CPLD] =
{
"11-0060",
"12-0062"
};
const char*
onlp_sysi_platform_get(void)
{
return "x86-64-accton-as5916-54xk-r1";
}
int
onlp_sysi_onie_data_get(uint8_t** data, int* size)
{
uint8_t* rdata = aim_zmalloc(256);
if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) {
if(*size == 256) {
*data = rdata;
return ONLP_STATUS_OK;
}
}
aim_free(rdata);
*size = 0;
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sysi_oids_get(onlp_oid_t* table, int max)
{
int i;
onlp_oid_t* e = table;
memset(table, 0, max*sizeof(onlp_oid_t));
/* 5 Thermal sensors on the chassis */
for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) {
*e++ = ONLP_THERMAL_ID_CREATE(i);
}
/* 5 LEDs on the chassis */
for (i = 1; i <= CHASSIS_LED_COUNT; i++) {
*e++ = ONLP_LED_ID_CREATE(i);
}
/* 2 PSUs on the chassis */
for (i = 1; i <= CHASSIS_PSU_COUNT; i++) {
*e++ = ONLP_PSU_ID_CREATE(i);
}
/* 6 Fans on the chassis */
for (i = 1; i <= CHASSIS_FAN_COUNT; i++) {
*e++ = ONLP_FAN_ID_CREATE(i);
}
return 0;
}
int
onlp_sysi_platform_info_get(onlp_platform_info_t* pi)
{
int i, v[NUM_OF_CPLD] = {0};
for (i = 0; i < AIM_ARRAYSIZE(cpld_path); i++) {
v[i] = 0;
if(onlp_file_read_int(v+i, CPLD_VERSION_FORMAT , cpld_path[i]) < 0) {
return ONLP_STATUS_E_INTERNAL;
}
}
pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]);
return ONLP_STATUS_OK;
}
void
onlp_sysi_platform_info_free(onlp_platform_info_t* pi)
{
aim_free(pi->cpld_versions);
}
#define FAN_DUTY_MAX (100)
#define FAN_DUTY_MID (69)
#define FAN_DUTY_MIN (38)
#define FANCTRL_DIR_FACTOR (ONLP_FAN_STATUS_B2F)
#define FANCTRL_DIR_FACTOR_DUTY_ADDON (6)
static int
sysi_fanctrl_fan_fault_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i;
*adjusted = 0;
/* Bring fan speed to FAN_DUTY_MAX if any fan is not operational */
for (i = 0; i < CHASSIS_FAN_COUNT; i++) {
if (!(fi[i].status & ONLP_FAN_STATUS_FAILED)) {
continue;
}
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_fan_absent_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i;
*adjusted = 0;
/* Bring fan speed to FAN_DUTY_MAX if fan is not present */
for (i = 0; i < CHASSIS_FAN_COUNT; i++) {
if (fi[i].status & ONLP_FAN_STATUS_PRESENT) {
continue;
}
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_fan_unknown_speed_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int fanduty;
int fanduty_min = FAN_DUTY_MIN;
int fanduty_mid = FAN_DUTY_MID;
*adjusted = 0;
fanduty_min += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0;
fanduty_mid += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0;
if (onlp_file_read_int(&fanduty, FAN_NODE(fan_duty_cycle_percentage)) < 0) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
/* Bring fan speed to max if current speed is not expected
*/
if (fanduty != fanduty_min && fanduty != fanduty_mid && fanduty != FAN_DUTY_MAX) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_single_thermal_sensor_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i;
*adjusted = 0;
/* When anyone higher than 50 degrees, all fans run with duty 100%.
*/
for (i = (THERMAL_1_ON_MAIN_BROAD); i <= (THERMAL_3_ON_MAIN_BROAD); i++) {
if (ti[i-1].mcelsius < 50000) {
continue;
}
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
/* When anyone higher than 45 degrees, all fans run with duty 62.5%.
*/
for (i = (THERMAL_1_ON_MAIN_BROAD); i <= (THERMAL_3_ON_MAIN_BROAD); i++) {
if (ti[i-1].mcelsius < 45000) {
continue;
}
int fanduty_mid = FAN_DUTY_MID;
fanduty_mid += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0;
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fanduty_mid);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_overall_thermal_sensor_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int fanduty_min = FAN_DUTY_MIN;
int fanduty_mid = FAN_DUTY_MID;
int i, num_of_sensor = 0, temp_avg = 0;
*adjusted = 0;
fanduty_min += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0;
fanduty_mid += (fi[0].status & FANCTRL_DIR_FACTOR) ? FANCTRL_DIR_FACTOR_DUTY_ADDON : 0;
for (i = (THERMAL_1_ON_MAIN_BROAD); i <= (THERMAL_3_ON_MAIN_BROAD); i++) {
num_of_sensor++;
temp_avg += ti[i-1].mcelsius;
}
temp_avg /= num_of_sensor;
if (temp_avg >= 45000) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
else if (temp_avg >= 40000) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fanduty_mid);
}
else if (temp_avg < 35000) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), fanduty_min);
}
return ONLP_STATUS_OK;
}
typedef int (*fan_control_policy)(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted);
fan_control_policy fan_control_policies[] = {
sysi_fanctrl_fan_fault_policy,
sysi_fanctrl_fan_absent_policy,
sysi_fanctrl_fan_unknown_speed_policy,
sysi_fanctrl_single_thermal_sensor_policy,
sysi_fanctrl_overall_thermal_sensor_policy,
};
int
onlp_sysi_platform_manage_fans(void)
{
int i, rc;
onlp_fan_info_t fi[CHASSIS_FAN_COUNT];
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT];
memset(fi, 0, sizeof(fi));
memset(ti, 0, sizeof(ti));
/* Get fan status
*/
for (i = 0; i < CHASSIS_FAN_COUNT; i++) {
rc = onlp_fani_info_get(ONLP_FAN_ID_CREATE(i+1), &fi[i]);
if (rc != ONLP_STATUS_OK) {
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
return ONLP_STATUS_E_INTERNAL;
}
}
/* Get thermal sensor status
*/
for (i = 0; i < CHASSIS_THERMAL_COUNT; i++) {
rc = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i+1), &ti[i]);
if (rc != ONLP_STATUS_OK) {
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
return ONLP_STATUS_E_INTERNAL;
}
}
/* Apply thermal policy according the policy list,
* If fan duty is adjusted by one of the policies, skip the others
*/
for (i = 0; i < AIM_ARRAYSIZE(fan_control_policies); i++) {
int adjusted = 0;
rc = fan_control_policies[i](fi, ti, &adjusted);
if (!adjusted) {
continue;
}
return rc;
}
return ONLP_STATUS_OK;
}
int
onlp_sysi_platform_manage_leds(void)
{
return ONLP_STATUS_E_UNSUPPORTED;
}

View File

@@ -0,0 +1,128 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
* Thermal Sensor Platform Implementation.
*
***********************************************************/
#include <onlplib/file.h>
#include <onlp/platformi/thermali.h>
#include "platform_lib.h"
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_THERMAL(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
static char* devfiles__[] = /* must map with onlp_thermal_id */
{
NULL,
NULL, /* CPU_CORE files */
"/sys/bus/i2c/devices/10-0048*temp1_input",
"/sys/bus/i2c/devices/10-0049*temp1_input",
"/sys/bus/i2c/devices/10-004a*temp1_input",
"/sys/bus/i2c/devices/10-004b*temp1_input",
"/sys/bus/i2c/devices/18-005b*psu_temp1_input",
"/sys/bus/i2c/devices/17-0058*psu_temp1_input",
};
static char* cpu_coretemp_files[] =
{
"/sys/devices/platform/coretemp.0*temp2_input",
"/sys/devices/platform/coretemp.0*temp3_input",
"/sys/devices/platform/coretemp.0*temp4_input",
"/sys/devices/platform/coretemp.0*temp5_input",
NULL,
};
/* Static values */
static onlp_thermal_info_t linfo[] = {
{ }, /* Not used */
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-48", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2-49", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3-4A", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-3-4B", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
}
};
/*
* This will be called to intiialize the thermali subsystem.
*/
int
onlp_thermali_init(void)
{
return ONLP_STATUS_OK;
}
/*
* Retrieve the information structure for the given thermal OID.
*
* If the OID is invalid, return ONLP_E_STATUS_INVALID.
* If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL.
* Otherwise, return ONLP_STATUS_OK with the OID's information.
*
* Note -- it is expected that you fill out the information
* structure even if the sensor described by the OID is not present.
*/
int
onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
{
int tid;
VALIDATE(id);
tid = ONLP_OID_ID_GET(id);
/* Set the onlp_oid_hdr_t and capabilities */
*info = linfo[tid];
if(tid == THERMAL_CPU_CORE) {
int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files);
return rv;
}
return onlp_file_read_int(&info->mcelsius, devfiles__[tid]);
}

View File

@@ -0,0 +1,80 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
/* <auto.start.cdefs(x86_64_accton_as5916_54xk_CONFIG_HEADER).source> */
#define __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(_x) #_x
#define __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(_x) __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(_x)
x86_64_accton_as5916_54xk_config_settings_t x86_64_accton_as5916_54xk_config_settings[] =
{
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_STDLIB(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_UCLI(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
{ __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) },
#else
{ X86_64_ACCTON_AS5916_54XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as5916_54xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
{ NULL, NULL }
};
#undef __x86_64_accton_as5916_54xk_config_STRINGIFY_VALUE
#undef __x86_64_accton_as5916_54xk_config_STRINGIFY_NAME
const char*
x86_64_accton_as5916_54xk_config_lookup(const char* setting)
{
int i;
for(i = 0; x86_64_accton_as5916_54xk_config_settings[i].name; i++) {
if(strcmp(x86_64_accton_as5916_54xk_config_settings[i].name, setting)) {
return x86_64_accton_as5916_54xk_config_settings[i].value;
}
}
return NULL;
}
int
x86_64_accton_as5916_54xk_config_show(struct aim_pvs_s* pvs)
{
int i;
for(i = 0; x86_64_accton_as5916_54xk_config_settings[i].name; i++) {
aim_printf(pvs, "%s = %s\n", x86_64_accton_as5916_54xk_config_settings[i].name, x86_64_accton_as5916_54xk_config_settings[i].value);
}
return i;
}
/* <auto.end.cdefs(x86_64_accton_as5916_54xk_CONFIG_HEADER).source> */

View File

@@ -0,0 +1,10 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
/* <--auto.start.enum(ALL).source> */
/* <auto.end.enum(ALL).source> */

View File

@@ -0,0 +1,12 @@
/**************************************************************************//**
*
* x86_64_accton_as5916_54xk Internal Header
*
*****************************************************************************/
#ifndef __x86_64_accton_as5916_54xk_INT_H__
#define __x86_64_accton_as5916_54xk_INT_H__
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
#endif /* __x86_64_accton_as5916_54xk_INT_H__ */

View File

@@ -0,0 +1,18 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
#include "x86_64_accton_as5916_54xk_log.h"
/*
* x86_64_accton_as5916_54xk log struct.
*/
AIM_LOG_STRUCT_DEFINE(
X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_OPTIONS_DEFAULT,
X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_BITS_DEFAULT,
NULL, /* Custom log map */
X86_64_ACCTON_AS5916_54XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
);

View File

@@ -0,0 +1,12 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#ifndef __x86_64_accton_as5916_54xk_LOG_H__
#define __x86_64_accton_as5916_54xk_LOG_H__
#define AIM_LOG_MODULE_NAME x86_64_accton_as5916_54xk
#include <AIM/aim_log.h>
#endif /* __x86_64_accton_as5916_54xk_LOG_H__ */

View File

@@ -0,0 +1,24 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
#include "x86_64_accton_as5916_54xk_log.h"
static int
datatypes_init__(void)
{
#define x86_64_accton_as5916_54xk_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL);
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk.x>
return 0;
}
void __x86_64_accton_as5916_54xk_module_init__(void)
{
AIM_LOG_STRUCT_REGISTER();
datatypes_init__();
}
int __onlp_platform_version__ = 1;

View File

@@ -0,0 +1,50 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as5916_54xk/x86_64_accton_as5916_54xk_config.h>
#if x86_64_accton_as5916_54xk_CONFIG_INCLUDE_UCLI == 1
#include <uCli/ucli.h>
#include <uCli/ucli_argparse.h>
#include <uCli/ucli_handler_macros.h>
static ucli_status_t
x86_64_accton_as5916_54xk_ucli_ucli__config__(ucli_context_t* uc)
{
UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as5916_54xk)
}
/* <auto.ucli.handlers.start> */
/* <auto.ucli.handlers.end> */
static ucli_module_t
x86_64_accton_as5916_54xk_ucli_module__ =
{
"x86_64_accton_as5916_54xk_ucli",
NULL,
x86_64_accton_as5916_54xk_ucli_ucli_handlers__,
NULL,
NULL,
};
ucli_node_t*
x86_64_accton_as5916_54xk_ucli_node_create(void)
{
ucli_node_t* n;
ucli_module_init(&x86_64_accton_as5916_54xk_ucli_module__);
n = ucli_node_create("x86_64_accton_as5916_54xk", NULL, &x86_64_accton_as5916_54xk_ucli_module__);
ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as5916_54xk"));
return n;
}
#else
void*
x86_64_accton_as5916_54xk_ucli_node_create(void)
{
return NULL;
}
#endif

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as5916-54xk REVISION=r1

View File

@@ -0,0 +1,33 @@
---
######################################################################
#
# platform-config for AS5916
#
######################################################################
x86-64-accton-as5916-54xk-r1:
grub:
serial: >-
--port=0x3f8
--speed=115200
--word=8
--parity=no
--stop=1
kernel:
<<: *kernel-3-16
args: >-
nopat
console=ttyS0,115200n8
tg3.short_preamble=1
tg3.bcm5718s_reset=1
##network:
## interfaces:
## ma1:
## name: ~
## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0

View File

@@ -0,0 +1,72 @@
from onl.platform.base import *
from onl.platform.accton import *
class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton,
OnlPlatformPortConfig_48x10_6x40):
PLATFORM='x86-64-accton-as5916-54xk-r1'
MODEL="AS5916-54XK"
SYS_OBJECT_ID=".5916.54"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.insmod("ym2651y")
for m in [ "sfp", "psu", "fan", "leds" ]:
self.insmod("x86-64-accton-as5916-54xk-%s" % m)
########### initialize I2C bus 0 ###########
self.new_i2c_devices(
[
# initialize multiplexer (PCA9548)
('pca9548', 0x77, 0),
('pca9548', 0x76, 1),
# initiate chassis fan
('as5916_54xk_fan', 0x66, 9),
# inititate LM75
('lm75', 0x48, 10),
('lm75', 0x49, 10),
('lm75', 0x4a, 10),
('lm75', 0x4b, 10),
# initialize CPLDs
('accton_i2c_cpld', 0x60, 11),
('accton_i2c_cpld', 0x62, 12),
# initialize multiplexer (PCA9548)
('pca9548', 0x74, 2),
# initiate PSU-1 AC Power
('as5916_54xk_psu1', 0x53, 18),
('ym2651', 0x5b, 18),
# initiate PSU-2 AC Power
('as5916_54xk_psu2', 0x50, 17),
('ym2651', 0x58, 17),
# initialize multiplexer (PCA9548)
('pca9548', 0x72, 2),
('pca9548', 0x75, 25),
('pca9548', 0x75, 26),
('pca9548', 0x75, 27),
('pca9548', 0x75, 28),
('pca9548', 0x75, 29),
('pca9548', 0x75, 30),
('pca9548', 0x75, 31),
# initiate IDPROM
('24c02', 0x56, 0),
]
)
# initialize SFP devices
for port in range(1, 49):
self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x50, port+32)
self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x51, port+32)
# initialize QSFP devices
for port in range(49, 55):
self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x50, port+32)
return True

View File

@@ -38,8 +38,8 @@
#define DEBUG_PRINT(fmt, args...)
#endif
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as5916_54xm_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5916_54xm_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
struct accton_as5916_54xm_led_data {
struct platform_device *pdev;
@@ -148,12 +148,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type,
static int accton_as5916_54xm_led_read_value(u8 reg)
{
return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
return as5916_54xm_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
}
static int accton_as5916_54xm_led_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
return as5916_54xm_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
}
static void accton_as5916_54xm_led_update(void)

View File

@@ -37,7 +37,7 @@
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
static int as5916_54xm_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as5916_54xm_cpld_read(unsigned short cpld_addr, u8 reg);
/* Addresses scanned
*/
@@ -234,7 +234,7 @@ static struct as5916_54xm_psu_data *as5916_54xm_psu_update_device(struct device
dev_dbg(&client->dev, "Starting as5916_54xm update\n");
/* Read psu status */
status = accton_i2c_cpld_read(0x60, 0x2);
status = as5916_54xm_cpld_read(0x60, 0x2);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);

View File

@@ -24,29 +24,21 @@
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/i2c.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#include "x86_64_accton_as5916_54xm_int.h"
#include "x86_64_accton_as5916_54xm_log.h"
#define NUM_OF_SFP_PORT 54
#define MAX_SFP_PATH 64
static char sfp_node_path[MAX_SFP_PATH] = {0};
#define FRONT_PORT_BUS_INDEX(port) ((port <48)? (port+41):(port-23))
#define PORT_BUS_INDEX(port) ((port <48)? (port+41):(port-23))
static char*
sfp_get_port_path_addr(int port, int addr, char *node_name)
{
sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s",
FRONT_PORT_BUS_INDEX(port), addr, node_name);
return sfp_node_path;
}
static char*
sfp_get_port_path(int port, char *node_name)
{
return sfp_get_port_path_addr(port, 50, node_name);
}
#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom"
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d"
#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d"
#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d"
#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d"
#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/11-0060/module_rx_los_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/12-0062/module_rx_los_all"
/************************************************************
*
@@ -67,8 +59,8 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap)
* Ports {0, 54}
*/
int p;
for(p = 0; p < NUM_OF_SFP_PORT; p++) {
for(p = 0; p < 54; p++) {
AIM_BITMAP_SET(bmap, p);
}
@@ -84,9 +76,12 @@ onlp_sfpi_is_present(int port)
* Return < 0 if error.
*/
int present;
char *path = sfp_get_port_path(port, "sfp_is_present");
int bus, addr;
if (onlp_file_read_int(&present, path) < 0) {
addr = (port < 24) ? 60 : 62;
bus = (addr == 60) ? 11 : 12;
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -97,33 +92,45 @@ onlp_sfpi_is_present(int port)
int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[7];
char* path;
uint32_t bytes[7], *ptr = NULL;
FILE* fp;
int addr;
AIM_BITMAP_CLR_ALL(dst);
ptr = bytes;
path = sfp_get_port_path(0, "sfp_is_present_all");
fp = fopen(path, "r");
for (addr = 60; addr <= 62; addr+=2) {
/* Read present status of port 0~53 */
int count = 0;
char file[64] = {0};
int bus = (addr == 60) ? 11 : 12;
sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr);
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5,
bytes+6
);
fclose(fp);
if(count != AIM_ARRAYSIZE(bytes)) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
if (addr == 60) { /* CPLD1 */
count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
else { /* CPLD2 */
count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3);
fclose(fp);
if(count != 4) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr);
return ONLP_STATUS_E_INTERNAL;
}
}
ptr += count;
}
/* Mask out non-existant QSFP ports */
@@ -150,34 +157,40 @@ int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t bytes[6];
char* path;
uint32_t *ptr = bytes;
FILE* fp;
path = sfp_get_port_path(0, "sfp_rx_los_all");
fp = fopen(path, "r");
/* Read present status of port 0~23 */
int addr, i = 0;
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x %x %x %x",
bytes+0,
bytes+1,
bytes+2,
bytes+3,
bytes+4,
bytes+5
);
fclose(fp);
if(count != 6) {
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
for (addr = 60; addr <= 62; addr+=2) {
if (addr == 60) {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD1, "r");
}
else {
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r");
}
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2);
fclose(fp);
if(count != 3) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr);
return ONLP_STATUS_E_INTERNAL;
}
ptr += count;
}
/* Convert to 64 bit integer in port order */
int i = 0;
i = 0;
uint64_t rx_los_all = 0 ;
for(i = 5; i >= 0; i--) {
for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) {
rx_los_all <<= 8;
rx_los_all |= bytes[i];
}
@@ -194,32 +207,51 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
char* path = sfp_get_port_path(port, "sfp_eeprom");
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
memset(data, 0, 256);
if (onlp_file_read_binary(path, (char*)data, 256, 256) != 0) {
if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if (size != 256) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom");
memset(data, 0, 256);
FILE* fp;
char file[64] = {0};
sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port));
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
if (onlp_file_read_binary(path, (char*)data, 256, 256) != 0) {
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
if (fseek(fp, 256, SEEK_CUR) != 0) {
fclose(fp);
AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
int ret = fread(data, 1, 256, fp);
fclose(fp);
if (ret != 256) {
AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -231,13 +263,18 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
{
int rv;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 60 : 62;
int bus = (addr == 60) ? 11 : 12;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
char* path = sfp_get_port_path(port, "sfp_tx_disable");
if (onlp_file_write_integer(path, value) != 0) {
if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -259,16 +296,20 @@ int
onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
char* path = NULL;
if (port < 0 || port >= 48) {
return ONLP_STATUS_E_UNSUPPORTED;
}
int addr = (port < 24) ? 60 : 62;
int bus = (addr == 60) ? 11 : 12;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
path = sfp_get_port_path(port, "sfp_rx_los");
if (onlp_file_read_int(value, path) < 0) {
AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port);
if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
@@ -279,9 +320,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_FAULT:
{
path = sfp_get_port_path(port, "sfp_tx_fault");
if (onlp_file_read_int(value, path) < 0) {
if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -293,9 +332,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_DISABLE:
{
path = sfp_get_port_path(port, "sfp_tx_disable");
if (onlp_file_read_int(value, path) < 0) {
if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -312,12 +349,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
return rv;
}
int
onlp_sfpi_denit(void)
{
return ONLP_STATUS_OK;
}

View File

@@ -8,9 +8,9 @@ class OnlPlatform_x86_64_accton_as5916_54xm_r0(OnlPlatformAccton,
SYS_OBJECT_ID=".5916.54"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.insmod('optoe')
self.insmod("ym2651y")
for m in [ "sfp", "psu", "fan", "leds" ]:
for m in [ "cpld", "psu", "fan", "leds" ]:
self.insmod("x86-64-accton-as5916-54xm-%s" % m)
########### initialize I2C bus 0 ###########
@@ -36,8 +36,8 @@ class OnlPlatform_x86_64_accton_as5916_54xm_r0(OnlPlatformAccton,
('lm75', 0x4b, 10),
# initialize CPLDs
('accton_i2c_cpld', 0x60, 11),
('accton_i2c_cpld', 0x62, 12),
('as5916_54xm_cpld1', 0x60, 11),
('as5916_54xm_cpld2', 0x62, 12),
]
)
@@ -65,8 +65,8 @@ class OnlPlatform_x86_64_accton_as5916_54xm_r0(OnlPlatformAccton,
)
# initialize QSFP devices
for port in range(49, 55):
self.new_i2c_device('as5916_54xm_sfp%d' % port, 0x50, port-24)
self.new_i2c_device('optoe1', 0x50, port-24)
subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port-24), shell=True)
########### initialize I2C bus 1 ###########
@@ -85,8 +85,8 @@ class OnlPlatform_x86_64_accton_as5916_54xm_r0(OnlPlatformAccton,
# initialize SFP devices
for port in range(1, 49):
self.new_i2c_device('as5916_54xm_sfp%d' % port, 0x50, port+40)
self.new_i2c_device('as5916_54xm_sfp%d' % port, 0x51, port+40)
self.new_i2c_device('optoe2', 0x50, port+40)
subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+40), shell=True)
return True

View File

@@ -33,44 +33,28 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/dmi.h>
#include <linux/version.h>
#include <linux/stat.h>
#include <linux/hwmon-sysfs.h>
#include <linux/delay.h>
static struct dmi_system_id as6812_dmi_table[] = {
{
.ident = "Accton AS6812",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
DMI_MATCH(DMI_PRODUCT_NAME, "AS6812"),
},
},
{
.ident = "Accton AS6812",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
DMI_MATCH(DMI_PRODUCT_NAME, "AS6812"),
},
},
};
int platform_accton_as6812_32x(void)
{
return dmi_check_system(as6812_dmi_table);
}
EXPORT_SYMBOL(platform_accton_as6812_32x);
#define I2C_RW_RETRY_COUNT 10
#define I2C_RW_RETRY_INTERVAL 60 /* ms */
#define NUM_OF_CPLD1_CHANS 0x0
#define NUM_OF_CPLD2_CHANS 0x10
#define NUM_OF_CPLD3_CHANS 0x10
#define NUM_OF_ALL_CPLD_CHANS (NUM_OF_CPLD2_CHANS + NUM_OF_CPLD3_CHANS)
#define ACCTON_I2C_CPLD_MUX_MAX_NCHANS NUM_OF_CPLD3_CHANS
#define CPLD_CHANNEL_SELECT_REG 0x2
#define CPLD_DESELECT_CHANNEL 0xFF
#define ACCTON_I2C_CPLD_MUX_MAX_NCHANS NUM_OF_CPLD3_CHANS
static LIST_HEAD(cpld_client_list);
static struct mutex list_lock;
static struct mutex list_lock;
struct cpld_client_node {
struct i2c_client *client;
struct list_head list;
struct i2c_client *client;
struct list_head list;
};
enum cpld_mux_type {
@@ -79,10 +63,13 @@ enum cpld_mux_type {
as6812_32x_cpld1
};
struct accton_i2c_cpld_mux {
enum cpld_mux_type type;
struct i2c_adapter *virt_adaps[ACCTON_I2C_CPLD_MUX_MAX_NCHANS];
u8 last_chan; /* last register value */
struct as6812_32x_cpld_data {
enum cpld_mux_type type;
struct i2c_adapter *virt_adaps[ACCTON_I2C_CPLD_MUX_MAX_NCHANS];
u8 last_chan; /* last register value */
struct device *hwmon_dev;
struct mutex update_lock;
};
struct chip_desc {
@@ -106,18 +93,289 @@ static const struct chip_desc chips[] = {
}
};
static const struct i2c_device_id accton_i2c_cpld_mux_id[] = {
static const struct i2c_device_id as6812_32x_cpld_mux_id[] = {
{ "as6812_32x_cpld1", as6812_32x_cpld1 },
{ "as6812_32x_cpld2", as6812_32x_cpld2 },
{ "as6812_32x_cpld3", as6812_32x_cpld3 },
{ }
};
MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_mux_id);
MODULE_DEVICE_TABLE(i2c, as6812_32x_cpld_mux_id);
#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index
#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index
#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index
#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index
enum as6812_32x_cpld_sysfs_attributes {
CPLD_VERSION,
ACCESS,
MODULE_PRESENT_ALL,
MODULE_RXLOS_ALL,
/* transceiver attributes */
TRANSCEIVER_PRESENT_ATTR_ID(1),
TRANSCEIVER_PRESENT_ATTR_ID(2),
TRANSCEIVER_PRESENT_ATTR_ID(3),
TRANSCEIVER_PRESENT_ATTR_ID(4),
TRANSCEIVER_PRESENT_ATTR_ID(5),
TRANSCEIVER_PRESENT_ATTR_ID(6),
TRANSCEIVER_PRESENT_ATTR_ID(7),
TRANSCEIVER_PRESENT_ATTR_ID(8),
TRANSCEIVER_PRESENT_ATTR_ID(9),
TRANSCEIVER_PRESENT_ATTR_ID(10),
TRANSCEIVER_PRESENT_ATTR_ID(11),
TRANSCEIVER_PRESENT_ATTR_ID(12),
TRANSCEIVER_PRESENT_ATTR_ID(13),
TRANSCEIVER_PRESENT_ATTR_ID(14),
TRANSCEIVER_PRESENT_ATTR_ID(15),
TRANSCEIVER_PRESENT_ATTR_ID(16),
TRANSCEIVER_PRESENT_ATTR_ID(17),
TRANSCEIVER_PRESENT_ATTR_ID(18),
TRANSCEIVER_PRESENT_ATTR_ID(19),
TRANSCEIVER_PRESENT_ATTR_ID(20),
TRANSCEIVER_PRESENT_ATTR_ID(21),
TRANSCEIVER_PRESENT_ATTR_ID(22),
TRANSCEIVER_PRESENT_ATTR_ID(23),
TRANSCEIVER_PRESENT_ATTR_ID(24),
TRANSCEIVER_PRESENT_ATTR_ID(25),
TRANSCEIVER_PRESENT_ATTR_ID(26),
TRANSCEIVER_PRESENT_ATTR_ID(27),
TRANSCEIVER_PRESENT_ATTR_ID(28),
TRANSCEIVER_PRESENT_ATTR_ID(29),
TRANSCEIVER_PRESENT_ATTR_ID(30),
TRANSCEIVER_PRESENT_ATTR_ID(31),
TRANSCEIVER_PRESENT_ATTR_ID(32),
};
/* sysfs attributes for hwmon
*/
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf);
static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
char *buf);
static ssize_t access(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
static ssize_t show_version(struct device *dev, struct device_attribute *da,
char *buf);
static int as6812_32x_cpld_read_internal(struct i2c_client *client, u8 reg);
static int as6812_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value);
/* transceiver attributes */
#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \
static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index)
#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr
static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION);
static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS);
/* transceiver attributes */
static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31);
DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32);
static struct attribute *as6812_32x_cpld1_attributes[] = {
&sensor_dev_attr_version.dev_attr.attr,
&sensor_dev_attr_access.dev_attr.attr,
NULL
};
static const struct attribute_group as6812_32x_cpld1_group = {
.attrs = as6812_32x_cpld1_attributes,
};
static struct attribute *as6812_32x_cpld2_attributes[] = {
&sensor_dev_attr_version.dev_attr.attr,
&sensor_dev_attr_access.dev_attr.attr,
/* transceiver attributes */
&sensor_dev_attr_module_present_all.dev_attr.attr,
DECLARE_TRANSCEIVER_PRESENT_ATTR(1),
DECLARE_TRANSCEIVER_PRESENT_ATTR(2),
DECLARE_TRANSCEIVER_PRESENT_ATTR(3),
DECLARE_TRANSCEIVER_PRESENT_ATTR(4),
DECLARE_TRANSCEIVER_PRESENT_ATTR(5),
DECLARE_TRANSCEIVER_PRESENT_ATTR(6),
DECLARE_TRANSCEIVER_PRESENT_ATTR(7),
DECLARE_TRANSCEIVER_PRESENT_ATTR(8),
DECLARE_TRANSCEIVER_PRESENT_ATTR(9),
DECLARE_TRANSCEIVER_PRESENT_ATTR(10),
DECLARE_TRANSCEIVER_PRESENT_ATTR(11),
DECLARE_TRANSCEIVER_PRESENT_ATTR(12),
DECLARE_TRANSCEIVER_PRESENT_ATTR(13),
DECLARE_TRANSCEIVER_PRESENT_ATTR(14),
DECLARE_TRANSCEIVER_PRESENT_ATTR(15),
DECLARE_TRANSCEIVER_PRESENT_ATTR(16),
NULL
};
static const struct attribute_group as6812_32x_cpld2_group = {
.attrs = as6812_32x_cpld2_attributes,
};
static struct attribute *as6812_32x_cpld3_attributes[] = {
&sensor_dev_attr_version.dev_attr.attr,
&sensor_dev_attr_access.dev_attr.attr,
/* transceiver attributes */
&sensor_dev_attr_module_present_all.dev_attr.attr,
DECLARE_TRANSCEIVER_PRESENT_ATTR(17),
DECLARE_TRANSCEIVER_PRESENT_ATTR(18),
DECLARE_TRANSCEIVER_PRESENT_ATTR(19),
DECLARE_TRANSCEIVER_PRESENT_ATTR(20),
DECLARE_TRANSCEIVER_PRESENT_ATTR(21),
DECLARE_TRANSCEIVER_PRESENT_ATTR(22),
DECLARE_TRANSCEIVER_PRESENT_ATTR(23),
DECLARE_TRANSCEIVER_PRESENT_ATTR(24),
DECLARE_TRANSCEIVER_PRESENT_ATTR(25),
DECLARE_TRANSCEIVER_PRESENT_ATTR(26),
DECLARE_TRANSCEIVER_PRESENT_ATTR(27),
DECLARE_TRANSCEIVER_PRESENT_ATTR(28),
DECLARE_TRANSCEIVER_PRESENT_ATTR(29),
DECLARE_TRANSCEIVER_PRESENT_ATTR(30),
DECLARE_TRANSCEIVER_PRESENT_ATTR(31),
DECLARE_TRANSCEIVER_PRESENT_ATTR(32),
NULL
};
static const struct attribute_group as6812_32x_cpld3_group = {
.attrs = as6812_32x_cpld3_attributes,
};
static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
char *buf)
{
int i, status;
u8 values[2] = {0};
u8 regs[] = {0xA, 0xB};
struct i2c_client *client = to_i2c_client(dev);
struct as6812_32x_cpld_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
for (i = 0; i < ARRAY_SIZE(regs); i++) {
status = as6812_32x_cpld_read_internal(client, regs[i]);
if (status < 0) {
goto exit;
}
values[i] = ~(u8)status;
}
mutex_unlock(&data->update_lock);
/* Return values 1 -> 32 in order */
return sprintf(buf, "%.2x %.2x\n", values[0], values[1]);
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct as6812_32x_cpld_data *data = i2c_get_clientdata(client);
int status = 0;
u8 reg = 0, mask = 0;
switch (attr->index) {
case MODULE_PRESENT_1 ... MODULE_PRESENT_8:
reg = 0xA;
mask = 0x1 << (attr->index - MODULE_PRESENT_1);
break;
case MODULE_PRESENT_9 ... MODULE_PRESENT_16:
reg = 0xB;
mask = 0x1 << (attr->index - MODULE_PRESENT_9);
break;
case MODULE_PRESENT_17 ... MODULE_PRESENT_24:
reg = 0xA;
mask = 0x1 << (attr->index - MODULE_PRESENT_17);
break;
case MODULE_PRESENT_25 ... MODULE_PRESENT_32:
reg = 0xB;
mask = 0x1 << (attr->index - MODULE_PRESENT_25);
break;
default:
return 0;
}
mutex_lock(&data->update_lock);
status = as6812_32x_cpld_read_internal(client, reg);
if (unlikely(status < 0)) {
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", !(status & mask));
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t access(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int status;
u32 addr, val;
struct i2c_client *client = to_i2c_client(dev);
struct as6812_32x_cpld_data *data = i2c_get_clientdata(client);
if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) {
return -EINVAL;
}
if (addr > 0xFF || val > 0xFF) {
return -EINVAL;
}
mutex_lock(&data->update_lock);
status = as6812_32x_cpld_write_internal(client, addr, val);
if (unlikely(status < 0)) {
goto exit;
}
mutex_unlock(&data->update_lock);
return count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
for this as they will try to lock adapter a second time */
static int accton_i2c_cpld_mux_reg_write(struct i2c_adapter *adap,
struct i2c_client *client, u8 val)
static int as6812_32x_cpld_mux_reg_write(struct i2c_adapter *adap,
struct i2c_client *client, u8 val)
{
unsigned long orig_jiffies;
unsigned short flags;
@@ -134,8 +392,8 @@ static int accton_i2c_cpld_mux_reg_write(struct i2c_adapter *adap,
orig_jiffies = jiffies;
for (res = 0, try = 0; try <= adap->retries; try++) {
res = adap->algo->smbus_xfer(adap, client->addr, flags,
I2C_SMBUS_WRITE, 0x2,
I2C_SMBUS_BYTE_DATA, &data);
I2C_SMBUS_WRITE, CPLD_CHANNEL_SELECT_REG,
I2C_SMBUS_BYTE_DATA, &data);
if (res != -EAGAIN)
break;
if (time_after(jiffies,
@@ -147,35 +405,35 @@ static int accton_i2c_cpld_mux_reg_write(struct i2c_adapter *adap,
return res;
}
static int accton_i2c_cpld_mux_select_chan(struct i2c_adapter *adap,
void *client, u32 chan)
static int as6812_32x_cpld_mux_select_chan(struct i2c_adapter *adap,
void *client, u32 chan)
{
struct accton_i2c_cpld_mux *data = i2c_get_clientdata(client);
struct as6812_32x_cpld_data *data = i2c_get_clientdata(client);
u8 regval;
int ret = 0;
regval = chan;
/* Only select the channel if its different from the last channel */
if (data->last_chan != regval) {
ret = accton_i2c_cpld_mux_reg_write(adap, client, regval);
ret = as6812_32x_cpld_mux_reg_write(adap, client, regval);
data->last_chan = regval;
}
return ret;
}
static int accton_i2c_cpld_mux_deselect_mux(struct i2c_adapter *adap,
static int as6812_32x_cpld_mux_deselect_mux(struct i2c_adapter *adap,
void *client, u32 chan)
{
struct accton_i2c_cpld_mux *data = i2c_get_clientdata(client);
struct as6812_32x_cpld_data *data = i2c_get_clientdata(client);
/* Deselect active channel */
data->last_chan = chips[data->type].deselectChan;
return accton_i2c_cpld_mux_reg_write(adap, client, data->last_chan);
return as6812_32x_cpld_mux_reg_write(adap, client, data->last_chan);
}
static void accton_i2c_cpld_add_client(struct i2c_client *client)
static void as6812_32x_cpld_add_client(struct i2c_client *client)
{
struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
@@ -191,7 +449,7 @@ static void accton_i2c_cpld_add_client(struct i2c_client *client)
mutex_unlock(&list_lock);
}
static void accton_i2c_cpld_remove_client(struct i2c_client *client)
static void as6812_32x_cpld_remove_client(struct i2c_client *client)
{
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
@@ -217,177 +475,250 @@ static void accton_i2c_cpld_remove_client(struct i2c_client *client)
mutex_unlock(&list_lock);
}
static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf)
{
u8 reg = 0x1;
struct i2c_client *client;
int len;
int val = 0;
struct i2c_client *client = to_i2c_client(dev);
val = i2c_smbus_read_byte_data(client, 0x1);
client = to_i2c_client(dev);
len = sprintf(buf, "%d", i2c_smbus_read_byte_data(client, reg));
return len;
if (val < 0) {
dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val);
}
return sprintf(buf, "%d", val);
}
static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL);
/*
* I2C init/probing/exit functions
*/
static int accton_i2c_cpld_mux_probe(struct i2c_client *client,
static int as6812_32x_cpld_mux_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
int chan=0;
struct accton_i2c_cpld_mux *data;
struct as6812_32x_cpld_data *data;
int ret = -ENODEV;
const struct attribute_group *group = NULL;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
goto err;
goto exit;
data = kzalloc(sizeof(struct accton_i2c_cpld_mux), GFP_KERNEL);
data = kzalloc(sizeof(struct as6812_32x_cpld_data), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto err;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
data->type = id->driver_data;
if (data->type == as6812_32x_cpld2 || data->type == as6812_32x_cpld3) {
data->last_chan = chips[data->type].deselectChan; /* force the first selection */
if (data->type == as6812_32x_cpld2 || data->type == as6812_32x_cpld3) {
data->last_chan = chips[data->type].deselectChan; /* force the first selection */
/* Now create an adapter for each channel */
for (chan = 0; chan < chips[data->type].nchans; chan++) {
data->virt_adaps[chan] = i2c_add_mux_adapter(adap, &client->dev, client, 0, chan,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
I2C_CLASS_HWMON | I2C_CLASS_SPD,
#endif
accton_i2c_cpld_mux_select_chan,
accton_i2c_cpld_mux_deselect_mux);
/* Now create an adapter for each channel */
for (chan = 0; chan < chips[data->type].nchans; chan++) {
data->virt_adaps[chan] = i2c_add_mux_adapter(adap, &client->dev, client, 0, chan, 0,
as6812_32x_cpld_mux_select_chan,
as6812_32x_cpld_mux_deselect_mux);
if (data->virt_adaps[chan] == NULL) {
ret = -ENODEV;
dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan);
goto virt_reg_failed;
}
}
if (data->virt_adaps[chan] == NULL) {
ret = -ENODEV;
dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan);
goto exit_mux_register;
}
}
dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n",
chan, client->name);
}
dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n",
chan, client->name);
}
accton_i2c_cpld_add_client(client);
/* Register sysfs hooks */
switch (data->type) {
case as6812_32x_cpld1:
group = &as6812_32x_cpld1_group;
break;
case as6812_32x_cpld2:
group = &as6812_32x_cpld2_group;
break;
case as6812_32x_cpld3:
group = &as6812_32x_cpld3_group;
break;
default:
break;
}
ret = sysfs_create_file(&client->dev.kobj, &ver.attr);
if (ret)
goto virt_reg_failed;
if (group) {
ret = sysfs_create_group(&client->dev.kobj, group);
if (ret) {
goto exit_mux_register;
}
}
return 0;
as6812_32x_cpld_add_client(client);
virt_reg_failed:
return 0;
exit_mux_register:
for (chan--; chan >= 0; chan--) {
i2c_del_mux_adapter(data->virt_adaps[chan]);
}
kfree(data);
err:
}
kfree(data);
exit:
return ret;
}
static int as6812_32x_cpld_mux_remove(struct i2c_client *client)
{
struct as6812_32x_cpld_data *data = i2c_get_clientdata(client);
const struct chip_desc *chip = &chips[data->type];
int chan;
const struct attribute_group *group = NULL;
as6812_32x_cpld_remove_client(client);
/* Remove sysfs hooks */
switch (data->type) {
case as6812_32x_cpld1:
group = &as6812_32x_cpld1_group;
break;
case as6812_32x_cpld2:
group = &as6812_32x_cpld2_group;
break;
case as6812_32x_cpld3:
group = &as6812_32x_cpld3_group;
break;
default:
break;
}
if (group) {
sysfs_remove_group(&client->dev.kobj, group);
}
for (chan = 0; chan < chip->nchans; ++chan) {
if (data->virt_adaps[chan]) {
i2c_del_mux_adapter(data->virt_adaps[chan]);
data->virt_adaps[chan] = NULL;
}
}
kfree(data);
return 0;
}
static int accton_i2c_cpld_mux_remove(struct i2c_client *client)
static int as6812_32x_cpld_read_internal(struct i2c_client *client, u8 reg)
{
struct accton_i2c_cpld_mux *data = i2c_get_clientdata(client);
const struct chip_desc *chip = &chips[data->type];
int chan;
int status = 0, retry = I2C_RW_RETRY_COUNT;
sysfs_remove_file(&client->dev.kobj, &ver.attr);
for (chan = 0; chan < chip->nchans; ++chan) {
if (data->virt_adaps[chan]) {
i2c_del_mux_adapter(data->virt_adaps[chan]);
data->virt_adaps[chan] = NULL;
while (retry) {
status = i2c_smbus_read_byte_data(client, reg);
if (unlikely(status < 0)) {
msleep(I2C_RW_RETRY_INTERVAL);
retry--;
continue;
}
break;
}
kfree(data);
accton_i2c_cpld_remove_client(client);
return 0;
return status;
}
int as6812_32x_i2c_cpld_read(unsigned short cpld_addr, u8 reg)
static int as6812_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value)
{
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
int ret = -EPERM;
int status = 0, retry = I2C_RW_RETRY_COUNT;
mutex_lock(&list_lock);
list_for_each(list_node, &cpld_client_list)
{
cpld_node = list_entry(list_node, struct cpld_client_node, list);
if (cpld_node->client->addr == cpld_addr) {
ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
break;
while (retry) {
status = i2c_smbus_write_byte_data(client, reg, value);
if (unlikely(status < 0)) {
msleep(I2C_RW_RETRY_INTERVAL);
retry--;
continue;
}
break;
}
return status;
}
int as6812_32x_cpld_read(unsigned short cpld_addr, u8 reg)
{
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
int ret = -EPERM;
mutex_lock(&list_lock);
list_for_each(list_node, &cpld_client_list)
{
cpld_node = list_entry(list_node, struct cpld_client_node, list);
if (cpld_node->client->addr == cpld_addr) {
ret = as6812_32x_cpld_read_internal(cpld_node->client, reg);
break;
}
}
mutex_unlock(&list_lock);
return ret;
return ret;
}
EXPORT_SYMBOL(as6812_32x_i2c_cpld_read);
EXPORT_SYMBOL(as6812_32x_cpld_read);
int as6812_32x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
int as6812_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
{
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
int ret = -EIO;
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
int ret = -EIO;
mutex_lock(&list_lock);
list_for_each(list_node, &cpld_client_list)
{
cpld_node = list_entry(list_node, struct cpld_client_node, list);
list_for_each(list_node, &cpld_client_list)
{
cpld_node = list_entry(list_node, struct cpld_client_node, list);
if (cpld_node->client->addr == cpld_addr) {
ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
break;
}
}
if (cpld_node->client->addr == cpld_addr) {
ret = as6812_32x_cpld_write_internal(cpld_node->client, reg, value);
break;
}
}
mutex_unlock(&list_lock);
return ret;
return ret;
}
EXPORT_SYMBOL(as6812_32x_i2c_cpld_write);
EXPORT_SYMBOL(as6812_32x_cpld_write);
static struct i2c_driver accton_i2c_cpld_mux_driver = {
static struct i2c_driver as6812_32x_cpld_mux_driver = {
.driver = {
.name = "as6812_32x_cpld",
.owner = THIS_MODULE,
},
.probe = accton_i2c_cpld_mux_probe,
.remove = accton_i2c_cpld_mux_remove,
.id_table = accton_i2c_cpld_mux_id,
.probe = as6812_32x_cpld_mux_probe,
.remove = as6812_32x_cpld_mux_remove,
.id_table = as6812_32x_cpld_mux_id,
};
static int __init accton_i2c_cpld_mux_init(void)
static int __init as6812_32x_cpld_mux_init(void)
{
mutex_init(&list_lock);
return i2c_add_driver(&accton_i2c_cpld_mux_driver);
mutex_init(&list_lock);
return i2c_add_driver(&as6812_32x_cpld_mux_driver);
}
static void __exit accton_i2c_cpld_mux_exit(void)
static void __exit as6812_32x_cpld_mux_exit(void)
{
i2c_del_driver(&accton_i2c_cpld_mux_driver);
i2c_del_driver(&as6812_32x_cpld_mux_driver);
}
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("Accton I2C CPLD mux driver");
MODULE_LICENSE("GPL");
module_init(accton_i2c_cpld_mux_init);
module_exit(accton_i2c_cpld_mux_exit);
module_init(as6812_32x_cpld_mux_init);
module_exit(as6812_32x_cpld_mux_exit);

View File

@@ -137,8 +137,8 @@ static ssize_t fan_set_duty_cycle(struct device *dev,
static ssize_t fan_show_value(struct device *dev,
struct device_attribute *da, char *buf);
extern int as6812_32x_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as6812_32x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
extern int as6812_32x_cpld_read(unsigned short cpld_addr, u8 reg);
extern int as6812_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
/*******************/
@@ -257,12 +257,12 @@ static const struct attribute_group accton_as6812_32x_fan_group = {
static int accton_as6812_32x_fan_read_value(u8 reg)
{
return as6812_32x_i2c_cpld_read(0x60, reg);
return as6812_32x_cpld_read(0x60, reg);
}
static int accton_as6812_32x_fan_write_value(u8 reg, u8 value)
{
return as6812_32x_i2c_cpld_write(0x60, reg, value);
return as6812_32x_cpld_write(0x60, reg, value);
}
static void accton_as6812_32x_fan_update_device(struct device *dev)
@@ -385,11 +385,6 @@ static struct platform_driver accton_as6812_32x_fan_driver = {
static int __init accton_as6812_32x_fan_init(void)
{
int ret;
extern int platform_accton_as6812_32x(void);
if(!platform_accton_as6812_32x()) {
return -ENODEV;
}
ret = platform_driver_register(&accton_as6812_32x_fan_driver);
if (ret < 0) {

Some files were not shown because too many files have changed in this diff Show More