[platform]: move dell platform modules into buildimage repo

Signed-off-by: Guohan Lu <gulv@microsoft.com>
This commit is contained in:
Guohan Lu 2018-08-13 10:31:11 +00:00
parent 0cd4ef0c85
commit 9047edc38e
62 changed files with 7715 additions and 10 deletions

8
.gitmodules vendored
View File

@ -36,17 +36,9 @@
[submodule "src/sonic-utilities"] [submodule "src/sonic-utilities"]
path = src/sonic-utilities path = src/sonic-utilities
url = https://github.com/Azure/sonic-utilities url = https://github.com/Azure/sonic-utilities
[submodule "platform/broadcom/sonic-platform-modules-s6000"]
path = platform/broadcom/sonic-platform-modules-s6000
url = https://github.com/Azure/sonic-platform-modules-s6000
branch = stretch
[submodule "platform/broadcom/sonic-platform-modules-arista"] [submodule "platform/broadcom/sonic-platform-modules-arista"]
path = platform/broadcom/sonic-platform-modules-arista path = platform/broadcom/sonic-platform-modules-arista
url = https://github.com/aristanetworks/sonic url = https://github.com/aristanetworks/sonic
[submodule "platform/broadcom/sonic-platform-modules-dell"]
path = platform/broadcom/sonic-platform-modules-dell
url = https://github.com/Azure/sonic-platform-modules-dell
branch = stretch
[submodule "src/sonic-platform-common"] [submodule "src/sonic-platform-common"]
path = src/sonic-platform-common path = src/sonic-platform-common
url = https://github.com/Azure/sonic-platform-common url = https://github.com/Azure/sonic-platform-common

@ -1 +0,0 @@
Subproject commit ae36817bbabc2825f184b5e7cdad5422b4f1d9db

View File

@ -0,0 +1,50 @@
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
# Kernel Module Compile Results
*.mod*
*.cmd
*.o.d
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# Debian packaging
*.debhelper.log
*.postinst.debhelper
*.postrm.debhelper
*.prerm.debhelper
*.substvars

View File

@ -0,0 +1,16 @@
Copyright (C) 2016 Microsoft, Inc
Copyright (C) 2017 Dell, Inc
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

View File

@ -0,0 +1 @@
platform drivers for Dell Z9100 for the SONiC project

View File

@ -0,0 +1,62 @@
# Perform an i2c device configuration : instantiate / delete.
# Input is of the form:
# "echo [driver] <i2c-address> > <i2c-bus/operation>"
# where operation = "new_device" or "delete_device"
i2c_config() {
local count=0
local MAX_BUS_RETRY=20
local MAX_I2C_OP_RETRY=10
i2c_bus_op=`echo "$@" | cut -d'>' -f 2`
i2c_bus=$(dirname $i2c_bus_op)
# check if bus exists
while [[ "$count" -lt "$MAX_BUS_RETRY" ]]; do
[[ -e $i2c_bus ]] && break || sleep .1
count=$((count+1))
done
if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then
echo "ERROR: $@ : i2c bus not created"
return
fi
# perform the add/delete
count=0
while [[ "$count" -lt "$MAX_I2C_OP_RETRY" ]]; do
eval "$@" > /dev/null 2>&1
[[ $? == 0 ]] && break || sleep .2
count=$((count+1))
done
if [[ "$count" -eq "$MAX_I2C_OP_RETRY" ]]; then
echo "ERROR: $@ : i2c operation failed"
return
fi
}
# Check if a i2c bus exists. Poll for upto 2 seconds since mux creation may take time..
# Input: bus to check for existence
i2c_poll_bus_exists() {
local count=0
local MAX_BUS_RETRY=20
local i2c_bus
i2c_bus=$1
# check if bus exists
while [[ "$count" -lt "$MAX_BUS_RETRY" ]]; do
[[ -e $i2c_bus ]] && break || sleep .1
count=$((count+1))
done
if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then
echo "ERROR: $@ : i2c bus not created"
return 1
else
return 0
fi
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
[Unit]
Description=Discard unused blocks
[Service]
Type=oneshot
ExecStart=/sbin/fstrim -av

View File

@ -0,0 +1,12 @@
[Unit]
Description=Discard unused blocks once a week
Documentation=man:fstrim
[Timer]
OnCalendar=weekly
OnBootSec=10min
AccuracySec=1h
Persistent=true
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,11 @@
sonic-dell-platform-modules (1.1) unstable; urgency=low
* Add support for Dell S6100
-- Dell Team <support@dell.com> Wed, 08 Feb 2017 15:57:40 -0800
sonic-dell-platform-modules (1.0) unstable; urgency=low
* Initial release
-- Dell Team <support@dell.com> Mon, 6 Feb 2017 10:10:10 -0800

View File

@ -0,0 +1 @@
9

View File

@ -0,0 +1,22 @@
Source: sonic-dell-platform-modules
Section: main
Priority: extra
Maintainer: Dell Team <support@dell.com>
Build-Depends: debhelper (>= 8.0.0), bzip2
Standards-Version: 3.9.3
Package: platform-modules-z9264f
Architecture: amd64
Depends: linux-image-4.9.0-5-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-z9100
Architecture: amd64
Depends: linux-image-4.9.0-5-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-s6100
Architecture: amd64
Depends: linux-image-4.9.0-5-amd64
Description: kernel modules for platform devices such as fan, led, sfp

View File

@ -0,0 +1,40 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: setup-board
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup S6100 board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
/usr/local/bin/iom_power_on.sh
/usr/local/bin/s6100_platform.sh init
echo "done."
;;
stop)
/usr/local/bin/s6100_platform.sh deinit
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/platform-modules-s6100.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,9 @@
s6100/scripts/io_rd_wr.py usr/local/bin
s6100/scripts/iom_power_*.sh usr/local/bin
s6100/scripts/s6100_platform.sh usr/local/bin
common/dell_i2c_utils.sh usr/local/bin
common/fstrim.timer etc/systemd/system
common/fstrim.service etc/systemd/system
s6100/scripts/platform_sensors.py usr/local/bin
s6100/scripts/sensors usr/bin

View File

@ -0,0 +1,7 @@
# postinst script for S6100
# Enable fstrim
systemctl enable fstrim.timer
systemctl start fstrim.timer
#DEBHELPER#

View File

@ -0,0 +1,40 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: setup-board
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup Z9100 board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
# /usr/local/bin/iom_power_on.sh
/usr/local/bin/z9100_platform.sh init
echo "done."
;;
stop)
/usr/local/bin/z9100_platform.sh deinit
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/platform-modules-z9100.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,8 @@
z9100/scripts/check_qsfp.sh usr/local/bin
z9100/scripts/z9100_platform.sh usr/local/bin
common/dell_i2c_utils.sh usr/local/bin
common/fstrim.timer etc/systemd/system
common/fstrim.service etc/systemd/system
z9100/scripts/platform_sensors.py usr/local/bin
z9100/scripts/sensors usr/bin
z9100/cfg/z9100-modules.conf etc/modules-load.d

View File

@ -0,0 +1,7 @@
# postinst script for Z9100
# Enable fstrim
systemctl enable fstrim.timer
systemctl start fstrim.timer
#DEBHELPER#

View File

@ -0,0 +1,40 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: setup-board
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup Z9264f board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
# /usr/local/bin/iom_power_on.sh
/usr/local/bin/z9264f_platform.sh init
echo "done."
;;
stop)
/usr/local/bin/z9100_platform.sh deinit
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/platform-modules-z9264f.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,6 @@
z9264f/scripts/z9264f_platform.sh usr/local/bin
z9264f/scripts/check_qsfp.sh usr/local/bin
z9264f/scripts/platform_sensors.py usr/local/bin
z9264f/scripts/sensors usr/bin
z9264f/scripts/pcisysfs.py usr/bin
z9264f/cfg/z9264f-modules.conf etc/modules-load.d

View File

