[platform/delta]: Add a new supported platform, Delta-agc032 (#4602)

* [platform]: Add a new supported platform, Delta-agc032

Switch Vendor: Delta
Switch SKU: Delta-agc032
CPU: BROADWELL-DE
ASIC Vendor: Broadcom
Switch ASIC: Tomahawk3, BCM56980
Port Configuration: 32x400G + 2x10G

- What I did
Add a new Delta platform Delta-agc032.

- How I did it
Add files by following SONiC Porting Guide.

- How to verify it
1. decode-syseeprom
2. sensors
3. psuutil
4. sfputil
5. show interface status
6. bcmcmd

Signed-off-by: zoe-kuan <ZOE.KUAN@deltaww.com>
This commit is contained in:
zoe-kuan 2020-05-28 00:33:02 +08:00 committed by GitHub
parent a406fdb57c
commit fa809c86dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 6747 additions and 2 deletions

View File

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

View File

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

View File

@ -0,0 +1,280 @@
#########################################
## cfg for AGC032
#########################################
pbmp_xport_xe=0x8000f8000fc000f8000f8000f8000fc000f8001e
ccm_dma_enable=0
ccmdma_intr_enable=0
ctr_evict_enable=0
mem_cache_enable=0
parity_correction=0
parity_enable=0
phy_enable=0
phy_null=1
pll_bypass=1
init_all_modules=0
################################################################################
# Pipe 0
portmap_1=1:400
portmap_2=9:400
portmap_3=17:400
portmap_4=25:400
#loopback port
portmap_19=259:10
################################################################################
# Pipe 1
portmap_20=33:400
portmap_21=41:400
portmap_22=49:400
portmap_23=57:400
#management port
portmap_38=257:10
#loopback port
portmap_39=260:10
################################################################################
# Pipe 2
portmap_40=65:400
portmap_41=73:400
portmap_42=81:400
portmap_43=89:400
#loopback port
portmap_59=261:10
################################################################################
# Pipe 3
portmap_60=97:400
portmap_61=105:400
portmap_62=113:400
portmap_63=121:400
#loopback port
portmap_79=262:10
################################################################################
# Pipe 4
portmap_80=129:400
portmap_81=137:400
portmap_82=145:400
portmap_83=153:400
#loopback port
portmap_99=263:10
################################################################################
# Pipe 5
portmap_100=161:400
portmap_101=169:400
portmap_102=177:400
portmap_103=185:400
#management port
portmap_118=258:10
#loopback port
portmap_119=264:10
################################################################################
# Pipe 6
portmap_120=193:400
portmap_121=201:400
portmap_122=209:400
portmap_123=217:400
#loopback port
portmap_139=265:10
################################################################################
# Pipe 7
portmap_140=225:400
portmap_141=233:400
portmap_142=241:400
portmap_143=249:400
#loopback port
portmap_159=266:10
################################################################################
dport_map_enable=1
dport_map_port_1=3
dport_map_port_2=4
dport_map_port_3=1
dport_map_port_4=2
dport_map_port_20=7
dport_map_port_21=8
dport_map_port_22=5
dport_map_port_23=6
dport_map_port_40=11
dport_map_port_41=12
dport_map_port_42=9
dport_map_port_43=10
dport_map_port_60=15
dport_map_port_61=16
dport_map_port_62=13
dport_map_port_63=14
dport_map_port_80=17
dport_map_port_81=18
dport_map_port_82=19
dport_map_port_83=20
dport_map_port_100=21
dport_map_port_101=22
dport_map_port_102=23
dport_map_port_103=24
dport_map_port_120=25
dport_map_port_121=26
dport_map_port_122=27
dport_map_port_123=28
dport_map_port_140=29
dport_map_port_141=30
dport_map_port_142=31
dport_map_port_143=32
dport_map_port_38=33
dport_map_port_118=34
################################################################################
# tx_lane map
phy_chain_tx_lane_map_physical{1.0}=0x14762350
phy_chain_tx_lane_map_physical{9.0}=0x36104527
phy_chain_tx_lane_map_physical{17.0}=0x17053624
phy_chain_tx_lane_map_physical{25.0}=0x57314602
phy_chain_tx_lane_map_physical{33.0}=0x46302517
phy_chain_tx_lane_map_physical{41.0}=0x76203514
phy_chain_tx_lane_map_physical{49.0}=0x26143507
phy_chain_tx_lane_map_physical{57.0}=0x74236510
phy_chain_tx_lane_map_physical{65.0}=0x75021436
phy_chain_tx_lane_map_physical{73.0}=0x67210435
phy_chain_tx_lane_map_physical{81.0}=0x26143507
phy_chain_tx_lane_map_physical{89.0}=0x75436120
phy_chain_tx_lane_map_physical{97.0}=0x54621730
phy_chain_tx_lane_map_physical{105.0}=0x64310725
phy_chain_tx_lane_map_physical{113.0}=0x07352416
phy_chain_tx_lane_map_physical{121.0}=0x13762054
phy_chain_tx_lane_map_physical{129.0}=0x13427506
phy_chain_tx_lane_map_physical{137.0}=0x54307612
phy_chain_tx_lane_map_physical{145.0}=0x76103524
phy_chain_tx_lane_map_physical{153.0}=0x67103425
phy_chain_tx_lane_map_physical{161.0}=0x15402637
phy_chain_tx_lane_map_physical{169.0}=0x76135420
phy_chain_tx_lane_map_physical{177.0}=0x67052431
phy_chain_tx_lane_map_physical{185.0}=0x57103624
phy_chain_tx_lane_map_physical{193.0}=0x15402637
phy_chain_tx_lane_map_physical{201.0}=0x54137620
phy_chain_tx_lane_map_physical{209.0}=0x56012734
phy_chain_tx_lane_map_physical{217.0}=0x57301426
phy_chain_tx_lane_map_physical{225.0}=0x07352641
phy_chain_tx_lane_map_physical{233.0}=0x57236401
phy_chain_tx_lane_map_physical{241.0}=0x16543720
phy_chain_tx_lane_map_physical{249.0}=0x50273416
# rx_lane_map
phy_chain_rx_lane_map_physical{1.0}=0x42305761
phy_chain_rx_lane_map_physical{9.0}=0x13605472
phy_chain_rx_lane_map_physical{17.0}=0x41730652
phy_chain_rx_lane_map_physical{25.0}=0x71206534
phy_chain_rx_lane_map_physical{33.0}=0x62170453
phy_chain_rx_lane_map_physical{41.0}=0x27641305
phy_chain_rx_lane_map_physical{49.0}=0x53604271
phy_chain_rx_lane_map_physical{57.0}=0x31607425
phy_chain_rx_lane_map_physical{65.0}=0x47612350
phy_chain_rx_lane_map_physical{73.0}=0x23471605
phy_chain_rx_lane_map_physical{81.0}=0x43710265
phy_chain_rx_lane_map_physical{89.0}=0x31706425
phy_chain_rx_lane_map_physical{97.0}=0x60317425
phy_chain_rx_lane_map_physical{105.0}=0x40635172
phy_chain_rx_lane_map_physical{113.0}=0x20573146
phy_chain_rx_lane_map_physical{121.0}=0x51204637
phy_chain_rx_lane_map_physical{129.0}=0x34102567
phy_chain_rx_lane_map_physical{137.0}=0x70143526
phy_chain_rx_lane_map_physical{145.0}=0x20316574
phy_chain_rx_lane_map_physical{153.0}=0x13572046
phy_chain_rx_lane_map_physical{161.0}=0x61253074
phy_chain_rx_lane_map_physical{169.0}=0x61043527
phy_chain_rx_lane_map_physical{177.0}=0x43617250
phy_chain_rx_lane_map_physical{185.0}=0x31067425
phy_chain_rx_lane_map_physical{193.0}=0x35162074
phy_chain_rx_lane_map_physical{201.0}=0x30146527
phy_chain_rx_lane_map_physical{209.0}=0x73506241
phy_chain_rx_lane_map_physical{217.0}=0x73241605
phy_chain_rx_lane_map_physical{225.0}=0x26573140
phy_chain_rx_lane_map_physical{233.0}=0x46213750
phy_chain_rx_lane_map_physical{241.0}=0x13650274
phy_chain_rx_lane_map_physical{249.0}=0x42305167
# tx polarity
serdes_core_tx_polarity_flip_physical{1}=0x5d
serdes_core_tx_polarity_flip_physical{9}=0x9c
serdes_core_tx_polarity_flip_physical{17}=0x72
serdes_core_tx_polarity_flip_physical{25}=0xad
serdes_core_tx_polarity_flip_physical{33}=0x38
serdes_core_tx_polarity_flip_physical{41}=0x86
serdes_core_tx_polarity_flip_physical{49}=0xaf
serdes_core_tx_polarity_flip_physical{57}=0xc6
serdes_core_tx_polarity_flip_physical{65}=0x70
serdes_core_tx_polarity_flip_physical{73}=0xc7
serdes_core_tx_polarity_flip_physical{81}=0xae
serdes_core_tx_polarity_flip_physical{89}=0xe0
serdes_core_tx_polarity_flip_physical{97}=0xf1
serdes_core_tx_polarity_flip_physical{105}=0x0c
serdes_core_tx_polarity_flip_physical{113}=0xc8
serdes_core_tx_polarity_flip_physical{121}=0x3f
serdes_core_tx_polarity_flip_physical{129}=0x8b
serdes_core_tx_polarity_flip_physical{137}=0x77
serdes_core_tx_polarity_flip_physical{145}=0x39
serdes_core_tx_polarity_flip_physical{153}=0xa5
serdes_core_tx_polarity_flip_physical{161}=0xd8
serdes_core_tx_polarity_flip_physical{169}=0x8b
serdes_core_tx_polarity_flip_physical{177}=0x29
serdes_core_tx_polarity_flip_physical{185}=0x30
serdes_core_tx_polarity_flip_physical{193}=0xf8
serdes_core_tx_polarity_flip_physical{201}=0x8a
serdes_core_tx_polarity_flip_physical{209}=0xb8
serdes_core_tx_polarity_flip_physical{217}=0x08
serdes_core_tx_polarity_flip_physical{225}=0xb3
serdes_core_tx_polarity_flip_physical{233}=0x62
serdes_core_tx_polarity_flip_physical{241}=0x70
serdes_core_tx_polarity_flip_physical{249}=0xd2
# rx poplarity
serdes_core_rx_polarity_flip_physical{1}=0x18
serdes_core_rx_polarity_flip_physical{9}=0xa0
serdes_core_rx_polarity_flip_physical{17}=0x9c
serdes_core_rx_polarity_flip_physical{25}=0x47
serdes_core_rx_polarity_flip_physical{33}=0xf5
serdes_core_rx_polarity_flip_physical{41}=0x38
serdes_core_rx_polarity_flip_physical{49}=0x87
serdes_core_rx_polarity_flip_physical{57}=0x1a
serdes_core_rx_polarity_flip_physical{65}=0xf0
serdes_core_rx_polarity_flip_physical{73}=0x68
serdes_core_rx_polarity_flip_physical{81}=0x96
serdes_core_rx_polarity_flip_physical{89}=0x32
serdes_core_rx_polarity_flip_physical{97}=0x5a
serdes_core_rx_polarity_flip_physical{105}=0xb4
serdes_core_rx_polarity_flip_physical{113}=0xe1
serdes_core_rx_polarity_flip_physical{121}=0x4a
serdes_core_rx_polarity_flip_physical{129}=0xf3
serdes_core_rx_polarity_flip_physical{137}=0xc3
serdes_core_rx_polarity_flip_physical{145}=0x12
serdes_core_rx_polarity_flip_physical{153}=0xb4
serdes_core_rx_polarity_flip_physical{161}=0xf0
serdes_core_rx_polarity_flip_physical{169}=0xa7
serdes_core_rx_polarity_flip_physical{177}=0xe1
serdes_core_rx_polarity_flip_physical{185}=0x90
serdes_core_rx_polarity_flip_physical{193}=0x0a
serdes_core_rx_polarity_flip_physical{201}=0x4e
serdes_core_rx_polarity_flip_physical{209}=0x5a
serdes_core_rx_polarity_flip_physical{217}=0x98
serdes_core_rx_polarity_flip_physical{225}=0x2f
serdes_core_rx_polarity_flip_physical{233}=0x5b
serdes_core_rx_polarity_flip_physical{241}=0xf4
serdes_core_rx_polarity_flip_physical{249}=0x1d
################################################################################
#firmware load, use fast load
load_firmware=0x2
core_clock_frequency=1325
dpr_clock_frequency=1000
device_clock_frequency=1325
port_flex_enable=1
################################################################################
serdes_tx_taps_cd=pam4:-36:118:0:8:6:0

Binary file not shown.

View File

@ -0,0 +1 @@
Delta-agc032 t1

View File

@ -0,0 +1,10 @@
INTERVAL=10
DEVPATH=hwmon1=/sys/bus/i2c/devices
DEVNAME=hwmon1=emc2305
FCTEMPS= hwmon1/i2c-4/4-004f/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004a/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004d/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004b/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-0049/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004e/hwmon/hwmon*/temp1_input
FCFANS=hwmon1/4-004c/fan1_input hwmon1/4-004c/fan2_input hwmon1/4-004c/fan3_input hwmon1/4-004c/fan4_input hwmon1/4-004c/fan5_input hwmon1/4-002d/fan1_input hwmon1/4-002d/fan2_input hwmon1/4-002d/fan3_input hwmon1/4-002d/fan4_input hwmon1/4-002d/fan5_input hwmon1/4-002e/fan1_input hwmon1/4-002e/fan2_input
MINTEMP=20
MAXTEMP=60
MINSTART=75
MINSTOP=22

View File

@ -0,0 +1,295 @@
#!/bin/bash
#
# Simple script implementing a temperature dependent fan speed control
# Supported Linux kernel versions: 2.6.5 and later
#
# Version 0.70
#
# Usage: fancontrol [CONFIGFILE]
#
# Dependencies:
# bash, egrep, sed, cut, sleep, readlink, lm_sensors :)
#
# Please send any questions, comments or success stories to
# marius.reiner@hdev.de
# Thanks!
#
# For configuration instructions and warnings please see fancontrol.txt, which
# can be found in the doc/ directory or at the website mentioned above.
#
#
# Copyright 2003 Marius Reiner <marius.reiner@hdev.de>
# Copyright (C) 2007-2009 Jean Delvare <khali@linux-fr.org>
#
# 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.
#
#
PIDFILE="/var/run/fancontrol.pid"
#DEBUG=1
MAX=255
function LoadConfig
{
local fcvcount fcv
echo "Loading configuration from $1 ..."
if [ ! -r "$1" ]
then
echo "Error: Can't read configuration file" >&2
exit 1
fi
# grep configuration from file
INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'`
DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'`
DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'`
FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'`
MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'`
MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'`
MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'`
MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'`
HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g')
FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g')
FCMINTEMP=$MINTEMP
FCMAXTEMP=$MAXTEMP
FCMINSTART=$MINSTART
FCMINSTOP=$MINSTOP
AFCTEMP_1_LOWER=(00 39 36 41 46 55)
AFCTEMP_1_UPPER=(39 39 44 49 54 150)
AFCTEMP_2_LOWER=(00 61 65 69 73 82)
AFCTEMP_2_UPPER=(63 67 71 75 79 150)
AFCTEMP_3_LOWER=(00 51 55 59 63 71)
AFCTEMP_3_UPPER=(53 57 61 65 69 150)
AFCTEMP_4_LOWER=(00 46 50 54 58 65)
AFCTEMP_4_UPPER=(45 52 56 60 64 150)
AFCTEMP_5_LOWER=(00 46 50 54 58 65)
AFCTEMP_5_UPPER=(45 52 56 60 64 150)
FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'`
# Check whether all mandatory settings are set
if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]]
then
echo "Some mandatory settings missing, please check your config file!" >&2
exit 1
fi
if [ "$INTERVAL" -le 0 ]
then
echo "Error in configuration file:" >&2
echo "INTERVAL must be at least 1" >&2
exit 1
fi
# write settings to arrays for easier use and print them
echo
echo "Common settings:"
temp_string=$FCTEMPS
let fcvcount=0
for fcv in $FCTEMPS
do
fcvcount=$((fcvcount+1))
AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount )
AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' )
AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' )
AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} )
AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 ))
done
fan_string=$FCFANS
fcvcount=0
zero=0
for fcv in $FCFANS
do
fcvcount=$((fcvcount+1))
AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount )
AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' )
AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' )
AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}" | sed 's/$/_percentage/g')
AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} )
if [ "${AFCFAN[$fcvcount]}" == 960 ]
then
AFCFAN[$fcvcount]=$zero
fi
done
}
# Check that all referenced sysfs files exist
function CheckFiles
{
local outdated=0 fcvcount tsen fan
if [ $outdated -eq 1 ]
then
echo >&2
echo "At least one referenced file is missing. Either some required kernel" >&2
echo "modules haven't been loaded, or your configuration file is outdated." >&2
echo "In the latter case, you should run pwmconfig again." >&2
fi
return $outdated
}
#LoadConfig $1
if [ -f "$1" ]
then
LoadConfig $1
else
LoadConfig /etc/fancontrol
fi
# Detect path to sensors
if [ ! -d $DIR ]
then
echo $0: 'No sensors found! (did you load the necessary modules?)' >&2
exit 1
fi
cd $DIR
# Check for configuration change
if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ]
then
echo "Configuration is too old, please run pwmconfig again" >&2
exit 1
fi
if [ "$DIR" = "/" -a -n "$DEVPATH" ]
then
echo "Unneeded DEVPATH with absolute device paths" >&2
exit 1
fi
CheckFiles || exit 1
if [ -f "$PIDFILE" ]
then
echo "File $PIDFILE exists, is fancontrol already running?" >&2
exit 1
fi
echo $$ > "$PIDFILE"
# main function
function UpdateThermalSensors
{
fcvcount=0
for fcv in $FCTEMPS
do
fcvcount=$((fcvcount+1))
AFCTEMP[$fcvcount]=$( cat ${AFCTEMP_PATH[$fcvcount]} )
AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 ))
done
}
function UpdateThermalLevel
{
AFCTEMP_NUM=$((6-${AFCTEMP_LEVEL[$i]}))
AFCTEMP_UPPER_BUF=AFCTEMP_"$i"_UPPER["$AFCTEMP_NUM"]
AFCTEMP_LOWER_BUF=AFCTEMP_"$i"_LOWER["$AFCTEMP_NUM"]
AFCTEMP_UPPER=${!AFCTEMP_UPPER_BUF}
AFCTEMP_LOWER=${!AFCTEMP_LOWER_BUF}
if (( ("${AFCTEMP[$i]}" <= "$AFCTEMP_UPPER") && ("${AFCTEMP[$i]}" >= "$AFCTEMP_LOWER") )) ; then
FLAG=2
elif (( "${AFCTEMP[$i]}" > "$AFCTEMP_UPPER" )); then
AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} - 1))
FLAG=1
elif (( "${AFCTEMP[$i]}" < "$AFCTEMP_LOWER" )); then
AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} + 1))
FLAG=1
else
AFCTEMP_LEVEL[$i]=1
FLAG=2
fi
}
function UpdateFanSpeeds
{
#echo "num tmp lev F L H"
#Update level
for i in 1 2 3 4 5
do
#echo "----------------------"
FLAG=0
#FLAG=0 : initial flag
#FLAG=1 : update level
#FLAG=2 : final level
while [ $FLAG -ne 2 ]
do
UpdateThermalLevel
#echo " $i ${AFCTEMP[$i]} ${AFCTEMP_LEVEL[$i]} $FLAG $AFCTEMP_LOWER $AFCTEMP_UPPER "
done
done
min=${AFCTEMP_LEVEL[0]}
for j in "${AFCTEMP_LEVEL[@]}"; do
(( j < min )) && min=$j
done
if (($min == 1 || $min == 2)); then
FAN_PERCENTAGE=100
elif (($min == 3)); then
FAN_PERCENTAGE=80
elif (($min == 4)); then
FAN_PERCENTAGE=60
elif (($min == 5)); then
FAN_PERCENTAGE=50
elif (($min == 6)); then
FAN_PERCENTAGE=40
else
FAN_PERCENTAGE=100
fi
echo "The lowest level of thermal sensors: $min "
echo "Trying to set fan speed to $FAN_PERCENTAGE %"
#Set speed to fan1~fan10
let fcvcount=0
for fcv in $FCFANS
do
fcvcount=$(( fcvcount + 1 ))
echo $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]}
AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} )
if [ "${AFCFAN[$fcvcount]}" == 960 ]
then
AFCFAN[$fcvcount]=$zero
fi
echo "FAN fan$fcvcount = ${AFCFAN[$fcvcount]} (rpm)"
done
FAN_ON_PSU_PERCENTAGE=$FAN_PERCENTAGE
#Set speed to PSU_FAN1
echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/1-0058/fan1_set_percentage'
echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/1-0058/fan1_input' ) (rpm)"
#Set speed to PSU_FAN2
echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/2-0058/fan1_set_percentage'
echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/2-0058/fan1_input' ) (rpm)"
rm -f "$PIDFILE"
}
# main loop calling the main function at specified intervals
AFCTEMP_LEVEL=(9 4 4 4 4 4) #inttial level
while true
do
UpdateThermalSensors
UpdateFanSpeeds
echo "Sleep $INTERVAL seconds ..."
echo
# Sleep while still handling signals
sleep $INTERVAL &
wait $!
done

View File

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

View File

@ -0,0 +1,5 @@
led auto off
led stop
m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin
led auto on
led start

View File

@ -0,0 +1 @@
usemsi=1

View File

@ -0,0 +1,12 @@
#!/usr/bin/env python
try:
from sonic_eeprom import eeprom_tlvinfo
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0053/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,62 @@
import os.path
try:
from sonic_psu.psu_base import PsuBase
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
def __init__(self):
PsuBase.__init__(self)
self.psu_path = "/sys/bus/i2c/devices/{}-0058/"
self.psu_oper_status = "in1_input"
self.psu_oper_status2 = "in2_input"
self.psu_presence = "i2cget -y {} 0x50 0x00"
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
return 2
def get_psu_status(self, index):
if index is None:
return False
Base_bus_number = 0
status = 0
#index from 1, psu attribute bus from 40
try:
with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status:
if int(power_status.read()) == 0 :
return False
else:
with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status2, 'r') as power_status2:
if int(power_status2.read()) == 0 :
return False
else:
status = 1
except IOError:
return False
return status == 1
def get_psu_presence(self, index):
if index is None:
return False
Base_bus_number = 0
status = 0
try:
p = os.popen(self.psu_presence.format(index + Base_bus_number)+ "> /dev/null 2>&1")
if p.readline() != None:
status = 1
p.close()
except IOError:
return False
return status == 1

View File