@ -0,0 +1,45 @@
#!/usr/bin/make -f
export INSTALL_MOD_DIR:=extra
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
MODULE_DIRS:= s6100 z9100 z9264f
COMMON_DIR := common
%:
dh $@
override_dh_auto_build:
(for mod in $(MODULE_DIRS); do \
if [ $$mod = "s6100" ]; then \
cp $(COMMON_DIR)/*.c $(MOD_SRC_DIR)/$${mod}/modules/dell_s6100_lpc.c; \
elif [ $$mod = "z9100" ]; then \
cp $(COMMON_DIR)/*.c $(MOD_SRC_DIR)/$${mod}/modules/dell_mailbox.c; \
fi; \
echo "making man page alias $$mod -> $$mod APIs";\
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
done)
override_dh_auto_install:
(for mod in $(MODULE_DIRS); do \
dh_installdirs -pplatform-modules-$${mod} \
$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \
debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
done)
override_dh_usrlocal:
override_dh_clean:
dh_clean
(for mod in $(MODULE_DIRS); do \
if [ $$mod = "s6100" ]; then \
rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_s6100_lpc.c; \
elif [ $$mod = "z9100" ]; then \
rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_mailbox.c; \
fi; \
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \
done)

View File

@ -0,0 +1,2 @@
obj-m := dell_s6100_iom_cpld.o dell_s6100_lpc.o

View File

@ -0,0 +1,266 @@
#include<linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/list.h>
//iom cpld slave address
#define IOM_CPLD_SLAVE_ADD 0x3e
//iom cpld ver register
#define IOM_CPLD_SLAVE_VER 0x00
//qsfp reset cntrl reg on each iom
#define QSFP_RST_CRTL_REG0 0x10
#define QSFP_RST_CRTL_REG1 0x11
//qsfp lp mode reg on each iom
#define QSFP_LPMODE_REG0 0x12
#define QSFP_LPMODE_REG1 0x13
//qsfp mod presence reg on each iom
#define QSFP_MOD_PRS_REG0 0x16
#define QSFP_MOD_PRS_REG1 0x17
struct cpld_data {
struct i2c_client *client;
struct mutex update_lock;
};
static void dell_s6100_iom_cpld_add_client(struct i2c_client *client)
{
struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
if (!data) {
dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
return;
}
data->client = client;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
}
static void dell_s6100_iom_cpld_remove_client(struct i2c_client *client)
{
struct cpld_data *data = i2c_get_clientdata(client);
kfree(data);
return;
}
int dell_s6100_iom_cpld_read(struct cpld_data *data,unsigned short cpld_addr, u8 reg)
{
int ret = -EPERM;
u8 high_reg =0x00;
mutex_lock(&data->update_lock);
ret = i2c_smbus_write_byte_data(data->client, high_reg,reg);
ret = i2c_smbus_read_byte(data->client);
mutex_unlock(&data->update_lock);
return ret;
}
int dell_s6100_iom_cpld_write(struct cpld_data *data,unsigned short cpld_addr, u8 reg, u8 value)
{
int ret = -EIO;
u16 devdata=0;
u8 high_reg =0x00;
mutex_lock(&data->update_lock);
devdata = (value << 8) | reg;
i2c_smbus_write_word_data(data->client,high_reg,devdata);
mutex_unlock(&data->update_lock);
return ret;
}
static ssize_t get_cpldver(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u8 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,IOM_CPLD_SLAVE_VER);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u8)ret & 0xff;
return sprintf(buf,"IOM CPLD Version:0x%02x\n",devdata);
}
static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u16 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_MOD_PRS_REG0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u16)ret & 0xff;
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_MOD_PRS_REG1);
if(ret < 0)
return sprintf(buf, "read error");
devdata |= (u16)(ret & 0xff) << 8;
return sprintf(buf,"0x%04x\n",devdata);
}
static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u16 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u16)ret & 0xff;
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG1);
if(ret < 0)
return sprintf(buf, "read error");
devdata |= (u16)(ret & 0xff) << 8;
return sprintf(buf,"0x%04x\n",devdata);
}
static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u16 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u16)ret & 0xff;
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG1);
if(ret < 0)
return sprintf(buf, "read error");
devdata |= (u16)(ret & 0xff) << 8;
return sprintf(buf,"0x%04x\n",devdata);
}
static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long devdata;
int err;
struct cpld_data *data = dev_get_drvdata(dev);
err = kstrtoul(buf, 16, &devdata);
if (err)
return err;
dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG0,(u8)(devdata & 0xff));
dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG1,(u8)((devdata >> 8) & 0xff));
return count;
}
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long devdata;
int err;
struct cpld_data *data = dev_get_drvdata(dev);
err = kstrtoul(buf, 16, &devdata);
if (err)
return err;
dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG0,(u8)(devdata & 0xff));
dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG1,(u8)((devdata >> 8) & 0xff));
return count;
}
static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL);
static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL);
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode);
static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR,get_reset, set_reset);
static struct attribute *i2c_cpld_attrs[] = {
&dev_attr_qsfp_lpmode.attr,
&dev_attr_qsfp_reset.attr,
&dev_attr_qsfp_modprs.attr,
&dev_attr_iom_cpld_vers.attr,
NULL,
};
static struct attribute_group i2c_cpld_attr_grp = {
.attrs = i2c_cpld_attrs,
};
static int dell_s6100_iom_cpld_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
status = -EIO;
goto exit;
}
dev_info(&client->dev, "chip found\n");
dell_s6100_iom_cpld_add_client(client);
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &i2c_cpld_attr_grp);
if (status) {
printk(KERN_INFO "Cannot create sysfs\n");
}
return 0;
exit:
return status;
}
static int dell_s6100_iom_cpld_remove(struct i2c_client *client)
{
dell_s6100_iom_cpld_remove_client(client);
return 0;
}
static const struct i2c_device_id dell_s6100_iom_cpld_id[] = {
{ "dell_s6100_iom_cpld", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, dell_s6100_iom_cpld_id);
static struct i2c_driver dell_s6100_iom_cpld_driver = {
.driver = {
.name = "dell_s6100_iom_cpld",
},
.probe = dell_s6100_iom_cpld_probe,
.remove = dell_s6100_iom_cpld_remove,
.id_table = dell_s6100_iom_cpld_id,
};
static int __init dell_s6100_iom_cpld_init(void)
{
return i2c_add_driver(&dell_s6100_iom_cpld_driver);
}
static void __exit dell_s6100_iom_cpld_exit(void)
{
i2c_del_driver(&dell_s6100_iom_cpld_driver);
}
MODULE_AUTHOR("Srideep Devireddy <srideep_devireddy@dell.com>");
MODULE_DESCRIPTION("dell_s6100_iom_cpld driver");
MODULE_LICENSE("GPL");
module_init(dell_s6100_iom_cpld_init);
module_exit(dell_s6100_iom_cpld_exit);

View File

@ -0,0 +1,146 @@
Dell S6100 64x40G support
------------------------
summary:-
S6100 has 64 x 40G port capacity
S6100 supports 4 IO Modules which are pluggable. Below section covers how to power on IO modules
and initialize the device drivers and configure necessary mux to send traffic.
Necessary drivers and scripts to package
1) Users are expected to build necessary drivers for kernel and package to acess it on the target
a) Mgmt phy driver
This supports BCM 54616 phy driver ( enable CONFIG_IGB in kernel config)
b) driver-support-sff-8436-eeprom.patch
c) driver-support-sff-8436-eeprom-update.patch
This driver supports QSFP EEPROM
d) dell_s6100_iom_cpld.ko
This driver provides support for cpld on 4 x 40Gig-IOM modules
e) i2c_mux_pca954x.ko
This driver provides support for i2c mux/switch (pca954x)
f) dell_s6100_lpc.ko
This driver porivide support for reading all the platform info from SMF.
2) Users are also expected to package below scripts for platform initialization and i2c tree creation
a) iom_power.sh
This script is used to power on IO modules on S6100
b) io_rd_wr.py
This script is generic LPC/io read/write utility (can also access system cpld)
steps to platform initialization (Tested with 3.16)
1) After power up of S6100
a) power up the io modules by executing (./iom_power.sh)
b) insert i2c_mux_pca954x.ko,dell_s6100_iom_cpld.ko,dell_s6100_lpc.ko
Above 2 steps can be called by including them in below 2 step
2) Build i2c device tree/device initialization by calling below script
./s6100_platform_init.sh
3) IOM cpld devices are created under "/sys/bus/i2c/drivers/dell_s6100_iom_cpld/"
QSFP handles via sysfs i2c bus #( 15,16,17,18-003e)
iom_cpld_vers -- Displays CPLD version(RO)
qsfp_lpmode -- lpmode settings(RW)
qsfp_modprs -- modules presence (RO)
qsfp_reset -- reset settings (RW)
ls /sys/bus/i2c/drivers/dell_s6100_iom_cpld/15-003e/
driver/ iom_cpld_vers modalias name power/ qsfp_lpmode qsfp_modprs qsfp_reset subsystem/ uevent
4) step 2 script also builds/attach sfp device tress in sysfs
Example for reading EEPROM data
cat /sys/bus/i2c/devices/19-0050/eeprom | hexdump -C
00000000 0d 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 18 1b 00 00 82 20 00 00 00 00 |........... ....|
00000020 00 00 00 00 00 00 00 00 00 00 16 4d 16 4d 16 4d |...........M.M.M|
00000030 16 4d 34 bf 44 bf 54 bf 64 bf 00 00 00 00 00 00 |.M4.D.T.d.......|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000070 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff 00 |................|
00000080 0d 00 0c 04 00 00 00 40 40 02 d5 05 69 00 00 32 |.......@@...i..2|
00000090 00 00 00 00 46 49 4e 49 53 41 52 20 43 4f 52 50 |....FINISAR CORP|
000000a0 20 20 20 20 07 00 90 65 46 54 4c 34 31 30 51 45 | ...eFTL410QE|
000000b0 31 43 20 20 20 20 20 20 41 33 42 68 07 d0 46 70 |1C A3Bh..Fp|
000000c0 00 01 04 d0 4d 4c 54 30 30 51 33 20 20 20 20 20 |....MLT00Q3 |
000000d0 20 20 20 20 31 32 30 31 31 35 20 20 08 00 00 38 | 120115 ...8|
000000e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200 4b 00 fb 00 46 00 00 00 00 00 00 00 00 00 00 00 |K...F...........|
00000210 94 70 6e f0 86 c4 7b 0c 00 00 00 00 00 00 00 00 |.pn...{.........|
00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000260 00 00 11 11 00 00 00 00 00 00 00 00 00 00 22 22 |..............""|
00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000280
5)SMF driver details/Readme are as below
S6100 SMF
---------
S6100 has one SMF soc on CPU board. This is via LPC interface, provide access to all the below functionality
a) Read sensors details on the system
b) Read PSU details on the system
c) Read fans/Fan tray details on the system
d) Read/Write to system led
dell_s6100_lpc create entry for all the above necessary platform components as attributes in below path.
/sys/devices/platform/dell_s6100_lpc/
LED:-
----
Get /set operations on sys_led
Get operation
cat /sys/devices/platform/dell_s6100_lpc/sys_led
0x80
Set operation
echo 83 > sys/devices/platform/dell_s6100_lpc/sys_led
Sensors:-
--------
Max no of sensors on the system ( 11 sensors are available on fully loaded system)
cat /sys/devices/platform/dell_s6100_lpc/max_num_temp_sensors
b
cat /sys/devices/platform/dell_s6100_lpc/temp_sensor_1 ( temp_sensor_1 <85>.temp_sensor_11)
Fan tray speed:-
--------------
/sys/devices/platform/dell_s6100_lpc/fan_tray_1_speed (fan_tray_1_speed - fan_tray_4_speed)
13700
cat /sys/devices/platform/dell_s6100_lpc/psu1_max_pwr
110
cat /sys/devices/platform/dell_s6100_lpc/psu2_max_pwr
110
cat /sys/devices/platform/dell_s6100_lpc/psu_total_pwr
232

View File

@ -0,0 +1,93 @@
#!/usr/bin/python
#Script to read/write the io based registers
import sys
import os
import getopt
import struct
io_resource='/dev/port'
def usage():
''' This is the Usage Method '''
print 'Utility for IO read/write'
print '\t\t io_rd_wr.py --get --offset <offset>'
print '\t\t io_rd_wr.py --set --val <val> --offset <offset>'
sys.exit(1)
def io_reg_read(io_resource,offset):
fd=os.open(io_resource, os.O_RDONLY)
if(fd<0):
print 'file open failed %s"%io_resource'
return
if(os.lseek(fd, offset, os.SEEK_SET) != offset):
print 'lseek failed on %s'%io_resource
return
buf=os.read(fd,1)
reg_val1=ord(buf)
print 'reg value %x'%reg_val1
os.close(fd)
def io_reg_write(io_resource,offset,val):
fd=os.open(io_resource,os.O_RDWR)
if(fd<0):
print 'file open failed %s"%io_resource'
return
if(os.lseek(fd, offset, os.SEEK_SET) != offset):
print 'lseek failed on %s'%io_resource
return
ret=os.write(fd,struct.pack('B',val))
if(ret != 1):
print 'write failed %d'%ret
return
os.close(fd)
def main(argv):
''' The main function will read the user input from the
command line argument and process the request '''
opts = ''
val = ''
choice = ''
resouce = ''
offset = ''
try:
opts, args = getopt.getopt(argv, "hgs:" , \
["val=","offset=","help", "get", "set"])
except getopt.GetoptError:
usage()
for opt,arg in opts:
if opt in ('-h','--help'):
choice = 'help'
elif opt in ('-g', '--get'):
choice = 'get'
elif opt in ('-s', '--set'):
choice = 'set'
elif opt == '--offset':
offset = int(arg,16)
elif opt == '--val':
val = int(arg,16)
if choice == 'get' and offset != '':
io_reg_read(io_resource,offset)
elif choice == 'set' and offset != '' and val != '':
io_reg_write(io_resource,offset,val)
else:
usage()
#Calling the main method
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,16 @@
#!/bin/bash
#This script is used to power off IO modules
# IOM can be controlled via SMF using mailbox registers
# write 0x2 to 0x04D9 to power off IOM 1
./io_rd_wr.py --set --val 0x04 --offset 0x210
./io_rd_wr.py --set --val 0xd9 --offset 0x211
./io_rd_wr.py --set --val 0x2 --offset 0x213
# write 0x2 to 0x04DA to power off IOM 2
./io_rd_wr.py --set --val 0xda --offset 0x211
./io_rd_wr.py --set --val 0x2 --offset 0x213
# write 0x2 to 0x04DB to power off IOM 3
./io_rd_wr.py --set --val 0xdb --offset 0x211
./io_rd_wr.py --set --val 0x2 --offset 0x213
# write 0x2 to 0x04DC to power off IOM 4
./io_rd_wr.py --set --val 0xdc --offset 0x211
./io_rd_wr.py --set --val 0x2 --offset 0x213

View File

@ -0,0 +1,17 @@
#!/bin/bash
# This script is used to power on IO modules
# IOM can be controlled via SMF using mailbox registers
# write 0x1 to 0x04D9 to power up IOM 1
/usr/local/bin/io_rd_wr.py --set --val 0x04 --offset 0x210
/usr/local/bin/io_rd_wr.py --set --val 0xd9 --offset 0x211
/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213
# write 0x1 to 0x04DA to power up IOM 2
/usr/local/bin/io_rd_wr.py --set --val 0xda --offset 0x211
/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213
# write 0x1 to 0x04DB to power up IOM 3
/usr/local/bin/io_rd_wr.py --set --val 0xdb --offset 0x211
/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213
# write 0x1 to 0x04DC to power up IOM 4
/usr/local/bin/io_rd_wr.py --set --val 0xdc --offset 0x211
/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213

View File

@ -0,0 +1,322 @@
#!/usr/bin/python
# On S6100, the Platform Management Controller runs the
# thermal algorithm. It provides a mailbox for the Host
# to query relevant thermals. The dell_mailbox module
# provides the sysfs support for the following objects:
# * onboard temperature sensors
# * FAN trays
# * PSU
#
import os
import sys
import logging
S6100_MAX_FAN_TRAYS = 4
S6100_MAX_PSUS = 2
S6100_MAX_IOMS = 4
MAILBOX_DIR = "/sys/devices/platform/SMF.512/hwmon/hwmon1"
iom_status_list = []
# Get a mailbox register
def get_pmc_register(reg_name):
retval = 'ERR'
mb_reg_file = MAILBOX_DIR+'/'+reg_name
if (not os.path.isfile(mb_reg_file)):
print mb_reg_file, 'not found !'
return retval
try:
with open(mb_reg_file, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", mb_reg_file, "file !")
retval = retval.rstrip('\r\n')
retval = retval.lstrip(" ")
return retval
logging.basicConfig(level=logging.DEBUG)
if (os.path.isdir(MAILBOX_DIR)):
print 'dell-s6100-lpc'
print 'Adapter: S6100 Platform Management Controller'
else:
logging.error('S6100 Platform Management Controller module not loaded !')
# sys.exit(0)
# Print the information for temperature sensors
def print_temperature_sensors():
print("\nOnboard Temperature Sensors:")
print ' CPU: ',\
int(get_pmc_register('temp1_input'))/1000, 'C'
print ' BCM56960 (PSU side): ',\
int(get_pmc_register('temp2_input'))/1000, 'C'
print ' System Outlet 1 (switch board): ',\
int(get_pmc_register('temp3_input'))/1000, 'C'
print ' BCM56960 (IO side): ',\
int(get_pmc_register('temp4_input'))/1000, 'C'
print ' System Outlet 2 (CPU board): ',\
int(get_pmc_register('temp9_input'))/1000, 'C'
print ' System Inlet Left (IO side): ',\
int(get_pmc_register('temp10_input'))/1000, 'C'
print ' System Inlet Right (IO side): ',\
int(get_pmc_register('temp11_input'))/1000, 'C'
iom_status = get_pmc_register('iom_presence')
iom_status = int(iom_status, 16)
iom_presence = get_pmc_register('iom_status')
if (iom_presence != 'ERR'):
iom_presence = int(iom_presence, 16)
# IOM presence : 0 => IOM present
# Temperature sensors 5..8 correspond to IOM 1..4
for iom in range(0, S6100_MAX_IOMS):
if (~iom_presence & (1 << iom)):
iom_sensor_indx = iom + 5
print ' IOM ' + str(iom + 1) + ':\t\t\t ',\
int(get_pmc_register('temp'+str(iom_sensor_indx) +
'_input'))/1000, 'C'
# Save the IOM Status for later use
if (~iom_status & (1 << iom)):
iom_status_list.append('ON')
else:
iom_status_list.append('OFF')
else:
iom_status_list.append('Not present')
print ' IOM ' + str(iom + 1) + ':\t\t\t ', 'Not present'
else:
logging.error('Unable to check IOM presence')
print_temperature_sensors()
# Print the information for voltage sensors
def print_voltage_sensors():
print("\nOnboard Voltage Sensors:")
print ' CPU XP3R3V_EARLY ',\
float(get_pmc_register('in1_input'))/1000, 'V'
print ' CPU XP5R0V_CP ',\
float(get_pmc_register('in2_input'))/1000, 'V'
print ' CPU XP3R3V_STD ',\
float(get_pmc_register('in3_input'))/1000, 'V'
print ' CPU XP3R3V_CP ',\
float(get_pmc_register('in4_input'))/1000, 'V'
print ' CPU XP0R75V_VTT_A ',\
float(get_pmc_register('in5_input'))/1000, 'V'
print ' CPU XPPR75V_VTT_B ',\
float(get_pmc_register('in6_input'))/1000, 'V'
print ' CPU XP1R07V_CPU ',\
float(get_pmc_register('in7_input'))/1000, 'V'
print ' CPU XP1R0V_CPU ',\
float(get_pmc_register('in8_input'))/1000, 'V'
print ' CPU XP12R0V ',\
float(get_pmc_register('in9_input'))/1000, 'V'
print ' CPU VDDR_CPU_2 ',\
float(get_pmc_register('in10_input'))/1000, 'V'
print ' CPU VDDR_CPU_1 ',\
float(get_pmc_register('in11_input'))/1000, 'V'
print ' CPU XP1R5V_CLK ',\
float(get_pmc_register('in12_input'))/1000, 'V'
print ' CPU XP1R8V_CPU ',\
float(get_pmc_register('in13_input'))/1000, 'V'
print ' CPU XP1R0V_CPU_VNN ',\
float(get_pmc_register('in14_input'))/1000, 'V'
print ' CPU XP1R0V_CPU_VCC ',\
float(get_pmc_register('in15_input'))/1000, 'V'
print ' CPU XP1R5V_EARLY ',\
float(get_pmc_register('in16_input'))/1000, 'V'
print ' SW XP3R3V_MON ',\
float(get_pmc_register('in17_input'))/1000, 'V'
print ' SW XP1R25V_MON ',\
float(get_pmc_register('in19_input'))/1000, 'V'
print ' SW XP1R2V_MON ',\
float(get_pmc_register('in20_input'))/1000, 'V'
print ' SW XP1R0V_SW_MON ',\
float(get_pmc_register('in21_input'))/1000, 'V'
print ' SW XP1R0V_ROV_SW_MON ',\
float(get_pmc_register('in22_input'))/1000, 'V'
print ' SW XR1R0V_BCM84752_MON ',\
float(get_pmc_register('in23_input'))/1000, 'V'
print ' SW XP5V_MB_MON ',\
float(get_pmc_register('in24_input'))/1000, 'V'
print ' SW XP3R3V_FPGA_MON ',\
float(get_pmc_register('in26_input'))/1000, 'V'
print ' SW XP3R3V_EARLY_MON ',\
float(get_pmc_register('in27_input'))/1000, 'V'
print_voltage_sensors()
# Print the information for 1 Fan Tray
def print_fan_tray(tray):
Fan_Status = ['Normal', 'Abnormal']
Airflow_Direction = ['B2F', 'F2B']
print ' Fan Tray ' + str(tray) + ':'
if (tray == 1):
fan1_speed = get_pmc_register('fan1_input')
air_flow_reg = int(get_pmc_register('fan1_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
print ' Fan Speed: ', fan1_speed, 'RPM'
print ' Fan State: ', Fan_Status[fan1_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 2):
fan1_speed = get_pmc_register('fan3_input')
air_flow_reg = int(get_pmc_register('fan3_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
print ' Fan Speed: ', fan1_speed, 'RPM'
print ' Fan State: ', Fan_Status[fan1_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 3):
fan1_speed = get_pmc_register('fan5_input')
air_flow_reg = int(get_pmc_register('fan5_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
print ' Fan Speed: ', fan1_speed, 'RPM'
print ' Fan State: ', Fan_Status[fan1_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 4):
fan1_speed = get_pmc_register('fan7_input')
air_flow_reg = int(get_pmc_register('fan7_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
print ' Fan Speed: ', fan1_speed, 'RPM'
print ' Fan State: ', Fan_Status[fan1_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
print('\nFan Trays:')
fan_tray_presence = get_pmc_register('fan_tray_presence')
if (fan_tray_presence != 'ERR'):
fan_tray_presence = int(fan_tray_presence, 16)
for tray in range(0, S6100_MAX_FAN_TRAYS):
if (fan_tray_presence & (1 << tray)):
print_fan_tray(tray + 1)
else:
print '\n Fan Tray ' + str(tray + 1) + ': Not present'
else:
logging.error('Unable to read FAN presence')
# Print the information for PSU1, PSU2
def print_psu(psu):
Psu_Type = ['Mismatch', 'Normal']
Psu_Input_Type = ['AC', 'DC']
PSU_STATUS_TYPE_BIT = 4
PSU_STATUS_INPUT_TYPE_BIT = 1
PSU_FAN_PRESENT_BIT = 2
PSU_FAN_STATUS_BIT = 1
PSU_FAN_AIR_FLOW_BIT = 0
Psu_Fan_Presence = ['Present', 'Absent']
Psu_Fan_Status = ['Normal', 'Abnormal']
Psu_Fan_Airflow = ['B2F', 'F2B']
print ' PSU ' + str(psu) + ':'
if (psu == 1):
psu_status = int(get_pmc_register('psu1_presence'), 16)
else:
psu_status = int(get_pmc_register('psu2_presence'), 16)
psu_input_type = (psu_status & (1 << PSU_STATUS_INPUT_TYPE_BIT)) >>\
PSU_STATUS_INPUT_TYPE_BIT
psu_type = (psu_status & (1 << PSU_STATUS_TYPE_BIT)) >>\
PSU_STATUS_TYPE_BIT
print ' Input: ', Psu_Input_Type[psu_input_type]
print ' Type: ', Psu_Type[psu_type]
# PSU FAN details
if (psu == 1):
print ' FAN Speed: ', get_pmc_register('fan11_input'), 'RPM'
psu_fan_airflow = int(get_pmc_register('fan11_airflow'))
psu_fan_status = int(get_pmc_register('fan11_alarm'))
psu_fan_present = int(get_pmc_register('fan11_fault'))
input_voltage = float(get_pmc_register('in29_input')) / 1000
output_voltage = float(get_pmc_register('in30_input')) / 1000
input_current = float(get_pmc_register('curr601_input')) / 100
output_current = float(get_pmc_register('curr602_input')) / 100
input_power = float(get_pmc_register('power1_input')) / 1000000
output_power = float(get_pmc_register('power2_input')) / 1000000
if (input_power != 0):
psu_fan_temp = int(get_pmc_register('temp14_input'))/1000
else:
print ' FAN Speed: ', get_pmc_register('fan12_input'), 'RPM'
psu_fan_airflow = int(get_pmc_register('fan12_airflow'))
psu_fan_status = int(get_pmc_register('fan12_alarm'))
psu_fan_present = int(get_pmc_register('fan12_fault'))
input_voltage = float(get_pmc_register('in31_input')) / 1000
output_voltage = float(get_pmc_register('in32_input')) / 1000
input_current = float(get_pmc_register('curr701_input')) / 100
output_current = float(get_pmc_register('curr702_input')) / 100
input_power = float(get_pmc_register('power3_input')) / 1000000
output_power = float(get_pmc_register('power4_input')) / 1000000
if (input_power != 0):
psu_fan_temp = int(get_pmc_register('temp15_input'))/1000
print ' FAN: ', Psu_Fan_Presence[psu_fan_present]
print ' FAN Status: ', Psu_Fan_Status[psu_fan_status]
print ' FAN AIRFLOW: ', Psu_Fan_Airflow[psu_fan_airflow]
# PSU input & output monitors
print ' Input Voltage: %6.2f' % (input_voltage), 'V'
print ' Output Voltage: %6.2f' % (output_voltage), 'V'
print ' Input Current: %6.2f' % (input_current), 'A'
print ' Output Current: %6.2f' % (output_current), 'A'
print ' Input Power: %6.2f' % (input_power), 'W'
print ' Output Power: %6.2f' % (output_power), 'W'
# PSU firmware gives spurious temperature reading without input power
if (input_power != 0):
print ' Temperature: ', psu_fan_temp, 'C'
else:
print ' Temperature: ', 'NA'
print('\nPSUs:')
for psu in range(1, S6100_MAX_PSUS + 1):
if (psu == 1):
psu_status = get_pmc_register('psu1_presence')
else:
psu_status = get_pmc_register('psu2_presence')
if (psu_status != 'ERR'):
psu_status = int(psu_status, 16)
if (~psu_status & 0b1):
print_psu(psu)
else:
print '\n PSU ', psu, 'Not present'
else:
logging.error('Unable to check PSU presence')
print '\n Total Power: ', get_pmc_register('current_total_power'), 'W'
print('\nIO Modules:')
for iom in range(1, S6100_MAX_IOMS+1):
print ' IOM ' + str(iom) + ' :' + iom_status_list[iom - 1]
print '\n'

View File

@ -0,0 +1,206 @@
#!/bin/bash
#platform init script for Dell S6100
source dell_i2c_utils.sh
init_devnum() {
found=0
for devnum in 0 1; do
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
# iSMT adapter can be at either dffd0000 or dfff0000
if [[ $devname == 'SMBus iSMT adapter at '* ]]; then
found=1
break
fi
done
[[ $found -eq 0 ]] && echo "cannot find iSMT" && exit 1
}
# Attach/Detach CPU board mux @ 0x70
cpu_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9547 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
;;
"delete_device") i2c_config "echo 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
;;
*) echo "s6100_platform: cpu_board_mux: invalid command !"
;;
esac
}
# Attach/Detach Switchboard MUX @ 0x71
switch_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
;;
"delete_device") i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
;;
*) echo "s6100_platform: switch_board_mux : invalid command !"
;;
esac
}
# Attach/Detach syseeprom on CPU board
sys_eeprom() {
case $1 in
"new_device") i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1"
;;
"delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1"
;;
*) echo "s6100_platform: sys_eeprom : invalid command !"
;;
esac
}
#Attach/Detach CPLD devices to drivers for each IOM
switch_board_cpld() {
case $1 in
"new_device")
for ((i=14;i<=17;i++));
do
i2c_config "echo dell_s6100_iom_cpld 0x3e > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
"delete_device")
for ((i=14;i<=17;i++));
do
i2c_config "echo 0x3e > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
*) echo "s6100_platform: switch_board_cpld : invalid command !"
;;
esac
}
#Attach/Detach the MUX connecting all QSFPs on each IOM @0x71 and 0x72
switch_board_qsfp_mux() {
case $1 in
"new_device")
for ((i=9;i>=6;i--));
do
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Attaching PCA9548 $mux_index"
i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$i/$1"
i2c_config "echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
"delete_device")
for ((i=9;i>=6;i--));
do
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Detaching PCA9548 $mux_index"
i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1"
i2c_config "echo 0x72 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1"
done
;;
*) echo "s6100_platform: switch_board_qsfp_mux: invalid command !"
;;
esac
}
#Attach/Detach the SFP modules on PCA9548_2
switch_board_sfp() {
case $1 in
"new_device") i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-11/$1"
i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-12/$1"
;;
"delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-11/$1"
i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-12/$1"
;;
*) echo "s6100_platform: switch_board_sfp: invalid command !"
;;
esac
}
#Add/Delete ($1) a range ($2..$3) of QSFPs
qsfp_device_mod() {
case $1 in
"new_device") for ((i=$2;i<=$3;i++));
do
i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
"delete_device") for ((i=$2;i<=$3;i++));
do
i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
*) echo "s6100_platform: qsfp_device_mod: invalid command $1:$2,$3!"
;;
esac
}
# Attach/Detach 16 instances of QSFP ports on each IO modules
# eeprom can dump data using below command
switch_board_qsfp() {
if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-18"; then
qsfp_device_mod $1 18 33
fi
if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-34"; then
qsfp_device_mod $1 34 49
fi
if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-50"; then
qsfp_device_mod $1 50 65
fi
if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-66"; then
qsfp_device_mod $1 66 81
fi
}
# Enable/Disable low power mode on all QSFP ports
switch_board_qsfp_lpmode() {
case $1 in
"enable") value=0xffff
;;
"disable") value=0x0
;;
*) echo "s6100_platform: switch_board_qsfp_lpmode: invalid command $1!"
return
;;
esac
echo $value > /sys/class/i2c-adapter/i2c-14/14-003e/qsfp_lpmode
echo $value > /sys/class/i2c-adapter/i2c-15/15-003e/qsfp_lpmode
echo $value > /sys/class/i2c-adapter/i2c-16/16-003e/qsfp_lpmode
echo $value > /sys/class/i2c-adapter/i2c-17/17-003e/qsfp_lpmode
}
init_devnum
if [[ "$1" == "init" ]]; then
depmod -a
modprobe i2c-dev
modprobe i2c-mux-pca954x force_deselect_on_exit=1
modprobe dell_s6100_iom_cpld
modprobe dell_s6100_lpc
cpu_board_mux "new_device"
switch_board_mux "new_device"
sys_eeprom "new_device"
switch_board_cpld "new_device"
switch_board_qsfp_mux "new_device"
switch_board_sfp "new_device"
switch_board_qsfp "new_device"
switch_board_qsfp_lpmode "disable"
elif [[ "$1" == "deinit" ]]; then
switch_board_sfp "delete_device"
switch_board_cpld "delete_device"
switch_board_mux "delete_device"
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
switch_board_qsfp_mux "delete_device"
cpu_board_mux "delete_device"
modprobe -r dell_s6100_lpc
modprobe -r dell_s6100_iom_cpld
modprobe -r i2c-mux-pca954x
modprobe -r i2c-dev
else
echo "s6100_platform : Invalid option !"
fi

View File

@ -0,0 +1,7 @@
#!/bin/bash
docker exec -i pmon sensors "$@"
#To probe sensors not part of lm-sensors
if [ -r /usr/local/bin/platform_sensors.py ]; then
python /usr/local/bin/platform_sensors.py
fi

View File

@ -0,0 +1,15 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-i801
i2c-isch
i2c-ismt
i2c-dev
i2c-mux
i2c-smbus
i2c-mux-gpio
i2c-mux-pca954x

View File

@ -0,0 +1,2 @@
obj-m := dell_mailbox.o dell_z9100_cpld.o

View File

@ -0,0 +1,273 @@
/* Includes only 3 things.
* a. QSFP Reset control
* b. LP Mode
* c. Module Presence
*/
#include<linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/list.h>
//iom cpld slave address
#define IOM_CPLD_SLAVE_ADD 0x3e
//iom cpld ver register
#define IOM_CPLD_SLAVE_VER 0x00
//qsfp reset cntrl reg on each iom
#define QSFP_RST_CRTL_REG0 0x10
#define QSFP_RST_CRTL_REG1 0x11
//qsfp lp mode reg on each iom
#define QSFP_LPMODE_REG0 0x12
#define QSFP_LPMODE_REG1 0x13
//qsfp mod presence reg on each iom
#define QSFP_MOD_PRS_REG0 0x16
#define QSFP_MOD_PRS_REG1 0x17
struct cpld_data {
struct i2c_client *client;
struct mutex update_lock;
};
static void dell_z9100_iom_cpld_add_client(struct i2c_client *client)
{
struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
if (!data) {
dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
return;
}
data->client = client;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
}
static void dell_z9100_iom_cpld_remove_client(struct i2c_client *client)
{
struct cpld_data *data = i2c_get_clientdata(client);
kfree(data);
return ;
}
int dell_z9100_iom_cpld_read(struct cpld_data *data, u8 reg)
{
int ret = -EPERM;
u8 high_reg =0x00;
mutex_lock(&data->update_lock);
ret = i2c_smbus_write_byte_data(data->client, high_reg,reg);
ret = i2c_smbus_read_byte(data->client);
mutex_unlock(&data->update_lock);
return ret;
}
int dell_z9100_iom_cpld_write(struct cpld_data *data,u8 reg, u8 value)
{
int ret = -EIO;
u16 devdata=0;
u8 high_reg =0x00;
mutex_lock(&data->update_lock);
devdata = (value << 8) | reg;
i2c_smbus_write_word_data(data->client,high_reg,devdata);
mutex_unlock(&data->update_lock);
return ret;
}
static ssize_t get_cpldver(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u8 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_z9100_iom_cpld_read(data,IOM_CPLD_SLAVE_VER);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u8)ret & 0xff;
return sprintf(buf,"IOM CPLD Version:0x%02x\n",devdata);
}
static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u16 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_z9100_iom_cpld_read(data,QSFP_MOD_PRS_REG0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u16)ret & 0xff;
ret = dell_z9100_iom_cpld_read(data,QSFP_MOD_PRS_REG1);
if(ret < 0)
return sprintf(buf, "read error");
devdata |= (u16)(ret & 0xff) << 8;
return sprintf(buf,"0x%04x\n",devdata);
}
static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u16 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_z9100_iom_cpld_read(data,QSFP_LPMODE_REG0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u16)ret & 0xff;
ret = dell_z9100_iom_cpld_read(data,QSFP_LPMODE_REG1);
if(ret < 0)
return sprintf(buf, "read error");
devdata |= (u16)(ret & 0xff) << 8;
return sprintf(buf,"0x%04x\n",devdata);
}
static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u16 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_z9100_iom_cpld_read(data,QSFP_RST_CRTL_REG0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u16)ret & 0xff;
ret = dell_z9100_iom_cpld_read(data,QSFP_RST_CRTL_REG1);
if(ret < 0)
return sprintf(buf, "read error");
devdata |= (u16)(ret & 0xff) << 8;
return sprintf(buf,"0x%04x\n",devdata);
}
static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long devdata;
int err;
struct cpld_data *data = dev_get_drvdata(dev);
err = kstrtoul(buf, 16, &devdata);
if (err)
return err;
dell_z9100_iom_cpld_write(data,QSFP_LPMODE_REG0,(u8)(devdata & 0xff));
dell_z9100_iom_cpld_write(data,QSFP_LPMODE_REG1,(u8)((devdata >> 8) & 0xff));
return count;
}
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long devdata;
int err;
struct cpld_data *data = dev_get_drvdata(dev);
err = kstrtoul(buf, 16, &devdata);
if (err)
return err;
dell_z9100_iom_cpld_write(data,QSFP_RST_CRTL_REG0,(u8)(devdata & 0xff));
dell_z9100_iom_cpld_write(data,QSFP_RST_CRTL_REG1,(u8)((devdata >> 8) & 0xff));
return count;
}
static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL);
static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL);
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode);
static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR,get_reset, set_reset);
static struct attribute *i2c_cpld_attrs[] = {
&dev_attr_qsfp_lpmode.attr,
&dev_attr_qsfp_reset.attr,
&dev_attr_qsfp_modprs.attr,
&dev_attr_iom_cpld_vers.attr,
NULL,
};
static struct attribute_group i2c_cpld_attr_grp = {
.attrs = i2c_cpld_attrs,
};
static int dell_z9100_iom_cpld_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
status = -EIO;
goto exit;
}
dev_info(&client->dev, "chip found- New\n");
dell_z9100_iom_cpld_add_client(client);
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &i2c_cpld_attr_grp);
if (status) {
printk(KERN_INFO "Cannot create sysfs\n");
}
return 0;
exit:
return status;
}
static int dell_z9100_iom_cpld_remove(struct i2c_client *client)
{
dell_z9100_iom_cpld_remove_client(client);
return 0;
}
static const struct i2c_device_id dell_z9100_iom_cpld_id[] = {
{ "dell_z9100_iom_cpld", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, dell_z9100_iom_cpld_id);
static struct i2c_driver dell_z9100_iom_cpld_driver = {
.driver = {
.name = "dell_z9100_iom_cpld",
},
.probe = dell_z9100_iom_cpld_probe,
.remove = dell_z9100_iom_cpld_remove,
.id_table = dell_z9100_iom_cpld_id,
};
static int __init dell_z9100_iom_cpld_init(void)
{
return i2c_add_driver(&dell_z9100_iom_cpld_driver);
}
static void __exit dell_z9100_iom_cpld_exit(void)
{
i2c_del_driver(&dell_z9100_iom_cpld_driver);
}
MODULE_AUTHOR("Srideep Devireddy <srideep_devireddy@dell.com>");
MODULE_DESCRIPTION("dell_z9100_iom_cpld driver");
MODULE_LICENSE("GPL");
module_init(dell_z9100_iom_cpld_init);
module_exit(dell_z9100_iom_cpld_exit);

View File

@ -0,0 +1,60 @@
#!/bin/bash
#Usage:
# check_qsfp.sh qsfp10
# check_qsfp.sh sffp2
# There are 34 optics ports. 32 QSFP28, 2 SFP+
# QSFP28 is orgainized is 3 banks
# CPLD-2 QSFP-1-12
# CPLD-3 QSFP-13-22
# CPLD-4 QSFP-23-32
# SFF+ 2 ports on CPLD-4
optics=$1
cpld_addr="003e"
if [ `expr match $optics qsfp` -ne 0 ]
then
type=qsfp
id=${optics:4}
if [ $id -le 0 -o $id -gt 32 ]
then
echo "Invalid QSFP id"
return -1
fi
if [ $id -le 12 ]
then
#cpld=2
cpld_bus=15
elif [ $id -le 22 ]
then
#cpld=3
cpld_bus=16
else
#cpld=4
cpld_bus=17
fi
if [ $id -le 8 ]
then
let qsfp_bus=42+$id
elif [ $id -le 16 ]
then
let qsfp_bus=34+${id}-8
elif [ $id -le 24 ]
then
let qsfp_bus=26+${id}-16
else
let qsfp_bus=18+${id}-24
fi
else
type=sff
id=${optics:3}
cpld=4
fi
echo "Preence:`cat /sys/class/i2c-dev/i2c-${cpld_bus}/device/${cpld_bus}-${cpld_addr}/qsfp_modprs`"
echo "Hexdump:"
cat /sys/bus/i2c/devices/${qsfp_bus}-0050/eeprom | hexdump -C

View File

@ -0,0 +1,324 @@
#!/usr/bin/python
#
# On Z9100, the Platform Management Controller runs the
# thermal algorithm. It provides a mailbox for the Host
# to query relevant thermals. The dell_mailbox module
# provides the sysfs support for the following objects:
# * onboard temperature sensors
# * FAN trays
# * PSU
import os
import sys
import logging
Z9100_MAX_FAN_TRAYS = 5
Z9100_MAX_PSUS = 2
S6100_MAX_IOMS = 4
MAILBOX_DIR = "/sys/devices/platform/SMF.512/hwmon/hwmon1"
# Get a mailbox register
def get_pmc_register(reg_name):
retval = 'ERR'
mb_reg_file = MAILBOX_DIR+'/'+reg_name
if (not os.path.isfile(mb_reg_file)):
print mb_reg_file, 'not found !'
return retval
try:
with open(mb_reg_file, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", mb_reg_file, "file !")
retval = retval.rstrip('\r\n')
retval = retval.lstrip(" ")
return retval
logging.basicConfig(level=logging.DEBUG)
if (os.path.isdir(MAILBOX_DIR)):
print 'dell-s6100-lpc'
print 'Adapter: S6100 Platform Management Controller'
else:
logging.error('S6100 Platform Management Controller module not loaded !')
# sys.exit(0)
# Print the information for temperature sensors
def print_temperature_sensors():
print("\nOnboard Temperature Sensors:")
print ' CPU: ',\
int(get_pmc_register('temp1_input'))/1000, 'C'
print ' BCM56960 (PSU side): ',\
int(get_pmc_register('temp2_input'))/1000, 'C'
print ' System Outlet 1 (switch board): ',\
int(get_pmc_register('temp3_input'))/1000, 'C'
print ' BCM56960 (IO side): ',\
int(get_pmc_register('temp4_input'))/1000, 'C'
print ' System Outlet 2 (CPU board): ',\
int(get_pmc_register('temp9_input'))/1000, 'C'
print ' System Inlet Left (IO side): ',\
int(get_pmc_register('temp6_input'))/1000, 'C'
print_temperature_sensors()
# Print the information for voltage sensors
def print_voltage_sensors():
print("\nOnboard Voltage Sensors:")
print ' CPU XP3R3V_EARLY ',\
float(get_pmc_register('in1_input'))/1000, 'V'
print '\n CPU XP5R0V_CP ',\
float(get_pmc_register('in2_input'))/1000, 'V'
print ' CPU XP3R3V_STD ',\
float(get_pmc_register('in3_input'))/1000, 'V'
print ' CPU XP3R3V_CP ',\
float(get_pmc_register('in4_input'))/1000, 'V'
print ' CPU XP0R75V_VTT_A ',\
float(get_pmc_register('in5_input'))/1000, 'V'
print ' CPU XPPR75V_VTT_B ',\
float(get_pmc_register('in6_input'))/1000, 'V'
print ' CPU XP1R07V_CPU ',\
float(get_pmc_register('in7_input'))/1000, 'V'
print ' CPU XP1R0V_CPU ',\
float(get_pmc_register('in8_input'))/1000, 'V'
print ' CPU XP12R0V ',\
float(get_pmc_register('in9_input'))/1000, 'V'
print ' CPU VDDR_CPU_2 ',\
float(get_pmc_register('in10_input'))/1000, 'V'
print ' CPU VDDR_CPU_1 ',\
float(get_pmc_register('in11_input'))/1000, 'V'
print ' CPU XP1R5V_CLK ',\
float(get_pmc_register('in12_input'))/1000, 'V'
print ' CPU XP1R8V_CPU ',\
float(get_pmc_register('in13_input'))/1000, 'V'
print ' CPU XP1R0V_CPU_VNN ',\
float(get_pmc_register('in14_input'))/1000, 'V'
print ' CPU XP1R0V_CPU_VCC ',\
float(get_pmc_register('in15_input'))/1000, 'V'
print ' CPU XP1R5V_EARLY ',\
float(get_pmc_register('in16_input'))/1000, 'V'
print ' SW XP3R3V_MON ',\
float(get_pmc_register('in17_input'))/1000, 'V'
print ' SW XP1R8V_MON ',\
float(get_pmc_register('in19_input'))/1000, 'V'
print ' SW XP1R2V_MON ',\
float(get_pmc_register('in20_input'))/1000, 'V'
print ' SW XP1R0V_SW_MON ',\
float(get_pmc_register('in21_input'))/1000, 'V'
print ' SW XP1R0V_ROV_SW_MON ',\
float(get_pmc_register('in22_input'))/1000, 'V'
print ' SW XR1R0V_BCM84752_MON ',\
float(get_pmc_register('in23_input'))/1000, 'V'
print ' SW XP5V_MB_MON ',\
float(get_pmc_register('in24_input'))/1000, 'V'
print ' SW XP1R8V_FPGA_MON ',\
float(get_pmc_register('in25_input'))/1000, 'V'
print ' SW XP3R3V_FPGA_MON ',\
float(get_pmc_register('in26_input'))/1000, 'V'
print ' SW XP3R3V_EARLY_MON ',\
float(get_pmc_register('in27_input'))/1000, 'V'
print ' SW XP1R0V_ ',\
float(get_pmc_register('curr21_input'))/10000, 'A'
print ' SW XP1R0V_ROV ',\
float(get_pmc_register('curr22_input'))/10000, 'A'
print_voltage_sensors()
# Print the information for 1 Fan Tray
def print_fan_tray(tray):
Fan_Status = ['Normal', 'Abnormal']
Airflow_Direction = ['B2F', 'F2B']
print ' Fan Tray ' + str(tray) + ':'
if (tray == 1):
fan1_speed = get_pmc_register('fan1_input')
fan2_speed = get_pmc_register('fan2_input')
air_flow_reg = int(get_pmc_register('fan1_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
fan2_status = 0 if fan2_speed >= 1000 else 1
print ' Fan1 Speed: ', fan1_speed, 'RPM'
print ' Fan2 Speed: ', fan2_speed, 'RPM'
print ' Fan1 State: ', Fan_Status[fan1_status]
print ' Fan2 State: ', Fan_Status[fan2_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 2):
fan1_speed = get_pmc_register('fan3_input')
fan2_speed = get_pmc_register('fan4_input')
air_flow_reg = int(get_pmc_register('fan3_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
fan2_status = 0 if fan2_speed >= 1000 else 1
print ' Fan1 Speed: ', fan1_speed, 'RPM'
print ' Fan2 Speed: ', fan2_speed, 'RPM'
print ' Fan1 State: ', Fan_Status[fan1_status]
print ' Fan2 State: ', Fan_Status[fan2_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 3):
fan1_speed = get_pmc_register('fan5_input')
fan2_speed = get_pmc_register('fan6_input')
air_flow_reg = int(get_pmc_register('fan5_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
fan2_status = 0 if fan2_speed >= 1000 else 1
print ' Fan1 Speed: ', fan1_speed, 'RPM'
print ' Fan2 Speed: ', fan2_speed, 'RPM'
print ' Fan1 State: ', Fan_Status[fan1_status]
print ' Fan2 State: ', Fan_Status[fan2_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 4):
fan1_speed = get_pmc_register('fan7_input')
fan2_speed = get_pmc_register('fan8_input')
air_flow_reg = int(get_pmc_register('fan7_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
fan2_status = 0 if fan2_speed >= 1000 else 1
print ' Fan1 Speed: ', fan1_speed, 'RPM'
print ' Fan2 Speed: ', fan2_speed, 'RPM'
print ' Fan1 State: ', Fan_Status[fan1_status]
print ' Fan2 State: ', Fan_Status[fan2_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
elif (tray == 5):
fan1_speed = get_pmc_register('fan9_input')
fan2_speed = get_pmc_register('fan10_input')
air_flow_reg = int(get_pmc_register('fan9_airflow'), 16)
fan1_status = 0 if fan1_speed >= 1000 else 1
fan2_status = 0 if fan2_speed >= 1000 else 1
print ' Fan1 Speed: ', fan1_speed, 'RPM'
print ' Fan2 Speed: ', fan2_speed, 'RPM'
print ' Fan1 State: ', Fan_Status[fan1_status]
print ' Fan2 State: ', Fan_Status[fan2_status]
print ' Air Flow: ', Airflow_Direction[air_flow_reg]
print('\nFan Trays:')
fan_tray_presence = get_pmc_register('fan_tray_presence')
if (fan_tray_presence != 'ERR'):
fan_tray_presence = int(fan_tray_presence, 16)
for tray in range(0, Z9100_MAX_FAN_TRAYS):
if (fan_tray_presence & (1 << tray)):
print_fan_tray(tray + 1)
else:
print '\n Fan Tray ' + str(tray + 1) + ': Not present'
else:
logging.error('Unable to read FAN presence')
# Print the information for PSU1, PSU2
def print_psu(psu):
Psu_Type = ['Normal', 'Mismatch']
Psu_Input_Type = ['AC', 'DC']
PSU_STATUS_TYPE_BIT = 4
PSU_STATUS_INPUT_TYPE_BIT = 1
PSU_FAN_PRESENT_BIT = 2
PSU_FAN_STATUS_BIT = 1
PSU_FAN_AIR_FLOW_BIT = 0
Psu_Fan_Presence = ['Present', 'Absent']
Psu_Fan_Status = ['Normal', 'Abnormal']
Psu_Fan_Airflow = ['B2F', 'F2B']
print ' PSU ' + str(psu) + ':'
if (psu == 1):
psu_status = int(get_pmc_register('psu1_presence'), 16)
else:
psu_status = int(get_pmc_register('psu2_presence'), 16)
psu_input_type = (psu_status & (1 << PSU_STATUS_INPUT_TYPE_BIT)) >>\
PSU_STATUS_INPUT_TYPE_BIT
psu_type = (psu_status & (1 << PSU_STATUS_TYPE_BIT)) >>\
PSU_STATUS_TYPE_BIT
print ' Input: ', Psu_Input_Type[psu_input_type]
print ' Type: ', Psu_Type[psu_type]
# PSU FAN details
if (psu == 1):
print ' FAN Speed: ', get_pmc_register('fan11_input'), 'RPM'
psu_fan_airflow = int(get_pmc_register('fan11_airflow'))
psu_fan_status = int(get_pmc_register('fan11_alarm'))
psu_fan_present = int(get_pmc_register('fan11_fault'))
input_voltage = float(get_pmc_register('in29_input')) / 1000
output_voltage = float(get_pmc_register('in30_input')) / 1000
input_current = float(get_pmc_register('curr601_input')) / 100
output_current = float(get_pmc_register('curr602_input')) /100
input_power = float(get_pmc_register('power1_input')) / 1000000
output_power = float(get_pmc_register('power2_input')) / 1000000
if (input_power != 0):
psu_fan_temp = int(get_pmc_register('temp14_input'))/1000
else:
print ' FAN Speed: ', get_pmc_register('fan12_input'), 'RPM'
psu_fan_airflow = int(get_pmc_register('fan12_airflow'))
psu_fan_status = int(get_pmc_register('fan12_alarm'))
psu_fan_present = int(get_pmc_register('fan12_fault'))
input_voltage = float(get_pmc_register('in31_input')) / 1000
output_voltage = float(get_pmc_register('in32_input')) / 1000
input_current = float(get_pmc_register('curr701_input')) / 100
output_current = float(get_pmc_register('curr702_input')) / 100
input_power = float(get_pmc_register('power3_input')) / 1000000
output_power = float(get_pmc_register('power4_input')) / 1000000
if (input_power != 0):
psu_fan_temp = int(get_pmc_register('temp15_input'))/1000
print ' FAN: ', Psu_Fan_Presence[psu_fan_present]
print ' FAN Status: ', Psu_Fan_Status[psu_fan_status]
print ' FAN AIRFLOW: ', Psu_Fan_Airflow[psu_fan_airflow]
# PSU input & output monitors
print ' Input Voltage: %6.2f' % (input_voltage), 'V'
print ' Output Voltage: %6.2f' % (output_voltage), 'V'
print ' Input Current: %6.2f' % (input_current), 'A'
print ' Output Current: %6.2f' % (output_current), 'A'
print ' Input Power: %6.2f' % (input_power), 'W'
print ' Output Power: %6.2f' % (output_power), 'W'
# PSU firmware gives spurious temperature reading without input power
if (input_power != 0):
print ' Temperature: ', psu_fan_temp, 'C'
else:
print ' Temperature: ', 'NA'
print('\nPSUs:')
for psu in range(1, Z9100_MAX_PSUS + 1):
if (psu == 1):
psu_status = get_pmc_register('psu1_presence')
else:
psu_status = get_pmc_register('psu2_presence')
if (psu_status != 'ERR'):
psu_status = int(psu_status, 16)
if (~psu_status & 0b1):
print_psu(psu)
else:
print '\n PSU ', psu, 'Not present'
else:
logging.error('Unable to check PSU presence')
print '\n Total Power: ', get_pmc_register('current_total_power'), 'W'

View File

@ -0,0 +1,7 @@
#!/bin/bash
docker exec -i pmon sensors "$@"
#To probe sensors not part of lm-sensors
if [ -r /usr/local/bin/platform_sensors.py ]; then
python /usr/local/bin/platform_sensors.py
fi

View File

@ -0,0 +1,170 @@
#!/bin/bash
#platform init script for Dell Z9100
source dell_i2c_utils.sh
init_devnum() {
found=0
for devnum in 0 1; do
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
# iSMT adapter can be at either dffd0000 or dfff0000
if [[ $devname == 'SMBus iSMT adapter at '* ]]; then
found=1
break
fi
done
[[ $found -eq 0 ]] && echo "cannot find iSMT" && exit 1
}
# Attach/Detach CPU board mux @ 0x70
cpu_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9547 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
;;
"delete_device") i2c_config "echo 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
;;
*) echo "z9100_platform: cpu_board_mux: invalid command !"
;;
esac
}
# Attach/Detach switch board MUX to IOM CPLDs @ 0x71
switch_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
;;
"delete_device") i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
;;
*) echo "z9100_platform: switch_board_mux : invalid command !"
;;
esac
}
# Attach/Detach syseeprom on CPU board
sys_eeprom() {
case $1 in
"new_device") i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1"
;;
"delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1"
;;
*) echo "z9100_platform: sys_eeprom : invalid command !"
;;
esac
}
#Attach/Detach cpld devices to drivers for each iom
switch_board_cpld() {
case $1 in
"new_device")
for ((i=14;i<=17;i++));
do
i2c_config "echo dell_z9100_iom_cpld 0x3e > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
"delete_device")
for ((i=14;i<=17;i++));
do
i2c_config "echo 0x3e > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
*) echo "z9100_platform: switch_board_cpld : invalid command !"
;;
esac
}
#Attach/Detach the MUX connecting all QSFPs
switch_board_qsfp_mux() {
case $1 in
"new_device")
for ((i=9;i>=6;i--));
do
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Attaching PCA9548 $mux_index"
i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
"delete_device")
for ((i=9;i>=6;i--));
do
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Detaching PCA9548 $mux_index"
i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1"
done
;;
*) echo "z9100_platform: switch_board_qsfp_mux: invalid command !"
;;
esac
}
#Attach/Detach the SFP modules on PCA9548_2
switch_board_sfp() {
case $1 in
"new_device") i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-11/$1"
i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-12/$1"
;;
"delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-11/$1"
i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-12/$1"
;;
*) echo "z9100_platform: switch_board_sfp: invalid command !"
;;
esac
}
# Attach/Detach 32 instances of EEPROM driver QSFP ports on IO module 1
#eeprom can dump data using below command
switch_board_qsfp() {
case $1 in
"new_device")
for ((i=18;i<=49;i++));
do
i2c_config "echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
"delete_device")
for ((i=18;i<=49;i++));
do
i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1"
done
;;
*) echo "z9100_platform: switch_board_qsfp: invalid command !"
;;
esac
}
init_devnum
if [[ "$1" == "init" ]]; then
depmod -a
modprobe i2c-dev
modprobe i2c-mux-pca954x force_deselect_on_exit=1
modprobe dell_mailbox
modprobe dell_z9100_cpld
cpu_board_mux "new_device"
switch_board_mux "new_device"
sys_eeprom "new_device"
switch_board_cpld "new_device"
switch_board_qsfp_mux "new_device"
switch_board_sfp "new_device"
switch_board_qsfp "new_device"
elif [[ "$1" == "deinit" ]]; then
switch_board_sfp "delete_device"
switch_board_cpld "delete_device"
switch_board_mux "delete_device"
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
switch_board_qsfp_mux "delete_device"
cpu_board_mux "delete_device"
modprobe -r dell_z9100_cpld
modprobe -r dell_mailbox
modprobe -r i2c-mux-pca954x
modprobe -r i2c-dev
else
echo "z9100_platform : Invalid option !"
fi

View File

@ -0,0 +1,19 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-i801
i2c-isch
i2c-ismt
i2c-dev
i2c-mux
i2c-smbus
i2c-mux-gpio
i2c-mux-pca954x
ipmi_devintf
ipmi_si
dell_z9264f_fpga_ocores
i2c_ocores

View File

@ -0,0 +1,2 @@
obj-m := dell_z9264f_fpga_ocores.o

View File

@ -0,0 +1,3 @@
# Temporary dummy file for z9264f.
# Will be updated soon.

View File

@ -0,0 +1,102 @@
#!/usr/bin/python
# Copyright (c) 2015 Dell Inc.
#
# Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
import struct
import sys
import getopt
from os import *
from mmap import *
def usage():
''' This is the Usage Method '''
print '\t\t pcisysfs.py --get --offset <offset> --res <resource>'
print '\t\t pcisysfs.py --set --val <val> --offset <offset> --res <resource>'
sys.exit(1)
def pci_mem_read(mm,offset):
mm.seek(offset)
read_data_stream=mm.read(4)
print ""
reg_val=struct.unpack('I',read_data_stream)
print "reg_val read:%x"%reg_val
return reg_val
def pci_mem_write(mm,offset,data):
mm.seek(offset)
print "data to write:%x"%data
mm.write(struct.pack('I',data))
def pci_set_value(resource,val,offset):
fd=open(resource,O_RDWR)
mm=mmap(fd,0)
pci_mem_write(mm,offset,val)
def pci_get_value(resource,offset):
fd=open(resource,O_RDWR)
mm=mmap(fd,0)
pci_mem_read(mm,offset)
def main(argv):
''' The main function will read the user input from the
command line argument and process the request '''
opts = ''
val = ''
choice = ''
resource = ''
offset = ''
try:
opts, args = getopt.getopt(argv, "hgsv:" , \
["val=","res=","offset=","help", "get", "set"])
except getopt.GetoptError:
usage()
for opt,arg in opts:
if opt in ('-h','--help'):
choice = 'help'
elif opt in ('-g', '--get'):
choice = 'get'
elif opt in ('-s', '--set'):
choice = 'set'
elif opt == '--res':
resource = arg
elif opt == '--val':
val = int(arg,16)
elif opt == '--offset':
offset = int(arg,16)
if choice == 'set' and val != '' and offset !='' and resource !='':
pci_set_value(resource,val,offset)
elif choice == 'get' and offset != '' and resource !='':
pci_get_value(resource,offset)
else:
usage()
#Calling the main method
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,251 @@
#!/usr/bin/python
# On Z9264f, the BaseBoard Management Controller is an
# autonomous subsystem provides monitoring and management
# facility independent of the host CPU. IPMI standard
# protocol is used with ipmitool to fetch sensor details.
# Current script support X00 board only. X01 support will
# be added soon. This provies support for the
# following objects:
# * Onboard temperature sensors
# * FAN trays
# * PSU
import os
import sys
import logging
import subprocess
import commands
Z9264F_MAX_FAN_TRAYS = 4
Z9264F_MAX_PSUS = 2
IPMI_SENSOR_DATA = "ipmitool sdr list"
IPMI_SENSOR_DUMP = "/tmp/sdr"
FAN_PRESENCE = "FAN{0}_prsnt"
PSU_PRESENCE = "PSU{0}_state"
# Use this for older firmware
# PSU_PRESENCE="PSU{0}_prsnt"
ipmi_sdr_list = ""
# Dump sensor registers
def ipmi_sensor_dump():
status = 1
global ipmi_sdr_list
ipmi_cmd = IPMI_SENSOR_DATA
status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd)
if status:
logging.error('Failed to execute:' + ipmi_sdr_list)
sys.exit(0)
# Fetch a BMC register
def get_pmc_register(reg_name):
for item in ipmi_sdr_list.split("\n"):
if reg_name in item:
output = item.strip()
if not output:
print('\nFailed to fetch: ' + reg_name + ' sensor ')
sys.exit(0)
output = output.split('|')[1]
logging.basicConfig(level=logging.DEBUG)
return output
# Print the information for temperature sensors
def print_temperature_sensors():
print("\nOnboard Temperature Sensors:")
print ' PT_Left_temp: ',\
(get_pmc_register('PT_Left_temp'))
print ' PT_Mid_temp: ',\
(get_pmc_register('PT_Mid_temp'))
print ' PT_Right_temp: ',\
(get_pmc_register('PT_Right_temp'))
print ' Broadcom Temp: ',\
(get_pmc_register('TC_Near_temp'))
print ' Inlet Airflow Temp: ',\
(get_pmc_register('ILET_AF_temp'))
print ' CPU Temp: ',\
(get_pmc_register('CPU_Near_temp'))
print ' CPU Near Temp: ',\
(get_pmc_register('CPU_temp'))
print ' DRAM Temp: ',\
(get_pmc_register('DRAM1_temp'))
ipmi_sensor_dump()
print_temperature_sensors()
# Print the information for 1 Fan Tray
def print_fan_tray(tray):
Fan_Status = [' Normal', ' Abnormal']
Airflow_Direction = ['B2F', 'F2B']
print ' Fan Tray ' + str(tray) + ':'
if (tray == 1):
fan1_status = int(get_pmc_register('Fan1_Front_state'), 16)
fan2_status = int(get_pmc_register('Fan1_Rear_state'), 16)
print ' Fan1 Speed: ',\
get_pmc_register('FAN1_Front_rpm')
print ' Fan2 Speed: ',\
get_pmc_register('FAN1_Rear_rpm')
print ' Fan1 State: ',\
Fan_Status[fan1_status]
print ' Fan2 State: ',\
Fan_Status[fan2_status]
elif (tray == 2):
fan1_status = int(get_pmc_register('Fan2_Front_state'), 16)
fan2_status = int(get_pmc_register('Fan2_Rear_state'), 16)
print ' Fan1 Speed: ',\
get_pmc_register('FAN2_Front_rpm')
print ' Fan2 Speed: ',\
get_pmc_register('FAN2_Rear_rpm')
print ' Fan1 State: ',\
Fan_Status[fan1_status]
print ' Fan2 State: ',\
Fan_Status[fan2_status]
elif (tray == 3):
fan1_status = int(get_pmc_register('Fan3_Front_state'), 16)
fan2_status = int(get_pmc_register('Fan3_Rear_state'), 16)
print ' Fan1 Speed: ',\
get_pmc_register('FAN3_Front_rpm')
print ' Fan2 Speed: ',\
get_pmc_register('FAN3_Rear_rpm')
print ' Fan1 State: ',\
Fan_Status[fan1_status]
print ' Fan2 State: ',\
Fan_Status[fan2_status]
elif (tray == 4):
fan1_status = int(get_pmc_register('Fan4_Front_state'), 16)
fan2_status = int(get_pmc_register('Fan4_Rear_state'), 16)
print ' Fan1 Speed: ',\
get_pmc_register('FAN4_Front_rpm')
print ' Fan2 Speed: ',\
get_pmc_register('FAN4_Rear_rpm')
print ' Fan1 State: ',\
Fan_Status[fan1_status]
print ' Fan2 State: ',\
Fan_Status[fan2_status]
print('\nFan Trays:')
for tray in range(1, Z9264F_MAX_FAN_TRAYS + 1):
fan_presence = FAN_PRESENCE.format(tray)
if (get_pmc_register(fan_presence)):
print_fan_tray(tray)
else:
print '\n Fan Tray ' + str(tray + 1) + ': Not present'
# Print the information for PSU1, PSU2
def print_psu(psu):
Psu_Type = ['Normal', 'Mismatch']
Psu_Input_Type = ['AC', 'DC']
PSU_STATUS_TYPE_BIT = 4
PSU_STATUS_INPUT_TYPE_BIT = 1
PSU_FAN_PRESENT_BIT = 2
PSU_FAN_STATUS_BIT = 1
PSU_FAN_AIR_FLOW_BIT = 0
Psu_Fan_Presence = ['Present', 'Absent']
Psu_Fan_Status = ['Normal', 'Abnormal']
Psu_Fan_Airflow = ['B2F', 'F2B']
# print ' Input: ', Psu_Input_Type[psu_input_type]
# print ' Type: ', Psu_Type[psu_type]
# PSU FAN details
if (psu == 1):
# psu1_fan_status = int(get_pmc_register('PSU1_status'),16)
print ' PSU1:'
print ' FAN Temperature: ',\
get_pmc_register('PSU1_temp')
print ' FAN AirFlow Temperature: ',\
get_pmc_register('PSU1_AF_temp')
print ' FAN RPM: ',\
get_pmc_register('PSU1_rpm')
# print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status]
# PSU input & output monitors
print ' Input Voltage: ',\
get_pmc_register('PSU1_In_volt')
print ' Output Voltage: ',\
get_pmc_register('PSU1_Out_volt')
print ' Input Power: ',\
get_pmc_register('PSU1_In_watt')
print ' Output Power: ',\
get_pmc_register('PSU1_Out_watt')
print ' Input Current: ',\
get_pmc_register('PSU1_In_amp')
print ' Output Current: ',\
get_pmc_register('PSU1_Out_amp')
else:
# psu2_fan_status = int(get_pmc_register('PSU1_status'),16)
print ' PSU2:'
print ' FAN Temperature: ',\
get_pmc_register('PSU2_temp')
print ' FAN AirFlow Temperature: ',\
get_pmc_register('PSU2_AF_temp')
print ' FAN RPM: ',\
get_pmc_register('PSU2_rpm')
# print ' FAN Status: ', Psu_Fan_Status[psu2_fan_status]
# PSU input & output monitors
print ' Input Voltage: ',\
get_pmc_register('PSU2_In_volt')
print ' Output Voltage: ',\
get_pmc_register('PSU2_Out_volt')
print ' Input Power: ',\
get_pmc_register('PSU2_In_watt')
print ' Output Power: ',\
get_pmc_register('PSU2_Out_watt')
print ' Input Current: ',\
get_pmc_register('PSU2_In_amp')
print ' Output Current: ',\
get_pmc_register('PSU2_Out_amp')
print('\nPSUs:')
for psu in range(1, Z9264F_MAX_PSUS + 1):
psu_presence = PSU_PRESENCE.format(psu)
if (get_pmc_register(psu_presence)):
print_psu(psu)
else:
print '\n PSU ', psu, 'Not present'
print '\n Total Power: ',\
get_pmc_register('PSU_Total_watt')