@ -0,0 +1,241 @@
# sfputil.py
#
# Platform-specific SFP transceiver interface for SONiC
#
try:
import time
from sonic_sfp.sfputilbase import SfpUtilBase
from sonic_sfp.sff8472 import sff8472InterfaceId
from sonic_sfp.sff8472 import sff8472InterfaceId
from sonic_sfp.sff8436 import sff8436InterfaceId
from sonic_sfp.sff8436 import sff8436Dom
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
PORT_START = 0
PORT_END = 33
PORTS_IN_BLOCK = 32
EEPROM_OFFSET = 1
CPLD_SWITCH = 0
_port_to_eeprom_mapping = {}
@property
def port_start(self):
return self.PORT_START
@property
def port_end(self):
return self.PORT_END
@property
def qsfp_ports(self):
return range(0, self.PORTS_IN_BLOCK)
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
def __init__(self):
eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom"
for x in range(0, self.port_end + 1):
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET)
SfpUtilBase.__init__(self)
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
# Retrieve file path of presence
port = (str(port_num + 1)).zfill(2)
# SWPLD2 for port 1~16, SWPLD3 for port 17~34
if port_num < 16:
present_path = "SWPLD2/qsfp_p{}_modprs".format(port)
elif port_num < self.PORTS_IN_BLOCK:
present_path = "SWPLD3/qsfp_p{}_modprs".format(port)
else:
present_path = "SWPLD3/sfp_p{}_modprs".format(str(port_num - self.PORTS_IN_BLOCK))
try:
with open("/sys/devices/platform/delta-agc032-swpld.0/" + present_path, 'r') as present:
if int(present.readline()) == 0:
return True
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
return False
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num >= self.PORTS_IN_BLOCK:
return False
# Retrieve file path of presence
port = (str(port_num + 1)).zfill(2)
# SWPLD2 for port 1~16, SWPLD3 for port 17~32
if port_num < 16:
lpmode_path = "SWPLD2/qsfp_p{}_lpmode".format(port)
else:
lpmode_path = "SWPLD3/qsfp_p{}_lpmode".format(port)
try:
with open("/sys/devices/platform/delta-agc032-swpld.0/" + lpmode_path, 'r') as lpmode:
if int(lpmode.readline()) == 1:
return True
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
return False
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self.port_start or port_num >= self.PORTS_IN_BLOCK:
return False
# Retrieve file path of presence
port = (str(port_num + 1)).zfill(2)
# SWPLD2 for port 1~16, SWPLD3 for port 17~32
if port_num < 16:
lpmode_path = "SWPLD2/qsfp_p{}_lpmode".format(port)
else:
lpmode_path = "SWPLD3/qsfp_p{}_lpmode".format(port)
try:
file = open("/sys/devices/platform/delta-agc032-swpld.0/" + lpmode_path, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
file.seek(0)
if lpmode is True:
# "1" for lpmode on
file.write('1')
else:
# "0" for lpmode off
file.write('0')
file.close()
return True
def reset(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num >= self.PORTS_IN_BLOCK:
return False
# Retrieve file path of presence
port = (str(port_num + 1)).zfill(2)
# SWPLD2 for port 1~16, SWPLD3 for port 17~32
if port_num < 16:
reset_path = "SWPLD2/qsfp_p{}_rst".format(port)
else:
reset_path = "SWPLD3/qsfp_p{}_rst".format(port)
try:
file = open("/sys/devices/platform/delta-agc032-swpld.0/" + reset_path, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
file.seek(0)
file.write('0')
file.close()
# Sleep 1 second to allow it to settle
time.sleep(1)
# Flip the bit back high and write back to the register to take port out of reset
try:
file = open("/sys/devices/platform/delta-agc032-swpld.0/" + reset_path, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
file.seek(0)
file.write('1')
file.close()
return True
def get_eeprom_dict(self, port_num):
sfp_data = {}
try:
file = open("/sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel", 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
# Switch CPLD to FRONT-PORT EEPROM MUX
file.seek(0)
file.write('3')
file.close()
eeprom_ifraw = self.get_eeprom_raw(port_num)
eeprom_domraw = self.get_eeprom_dom_raw(port_num)
try:
file = open("/sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel", 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
# Switch CPLD to FRONT-PORT EEPROM MUX
file.seek(0)
file.write('1')
file.close()
if eeprom_ifraw is None:
return None
if port_num in self.osfp_ports:
sfpi_obj = inf8628InterfaceId(eeprom_ifraw)
if sfpi_obj is not None:
sfp_data['interface'] = sfpi_obj.get_data_pretty()
return sfp_data
elif port_num in self.qsfp_ports:
sfpi_obj = sff8436InterfaceId(eeprom_ifraw)
if sfpi_obj is not None:
sfp_data['interface'] = sfpi_obj.get_data_pretty()
# For Qsfp's the dom data is part of eeprom_if_raw
# The first 128 bytes
sfpd_obj = sff8436Dom(eeprom_ifraw)
if sfpd_obj is not None:
sfp_data['dom'] = sfpd_obj.get_data_pretty()
return sfp_data
else:
sfpi_obj = sff8472InterfaceId(eeprom_ifraw)
if sfpi_obj is not None:
sfp_data['interface'] = sfpi_obj.get_data_pretty()
cal_type = sfpi_obj.get_calibration_type()
if eeprom_domraw is not None:
sfpd_obj = sff8472Dom(eeprom_domraw, cal_type)
if sfpd_obj is not None:
sfp_data['dom'] = sfpd_obj.get_data_pretty()
return sfp_data
def get_transceiver_change_event(self):
"""
TODO: This function need to be implemented
when decide to support monitoring SFP(Xcvrd)
on this platform.
"""
raise NotImplementedError

View File

@ -0,0 +1,6 @@
{
"skip_thermalctld": true,
"skip_syseepromd": true,
"skip_fancontrol": true,
"skip_xcvrd": true
}

View File

@ -0,0 +1,47 @@
# libsensors configuration file for DCS-7060CX-32S
# ------------------------------------------------
#
bus "i2c-4" "i2c-0-mux (chan_id 3)"
bus "i2c-5" "i2c-0-mux (chan_id 4)"
chip "tmp75-i2c-4-4f"
label temp1 "Wind thermal sensor"
set temp1_max 65
set temp1_max_hyst 60
chip "tmp75-i2c-5-4d"
label temp1 "CPU below side thermal sensor"
set temp1_max 60
set temp1_max_hyst 55
chip "tmp75-i2c-5-49"
label temp1 "Surroundings thermal sensor1"
set temp1_max 65
set temp1_max_hyst 60
chip "tmp75-i2c-5-4a"
label temp1 "Surroundings thermal sensor2"
set temp1_max 65
set temp1_max_hyst 60
chip "tmp75-i2c-5-4b"
label temp1 "Surroundings thermal sensor3"
set temp1_max 65
set temp1_max_hyst 60
chip "tmp75-i2c-5-4d"
label temp1 "Surroundings thermal sensor4"
set temp1_max 65
set temp1_max_hyst 60
chip "emc2305-i2c-4-4c"
label fan1 "FANTRAY 1 FRONT"
label fan2 "FANTRAY 2 REAR"
label fan3 "FANTRAY 3 FRONT"
label fan4 "FANTRAY 4 REAR"
label fan5 "FANTRAY 5 FRONT"
chip "emc2305-i2c-4-2d"
label fan1 "FANTRAY 1 REAR"
label fan2 "FANTRAY 2 FRONT"
label fan3 "FANTRAY 3 REAR"
label fan4 "FANTRAY 4 FRONT"
label fan5 "FANTRAY 5 REAR"
chip "emc2302-i2c-4-2e"
label fan1 "FANTRAY 1 FRONT"
label fan2 "FANTRAY 2 REAR"

View File

@ -58,7 +58,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(DELTA_AG9032V2A_PLATFORM_MODULE) \
$(JUNIPER_QFX5210_PLATFORM_MODULE) \
$(CEL_SILVERSTONE_PLATFORM_MODULE) \
$(JUNIPER_QFX5200_PLATFORM_MODULE)
$(JUNIPER_QFX5200_PLATFORM_MODULE) \
$(DELTA_AGC032_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))

View File

@ -5,12 +5,14 @@ DELTA_AG9064_PLATFORM_MODULE_VERSION = 1.1
DELTA_AG5648_PLATFORM_MODULE_VERSION = 1.1
DELTA_ET6248BRB_PLATFORM_MODULE_VERSION = 1.1
DELTA_AG9032V2A_PLATFORM_MODULE_VERSION = 1.1
DELTA_AGC032_PLATFORM_MODULE_VERSION = 1.1
export DELTA_AG9032V1_PLATFORM_MODULE_VERSION
export DELTA_AG9064_PLATFORM_MODULE_VERSION
export DELTA_AG5648_PLATFORM_MODULE_VERSION
export DELTA_ET6248BRB_PLATFORM_MODULE_VERSION
export DELTA_AG9032V2A_PLATFORM_MODULE_VERSION
export DELTA_AGC032_PLATFORM_MODULE_VERSION
DELTA_AG9032V1_PLATFORM_MODULE = platform-modules-ag9032v1_$(DELTA_AG9032V1_PLATFORM_MODULE_VERSION)_amd64.deb
$(DELTA_AG9032V1_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-delta
@ -34,3 +36,8 @@ DELTA_AG9032V2A_PLATFORM_MODULE = platform-modules-ag9032v2a_$(DELTA_AG9032V2A_P
$(DELTA_AG9032V2A_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9032v2a-r0
$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AG9032V2A_PLATFORM_MODULE)))
DELTA_AGC032_PLATFORM_MODULE = platform-modules-agc032_$(DELTA_AGC032_PLATFORM_MODULE_VERSION)_amd64.deb
$(DELTA_AGC032_PLATFORM_MODULE)_PLATFORM = x86_64-delta_agc032-r0
$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AGC032_PLATFORM_MODULE)))
SONIC_STRETCH_DEBS += $(DELTA_AG9032V1_PLATFORM_MODULE)

View File

@ -0,0 +1,13 @@
# /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 @@
obj-m := dni_agc032_psu.o dni_emc2305.o delta_agc032_platform.o delta_agc032_cpupld.o dni_emc2302.o delta_agc032_swpld.o delta_agc032_qsfp.o

View File

@ -0,0 +1,746 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#define CPUPLD_I2C_ADDR 0x31
enum cpld_type {
cpld,
};
struct platform_data {
int reg_addr;
struct i2c_client *client;
};
enum{
BUS0 = 0,
BUS1,
BUS2,
BUS3,
BUS4,
BUS5,
BUS6,
BUS7,
BUS8,
};
enum{
CPU_PCB_NUM = 0,
CPUPLD_VER_TYPE,
CPUPLD_VER,
BDXDE_PLAT_RST,
BDXDE_SLP3_STAT,
BDXDE_SLP4_STAT,
BDXDE_CPU_RST,
CPLD_DEBUG_MODE,
APWROK_STAT,
EDGE_PROCHOT_SIG_DIS,
PSU_THERMAL_STAT,
PR_THERMAL_STAT,
ME_DRIVE_SIG_EN,
CPU_THERMAL_STAT,
DDR_THERMAL_STAT,
SYS_THERMAL_STAT,
DEBUG_LED3_EN,
DEBUG_LED2_EN,
DEBUG_LED1_EN,
DEBUG_LED0_EN,
CPU_STANDBY_MODE,
CPLD_RST,
MB_POWER_STAT,
BIOS1_SPI_WP,
BIOS2_SPI_WP,
BIOS_MUX_SEL,
GBE_SPI_WP,
PCH_THERMTRIP_EN,
ID_EEPROM_EN,
CPU_I2C_MUX_EN,
CPU_I2C_MUX_SEL,
PSU_FAN_INTR,
WD_TIMER,
WD_EN,
WD_CLEAR_FLAG,
};
static unsigned char cpupld_reg_addr;
static ssize_t cpupld_reg_value_show(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
struct platform_data *pdata = dev->platform_data;
ret = i2c_smbus_read_byte_data(pdata[cpld].client, cpupld_reg_addr);
return scnprintf(buf, PAGE_SIZE, "0x%02x\n", ret);
}
static ssize_t cpupld_reg_value_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long data;
int err;
struct platform_data *pdata = dev->platform_data;
err = kstrtoul(buf, 0, &data);
if (err){
return err;
}
if (data > 0xff){
printk(KERN_ALERT "address out of range (0x00-0xFF)\n");
return count;
}
i2c_smbus_write_byte_data(pdata[cpld].client, cpupld_reg_addr, data);
return count;
}
static ssize_t cpupld_reg_addr_show(struct device *dev, struct device_attribute *devattr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "0x%02x\n", cpupld_reg_addr);
}
static ssize_t cpupld_reg_addr_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long data;
int err;
err = kstrtoul(buf, 0, &data);
if (err){
return err;
}
if (data > 0xff){
printk(KERN_ALERT "address out of range (0x00-0xFF)\n");
return count;
}
cpupld_reg_addr = data;
return count;
}
static ssize_t cpupld_data_show(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct platform_data *pdata = dev->platform_data;
unsigned int select = 0;
unsigned char offset = 0;
int mask = 0xFF;
int shift = 0;
int value = 0;
bool hex_fmt = 0;
char desc[256] = {0};
select = attr->index;
switch(select) {
case CPU_PCB_NUM:
offset = 0x0;
hex_fmt = 1;
scnprintf(desc, PAGE_SIZE, "\nCPU Borad PCB Number.\n");
break;
case CPUPLD_VER_TYPE:
offset = 0x1;
shift = 7;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\nCPUPLD Version Type.\n");
break;
case CPUPLD_VER:
offset = 0x1;
mask = 0x7F;
scnprintf(desc, PAGE_SIZE, "\nCPUPLD Version.\n");
break;
case BDXDE_PLAT_RST:
offset = 0x9;
shift = 4;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Platform Reset State\n“0” = Platform Not Reset State.\n");
break;
case BDXDE_SLP3_STAT:
offset = 0x9;
shift = 3;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = CPU at S3 State\n“0” = CPU Not at S3 State.\n");
break;
case BDXDE_SLP4_STAT:
offset = 0x9;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = CPU at S4Sstate\n“0” = CPU Not at S4 State.\n");
break;
case BDXDE_CPU_RST:
offset = 0x9;
shift = 1;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = CPU Not Reset State\n“0” = CPU Reset State.\n");
break;
case CPLD_DEBUG_MODE:
offset = 0x9;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\nCPLD Power Sequence\n“1” = Debug Mode\n“0” = Normal Mode.\n");
break;
case APWROK_STAT:
offset = 0xA;
shift = 1;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = APWROK Stable\n“0” = APWROK Unstable.\n");
break;
case EDGE_PROCHOT_SIG_DIS:
offset = 0xB;
shift = 5;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Power Supply Thermal Signal\n“0” = Enable Power Supply Thermal Signal.\n");
break;
case PSU_THERMAL_STAT:
offset = 0xB;
shift = 4;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Power Supply Normal Temperature\n“0” = Power Supply Over Temperature.\n");
break;
case PR_THERMAL_STAT:
offset = 0xB;
shift = 3;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Power Rail Normal Temperature\n“0” = Power Rail Over Temperature.\n");
break;
case ME_DRIVE_SIG_EN:
offset = 0xB;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable System Thermal Alarm to CPU\n“0” = System Thermal Alarm to CPU.\n");
break;
case CPU_THERMAL_STAT:
offset = 0xB;
shift = 1;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = CPU Disomic Normal Temperature\n“0” = CPU Disomic Over Temperatur.\n");
break;
case DDR_THERMAL_STAT:
offset = 0xB;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = DDR Normal Temperature\n“0” = DDR Over Temperature.\n");
break;
case SYS_THERMAL_STAT:
offset = 0xC;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = System Normal Temperature.\n“0” = System Over Temperature.\n");
break;
case DEBUG_LED3_EN:
offset = 0xD;
shift = 3;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED3\n“0” = Enable Debug LED3.\n");
break;
case DEBUG_LED2_EN:
offset = 0xD;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED2\n“0” = Enable Debug LED2.\n");
break;
case DEBUG_LED1_EN:
offset = 0xD;
shift = 1;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED1\n“0” = Enable Debug LED1.\n");
break;
case DEBUG_LED0_EN:
offset = 0xD;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED0\n“0” = Enable Debug LED0.\n");
break;
case CPU_STANDBY_MODE:
offset = 0x11;
shift = 3;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = CPU Power Stanby Not Ready\n“0” = CPU Power Stanby Ready.\n");
break;
case CPLD_RST:
offset = 0x11;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation\n“0” = CPLD Reset.\n");
break;
case MB_POWER_STAT:
offset = 0x12;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Power Rail Good\n“0” = Power Rail Failed.\n");
break;
case BIOS2_SPI_WP:
offset = 0x13;
shift = 3;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable BIOS2 SPI Write Protect\n“0” = Enable BIOS2 SPI Write Protect.\n");
break;
case BIOS1_SPI_WP:
offset = 0x13;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable BIOS1 SPI Write Protect\n“0” = Enable BIOS1 SPI Write Protect.\n");
break;
case BIOS_MUX_SEL:
offset = 0x13;
shift = 1;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Primary BIOS\n“0” = Backup BIOS.\n");
break;
case GBE_SPI_WP:
offset = 0x13;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable GBE SPI Write Protect\n“0” = Enable GBE SPI Write Protect.\n");
break;
case PCH_THERMTRIP_EN:
offset = 0x14;
shift = 4;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Thermal Trip Not Occured\n“0” = Thermal Trip Occured.\n");
break;
case ID_EEPROM_EN:
offset = 0x14;
shift = 3;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable ID EEPROM Write Protect\n“0” = Enable ID EEPROM Write Protect.\n");
break;
case CPU_I2C_MUX_EN:
offset = 0x14;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Enable CPU I2C Mux\n“0” = Disable CPU I2C Mux.\n");
break;
case CPU_I2C_MUX_SEL:
offset = 0x14;
shift = 0;
mask = 0x3;
scnprintf(desc, PAGE_SIZE, "\n“3” = Select MB Panel Port.\n“2” = Select MB SWPLD.\n“1” = Select MB Mux.\n“0” = Select ONIE EEPROM.\n");
break;
case PSU_FAN_INTR:
offset = 0x15;
shift = 1;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = PSU Fan Interrupt Occured\n“0” = PSU Fan Interrupt Not Occured.\n");
break;
case WD_TIMER:
offset = 0x1E;
shift = 3;
mask = 0x38;
scnprintf(desc, PAGE_SIZE, "\n“5” = Timer 60 sec.\n“4” = Timer 50 sec.\n“3” = Timer 40 sec.\n“2” = Timer 30 sec.\n“1” = Timer 20 sec.\n“0” = Timer 15 sec.\n");
break;
case WD_EN:
offset = 0x1E;
shift = 2;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Watchdog Function\n“0” = Enable Watchdog Function.\n");
break;
case WD_CLEAR_FLAG:
offset = 0x1E;
shift = 0;
mask = (1 << shift);
scnprintf(desc, PAGE_SIZE, "\n“1” = Watchdog Timer Flag Clear\n“0” = Watchdog Timer Flag Not Clear.\n");
break;
}
value = i2c_smbus_read_byte_data(pdata[cpld].client, offset);
value = (value & mask) >> shift;
if(hex_fmt) {
return scnprintf(buf, PAGE_SIZE, "0x%02x%s", value, desc);
} else {
return scnprintf(buf, PAGE_SIZE, "%d%s", value, desc);
}
}
static ssize_t cpupld_data_store(struct device *dev, struct device_attribute *dev_attr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct platform_data *pdata = dev->platform_data;
unsigned int select = 0;
unsigned char offset = 0;
int mask = 0xFF;
int shift = 0;
int value = 0;
int err = 0;
unsigned long data;
err = kstrtoul(buf, 0, &data);
if (err){
return err;
}
if (data > 0xff){
printk(KERN_ALERT "address out of range (0x00-0xFF)\n");
return count;
}
switch (attr->index) {
case DEBUG_LED3_EN:
offset = 0xD;
shift = 3;
mask = (1 << shift);
break;
case DEBUG_LED2_EN:
offset = 0xD;
shift = 2;
mask = (1 << shift);
break;
case DEBUG_LED1_EN:
offset = 0xD;
shift = 1;
mask = (1 << shift);
break;
case DEBUG_LED0_EN:
offset = 0xD;
shift = 0;
mask = (1 << shift);
break;
case CPLD_RST:
offset = 0x11;
shift = 0;
mask = (1 << shift);
break;
case MB_POWER_STAT:
offset = 0x12;
shift = 2;
mask = (1 << shift);
break;
case BIOS2_SPI_WP:
offset = 0x13;
shift = 3;
mask = (1 << shift);
break;
case BIOS1_SPI_WP:
offset = 0x13;
shift = 2;
mask = (1 << shift);
break;
case BIOS_MUX_SEL:
offset = 0x13;
shift = 1;
mask = (1 << shift);
break;
case GBE_SPI_WP:
offset = 0x13;
shift = 0;
mask = (1 << shift);
break;
case PCH_THERMTRIP_EN:
offset = 0x14;
shift = 4;
mask = (1 << shift);
break;
case ID_EEPROM_EN:
offset = 0x14;
shift = 3;
mask = (1 << shift);
break;
case CPU_I2C_MUX_EN:
offset = 0x14;
shift = 2;
mask = (1 << shift);
break;
case CPU_I2C_MUX_SEL:
offset = 0x14;
shift = 0;
mask = 0x3;
break;
case WD_TIMER:
offset = 0x1E;
shift = 3;
mask = 0x38;
break;
case WD_EN:
offset = 0x1E;
shift = 2;
mask = (1 << shift);
break;
case WD_CLEAR_FLAG:
offset = 0x1E;
shift = 0;
mask = (1 << shift);
break;
}
value = i2c_smbus_read_byte_data(pdata[cpld].client, offset);
data = (value & ~mask) | (data << shift);
i2c_smbus_write_byte_data(pdata[cpld].client, offset, data);
return count;
}
static DEVICE_ATTR(cpupld_reg_value, S_IRUGO | S_IWUSR, cpupld_reg_value_show, cpupld_reg_value_store);
static DEVICE_ATTR(cpupld_reg_addr, S_IRUGO | S_IWUSR, cpupld_reg_addr_show, cpupld_reg_addr_store);
/* offset 0x0 */
static SENSOR_DEVICE_ATTR(cpu_pcb_num, S_IRUGO, cpupld_data_show, NULL, CPU_PCB_NUM );
/* offset 0x1 */
static SENSOR_DEVICE_ATTR(cpupld_ver_type, S_IRUGO, cpupld_data_show, NULL, CPUPLD_VER_TYPE );
static SENSOR_DEVICE_ATTR(cpupld_ver, S_IRUGO, cpupld_data_show, NULL, CPUPLD_VER );
#if 0
/* offset 0x5 */
static SENSOR_DEVICE_ATTR(p1v2_vddq_en, S_IRUGO, cpupld_data_show, NULL, P1V2_VDDQ_EN );
static SENSOR_DEVICE_ATTR(p1v5_pch_en, S_IRUGO, cpupld_data_show, NULL, P1V5_PCH_EN );
static SENSOR_DEVICE_ATTR(p2v5_vpp_en, S_IRUGO, cpupld_data_show, NULL, P2V5_VPP_EN );
static SENSOR_DEVICE_ATTR(pvccin_en, S_IRUGO, cpupld_data_show, NULL, PVCCIN_EN );
static SENSOR_DEVICE_ATTR(pvccioin_en, S_IRUGO, cpupld_data_show, NULL, PVCCIOIN_EN );
static SENSOR_DEVICE_ATTR(pvcckrhv_en, S_IRUGO, cpupld_data_show, NULL, PVCCKRHV_EN );
static SENSOR_DEVICE_ATTR(pvccscfusesus_en, S_IRUGO, cpupld_data_show, NULL, PVCCSCFUSESUS_EN );
static SENSOR_DEVICE_ATTR(vr_p3v3_en, S_IRUGO, cpupld_data_show, NULL, VR_P3V3_EN );
/* offset 0x6 */
static SENSOR_DEVICE_ATTR(cpu_sys_power, S_IRUGO, cpupld_data_show, NULL, CPU_SYS_POWER );
static SENSOR_DEVICE_ATTR(p0v6_vtt_dimm_en, S_IRUGO, cpupld_data_show, NULL, P0V6_VTT_DIMM_EN );
static SENSOR_DEVICE_ATTR(p1v05_pch_en, S_IRUGO, cpupld_data_show, NULL, P1V05_PCH_EN );
/* offser 0x7 */
static SENSOR_DEVICE_ATTR(p1v5_pch_pwrgd, S_IRUGO, cpupld_data_show, NULL, P1V5_PCH_GOOD );
static SENSOR_DEVICE_ATTR(p2v5_vpp_pwrgd, S_IRUGO, cpupld_data_show, NULL, P2V5_VPP_GOOD );
static SENSOR_DEVICE_ATTR(pch_pwr_pwrgd, S_IRUGO, cpupld_data_show, NULL, PCH_PWR_GOOD );
static SENSOR_DEVICE_ATTR(pvccin_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCIN_GOOD );
static SENSOR_DEVICE_ATTR(pvccioin_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCIOIN_GOOD );
static SENSOR_DEVICE_ATTR(pvcckrhv_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCKRHV_GOOD );
static SENSOR_DEVICE_ATTR(pvccscfusesus_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCSCFUSESUS_GOOD );
static SENSOR_DEVICE_ATTR(vr_p3v3_pwrgd, S_IRUGO, cpupld_data_show, NULL, VR_P3V3_GOOD );
/* offset 0x8 */
static SENSOR_DEVICE_ATTR(bdxde_lan_pwrgd, S_IRUGO, cpupld_data_show, NULL, BDXDE_LAN_GOOD );
static SENSOR_DEVICE_ATTR(CPU0_pwrgd, S_IRUGO, cpupld_data_show, NULL, CPU0_GOOD );
static SENSOR_DEVICE_ATTR(p0v6_vtt_dimm_pwrgd, S_IRUGO, cpupld_data_show, NULL, P0V6_VTT_DIMM_GOOD );
static SENSOR_DEVICE_ATTR(p1v05_procio_pwrgd, S_IRUGO, cpupld_data_show, NULL, P1V05_PROCIO_GOOD );
static SENSOR_DEVICE_ATTR(p1v2_vddq_pwrgd, S_IRUGO, cpupld_data_show, NULL, P1V2_VDDQ_GOOD );
#endif
/* offset 0x9 */
static SENSOR_DEVICE_ATTR(bdxde_plat_rst, S_IRUGO, cpupld_data_show, NULL, BDXDE_PLAT_RST );
static SENSOR_DEVICE_ATTR(bdxde_slp3_stat, S_IRUGO, cpupld_data_show, NULL, BDXDE_SLP3_STAT );
static SENSOR_DEVICE_ATTR(bdxde_slp4_stat, S_IRUGO, cpupld_data_show, NULL, BDXDE_SLP4_STAT );
static SENSOR_DEVICE_ATTR(bdxde_cpu_rst, S_IRUGO, cpupld_data_show, NULL, BDXDE_CPU_RST );
static SENSOR_DEVICE_ATTR(cpld_debug_mode, S_IRUGO, cpupld_data_show, NULL, CPLD_DEBUG_MODE );
/* offset 0xA */
static SENSOR_DEVICE_ATTR(apwrok_stat, S_IRUGO, cpupld_data_show, NULL, APWROK_STAT );
//static SENSOR_DEVICE_ATTR(cpu_standby_mode, S_IRUGO, cpupld_data_show, NULL, CPU_STANDBY_MODE );
/* offset 0xB */
static SENSOR_DEVICE_ATTR(edge_prochot_sig_dis, S_IRUGO, cpupld_data_show, NULL, EDGE_PROCHOT_SIG_DIS );
static SENSOR_DEVICE_ATTR(psu_thermal_stat, S_IRUGO, cpupld_data_show, NULL, PSU_THERMAL_STAT );
static SENSOR_DEVICE_ATTR(pr_thermal_stat, S_IRUGO, cpupld_data_show, NULL, PR_THERMAL_STAT );
static SENSOR_DEVICE_ATTR(me_drv_sig_en, S_IRUGO, cpupld_data_show, NULL, ME_DRIVE_SIG_EN );
static SENSOR_DEVICE_ATTR(cpu_thermal_stat, S_IRUGO, cpupld_data_show, NULL, CPU_THERMAL_STAT );
static SENSOR_DEVICE_ATTR(ddr_thermal_stat, S_IRUGO, cpupld_data_show, NULL, DDR_THERMAL_STAT );
/* offset 0xC */
static SENSOR_DEVICE_ATTR(sys_thermal_stat, S_IRUGO, cpupld_data_show, NULL, SYS_THERMAL_STAT );
/* offset 0xD */
static SENSOR_DEVICE_ATTR(debug_led3_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED3_EN );
static SENSOR_DEVICE_ATTR(debug_led2_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED2_EN );
static SENSOR_DEVICE_ATTR(debug_led1_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED1_EN );
static SENSOR_DEVICE_ATTR(debug_led0_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED0_EN );
/* offset 0x11 */
static SENSOR_DEVICE_ATTR(cpu_standby_mode, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPU_STANDBY_MODE );
static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPLD_RST );
/* offset 0x12 */
static SENSOR_DEVICE_ATTR(mb_power_stat, S_IRUGO, cpupld_data_show, NULL, MB_POWER_STAT );
/* offset 0x13 */
static SENSOR_DEVICE_ATTR(bios1_spi_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, BIOS1_SPI_WP );
static SENSOR_DEVICE_ATTR(bios2_spi_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, BIOS2_SPI_WP );
static SENSOR_DEVICE_ATTR(bios_mux_sel, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, BIOS_MUX_SEL );
static SENSOR_DEVICE_ATTR(gbe_spi_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, GBE_SPI_WP );
/* offset 0x14 */
static SENSOR_DEVICE_ATTR(pch_thermtrip_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, PCH_THERMTRIP_EN );
static SENSOR_DEVICE_ATTR(id_eeprom_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, ID_EEPROM_EN );
static SENSOR_DEVICE_ATTR(cpu_i2c_mux_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPU_I2C_MUX_EN );
static SENSOR_DEVICE_ATTR(cpu_i2c_mux_sel, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPU_I2C_MUX_SEL );
/* offset 0x15 */
static SENSOR_DEVICE_ATTR(psu_fan_intr, S_IRUGO, cpupld_data_show, NULL, PSU_FAN_INTR );
/* offset 0x1E */
static SENSOR_DEVICE_ATTR(wd_timer, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, WD_TIMER );
static SENSOR_DEVICE_ATTR(wd_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, WD_EN );
static SENSOR_DEVICE_ATTR(wd_clear_flag, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, WD_CLEAR_FLAG );
static struct attribute *agc032_cpupld_attrs[] = {
&dev_attr_cpupld_reg_value.attr,
&dev_attr_cpupld_reg_addr.attr,
&sensor_dev_attr_cpu_pcb_num.dev_attr.attr,
&sensor_dev_attr_cpupld_ver_type.dev_attr.attr,
&sensor_dev_attr_cpupld_ver.dev_attr.attr,
&sensor_dev_attr_bdxde_plat_rst.dev_attr.attr,
&sensor_dev_attr_bdxde_slp3_stat.dev_attr.attr,
&sensor_dev_attr_bdxde_slp4_stat.dev_attr.attr,
&sensor_dev_attr_bdxde_cpu_rst.dev_attr.attr,
&sensor_dev_attr_cpld_debug_mode.dev_attr.attr,
&sensor_dev_attr_apwrok_stat.dev_attr.attr,
&sensor_dev_attr_edge_prochot_sig_dis.dev_attr.attr,
&sensor_dev_attr_psu_thermal_stat.dev_attr.attr,
&sensor_dev_attr_pr_thermal_stat.dev_attr.attr,
&sensor_dev_attr_me_drv_sig_en.dev_attr.attr,
&sensor_dev_attr_cpu_thermal_stat.dev_attr.attr,
&sensor_dev_attr_ddr_thermal_stat.dev_attr.attr,
&sensor_dev_attr_sys_thermal_stat.dev_attr.attr,
&sensor_dev_attr_debug_led3_en.dev_attr.attr,
&sensor_dev_attr_debug_led2_en.dev_attr.attr,
&sensor_dev_attr_debug_led1_en.dev_attr.attr,
&sensor_dev_attr_debug_led0_en.dev_attr.attr,
&sensor_dev_attr_cpu_standby_mode.dev_attr.attr,
&sensor_dev_attr_cpld_rst.dev_attr.attr,
&sensor_dev_attr_mb_power_stat.dev_attr.attr,
&sensor_dev_attr_bios1_spi_wp.dev_attr.attr,
&sensor_dev_attr_bios2_spi_wp.dev_attr.attr,
&sensor_dev_attr_bios_mux_sel.dev_attr.attr,
&sensor_dev_attr_gbe_spi_wp.dev_attr.attr,
&sensor_dev_attr_pch_thermtrip_en.dev_attr.attr,
&sensor_dev_attr_id_eeprom_wp.dev_attr.attr,
&sensor_dev_attr_cpu_i2c_mux_en.dev_attr.attr,
&sensor_dev_attr_cpu_i2c_mux_sel.dev_attr.attr,
&sensor_dev_attr_psu_fan_intr.dev_attr.attr,
&sensor_dev_attr_wd_timer.dev_attr.attr,
&sensor_dev_attr_wd_en.dev_attr.attr,
&sensor_dev_attr_wd_clear_flag.dev_attr.attr,
NULL,
};
static struct attribute_group agc032_cpupld_attr_group = {
.attrs = agc032_cpupld_attrs,
};
static int __init cpupld_probe(struct platform_device *pdev)
{
struct platform_data *pdata;
struct i2c_adapter *parent;
int rv;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "CPUPLD platform data not found\n");
return -ENODEV;
}
parent = i2c_get_adapter(BUS0);
if (!parent) {
printk(KERN_ERR "Parent adapter (%d) not found\n",BUS0);
return -ENODEV;
}
pdata[cpld].client = i2c_new_dummy(parent, pdata[cpld].reg_addr);
if (!pdata[cpld].client) {
printk(KERN_ERR "Fail to create dummy i2c client for addr %d\n", pdata[cpld].reg_addr);
goto error;
}
#if 0
/* set default cpu_i2c_mux 0x14 be 0x1 */
rv = i2c_smbus_write_byte_data(pdata[cpld].client, 0x14, 0x1);
if (rv < 0) {
printk(KERN_WARNING, "Error: Failed to set addr 0x14.\n");
goto error;
}
#endif
/* /sys/device/platform */
rv = sysfs_create_group(&pdev->dev.kobj, &agc032_cpupld_attr_group);
if (rv){
printk(KERN_ERR "Fail to create cpupld attribute group");
goto error;
}
return 0;
error:
i2c_unregister_device(pdata[cpld].client);
i2c_put_adapter(parent);
return -ENODEV;
}
static int __exit cpupld_remove(struct platform_device *pdev)
{
struct i2c_adapter *parent = NULL;
struct platform_data *pdata = pdev->dev.platform_data;
sysfs_remove_group(&pdev->dev.kobj, &agc032_cpupld_attr_group);
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
}
else {
if (pdata[cpld].client) {
if (!parent) {
parent = (pdata[cpld].client)->adapter;
}
i2c_unregister_device(pdata[cpld].client);
}
}
i2c_put_adapter(parent);
return 0;
}
static struct platform_driver cpupld_driver = {
.probe = cpupld_probe,
.remove = __exit_p(cpupld_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-cpupld",
},
};
static struct platform_data agc032_cpupld_platform_data[] = {
[cpld] = {
.reg_addr = CPUPLD_I2C_ADDR,
},
};
static void device_release(struct device *dev)
{
return;
}
static struct platform_device cpupld_agc032 = {
.name = "delta-agc032-cpupld",
.id = 0,
.dev = {
.platform_data = agc032_cpupld_platform_data,
.release = device_release
},
};
/* module initialization */
static int __init delta_agc032_cpupld_init(void)
{
int rc = 0;
printk(KERN_INFO "CPUPLD module initializating\n");
/* register CPUPLD driver */
rc = platform_driver_register(&cpupld_driver);
if (rc < 0) {
printk(KERN_ERR "Fail to register CPUPLD driver, rc = %d\n", rc);
goto error_register_driver;
}
/* register CPUPLD device */
rc = platform_device_register(&cpupld_agc032);
if (rc) {
printk(KERN_ERR "Fail to create cpupld device, rc = %d\n", rc);
goto error_register_device;
}
return 0;
error_register_device:
platform_driver_unregister(&cpupld_driver);
error_register_driver:
return rc;
}
static void __exit delta_agc032_cpupld_exit(void)
{
platform_device_unregister(&cpupld_agc032);
platform_driver_unregister(&cpupld_driver);
}
module_init(delta_agc032_cpupld_init);
module_exit(delta_agc032_cpupld_exit);
MODULE_DESCRIPTION("DNI agc032 CPLD Platform Support");
MODULE_AUTHOR("James Ke <James.ke@deltaww.com>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,299 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/version.h>
#include <linux/ctype.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/i2c/sff-8436.h>
#include <linux/platform_data/pca954x.h>
#include <linux/platform_data/i2c-mux-gpio.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#define agc032_i2c_device_num(c){ \
.name = "delta-agc032-i2c-device", \
.id = c, \
.dev = { \
.platform_data = &agc032_i2c_device_platform_data[c], \
.release = device_release, \
}, \
}
/* Define struct to get client of i2c_new_deivce at 0x70 */
struct i2c_client * i2c_client_9548;
enum{
BUS0 = 0,
BUS1,
BUS2,
BUS3,
BUS4,
BUS5,
BUS6,
BUS7,
BUS8,
};
struct i2c_device_platform_data {
int parent;
struct i2c_board_info info;
struct i2c_client *client;
};
/* pca9548 - add 8 bus */
static struct pca954x_platform_mode pca954x_mode[] = {
{ .adap_id = 1,
.deselect_on_exit = 1,
},
{ .adap_id = 2,
.deselect_on_exit = 1,
},
{ .adap_id = 3,
.deselect_on_exit = 1,
},
{ .adap_id = 4,
.deselect_on_exit = 1,
},
{ .adap_id = 5,
.deselect_on_exit = 1,
},
{ .adap_id = 6,
.deselect_on_exit = 1,
},
{ .adap_id = 7,
.deselect_on_exit = 1,
},
{ .adap_id = 8,
.deselect_on_exit = 1,
},
};
static struct pca954x_platform_data pca954x_data = {
.modes = pca954x_mode,
.num_modes = ARRAY_SIZE(pca954x_mode),
};
static struct i2c_board_info __initdata i2c_info_pca9548[] =
{
{
I2C_BOARD_INFO("pca9548", 0x70),
.platform_data = &pca954x_data,
},
};
static struct i2c_device_platform_data agc032_i2c_device_platform_data[] = {
{
/* psu 1 (0x58) */
.parent = 1,
.info = { .type = "dni_agc032_psu", .addr = 0x58, .platform_data = (void *) 0 },
.client = NULL,
},
{
/* psu 2 (0x58) */
.parent = 2,
.info = { .type = "dni_agc032_psu", .addr = 0x58, .platform_data = (void *) 1 },
.client = NULL,
},
{
/* FAN 1 Controller (0x2e) */
.parent = 4,
.info = { I2C_BOARD_INFO("emc2302", 0x2e) },
.client = NULL,
},
{
/* FAN 2 Controller (0x4c) */
.parent = 4,
.info = { I2C_BOARD_INFO("emc2305", 0x4c) },
.client = NULL,
},
{
/* FAN 3 Controller (0x2d) */
.parent = 4,
.info = { I2C_BOARD_INFO("emc2305", 0x2d) },
.client = NULL,
},
{
/* tmp75 (0x4f) */
.parent = 4,
.info = { I2C_BOARD_INFO("tmp75", 0x4f) },
.client = NULL,
},
{
/* tmp75 (0x49) */
.parent = 5,
.info = { I2C_BOARD_INFO("tmp75", 0x49) },
.client = NULL,
},
{
/* tmp75 (0x4a) */
.parent = 5,
.info = { I2C_BOARD_INFO("tmp75", 0x4a) },
.client = NULL,
},
{
/* tmp75 (0x4b) */
.parent = 5,
.info = { I2C_BOARD_INFO("tmp75", 0x4b) },
.client = NULL,
},
{
/* tmp75 (0x4d) */
.parent = 5,
.info = { I2C_BOARD_INFO("tmp75", 0x4d) },
.client = NULL,
},
{
/* tmp75 (0x4e) */
.parent = 5,
.info = { I2C_BOARD_INFO("tmp75", 0x4e) },
.client = NULL,
},
};
static void device_release(struct device *dev)
{
return;
}
static struct platform_device agc032_i2c_device[] = {
agc032_i2c_device_num(0),
agc032_i2c_device_num(1),
agc032_i2c_device_num(2),
agc032_i2c_device_num(3),
agc032_i2c_device_num(4),
agc032_i2c_device_num(5),
agc032_i2c_device_num(6),
agc032_i2c_device_num(7),
agc032_i2c_device_num(8),
agc032_i2c_device_num(9),
agc032_i2c_device_num(10),
};
static int __init i2c_device_probe(struct platform_device *pdev)
{
struct i2c_device_platform_data *pdata;
struct i2c_adapter *parent;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
return -ENODEV;
}
parent = i2c_get_adapter(pdata->parent);
if (!parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
pdata->parent);
return -ENODEV;
}
pdata->client = i2c_new_device(parent, &pdata->info);
if (!pdata->client) {
dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n",
pdata->info.type, pdata->parent);
return -ENODEV;
}
return 0;
}
static int __exit i2c_deivce_remove(struct platform_device *pdev)
{
struct i2c_adapter *parent;
struct i2c_device_platform_data *pdata;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
return -ENODEV;
}
if (pdata->client) {
parent = (pdata->client)->adapter;
i2c_unregister_device(pdata->client);
i2c_put_adapter(parent);
}
return 0;
}
static struct platform_driver i2c_device_driver = {
.probe = i2c_device_probe,
.remove = __exit_p(i2c_deivce_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-i2c-device",
}
};
static int __init delta_agc032_platform_init(void)
{
struct i2c_adapter *adapter;
struct cpld_platform_data *cpld_pdata;
int ret = 0;
int cnt = 0;
printk("agc032_platform module initialization\n");
adapter = i2c_get_adapter(BUS0);
// i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]);
i2c_put_adapter(adapter);
/* register the i2c devices */
ret = platform_driver_register(&i2c_device_driver);
if (ret) {
printk(KERN_WARNING "Fail to register i2c device driver\n");
goto error_i2c_device_driver;
}
for (cnt = 0; cnt < ARRAY_SIZE(agc032_i2c_device); cnt++)
{
ret = platform_device_register(&agc032_i2c_device[cnt]);
if (ret) {
printk(KERN_WARNING "Fail to create i2c device %d\n", cnt);
goto error_agc032_i2c_device;
}
}
return 0;
error_agc032_i2c_device:
for (; cnt >= 0; cnt--) {
platform_device_unregister(&agc032_i2c_device[cnt]);
}
platform_driver_unregister(&i2c_device_driver);
error_i2c_device_driver:
return ret;
}
static void __exit delta_agc032_platform_exit(void)
{
int i = 0;
for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device); i++ ) {
platform_device_unregister(&agc032_i2c_device[i]);
}
platform_driver_unregister(&i2c_device_driver);
// i2c_unregister_device(i2c_client_9548);
}
module_init(delta_agc032_platform_init);
module_exit(delta_agc032_platform_exit);
MODULE_DESCRIPTION("DNI agc032 Platform Support");
MODULE_AUTHOR("James Ke <james.ke@deltaww.com>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,819 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/version.h>
#include <linux/ctype.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/i2c/sff-8436.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/platform_data/pca954x.h>
#include <linux/platform_data/i2c-mux-gpio.h>
#define agc032_i2c_device1_num(c){ \
.name = "delta-agc032-i2c-pca9548-1", \
.id = c, \
.dev = { \
.platform_data = &agc032_i2c_device_pca9548_1_data[c], \
.release = device_release, \
}, \
}
#define agc032_i2c_device2_num(c){ \
.name = "delta-agc032-i2c-pca9548-2", \
.id = c, \
.dev = { \
.platform_data = &agc032_i2c_device_pca9548_2_data[c], \
.release = device_release, \
}, \
}
#define agc032_i2c_device3_num(c){ \
.name = "delta-agc032-i2c-pca9548-3", \
.id = c, \
.dev = { \
.platform_data = &agc032_i2c_device_pca9548_3_data[c], \
.release = device_release, \
}, \
}
#define agc032_i2c_device4_num(c){ \
.name = "delta-agc032-i2c-pca9548-4", \
.id = c, \
.dev = { \
.platform_data = &agc032_i2c_device_pca9548_4_data[c], \
.release = device_release, \
}, \
}
#define agc032_i2c_device5_num(c){ \
.name = "delta-agc032-i2c-pca9548-5", \
.id = c, \
.dev = { \
.platform_data = &agc032_i2c_device_pca9548_5_data[c], \
.release = device_release, \
}, \
}
/* Define struct to get client of i2c_new_deivce at 0x70, 0x71, 0x72, 0x73 */
struct i2c_client * i2c_client_9548_1;
struct i2c_client * i2c_client_9548_2;
struct i2c_client * i2c_client_9548_3;
struct i2c_client * i2c_client_9548_4;
struct i2c_client * i2c_client_9548_5;
enum{
BUS0 = 0,
BUS1,
BUS2,
BUS3,
BUS4,
BUS5,
BUS6,
BUS7,
BUS8,
};
struct i2c_device_platform_data {
int parent;
struct i2c_board_info info;
struct i2c_client *client;
};
/* pca9548-1 - add 8 bus */
static struct pca954x_platform_mode pca954x_mode[] = {
{ .adap_id = 1,
.deselect_on_exit = 1,
},
{ .adap_id = 2,
.deselect_on_exit = 1,
},
{ .adap_id = 3,
.deselect_on_exit = 1,
},
{ .adap_id = 4,
.deselect_on_exit = 1,
},
{ .adap_id = 5,
.deselect_on_exit = 1,
},
{ .adap_id = 6,
.deselect_on_exit = 1,
},
{ .adap_id = 7,
.deselect_on_exit = 1,
},
{ .adap_id = 8,
.deselect_on_exit = 1,
},
};
/* pca9548-2 - add 8 bus */
static struct pca954x_platform_mode pca954x_mode2[] = {
{ .adap_id = 9,
.deselect_on_exit = 1,
},
{ .adap_id = 10,
.deselect_on_exit = 1,
},
{ .adap_id = 11,
.deselect_on_exit = 1,
},
{ .adap_id = 12,
.deselect_on_exit = 1,
},
{ .adap_id = 13,
.deselect_on_exit = 1,
},
{ .adap_id = 14,
.deselect_on_exit = 1,
},
{ .adap_id = 15,
.deselect_on_exit = 1,
},
{ .adap_id = 16,
.deselect_on_exit = 1,
},
};
/* pca9548-3 - add 8 bus */
static struct pca954x_platform_mode pca954x_mode3[] = {
{ .adap_id = 17,
.deselect_on_exit = 1,
},
{ .adap_id = 18,
.deselect_on_exit = 1,
},
{ .adap_id = 19,
.deselect_on_exit = 1,
},
{ .adap_id = 20,
.deselect_on_exit = 1,
},
{ .adap_id = 21,
.deselect_on_exit = 1,
},
{ .adap_id = 22,
.deselect_on_exit = 1,
},
{ .adap_id = 23,
.deselect_on_exit = 1,
},
{ .adap_id = 24,
.deselect_on_exit = 1,
},
};
/* pca9548-4 - add 8 bus */
static struct pca954x_platform_mode pca954x_mode4[] = {
{ .adap_id = 25,
.deselect_on_exit = 1,
},
{ .adap_id = 26,
.deselect_on_exit = 1,
},
{ .adap_id = 27,
.deselect_on_exit = 1,
},
{ .adap_id = 28,
.deselect_on_exit = 1,
},
{ .adap_id = 29,
.deselect_on_exit = 1,
},
{ .adap_id = 30,
.deselect_on_exit = 1,
},
{ .adap_id = 31,
.deselect_on_exit = 1,
},
{ .adap_id = 32,
.deselect_on_exit = 1,
},
};
/* pca9548-5 - add 2 bus */
static struct pca954x_platform_mode pca954x_mode5[] = {
{ .adap_id = 33,
.deselect_on_exit = 1,
},
{ .adap_id = 34,
.deselect_on_exit = 1,
},
};
static struct pca954x_platform_data pca954x_data = {
.modes = pca954x_mode,
.num_modes = ARRAY_SIZE(pca954x_mode),
};
static struct pca954x_platform_data pca954x_data2 = {
.modes = pca954x_mode2,
.num_modes = ARRAY_SIZE(pca954x_mode2),
};
static struct pca954x_platform_data pca954x_data3 = {
.modes = pca954x_mode3,
.num_modes = ARRAY_SIZE(pca954x_mode3),
};
static struct pca954x_platform_data pca954x_data4 = {
.modes = pca954x_mode4,
.num_modes = ARRAY_SIZE(pca954x_mode4),
};
static struct pca954x_platform_data pca954x_data5 = {
.modes = pca954x_mode5,
.num_modes = ARRAY_SIZE(pca954x_mode5),
};
static struct i2c_board_info __initdata i2c_info_pca9548[] =
{
{
I2C_BOARD_INFO("pca9548", 0x70),
.platform_data = &pca954x_data,
},
{
I2C_BOARD_INFO("pca9548", 0x71),
.platform_data = &pca954x_data2,
},
{
I2C_BOARD_INFO("pca9548", 0x72),
.platform_data = &pca954x_data3,
},
{
I2C_BOARD_INFO("pca9548", 0x73),
.platform_data = &pca954x_data4,
},
{
I2C_BOARD_INFO("pca9548", 0x74),
.platform_data = &pca954x_data5,
},
};
static struct i2c_device_platform_data agc032_i2c_device_pca9548_1_data[] = {
{
// qsfp 1 (0x50)
.parent = 1,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 2 (0x50)
.parent = 2,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 3 (0x50)
.parent = 3,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 4 (0x50)
.parent = 4,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 5 (0x50)
.parent = 5,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 6 (0x50)
.parent = 6,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 7 (0x50)
.parent = 7,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 8 (0x50)
.parent = 8,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
};
static struct i2c_device_platform_data agc032_i2c_device_pca9548_2_data[] = {
{
// qsfp 9 (0x50)
.parent = 9,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 10 (0x50)
.parent = 10,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 11 (0x50)
.parent = 11,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 12 (0x50)
.parent = 12,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 13 (0x50)
.parent = 13,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 14 (0x50)
.parent = 14,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 15 (0x50)
.parent = 15,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 16 (0x50)
.parent = 16,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
};
static struct i2c_device_platform_data agc032_i2c_device_pca9548_3_data[] = {
{
// qsfp 17 (0x50)
.parent = 17,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 18 (0x50)
.parent = 18,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 19 (0x50)
.parent = 19,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 20 (0x50)
.parent = 20,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 21 (0x50)
.parent = 21,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 22 (0x50)
.parent = 22,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 23 (0x50)
.parent = 23,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 24 (0x50)
.parent = 24,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
};
static struct i2c_device_platform_data agc032_i2c_device_pca9548_4_data[] = {
{
// qsfp 25 (0x50)
.parent = 25,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 26 (0x50)
.parent = 26,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 27 (0x50)
.parent = 27,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 28 (0x50)
.parent = 28,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 29 (0x50)
.parent = 29,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 30 (0x50)
.parent = 30,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 31 (0x50)
.parent = 31,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 32 (0x50)
.parent = 32,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
};
static struct i2c_device_platform_data agc032_i2c_device_pca9548_5_data[] = {
{
// qsfp 33 (0x50)
.parent = 33,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
{
// qsfp 34 (0x50)
.parent = 34,
.info = { .type = "optoe1", .addr = 0x50 },
.client = NULL,
},
};
static void device_release(struct device *dev)
{
return;
}
static struct platform_device agc032_i2c_device1[] = {
agc032_i2c_device1_num(0),
agc032_i2c_device1_num(1),
agc032_i2c_device1_num(2),
agc032_i2c_device1_num(3),
agc032_i2c_device1_num(4),
agc032_i2c_device1_num(5),
agc032_i2c_device1_num(6),
agc032_i2c_device1_num(7),
};
static struct platform_device agc032_i2c_device2[] = {
agc032_i2c_device2_num(0),
agc032_i2c_device2_num(1),
agc032_i2c_device2_num(2),
agc032_i2c_device2_num(3),
agc032_i2c_device2_num(4),
agc032_i2c_device2_num(5),
agc032_i2c_device2_num(6),
agc032_i2c_device2_num(7),
};
static struct platform_device agc032_i2c_device3[] = {
agc032_i2c_device3_num(0),
agc032_i2c_device3_num(1),
agc032_i2c_device3_num(2),
agc032_i2c_device3_num(3),
agc032_i2c_device3_num(4),
agc032_i2c_device3_num(5),
agc032_i2c_device3_num(6),
agc032_i2c_device3_num(7),
};
static struct platform_device agc032_i2c_device4[] = {
agc032_i2c_device4_num(0),
agc032_i2c_device4_num(1),
agc032_i2c_device4_num(2),
agc032_i2c_device4_num(3),
agc032_i2c_device4_num(4),
agc032_i2c_device4_num(5),
agc032_i2c_device4_num(6),
agc032_i2c_device4_num(7),
};
static struct platform_device agc032_i2c_device5[] = {
agc032_i2c_device5_num(0),
agc032_i2c_device5_num(1),
};
static int __init i2c_device_probe(struct platform_device *pdev)
{
struct i2c_device_platform_data *pdata;
struct i2c_adapter *parent;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
return -ENODEV;
}
parent = i2c_get_adapter(pdata->parent);
if (!parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
pdata->parent);
return -ENODEV;
}
pdata->client = i2c_new_device(parent, &pdata->info);
if (!pdata->client) {
dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n",
pdata->info.type, pdata->parent);
return -ENODEV;
}
return 0;
}
static int __exit i2c_deivce_remove(struct platform_device *pdev)
{
struct i2c_adapter *parent;
struct i2c_device_platform_data *pdata;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
return -ENODEV;
}
if (pdata->client) {
parent = (pdata->client)->adapter;
i2c_unregister_device(pdata->client);
i2c_put_adapter(parent);
}
return 0;
}
static struct platform_driver i2c_device_pca9548_1_driver = {
.probe = i2c_device_probe,
.remove = __exit_p(i2c_deivce_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-i2c-pca9548-1",
}
};
static struct platform_driver i2c_device_pca9548_2_driver = {
.probe = i2c_device_probe,
.remove = __exit_p(i2c_deivce_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-i2c-pca9548-2",
}
};
static struct platform_driver i2c_device_pca9548_3_driver = {
.probe = i2c_device_probe,
.remove = __exit_p(i2c_deivce_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-i2c-pca9548-3",
}
};
static struct platform_driver i2c_device_pca9548_4_driver = {
.probe = i2c_device_probe,
.remove = __exit_p(i2c_deivce_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-i2c-pca9548-4",
}
};
static struct platform_driver i2c_device_pca9548_5_driver = {
.probe = i2c_device_probe,
.remove = __exit_p(i2c_deivce_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-agc032-i2c-pca9548-5",
}
};
static int __init delta_agc032_platform_init(void)
{
struct i2c_adapter *adapter;
int ret = 0;
int device1_cnt = 0;
int device2_cnt = 0;
int device3_cnt = 0;
int device4_cnt = 0;
int device5_cnt = 0;
printk("agc032_qsfp module initialization\n");
adapter = i2c_get_adapter(BUS0);
i2c_client_9548_1 = i2c_new_device(adapter, &i2c_info_pca9548[0]);
i2c_client_9548_2 = i2c_new_device(adapter, &i2c_info_pca9548[1]);
i2c_client_9548_3 = i2c_new_device(adapter, &i2c_info_pca9548[2]);
i2c_client_9548_4 = i2c_new_device(adapter, &i2c_info_pca9548[3]);
i2c_client_9548_5 = i2c_new_device(adapter, &i2c_info_pca9548[4]);
i2c_put_adapter(adapter);
/* pca9548-0x70 */
ret = platform_driver_register(&i2c_device_pca9548_1_driver);
if (ret) {
printk(KERN_WARNING "Fail to register i2c device driver\n");
goto error_i2c_device_pca9548_1_driver;
}
for (device1_cnt = 0; device1_cnt < ARRAY_SIZE(agc032_i2c_device1); device1_cnt++)
{
ret = platform_device_register(&agc032_i2c_device1[device1_cnt]);
if (ret) {
printk(KERN_WARNING "Fail to create i2c device %d\n", device1_cnt);
goto error_agc032_i2c_device;
}
}
/* pca9548-0x71 */
ret = platform_driver_register(&i2c_device_pca9548_2_driver);
if (ret) {
printk(KERN_WARNING "Fail to register i2c device driver\n");
goto error_i2c_device_pca9548_2_driver;
}
for (device2_cnt = 0; device2_cnt < ARRAY_SIZE(agc032_i2c_device2); device2_cnt++)
{
ret = platform_device_register(&agc032_i2c_device2[device2_cnt]);
if (ret) {
printk(KERN_WARNING "Fail to create i2c device %d\n", device2_cnt);
goto error_agc032_i2c_device2;
}
}
/* pca9548-0x72 */
ret = platform_driver_register(&i2c_device_pca9548_3_driver);
if (ret) {
printk(KERN_WARNING "Fail to register i2c device driver\n");
goto error_i2c_device_pca9548_3_driver;
}
for (device3_cnt = 0; device3_cnt < ARRAY_SIZE(agc032_i2c_device3); device3_cnt++)
{
ret = platform_device_register(&agc032_i2c_device3[device3_cnt]);
if (ret) {
printk(KERN_WARNING "Fail to create i2c device %d\n", device3_cnt);
goto error_agc032_i2c_device3;
}
}
/* pca9548-0x73 */
ret = platform_driver_register(&i2c_device_pca9548_4_driver);
if (ret) {
printk(KERN_WARNING "Fail to register i2c device driver\n");
goto error_i2c_device_pca9548_4_driver;
}
for (device4_cnt = 0; device4_cnt < ARRAY_SIZE(agc032_i2c_device4); device4_cnt++)
{
ret = platform_device_register(&agc032_i2c_device4[device4_cnt]);
if (ret) {
printk(KERN_WARNING "Fail to create i2c device %d\n", device4_cnt);
goto error_agc032_i2c_device4;
}
}
/* pca9548-0x74 */
ret = platform_driver_register(&i2c_device_pca9548_5_driver);
if (ret) {
printk(KERN_WARNING "Fail to register i2c device driver\n");
goto error_i2c_device_pca9548_5_driver;
}
for (device5_cnt = 0; device5_cnt < ARRAY_SIZE(agc032_i2c_device5); device5_cnt++)
{
ret = platform_device_register(&agc032_i2c_device5[device5_cnt]);
if (ret) {
printk(KERN_WARNING "Fail to create i2c device %d\n", device5_cnt);
goto error_agc032_i2c_device5;
}
}
return 0;
/* Error handling */
error_agc032_i2c_device5:
for (; device5_cnt >= 0; device5_cnt--) {
platform_device_unregister(&agc032_i2c_device5[device5_cnt]);
}
platform_driver_unregister(&i2c_device_pca9548_5_driver);
error_i2c_device_pca9548_5_driver:
error_agc032_i2c_device4:
for (; device4_cnt >= 0; device4_cnt--) {
platform_device_unregister(&agc032_i2c_device4[device4_cnt]);
}
platform_driver_unregister(&i2c_device_pca9548_4_driver);
error_i2c_device_pca9548_4_driver:
error_agc032_i2c_device3:
for (; device3_cnt >= 0; device3_cnt--) {
platform_device_unregister(&agc032_i2c_device3[device3_cnt]);
}
platform_driver_unregister(&i2c_device_pca9548_3_driver);
error_i2c_device_pca9548_3_driver:
error_agc032_i2c_device2:
for (; device2_cnt >= 0; device2_cnt--) {
platform_device_unregister(&agc032_i2c_device2[device2_cnt]);
}
platform_driver_unregister(&i2c_device_pca9548_2_driver);
error_i2c_device_pca9548_2_driver:
error_agc032_i2c_device:
for (; device1_cnt >= 0; device1_cnt--) {
platform_device_unregister(&agc032_i2c_device1[device1_cnt]);
}
platform_driver_unregister(&i2c_device_pca9548_1_driver);
error_i2c_device_pca9548_1_driver:
return ret;
}
static void __exit delta_agc032_platform_exit(void)
{
int i = 0;
// unregister pca9548-1 (0x70)
for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device1); i++ ) {
platform_device_unregister(&agc032_i2c_device1[i]);
}
platform_driver_unregister(&i2c_device_pca9548_1_driver);
i2c_unregister_device(i2c_client_9548_1);
// unregister pca9548-2 (0x71)
for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device2); i++ ) {
platform_device_unregister(&agc032_i2c_device2[i]);
}
platform_driver_unregister(&i2c_device_pca9548_2_driver);
i2c_unregister_device(i2c_client_9548_2);
// unregister pca9548-3 (0x72)
for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device3); i++ ) {
platform_device_unregister(&agc032_i2c_device3[i]);
}
platform_driver_unregister(&i2c_device_pca9548_3_driver);
i2c_unregister_device(i2c_client_9548_3);
// unregister pca9548-4 (0x73)
for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device4); i++ ) {
platform_device_unregister(&agc032_i2c_device4[i]);
}
platform_driver_unregister(&i2c_device_pca9548_4_driver);
i2c_unregister_device(i2c_client_9548_4);
// unregister pca9548-5 (0x74)
for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device5); i++ ) {
platform_device_unregister(&agc032_i2c_device5[i]);
}
platform_driver_unregister(&i2c_device_pca9548_5_driver);
i2c_unregister_device(i2c_client_9548_5);
}
module_init(delta_agc032_platform_init);
module_exit(delta_agc032_platform_exit);
MODULE_DESCRIPTION("Delta agc032 QSFP-DD eeprom Support");
MODULE_AUTHOR("Zoe Kuan <zoe.kuan@deltaww.com>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,549 @@
/*
* An hwmon driver for delta AGC032 PSU
* dps_1600ab_29_a.c - Support for DPS-1600AB-29 A Power Supply Module
*
* Copyright (C) 2016 Delta Network Technology Corporation
*
* DNI <DNIsales@delta.com.tw>
*
* Based on ym2651y.c
* Based on ad7414.c
*
* 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/i2c.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#define MAX_FAN_DUTY_CYCLE 100
#define SWPLD_REG 0x31
#define SWPLD_PSU_MUX_REG 0x21
#define SELECT_PSU1_EEPROM 0x00
#define SELECT_PSU2_EEPROM 0x20
u8 psu_member_data = 0x00;
/* Address scanned */
static const unsigned short normal_i2c[] = { 0x58, I2C_CLIENT_END };
/* This is additional data */
struct dps_1600ab_29_a_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid;
unsigned long last_updated; /* In jiffies */
/* Registers value */
u8 vout_mode;
u16 in1_input;
u16 in2_input;
u16 curr1_input;
u16 curr2_input;
u16 power1_input;
u16 power2_input;
u16 temp_input[2];
u8 fan_target;
u16 fan_duty_cycle_input[2];
u16 fan_speed_input[2];
u8 mfr_model[16];
u8 mfr_serial[16];
};
static int two_complement_to_int(u16 data, u8 valid_bit, int mask);
static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \
*dev_attr, const char *buf, size_t count);
static ssize_t for_linear_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf);
static ssize_t for_fan_target(struct device *dev, struct device_attribute \
*dev_attr, char *buf);
static ssize_t for_vout_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf);
static int dps_1600ab_29_a_read_byte(struct i2c_client *client, u8 reg);
static int dps_1600ab_29_a_read_word(struct i2c_client *client, u8 reg);
static int dps_1600ab_29_a_write_word(struct i2c_client *client, u8 reg, \
u16 value);
static int dps_1600ab_29_a_read_block(struct i2c_client *client, u8 command, \
u8 *data, int data_len);
static struct dps_1600ab_29_a_data *dps_1600ab_29_a_update_device( \
struct device *dev);
static ssize_t for_ascii(struct device *dev, struct device_attribute \
*dev_attr, char *buf);
static ssize_t set_w_member_data(struct device *dev, struct device_attribute \
*dev_att, const char *buf, size_t count);
static ssize_t for_r_member_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf);
enum dps_1600ab_29_a_sysfs_attributes {
PSU_V_IN,
PSU_V_OUT,
PSU_I_IN,
PSU_I_OUT,
PSU_P_IN,
PSU_P_OUT,
PSU_TEMP1_INPUT,
PSU_FAN1_FAULT,
PSU_FAN1_DUTY_CYCLE,
PSU_FAN1_SPEED,
PSU_MFR_MODEL,
PSU_MFR_SERIAL,
PSU_SELECT_MEMBER,
};
static ssize_t set_w_member_data(struct device *dev, struct device_attribute \
*dev_attr, const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
long data;
int error;
if (attr->index == PSU_SELECT_MEMBER) {
error = kstrtol(buf, 16, &data);
if (error)
return error;
if (SELECT_PSU1_EEPROM == data) {
psu_member_data = SELECT_PSU1_EEPROM;
} else if (SELECT_PSU2_EEPROM == data) {
psu_member_data = SELECT_PSU2_EEPROM;
} else {
return -EINVAL;
}
}
return count;
}
static ssize_t for_r_member_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
return sprintf(buf, "0x%02X\n", psu_member_data);
}
static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
{
u16 valid_data = data & mask;
bool is_negative = valid_data >> (valid_bit - 1);
return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
}
static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \
*dev_attr, const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct i2c_client *client = to_i2c_client(dev);
struct dps_1600ab_29_a_data *data = i2c_get_clientdata(client);
int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
long speed;
int error;
error = kstrtol(buf, 10, &speed);
if (error)
return error;
if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE)
return -EINVAL;
/* Select SWPLD PSU offset */
mutex_lock(&data->update_lock);
data->fan_duty_cycle_input[nr] = speed;
dps_1600ab_29_a_write_word(client, 0x3B + nr, data->fan_duty_cycle_input[nr]);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t for_linear_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev);
u16 value = 0;
int exponent, mantissa;
int multiplier = 1000;
switch (attr->index) {
case PSU_V_IN:
value = data->in1_input;
break;
case PSU_I_IN:
value = data->curr1_input;
break;
case PSU_I_OUT:
value = data->curr2_input;
break;
case PSU_P_IN:
value = data->power1_input;
multiplier = 1000*1000;
break;
case PSU_P_OUT:
value = data->power2_input;
multiplier = 1000*1000;
break;
case PSU_TEMP1_INPUT:
value = data->temp_input[0];
break;
case PSU_FAN1_DUTY_CYCLE:
multiplier = 1;
value = data->fan_duty_cycle_input[0];
break;
case PSU_FAN1_SPEED:
multiplier = 1;
value = data->fan_speed_input[0];
break;
default:
break;
}
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
return (exponent >= 0) ? sprintf(buf, "%d\n", \
(mantissa << exponent) * multiplier) : \
sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
}
static ssize_t for_fan_target(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev);
u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
return sprintf(buf, "%d\n", data->fan_target >> shift);
}
static ssize_t for_vout_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev);
int exponent, mantissa;
int multiplier = 1000;
exponent = two_complement_to_int(data->vout_mode, 5, 0x1f);
mantissa = data->in2_input;
return (exponent > 0) ? sprintf(buf, "%d\n", \
(mantissa * multiplier) / (1 << exponent)): \
sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
}
static ssize_t for_ascii(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev);
u8 *ptr = NULL;
if (!data->valid)
return 0;
switch (attr->index) {
case PSU_MFR_MODEL:
ptr = data->mfr_model + 1;
break;
case PSU_MFR_SERIAL:
ptr = data->mfr_serial + 1;
break;
default:
return 0;
}
return sprintf(buf, "%s\n", ptr);
}
static int dps_1600ab_29_a_read_byte(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
static int dps_1600ab_29_a_read_word(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_word_data(client, reg);
}
static int dps_1600ab_29_a_write_word(struct i2c_client *client, u8 reg, \
u16 value)
{
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_xfer(client->adapter, client->addr,
client->flags |= I2C_CLIENT_PEC,
I2C_SMBUS_WRITE, reg,
I2C_SMBUS_WORD_DATA, &data);
}
static int dps_1600ab_29_a_read_block(struct i2c_client *client, u8 command, \
u8 *data, int data_len)
{
int result = i2c_smbus_read_i2c_block_data(client, command, data_len,
data);
if (unlikely(result < 0))
goto abort;
if (unlikely(result != data_len)) {
result = -EIO;
goto abort;
}
result = 0;
abort:
return result;
}
struct reg_data_byte {
u8 reg;
u8 *value;
};
struct reg_data_word {
u8 reg;
u16 *value;
};
static struct dps_1600ab_29_a_data *dps_1600ab_29_a_update_device( \
struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct dps_1600ab_29_a_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
/* Select SWPLD PSU offset */
if (time_after(jiffies, data->last_updated)) {
int i, status;
u8 command;
struct reg_data_byte regs_byte[] = {
{0x20, &data->vout_mode},
{0x81, &data->fan_target}
};
struct reg_data_word regs_word[] = {
{0x88, &data->in1_input},
{0x8b, &data->in2_input},
{0x89, &data->curr1_input},
{0x8c, &data->curr2_input},
{0x96, &data->power2_input},
{0x97, &data->power1_input},
{0x8d, &(data->temp_input[0])},
{0x8e, &(data->temp_input[1])},
{0x3b, &(data->fan_duty_cycle_input[0])},
{0x90, &(data->fan_speed_input[0])},
};
dev_dbg(&client->dev, "start data update\n");
/* one milliseconds from now */
data->last_updated = jiffies + HZ / 1000;
for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
status = dps_1600ab_29_a_read_byte(client,
regs_byte[i].reg);
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_byte[i].reg, status);
*(regs_byte[i].value) = 0;
} else {
*(regs_byte[i].value) = status;
}
}
for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
status = dps_1600ab_29_a_read_word(client,
regs_word[i].reg);
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_word[i].reg, status);
*(regs_word[i].value) = 0;
} else {
*(regs_word[i].value) = status;
}
}
command = 0x9a; /* PSU mfr_model */
//data->mfr_model[1] = '\0';
status = dps_1600ab_29_a_read_block(client, command,
data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1);
data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command,status);
data->mfr_model[1] = '\0';
}
command = 0x9e; /* PSU mfr_serial */
//data->mfr_serial[1] = '\0';
status = dps_1600ab_29_a_read_block(client, command,
data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1);
data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command,status);
data->mfr_serial[1] = '\0';
}
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
/* sysfs attributes for hwmon */
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, for_linear_data, NULL, PSU_V_IN);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, for_vout_data, NULL, PSU_V_OUT);
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, for_linear_data, NULL, PSU_I_IN);
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, for_linear_data, NULL, PSU_I_OUT);
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, for_linear_data, NULL, PSU_P_IN);
static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, for_linear_data, NULL, PSU_P_OUT);
static SENSOR_DEVICE_ATTR(temp1_input, \
S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT);
static SENSOR_DEVICE_ATTR(fan1_target, \
S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT);
static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \
for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE);
static SENSOR_DEVICE_ATTR(fan1_input, \
S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED);
static SENSOR_DEVICE_ATTR(psu_mfr_model, \
S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL);
static SENSOR_DEVICE_ATTR(psu_mfr_serial, \
S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL);
static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUSR | S_IRUGO, \
for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER);
static struct attribute *dps_1600ab_29_a_attributes[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_curr1_input.dev_attr.attr,
&sensor_dev_attr_curr2_input.dev_attr.attr,
&sensor_dev_attr_power1_input.dev_attr.attr,
&sensor_dev_attr_power2_input.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_fan1_target.dev_attr.attr,
&sensor_dev_attr_fan1_set_percentage.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_psu_mfr_model.dev_attr.attr,
&sensor_dev_attr_psu_mfr_serial.dev_attr.attr,
&sensor_dev_attr_psu_select_member.dev_attr.attr,
NULL
};
static const struct attribute_group dps_1600ab_29_a_group = {
.attrs = dps_1600ab_29_a_attributes,
};
static int dps_1600ab_29_a_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct dps_1600ab_29_a_data *data;
int status;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(*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, "new chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &dps_1600ab_29_a_group);
if (status)
goto exit_sysfs_create_group;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_hwmon_device_register;
}
return 0;
exit_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &dps_1600ab_29_a_group);
exit_sysfs_create_group:
kfree(data);
exit:
return status;
}
static int dps_1600ab_29_a_remove(struct i2c_client *client)
{
struct dps_1600ab_29_a_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &dps_1600ab_29_a_group);
kfree(data);
return 0;
}
enum id_name {
dni_agc032_psu,
dps_1600ab_29_a
};
static const struct i2c_device_id dps_1600ab_29_a_id[] = {
{ "dni_agc032_psu", dni_agc032_psu },
{ "dps_1600ab_29_a", dps_1600ab_29_a },
{}
};
MODULE_DEVICE_TABLE(i2c, dps_1600ab_29_a_id);
/* This is the driver that will be inserted */
static struct i2c_driver dps_1600ab_29_a_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "dps_1600ab_29_a",
},
.probe = dps_1600ab_29_a_probe,
.remove = dps_1600ab_29_a_remove,
.id_table = dps_1600ab_29_a_id,
.address_list = normal_i2c,
};
static int __init dps_1600ab_29_a_init(void)
{
return i2c_add_driver(&dps_1600ab_29_a_driver);
}
static void __exit dps_1600ab_29_a_exit(void)
{
i2c_del_driver(&dps_1600ab_29_a_driver);
}
MODULE_DESCRIPTION("DPS_1600AB_29_A Driver");
MODULE_LICENSE("GPL");
module_init(dps_1600ab_29_a_init);
module_exit(dps_1600ab_29_a_exit);