View File

@ -0,0 +1,8 @@
#!/bin/bash
docker exec -i pmon sensors "$@"
docker exec -i pmon /usr/bin/platform_sensors.py "$@"
#To probe sensors not part of lm-sensors
#if [ -r /usr/local/bin/platform_sensors.py ]; then
# python /usr/local/bin/platform_sensors.py
#fi

View File

@ -0,0 +1,125 @@
#!/bin/bash
init_devnum() {
found=0
for devnum in 0 1; do
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
# iSMT adapter can be at either dffd0000 or dfff0000
if [[ $devname == 'SMBus iSMT adapter at '* ]]; then
found=1
break
fi
done
[ $found -eq 0 ] && echo "cannot find iSMT" && exit 1
}
# Attach/Detach syseeprom on CPU board
sys_eeprom() {
case $1 in
"new_device") echo 24c02 0x53 > /sys/bus/i2c/devices/i2c-0/$1
;;
"delete_device") echo 0x53 > /sys/bus/i2c/devices/i2c-0/$1
;;
*) echo "z9264f_platform: sys_eeprom : invalid command !"
;;
esac
}
#Attach/Detach the MUX connecting all QSFPs
switch_board_qsfp_mux() {
case $1 in
"new_device")
for ((i=74;i<=77;i++));
do
echo "Attaching PCA9548 @ $i"
echo pca9548 0x$i > /sys/bus/i2c/devices/i2c-604/$1
sleep 2
done
for ((i=74;i<=77;i++));
do
echo "Attaching PCA9548 @ $i"
echo pca9548 0x$i > /sys/bus/i2c/devices/i2c-603/$1
sleep 2
done
;;
"delete_device")
for ((i=74;i<=77;i++));
do
echo "Detaching PCA9548 @ $i"
echo 0x$i > /sys/bus/i2c/devices/i2c-604/$1
sleep 2
done
for ((i=74;i<=77;i++));
do
echo "Detaching PCA9548 @ $i"
echo 0x$i > /sys/bus/i2c/devices/i2c-603/$1
sleep 2
done
;;
*) echo "z9264f_platform: switch_board_qsfp_mux: invalid command !"
;;
esac
sleep 2
}
#Attach/Detach 64 instances of EEPROM driver QSFP ports
#eeprom can dump data using below command
switch_board_qsfp() {
case $1 in
"new_device")
for ((i=2;i<=65;i++));
do
echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
"delete_device")
for ((i=2;i<=65;i++));
do
echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
*) echo "z9264f_platform: switch_board_qsfp: invalid command !"
;;
esac
}
#Modsel 64 ports to applicable QSFP type modules
#This enables the adapter to respond for i2c commands
switch_board_modsel() {
resource="/sys/bus/pci/devices/0000:04:00.0/resource0"
for ((i=1;i<=64;i++));
do
port_addr=$( 16384 + ((i - 1) * 16))
hex=$( printf "0x%x" $port_addr )
python /bin/pcisysfs.py --set --offset $hex --val 0x41 --res $resource > /dev/null 2>&1
done
}
init_devnum
if [ "$1" == "init" ]; then
depmod -a
modprobe i2c-dev
modprobe i2c-mux-pca954x force_deselect_on_exit=1
modprobe i2c_ocores
modprobe dell_z9264f_fpga_ocores
sys_eeprom "new_device"
switch_board_qsfp_mux "new_device"
switch_board_qsfp "new_device"
switch_board_modsel
elif [ "$1" == "deinit" ]; then
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
switch_board_qsfp_mux "delete_device"
modprobe -r i2c-mux-pca954x
modprobe -r i2c-dev
else
echo "z9264f_platform : Invalid option !"
fi

@ -1 +0,0 @@
Subproject commit 6c4da534410c037892ad0338d1c930b5b9b1493b

View File

@ -0,0 +1,50 @@
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
# Kernel Module Compile Results
*.mod*
*.cmd
*.o.d
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# Debian packaging
*.debhelper.log
*.postinst.debhelper
*.postrm.debhelper
*.prerm.debhelper
*.substvars

View File

@ -0,0 +1,15 @@
Copyright (C) 2016 Microsoft, Inc
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

View File

@ -0,0 +1,7 @@
# This file describes the maintainers for sonic-platform-modules-s6000
# See the SONiC project governance document for more information
Name = "Shuotian Cheng"
Email = "shuche@microsoft.com"
Github = stcheng
Mailinglist = sonicproject@googlegroups.com

View File

@ -0,0 +1,2 @@
# sonic-platform-modules-s6000
Device drivers for support of Dell S6000 for the SONiC project

View File

@ -0,0 +1,5 @@
platform-modules-s6000 (1.0) unstable; urgency=low
* Initial release
-- Shuotian Cheng <shuche@microsoft.com> Mon, 11 Nov 2015 11:11:11 -0800

View File

@ -0,0 +1 @@
8

View File

@ -0,0 +1,12 @@
Source: platform-modules-s6000
Section: main
Priority: extra
Maintainer: Shuotian Cheng <shuche@microsoft.com>
Build-Depends: debhelper (>= 8.0.0), bzip2
Standards-Version: 3.9.3
Package: platform-modules-s6000
Architecture: amd64
Depends: linux-image-4.9.0-5-amd64
Description: kernel modules for platform devices such as fan, led, sfp