View File

@ -0,0 +1,363 @@
/*
* <bsn.cl fy=2013 v=gpl>
*
* Copyright (C) 2017 Delta Networks, Inc.
*
* This program is free software; you can redistribute it
* and/or modify it under the terms ofthe GNU General Public License as
* published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
*
* </bsn.cl>
*
*
* A hwmon driver for the SMSC EMC2302 fan controller
* Complete datasheet is available (6/2013) at:
*
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count);
static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
char *buf);
static ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count);
static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
char *buf);
static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count);
static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr,
char *buf);
static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4C,
0x4D, I2C_CLIENT_END
};
#define EMC2302_REG_DEVICE 0xFD
#define EMC2302_REG_VENDOR 0xFE
//#define FAN_MINIMUN 0x33 /*20%*/
#define FAN_MINIMUN 0x0 /*0%*/
#define FAN_RPM_BASED 0xAB
#define EMC2302_REG_FAN_DRIVE(n) (0x30 + 0x10 * n)
#define EMC2302_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n)
#define EMC2302_REG_FAN_TACH(n) (0x3E + 0x10 * n)
#define EMC2302_REG_FAN_CONF(n) (0x32 + 0x10 * n)
#define EMC2302_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n)
#define EMC2302_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n)
#define EMC2302_DEVICE 0x36
#define EMC2302_VENDOR 0x5D
#define MAX_FAN_SPEED 23000
struct emc2302_data
{
struct device *hwmon_dev;
struct attribute_group attrs;
struct mutex lock;
};
static int emc2302_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int emc2302_detect(struct i2c_client *client,
struct i2c_board_info *info);
static int emc2302_remove(struct i2c_client *client);
static const struct i2c_device_id emc2302_id[] =
{
{ "emc2302", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, emc2302_id);
static struct i2c_driver emc2302_driver =
{
.class = I2C_CLASS_HWMON,
.driver = {
.name = "emc2302",
},
.probe = emc2302_probe,
.remove = emc2302_remove,
.id_table = emc2302_id,
.detect = emc2302_detect,
.address_list = normal_i2c,
};
static SENSOR_DEVICE_ATTR(fan1_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 0);
static SENSOR_DEVICE_ATTR(fan2_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 1);
static SENSOR_DEVICE_ATTR(fan1_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 0);
static SENSOR_DEVICE_ATTR(fan2_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 1);
static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
static struct attribute *emc2302_attr[] =
{
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
&sensor_dev_attr_fan1_input_percentage.dev_attr.attr,
&sensor_dev_attr_fan2_input_percentage.dev_attr.attr,
&sensor_dev_attr_pwm1.dev_attr.attr,
&sensor_dev_attr_pwm2.dev_attr.attr,
NULL
};
static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct emc2302_data *data = i2c_get_clientdata(client);
int val;
mutex_lock(&data->lock);
val = i2c_smbus_read_word_swapped(client,
EMC2302_REG_FAN_TACH(attr->index));
mutex_unlock(&data->lock);
/* Left shift 3 bits for showing correct RPM */
val = val >> 3;
if ((int)(3932160 * 2 / (val > 0 ? val : 1) == 960))return sprintf(buf, "%d\n", 0);
return sprintf(buf, "%d\n", (int)(3932160 * 2 / (val > 0 ? val : 1) * 100 / MAX_FAN_SPEED));
}
static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct emc2302_data *data = i2c_get_clientdata(client);
unsigned long hsb, lsb;
unsigned long tech;
unsigned long val;
int ret;
ret = kstrtoul(buf, 10, &val);
if (ret)
{
return ret;
}
if (val > 100)
{
return -EINVAL;
}
if (val <= 5)
{
hsb = 0xff; /*high bit*/
lsb = 0xe0; /*low bit*/
}
else
{
val = val * 230;
tech = (3932160 * 2) / (val > 0 ? val : 1);
hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff);
lsb = (uint8_t)((tech << 3) & 0x0f8);
}
mutex_lock(&data->lock);
i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_H_RPM(attr->index), hsb);
i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_L_RPM(attr->index), lsb);
mutex_unlock(&data->lock);
return count;
}
static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct emc2302_data *data = i2c_get_clientdata(client);
int val;
mutex_lock(&data->lock);
val = i2c_smbus_read_word_swapped(client,
EMC2302_REG_FAN_TACH(attr->index));
mutex_unlock(&data->lock);
/* Left shift 3 bits for showing correct RPM */
val = val >> 3;
return sprintf(buf, "%d\n", 3932160 * 2 / (val > 0 ? val : 1));
}
static ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct emc2302_data *data = i2c_get_clientdata(client);
unsigned long hsb, lsb;
unsigned long tech;
unsigned long val;
int ret;
ret = kstrtoul(buf, 10, &val);
if (ret)
{
return ret;
}
if (val > 23000)
{
return -EINVAL;
}
if (val <= 960)
{
hsb = 0xff; /*high bit*/
lsb = 0xe0; /*low bit*/
}
else
{
tech = (3932160 * 2) / (val > 0 ? val : 1);
hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff);
lsb = (uint8_t)((tech << 3) & 0x0f8);
}
mutex_lock(&data->lock);
i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_H_RPM(attr->index), hsb);
i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_L_RPM(attr->index), lsb);
mutex_unlock(&data->lock);
return count;
}
static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct emc2302_data *data = i2c_get_clientdata(client);
int val;
mutex_lock(&data->lock);
val = i2c_smbus_read_byte_data(client,
EMC2302_REG_FAN_DRIVE(attr->index));
mutex_unlock(&data->lock);
return sprintf(buf, "%d\n", val);
}
static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct emc2302_data *data = i2c_get_clientdata(client);
unsigned long val;
int ret;
ret = kstrtoul(buf, 10, &val);
if (ret)
{
return ret;
}
if (val > 255)
{
return -EINVAL;
}
mutex_lock(&data->lock);
i2c_smbus_write_byte_data(client,
EMC2302_REG_FAN_DRIVE(attr->index),
val);
mutex_unlock(&data->lock);
return count;
}
static int emc2302_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
int vendor, device;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
{
return -ENODEV;
}
vendor = i2c_smbus_read_byte_data(client, EMC2302_REG_VENDOR);
if (vendor != EMC2302_VENDOR)
{
return -ENODEV;
}
device = i2c_smbus_read_byte_data(client, EMC2302_REG_DEVICE);
if (device != EMC2302_DEVICE)
{
return -ENODEV;
}
strlcpy(info->type, "emc2302", I2C_NAME_SIZE);
return 0;
}
static int emc2302_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct emc2302_data *data;
int err;
int i;
data = devm_kzalloc(&client->dev, sizeof(struct emc2302_data),
GFP_KERNEL);
if (!data)
{
return -ENOMEM;
}
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
dev_info(&client->dev, "%s chip found\n", client->name);
data->attrs.attrs = emc2302_attr;
err = sysfs_create_group(&client->dev.kobj, &data->attrs);
if (err)
{
return err;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev))
{
err = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
for (i = 0; i < 2; i++)
{
/* set minimum drive to 0% */
i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN);
i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_CONF(i), FAN_RPM_BASED);
}
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &data->attrs);
return err;
}
static int emc2302_remove(struct i2c_client *client)
{
struct emc2302_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &data->attrs);
return 0;
}
module_i2c_driver(emc2302_driver);
MODULE_AUTHOR("Zoe Kuan<zoe.kuan@deltaww.com>");
MODULE_DESCRIPTION("SMSC EMC2302 fan controller driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1 @@
../../common/modules/dni_emc2305.c

View File

@ -0,0 +1,22 @@
#!/bin/bash
#platform init script for Delta agc032
#fan speed monitor start
/usr/share/sonic/device/x86_64-delta_agc032-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_agc032-r0/fancontrol &
# On Delta-agc032 platform,
# syseeprom is on the different mux with main board after CPLD,
# we have to switch CPLD mux from main board to syseeprom before getting syseeprom data.
#
# The purpose of switching CPLD mux and getting syseeprom information here
# is to store data in syseeprom_cache.
# After that, we can read "syseeprom_cache" directly when executing command
# "show platform syseeprom", "sudo decode-syseeprom", "show version".
echo 0 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel
decode-syseeprom
echo 1 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel
exit 0

View File

@ -29,3 +29,8 @@ Package: platform-modules-ag9032v2a
Architecture: amd64
Depends: linux-image-4.19.0-6-amd64-unsigned
Description: kernel modules for platform devices such as syseeprom, sfp
Package: platform-modules-agc032
Architecture: amd64
Depends: linux-image-4.19.0-6-amd64-unsigned
Description: kernel modules for platform devices such as fan, led, sfp

View File

@ -0,0 +1,62 @@
#!/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 agc032 board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
depmod -a
rmmod i2c-i801
rmmod i2c-ismt
modprobe i2c-dev
modprobe i2c-i801
modprobe i2c-ismt
modprobe i2c-mux-pca954x
modprobe dni_agc032_psu
modprobe dni_emc2305
modprobe dni_emc2302
modprobe at24
modprobe optoe
modprobe delta_agc032_cpupld
# Switch CPUPLD to ONIE EEPROM Mux
echo 0 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel
modprobe eeprom
# Switch CPUPLD to Front Port Mux
echo 3 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel
modprobe delta_agc032_qsfp
# Switch CPUPLD to MainBoard Mux
echo 1 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel
modprobe delta_agc032_platform
modprobe delta_agc032_swpld
/usr/local/bin/agc032_platform_init.sh
echo "done."
;;
stop)
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/platform-modules-agc032.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,3 @@
agc032/scripts/agc032_platform_init.sh usr/local/bin
agc032/cfg/agc032-modules.conf etc/modules-load.d
systemd/platform-modules-agc032.service lib/systemd/system

View File

@ -5,7 +5,7 @@ export INSTALL_MOD_DIR:=extra
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
MODULE_DIRS:= ag9032v1 ag9064 ag5648 et-6248brb ag9032v2a
MODULE_DIRS:= ag9032v1 ag9064 ag5648 et-6248brb ag9032v2a agc032
%:
dh $@ --with=systemd

View File

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

View File

@ -133,6 +133,7 @@ serdes_pre_driver_current
serdes_preemphasis
serdes_rx_los
serdes_sgmii_m
serdes_tx_taps_cd
serdes_tx_taps
skip_L2_USER_ENTRY
sram_scan_enable