View File

@ -0,0 +1,16 @@
Provides linux sysfs interface to Dell S6000 platform hardware peripherals
Copyright (C) 2016 Microsoft
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

View File

@ -0,0 +1,99 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: setup-board
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup S6000 board.
### END INIT INFO
add_i2c_devices() {
echo 24c02 0x50 > /sys/class/i2c-adapter/i2c-1/new_device
echo 24c02 0x51 > /sys/class/i2c-adapter/i2c-1/new_device
echo dni_dps460 0x58 > /sys/class/i2c-adapter/i2c-1/new_device
echo dni_dps460 0x59 > /sys/class/i2c-adapter/i2c-1/new_device
echo jc42 0x18 > /sys/class/i2c-adapter/i2c-10/new_device
echo emc1403 0x4d > /sys/class/i2c-adapter/i2c-10/new_device
echo spd 0x50 > /sys/class/i2c-adapter/i2c-10/new_device
echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-10/new_device
echo max6620 0x29 > /sys/class/i2c-adapter/i2c-11/new_device
echo max6620 0x2a > /sys/class/i2c-adapter/i2c-11/new_device
echo ltc4215 0x40 > /sys/class/i2c-adapter/i2c-11/new_device
echo ltc4215 0x42 > /sys/class/i2c-adapter/i2c-11/new_device
echo tmp75 0x4c > /sys/class/i2c-adapter/i2c-11/new_device
echo tmp75 0x4d > /sys/class/i2c-adapter/i2c-11/new_device
echo tmp75 0x4e > /sys/class/i2c-adapter/i2c-11/new_device
echo 24c02 0x51 > /sys/class/i2c-adapter/i2c-11/new_device
echo 24c02 0x52 > /sys/class/i2c-adapter/i2c-11/new_device
echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-11/new_device
for i in `seq 0 31`; do
echo sff8436 0x50 > /sys/class/i2c-adapter/i2c-$((20+i))/new_device
done
}
remove_i2c_devices() {
echo 0x50 > /sys/class/i2c-adapter/i2c-1/delete_device
echo 0x51 > /sys/class/i2c-adapter/i2c-1/delete_device
echo 0x58 > /sys/class/i2c-adapter/i2c-1/delete_device
echo 0x59 > /sys/class/i2c-adapter/i2c-1/delete_device
echo 0x18 > /sys/class/i2c-adapter/i2c-10/delete_device
echo 0x4d > /sys/class/i2c-adapter/i2c-10/delete_device
echo 0x50 > /sys/class/i2c-adapter/i2c-10/delete_device
echo 0x53 > /sys/class/i2c-adapter/i2c-10/delete_device
echo 0x29 > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x2a > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x40 > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x42 > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x4c > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x4d > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x4e > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x51 > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x52 > /sys/class/i2c-adapter/i2c-11/delete_device
echo 0x53 > /sys/class/i2c-adapter/i2c-11/delete_device
for i in `seq 0 31`; do
echo 0x50 > /sys/class/i2c-adapter/i2c-$((20+i))/delete_device
done
}
case "$1" in
start)
echo -n "Setting up board... "
depmod -a
modprobe i2c_mux_gpio
modprobe dell_s6000_platform
add_i2c_devices
/usr/local/bin/set-fan-speed 15000
/usr/local/bin/reset-qsfp
echo "done."
;;
stop)
echo "done."
remove_i2c_devices
rmmod dell_s6000_platform
rmmod i2c_mux_gpio
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/platform-modules-s6000.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1 @@
systemd/platform-modules-s6000.service lib/systemd/system

View File

@ -0,0 +1,32 @@
#!/usr/bin/make -f
export INSTALL_MOD_DIR:=extra
PACKAGE_NAME := platform-modules-s6000
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MODULE_SRC := $(shell pwd)/modules
SCRIPT_SRC := $(shell pwd)/scripts
%:
dh $@ --with=systemd
override_dh_auto_build:
make -C $(KERNEL_SRC)/build M=$(MODULE_SRC)
override_dh_auto_install:
dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR)
cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR)
dh_installdirs -p$(PACKAGE_NAME) usr/local/bin
cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin
override_dh_usrlocal:
override_dh_pysupport:
override_dh_clean:
dh_clean
rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd
rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order
rm -rf $(MODULE_SRC)/.tmp_versions

View File

@ -0,0 +1 @@
obj-m := dell_s6000_platform.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
#!/bin/bash
# Usage:
# Reset QSFP manually by writing 1/0 to QSFP reset pin
QSFP_RESET=/sys/bus/platform/devices/dell-s6000-cpld.0/qsfp_reset
logger -t platform-modules "Reset QSFP modules"
# Retry three times
for i in `seq 1 3`
do
if [ -w $QSFP_RESET ]; then
echo 0x00000000 > $QSFP_RESET
# Sleep 1 second to reset QSFP
sleep 1
echo 0xffffffff > $QSFP_RESET
exit 0
fi
# Sleep for 3 seconds to wait for device tree to be ready
sleep 3
done
logger -p user.error -t platform-modules "Failed to reset QSFP modules!"
exit 1

View File

@ -0,0 +1,58 @@
#!/bin/bash
# Usage:
# Set all fans speed to $1
usage() {
echo "This script must be run with super-user privilege."
echo "Warning! Wrongly set fan speed may result in physical damage to the device."
echo ""
echo "usage: set-fan-speed speed_in_rpm"
echo "example: set-fan-speed 15000"
}
if [ $# -ne 1 ]; then
usage
exit 1
fi
PSU_FAN1=/sys/class/i2c-adapter/i2c-1/1-0058/fan1_target
PSU_FAN2=/sys/class/i2c-adapter/i2c-1/1-0059/fan1_target
# Three fan trays with each contains two separate fans
# fan1-fan4 fan2-fan5 fan3-fan6
FAN1=/sys/class/i2c-adapter/i2c-11/11-0029/fan1_target
FAN2=/sys/class/i2c-adapter/i2c-11/11-0029/fan2_target
FAN3=/sys/class/i2c-adapter/i2c-11/11-0029/fan3_target
FAN4=/sys/class/i2c-adapter/i2c-11/11-0029/fan4_target
FAN5=/sys/class/i2c-adapter/i2c-11/11-002a/fan1_target
FAN6=/sys/class/i2c-adapter/i2c-11/11-002a/fan2_target
speed=$1
logger -t platform-modules "Trying to set fan speed to $speed"
# Retry three times
for i in `seq 1 3`
do
if [ -w $FAN1 -o -w $FAN2 -o -w $FAN3 ]; then
# set default psu fan speed
echo $speed > $PSU_FAN1
echo $speed > $PSU_FAN2
# set default fan speed
echo $speed > $FAN1
echo $speed > $FAN2
echo $speed > $FAN3
echo $speed > $FAN4
echo $speed > $FAN5
echo $speed > $FAN6
logger -t platform-modules "Fan speed is set to $speed"
exit 0
fi
# Sleep for 3 seconds to wait for device tree to be ready
sleep 3
done
logger -p user.error -t platform-modules "Failed to set fan speed!"
exit 1

View File

@ -0,0 +1,13 @@
[Unit]
Description=Dell S6000 Platform modules
After=local-fs.target
Before=pmon.service
[Service]
Type=oneshot
ExecStart=-/etc/init.d/platform-modules-s6000 start
ExecStop=-/etc/init.d/platform-modules-s6000 stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target