diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini new file mode 100644 index 000000000000..e000f29bef38 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1/1 +Ethernet4 53,54,55,56 hundredGigE1/2 +Ethernet8 57,58,59,60 hundredGigE1/3 +Ethernet12 61,62,63,64 hundredGigE1/4 +Ethernet16 65,66,67,68 hundredGigE1/5 +Ethernet20 69,70,71,72 hundredGigE1/6 +Ethernet24 73,74,75,76 hundredGigE1/7 +Ethernet28 77,78,79,80 hundredGigE1/8 +Ethernet32 37,38,39,40 hundredGigE1/9 +Ethernet36 33,34,35,36 hundredGigE1/10 +Ethernet40 45,46,47,48 hundredGigE1/11 +Ethernet44 41,42,43,44 hundredGigE1/12 +Ethernet48 81,82,83,84 hundredGigE1/13 +Ethernet52 85,86,87,88 hundredGigE1/14 +Ethernet56 89,90,91,92 hundredGigE1/15 +Ethernet60 93,94,95,96 hundredGigE1/16 +Ethernet64 97,98,99,100 hundredGigE1/17 +Ethernet68 101,102,103,104 hundredGigE1/18 +Ethernet72 105,106,107,108 hundredGigE1/19 +Ethernet76 109,110,111,112 hundredGigE1/20 +Ethernet80 21,22,23,24 hundredGigE1/21 +Ethernet84 17,18,19,20 hundredGigE1/22 +Ethernet88 29,30,31,32 hundredGigE1/23 +Ethernet92 25,26,27,28 hundredGigE1/24 +Ethernet96 117,118,119,120 hundredGigE1/25 +Ethernet100 113,114,115,116 hundredGigE1/26 +Ethernet104 125,126,127,128 hundredGigE1/27 +Ethernet108 121,122,123,124 hundredGigE1/28 +Ethernet112 5,6,7,8 hundredGigE1/29 +Ethernet116 1,2,3,4 hundredGigE1/30 +Ethernet120 13,14,15,16 hundredGigE1/31 +Ethernet124 9,10,11,12 hundredGigE1/32 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile new file mode 100644 index 000000000000..08d9e7fa3b47 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/th-ag9032v1-32x100G.config.bcm diff --git a/device/delta/x86_64-delta_ag9032v1-r0/fancontrol b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol new file mode 100644 index 000000000000..4a1cde92478f --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=emc2305 +FCTEMPS=hwmon1/2-004d/hwmon/hwmon*/temp1_input hwmon1/7-004c/hwmon/hwmon*/temp1_input hwmon1/7-004d/hwmon/hwmon*/temp1_input hwmon1/7-004e/hwmon/hwmon*/temp1_input hwmon1/30-004f/hwmon/hwmon*/temp1_input hwmon1/40-0058/temp1_input hwmon1/41-0058/temp1_input + +FCFANS=hwmon1/37-002c/fan1_input hwmon1/37-002c/fan2_input hwmon1/37-002c/fan3_input hwmon1/37-002c/fan4_input hwmon1/37-002c/fan5_input hwmon1/38-002d/fan1_input hwmon1/38-002d/fan2_input hwmon1/38-002d/fan3_input hwmon1/38-002d/fan4_input hwmon1/38-002d/fan5_input +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service new file mode 100755 index 000000000000..17f647effb5b --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service @@ -0,0 +1,244 @@ +#!/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 +# Copyright (C) 2007-2009 Jean Delvare +# +# 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 + + 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 + +# 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 +{ + echo "" + TEMP_HIGHEST=0 + FAN_PERCENTAGE=0 + + for i in ${AFCTEMP_PATH[@]}; do + if (( $(cat $i) > $TEMP_HIGHEST )); then + TEMP_HIGHEST=$(cat $i); + fi; + done + TEMP_HIGHEST=$((TEMP_HIGHEST/1000)) + echo "The highest temperature of thermal sensors: $TEMP_HIGHEST °C" +} + +function UpdateFanSpeeds +{ + if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50 + FAN_PERCENTAGE=40 + elif [ $TEMP_HIGHEST -lt 56 -a $TEMP_HIGHEST -gt 50 ]; then #50 ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + done + + if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50 + FAN_ON_PSU_PERCENTAGE=50 + elif [ $TEMP_HIGHEST -lt 100 -a $TEMP_HIGHEST -gt 50 ]; then #50 '/sys/bus/i2c/devices/4-0058/psu_select_member' + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/40-0058/fan1_set_percentage' + echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/40-0058/fan1_input' ) (rpm)" + #Set speed to PSU_FAN2 + #echo "0x20" > '/sys/bus/i2c/devices/4-0058/psu_select_member' + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/41-0058/fan1_set_percentage' + echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/41-0058/fan1_input' ) (rpm)" + + rm -f "$PIDFILE" +} +# main loop calling the main function at specified intervals +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_ag9032v1-r0/installer.conf b/device/delta/x86_64-delta_ag9032v1-r0/installer.conf new file mode 100644 index 000000000000..fa2af8b7a007 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc new file mode 100644 index 000000000000..7f6789e90123 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +s CMIC_LEDUP0_PROGRAM_RAM 0 +s CMIC_LEDUP1_PROGRAM_RAM 0 + +led 0 stop +led 0 prog 02 00 60 E0 86 ED 2E E0 32 08 97 02 00 0E 00 60 E3 2E E0 32 00 32 01 B7 97 02 00 0E 00 12 E7 50 86 E0 86 E0 86 E0 86 E0 16 E7 61 EB 06 E3 67 4E 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 06 E0 D2 40 74 06 3A C0 D2 01 74 66 06 EB D2 00 70 62 16 ED 99 99 1A 00 71 62 77 66 32 0F 87 57 32 0E 87 57 +led 0 auto on +led 0 start +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 REMAP_PORT_17=14 REMAP_PORT_18=13 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 REMAP_PORT_37=58 REMAP_PORT_38=57 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 REMAP_PORT_41=54 REMAP_PORT_42=53 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 REMAP_PORT_45=50 REMAP_PORT_46=49 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 REMAP_PORT_49=46 REMAP_PORT_50=45 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 REMAP_PORT_53=42 REMAP_PORT_54=41 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 REMAP_PORT_57=38 REMAP_PORT_58=37 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 REMAP_PORT_61=34 REMAP_PORT_62=33 REMAP_PORT_63=32 + +led 1 stop +led 1 prog 02 00 60 E0 86 ED 2E E0 32 08 97 02 00 0E 00 60 E3 2E E0 32 00 32 01 B7 97 02 00 0E 00 12 E7 50 86 E0 86 E0 86 E0 86 E0 16 E7 61 EB 06 E3 67 4E 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 06 E0 D2 40 74 06 3A C0 D2 01 74 66 06 EB D2 00 70 62 16 ED 99 99 1A 00 71 62 77 66 32 0F 87 57 32 0E 87 57 +led 1 auto on +led 1 start +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + diff --git a/device/delta/x86_64-delta_ag9032v1-r0/minigraph.xml b/device/delta/x86_64-delta_ag9032v1-r0/minigraph.xml new file mode 100644 index 000000000000..db8d62440534 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/minigraph.xml @@ -0,0 +1,1079 @@ + + + + + + ARISTA01T0 + 10.0.0.33 + switch1 + 10.0.0.32 + 1 + 180 + 60 + + + switch1 + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 180 + 60 + + + ARISTA02T0 + 10.0.0.35 + switch1 + 10.0.0.34 + 1 + 180 + 60 + + + switch1 + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 180 + 60 + + + ARISTA03T0 + 10.0.0.37 + switch1 + 10.0.0.36 + 1 + 180 + 60 + + + switch1 + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 180 + 60 + + + ARISTA04T0 + 10.0.0.39 + switch1 + 10.0.0.38 + 1 + 180 + 60 + + + switch1 + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 180 + 60 + + + ARISTA05T0 + 10.0.0.41 + switch1 + 10.0.0.40 + 1 + 180 + 60 + + + switch1 + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 180 + 60 + + + ARISTA06T0 + 10.0.0.43 + switch1 + 10.0.0.42 + 1 + 180 + 60 + + + switch1 + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 180 + 60 + + + ARISTA07T0 + 10.0.0.45 + switch1 + 10.0.0.44 + 1 + 180 + 60 + + + switch1 + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 180 + 60 + + + ARISTA08T0 + 10.0.0.47 + switch1 + 10.0.0.46 + 1 + 180 + 60 + + + switch1 + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 180 + 60 + + + ARISTA09T0 + 10.0.0.49 + switch1 + 10.0.0.48 + 1 + 180 + 60 + + + switch1 + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 180 + 60 + + + ARISTA10T0 + 10.0.0.51 + switch1 + 10.0.0.50 + 1 + 180 + 60 + + + switch1 + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 180 + 60 + + + ARISTA11T0 + 10.0.0.53 + switch1 + 10.0.0.52 + 1 + 180 + 60 + + + switch1 + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 180 + 60 + + + ARISTA12T0 + 10.0.0.55 + switch1 + 10.0.0.54 + 1 + 180 + 60 + + + switch1 + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 180 + 60 + + + ARISTA13T0 + 10.0.0.57 + switch1 + 10.0.0.56 + 1 + 180 + 60 + + + switch1 + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 180 + 60 + + + ARISTA14T0 + 10.0.0.59 + switch1 + 10.0.0.58 + 1 + 180 + 60 + + + switch1 + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 180 + 60 + + + ARISTA15T0 + 10.0.0.61 + switch1 + 10.0.0.60 + 1 + 180 + 60 + + + switch1 + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 180 + 60 + + + ARISTA16T0 + 10.0.0.63 + switch1 + 10.0.0.62 + 1 + 180 + 60 + + + switch1 + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 180 + 60 + + + + + 65100 + switch1 + + +
10.0.0.33
+ + +
+ +
10.0.0.1
+ + +
+ +
10.0.0.35
+ + +
+ +
10.0.0.3
+ + +
+ +
10.0.0.37
+ + +
+ +
10.0.0.5
+ + +
+ +
10.0.0.39
+ + +
+ +
10.0.0.7
+ + +
+ +
10.0.0.41
+ + +
+ +
10.0.0.9
+ + +
+ +
10.0.0.43
+ + +
+ +
10.0.0.11
+ + +
+ +
10.0.0.45
+ + +
+ +
10.0.0.13
+ + +
+ +
10.0.0.47
+ + +
+ +
10.0.0.15
+ + +
+ +
10.0.0.49
+ + +
+ +
10.0.0.17
+ + +
+ +
10.0.0.51
+ + +
+ +
10.0.0.19
+ + +
+ +
10.0.0.53
+ + +
+ +
10.0.0.21
+ + +
+ +
10.0.0.55
+ + +
+ +
10.0.0.23
+ + +
+ +
10.0.0.57
+ + +
+ +
10.0.0.25
+ + +
+ +
10.0.0.59
+ + +
+ +
10.0.0.27
+ + +
+ +
10.0.0.61
+ + +
+ +
10.0.0.29
+ + +
+ +
10.0.0.63
+ + +
+ +
10.0.0.31
+ + +
+
+ +
+ + 64001 + ARISTA01T0 + + + + 65200 + ARISTA01T2 + + + + 64002 + ARISTA02T0 + + + + 65200 + ARISTA02T2 + + + + 64003 + ARISTA03T0 + + + + 65200 + ARISTA03T2 + + + + 64004 + ARISTA04T0 + + + + 65200 + ARISTA04T2 + + + + 64005 + ARISTA05T0 + + + + 65200 + ARISTA05T2 + + + + 64006 + ARISTA06T0 + + + + 65200 + ARISTA06T2 + + + + 64007 + ARISTA07T0 + + + + 65200 + ARISTA07T2 + + + + 64008 + ARISTA08T0 + + + + 65200 + ARISTA08T2 + + + + 64009 + ARISTA09T0 + + + + 65200 + ARISTA09T2 + + + + 64010 + ARISTA10T0 + + + + 65200 + ARISTA10T2 + + + + 64011 + ARISTA11T0 + + + + 65200 + ARISTA11T2 + + + + 64012 + ARISTA12T0 + + + + 65200 + ARISTA12T2 + + + + 64013 + ARISTA13T0 + + + + 65200 + ARISTA13T2 + + + + 64014 + ARISTA14T0 + + + + 65200 + ARISTA14T2 + + + + 64015 + ARISTA15T0 + + + + 65200 + ARISTA15T2 + + + + 64016 + ARISTA16T0 + + + + 65200 + ARISTA16T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + + + + + + switch1 + + + + + + hundredGigE1/1 + 10.0.0.0/31 + + + + hundredGigE1/2 + 10.0.0.2/31 + + + + hundredGigE1/3 + 10.0.0.4/31 + + + + hundredGigE1/4 + 10.0.0.6/31 + + + + hundredGigE1/5 + 10.0.0.8/31 + + + + hundredGigE1/6 + 10.0.0.10/31 + + + + hundredGigE1/7 + 10.0.0.12/31 + + + + hundredGigE1/8 + 10.0.0.14/31 + + + + hundredGigE1/9 + 10.0.0.16/31 + + + + hundredGigE1/10 + 10.0.0.18/31 + + + + hundredGigE1/11 + 10.0.0.20/31 + + + + hundredGigE1/12 + 10.0.0.22/31 + + + + hundredGigE1/13 + 10.0.0.24/31 + + + + hundredGigE1/14 + 10.0.0.26/31 + + + + hundredGigE1/15 + 10.0.0.28/31 + + + + hundredGigE1/16 + 10.0.0.30/31 + + + + hundredGigE1/17 + 10.0.0.32/31 + + + + hundredGigE1/18 + 10.0.0.34/31 + + + + hundredGigE1/19 + 10.0.0.36/31 + + + + hundredGigE1/20 + 10.0.0.38/31 + + + + hundredGigE1/21 + 10.0.0.40/31 + + + + hundredGigE1/22 + 10.0.0.42/31 + + + + hundredGigE1/23 + 10.0.0.44/31 + + + + hundredGigE1/24 + 10.0.0.46/31 + + + + hundredGigE1/25 + 10.0.0.48/31 + + + + hundredGigE1/26 + 10.0.0.50/31 + + + + hundredGigE1/27 + 10.0.0.52/31 + + + + hundredGigE1/28 + 10.0.0.54/31 + + + + hundredGigE1/29 + 10.0.0.56/31 + + + + hundredGigE1/30 + 10.0.0.58/31 + + + + hundredGigE1/31 + 10.0.0.60/31 + + + + hundredGigE1/32 + 10.0.0.62/31 + + + + + + + + + + + + DeviceInterfaceLink + switch1 + hundredGigE1/1 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/2 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/3 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/4 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/5 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/6 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/7 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/8 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/9 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/10 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/11 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/12 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/13 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/14 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/15 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/16 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/17 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/18 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/19 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/20 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/21 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/22 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/23 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/24 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/25 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/26 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/27 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/28 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/29 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/30 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/31 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + switch1 + hundredGigE1/32 + ARISTA16T0 + Ethernet1 + + + + + switch1 + Delta-ag9032v1 + + + + + + + switch1 + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch1 + Delta-ag9032v1 +
diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py new file mode 100644 index 000000000000..786e1fdc85e3 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + import subprocess +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py new file mode 100644 index 000000000000..54d69446b1d8 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py @@ -0,0 +1,175 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 50 + + _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 + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{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 + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-cpld.0/sfp_present") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-cpld.0/sfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-cpld.0/sfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag9032v1-cpld.0/sfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_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: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True \ No newline at end of file diff --git a/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf b/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf new file mode 100644 index 000000000000..d3b2aea2a5af --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf @@ -0,0 +1,61 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + + +# tmp75-i2c-2-4d CPU below side thermal sensor. +# tmp75-i2c-3-4f Wind thermal sensor. +# tmp75-i2c-7-4c MAC up side thermal sensor. +# tmp75-i2c-7-4d MAC down side thermal sensor. +# tmp75-i2c-7-4e Surroundings thermal sensor. + +chip "tmp75-i2c-2-4d" + label temp1 "CPU below side thermal sensor" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-4f" + label temp1 "Wind thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-7-4c" + label temp1 "MAC up side thermal sensor" + set temp1_max 80 + set temp1_max_hyst 75 +chip "tmp75-i2c-7-4d" + label temp1 "MAC down side thermal sensor" + set temp1_max 75 + set temp1_max_hyst 70 +chip "tmp75-i2c-7-4e" + label temp1 "Surroundings thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 + + +chip "emc2305-i2c-3-2d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + label fan5 "FANTRAY 5 REAR" +chip "emc2305-i2c-3-2c" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + label fan5 "FANTRAY 5 FRONT" +chip "pmbus-i2c-4-50" + label temp1 "Fan of power supply controller 1 sensor 1" + label temp2 "Fan of Power supply controller 1 sensor 2" + +chip "pmbus-i2c-4-40" + label temp1 "Power supply 1 hotspot sensor" + +chip "pmbus-i2c-4-40" + label temp1 "Power supply 2 hotspot sensor" + diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 378129d4da03..717ba7fa0f6b 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -15,6 +15,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(ACCTON_AS5712_54X_PLATFORM_MODULE) \ $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ - $(CEL_DX010_PLATFORM_MODULE) + $(CEL_DX010_PLATFORM_MODULE) \ + $(DELTA_AG9032V1_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/broadcom/platform-modules-delta.mk b/platform/broadcom/platform-modules-delta.mk new file mode 100644 index 000000000000..c73b128106a9 --- /dev/null +++ b/platform/broadcom/platform-modules-delta.mk @@ -0,0 +1,12 @@ +# Delta AG9032v1 Platform modules + +DELTA_AG9032V1_PLATFORM_MODULE_VERSION = 1.1 + +export DELTA_AG9032V1_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 +$(DELTA_AG9032V1_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELTA_AG9032V1_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9032v1-r0 +SONIC_DPKG_DEBS += $(DELTA_AG9032V1_PLATFORM_MODULE) + diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk index b52118570251..e94361987963 100755 --- a/platform/broadcom/rules.mk +++ b/platform/broadcom/rules.mk @@ -7,6 +7,7 @@ include $(PLATFORM_PATH)/platform-modules-ingrasys.mk include $(PLATFORM_PATH)/platform-modules-accton.mk include $(PLATFORM_PATH)/platform-modules-inventec.mk include $(PLATFORM_PATH)/platform-modules-cel.mk +include $(PLATFORM_PATH)/platform-modules-delta.mk include $(PLATFORM_PATH)/docker-orchagent-brcm.mk include $(PLATFORM_PATH)/docker-syncd-brcm.mk include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk diff --git a/platform/broadcom/sonic-platform-modules-delta/LICENSE b/platform/broadcom/sonic-platform-modules-delta/LICENSE new file mode 100644 index 000000000000..ea87fe9caabe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Delta Networks, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +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. diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf @@ -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 diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile new file mode 100644 index 000000000000..69b3b48885d3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := at24.o dni_ag9032v1_psu.o dni_emc2305.o delta_ag9032v1_platform.o + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c new file mode 100644 index 000000000000..8e73691647d8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/at24.c @@ -0,0 +1,698 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + struct memory_accessor macc; + int use_smbus; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 32; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 32)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +static const struct i2c_device_id at24_ids[] = { + /* needs 8 addresses as A0-A2 are ignored */ + { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) }, + /* old variants can't be handled with this generic entry! */ + { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) }, + { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) }, + /* spd is a 24c02 in memory DIMMs */ + { "spd", AT24_DEVICE_MAGIC(2048 / 8, + AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, + { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, + /* 24rf08 quirk is handled at i2c-core */ + { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, + { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, + { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, + { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, + { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) }, + { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) }, + { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) }, + { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) }, + { "at24", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned *offset) +{ + unsigned i; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + struct i2c_client *client; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + /* + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ + + /* + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + */ + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + switch (at24->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /* Smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. Note that read page rollover helps us + * here (unlike writes). msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msgbuf[i++] = offset >> 8; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + switch (at24->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_read(struct at24_data *at24, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_read(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_read(at24, buf, off, count); +} + + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. This routine + * writes at most one page. + */ +static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + unsigned offset, size_t count) +{ + struct i2c_client *client; + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + /* If we'll use I2C calls for I/O, set up the message */ + if (!at24->use_smbus) { + int i = 0; + + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = at24->writebuf; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msg.buf[i++] = offset >> 8; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + } + + /* + * Writes fail if the previous one didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + if (at24->use_smbus) { + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + } else { + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + } + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, + size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_write(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + if (unlikely(off >= attr->size)) + return -EFBIG; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_write(at24, buf, off, count); +} + +/*-------------------------------------------------------------------------*/ + +/* + * This lets other kernel code access the eeprom data. For example, it + * might hold a board's Ethernet address, or board-specific calibration + * data generated on the manufacturing floor. + */ + +static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf, + off_t offset, size_t count) +{ + struct at24_data *at24 = container_of(macc, struct at24_data, macc); + + return at24_read(at24, buf, offset, count); +} + +static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf, + off_t offset, size_t count) +{ + struct at24_data *at24 = container_of(macc, struct at24_data, macc); + + return at24_write(at24, buf, offset, count); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + bool writable; + int use_smbus = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + kernel_ulong_t magic; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (!id->driver_data) + return -ENODEV; + + magic = id->driver_data; + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (chip.flags & AT24_FLAG_ADDR16) + return -EPFNOSUPPORT; + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, + (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->chip = chip; + at24->num_addresses = num_addresses; + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + sysfs_bin_attr_init(&at24->bin); + at24->bin.attr.name = "eeprom"; + at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; + at24->bin.read = at24_bin_read; + at24->bin.size = chip.byte_len; + + at24->macc.read = at24_macc_read; + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + + unsigned write_max = chip.page_size; + + at24->macc.write = at24_macc_write; + + at24->bin.write = at24_bin_write; + at24->bin.attr.mode |= S_IWUSR; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, + write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, + client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", + client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); + if (err) + goto err_clients; + + i2c_set_clientdata(client, at24); + + dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n", + at24->bin.size, client->name, + writable ? "writable" : "read-only", at24->write_max); + if (use_smbus == I2C_SMBUS_WORD_DATA || + use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } + + /* export data to kernel code */ + if (chip.setup) + chip.setup(&at24->macc, chip.context); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_driver at24_driver = { + .driver = { + .name = "at24", + .owner = THIS_MODULE, + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ids, +}; + +static int __init at24_init(void) +{ + if (!io_limit) { + pr_err("at24: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + return i2c_add_driver(&at24_driver); +} +module_init(at24_init); + +static void __exit at24_exit(void) +{ + i2c_del_driver(&at24_driver); +} +module_exit(at24_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c new file mode 100644 index 000000000000..90454a5bdb4a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c @@ -0,0 +1,1530 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUS3_DEV_NUM 9 +#define BUS4_DEV_NUM 6 +#define BUS5_DEV_NUM 32 +#define DEFAULT_NUM 1 +#define BUS3_BASE_NUM 30 +#define BUS4_BASE_NUM 40 +#define BUS5_BASE_NUM 50 + +#define BUS3_MUX_REG 0x21 +#define BUS4_MUX_REG 0x21 +#define BUS5_MUX_REG 0x20 + +#define TEMP_FAN_VAL 0x06 +#define FANIO_CTL_VAL 0x07 +#define FAN_CTRL_VAL 0x05 +#define PSU1_VAL 0x00 +#define PSU2_VAL 0x20 +#define HOT_SWAP1_VAL 0x10 +#define HOT_SWAP2_VAL 0x30 +#define FAN_EEPROM1_VAL 0x00 +#define FAN_EEPROM2_VAL 0x01 +#define FAN_EEPROM3_VAL 0x02 +#define FAN_EEPROM4_VAL 0x03 +#define FAN_EEPROM5_VAL 0x04 + +#define SWPLD_REG 0x31 +#define SWPLD_SFP_MUX_REG 0x20 + +#define SYS_LED_REG 0x1C +#define FAN1_LED_REG 0x1D +#define FAN2_LED_REG 0x1E + +#define SFP_PRESENCE_1 0x38 +#define SFP_PRESENCE_2 0x39 +#define SFP_PRESENCE_3 0x3A +#define SFP_PRESENCE_4 0x3B + +#define SFP_LP_MODE_1 0x34 +#define SFP_LP_MODE_2 0x35 +#define SFP_LP_MODE_3 0x36 +#define SFP_LP_MODE_4 0x37 + +#define SFP_RESET_1 0x3C +#define SFP_RESET_2 0x3D +#define SFP_RESET_3 0x3E +#define SFP_RESET_4 0x3F + +#define SFP_RESPONSE_1 0x30 +#define SFP_RESPONSE_2 0x31 +#define SFP_RESPONSE_3 0x32 +#define SFP_RESPONSE_4 0x33 + +#define SFF8436_INFO(data) \ + .type = "sff8436", .addr = 0x50, .platform_data = (data) + +#define SFF_8346_PORT(eedata) \ + .byte_len = 256, .page_size = 1, .flags = SFF_8436_FLAG_READONLY + +#define ag9032v1_i2c_device_num(NUM){ \ + .name = "delta-ag9032v1-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9032v1_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9547; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9547 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .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, + }, + { .adap_id = 9, + .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_pca9547[] = +{ + { + I2C_BOARD_INFO("pca9547", 0x71), + .platform_data = &pca954x_data, + }, +}; + + +static struct sff_8436_platform_data sff_8436_port[] = { + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, +}; + +static struct i2c_device_platform_data ag9032v1_i2c_device_platform_data[] = { + { + /* tmp75 (0x4d) */ + .parent = 2, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* id eeprom (0x53) */ + .parent = 2, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + /* tmp75 (0x4c) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4c) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x4e) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + /* tmp75 (0x4f) */ + .parent = 30, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + /* FAN 1 Controller (0x2c) */ + .parent = 37, + .info = { I2C_BOARD_INFO("emc2305", 0x2c) }, + .client = NULL, + }, + { + /* FAN 2 Controller (0x2d) */ + .parent = 38, + .info = { I2C_BOARD_INFO("emc2305", 0x2d) }, + .client = NULL, + }, + { + /* psu 1 (0x58) */ + .parent = 40, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = 0 }, + .client = NULL, + }, + { + /* psu 2 (0x58) */ + .parent = 41, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = 1 }, + .client = NULL, + }, + { + /* hot-swap 1 (0x40) */ + .parent = 42, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = 0 }, + .client = NULL, + }, + { + /* hot-swap 2 (0x40) */ + .parent = 43, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = 1 }, + .client = NULL, + }, + { + /* qsfp 1 (0x50) */ + .parent = 50, + .info = { SFF8436_INFO(&sff_8436_port[0]) }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 51, + .info = { SFF8436_INFO(&sff_8436_port[1]) }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 52, + .info = { SFF8436_INFO(&sff_8436_port[2]) }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 53, + .info = { SFF8436_INFO(&sff_8436_port[3]) }, + .client = NULL, + }, + { + /* qsfp 5 (0x50) */ + .parent = 54, + .info = { SFF8436_INFO(&sff_8436_port[4]) }, + .client = NULL, + }, + { + /* qsfp 6 (0x50) */ + .parent = 55, + .info = { SFF8436_INFO(&sff_8436_port[5]) }, + .client = NULL, + }, + { + /* qsfp 7 (0x50) */ + .parent = 56, + .info = { SFF8436_INFO(&sff_8436_port[6]) }, + .client = NULL, + }, + { + /* qsfp 8 (0x50) */ + .parent = 57, + .info = { SFF8436_INFO(&sff_8436_port[7]) }, + .client = NULL, + }, + { + /* qsfp 9 (0x50) */ + .parent = 58, + .info = { SFF8436_INFO(&sff_8436_port[8]) }, + .client = NULL, + }, + { + /* qsfp 10 (0x50) */ + .parent = 59, + .info = { SFF8436_INFO(&sff_8436_port[9]) }, + .client = NULL, + }, + { + /* qsfp 11 (0x50) */ + .parent = 60, + .info = { SFF8436_INFO(&sff_8436_port[10]) }, + .client = NULL, + }, + { + /* qsfp 12 (0x50) */ + .parent = 61, + .info = { SFF8436_INFO(&sff_8436_port[11]) }, + .client = NULL, + }, + { + /* qsfp 13 (0x50) */ + .parent = 62, + .info = { SFF8436_INFO(&sff_8436_port[12]) }, + .client = NULL, + }, + { + /* qsfp 14 (0x50) */ + .parent = 63, + .info = { SFF8436_INFO(&sff_8436_port[13]) }, + .client = NULL, + }, + { + /* qsfp 15 (0x50) */ + .parent = 64, + .info = { SFF8436_INFO(&sff_8436_port[14]) }, + .client = NULL, + }, + { + /* qsfp 16 (0x50) */ + .parent = 65, + .info = { SFF8436_INFO(&sff_8436_port[15]) }, + .client = NULL, + }, + { + /* qsfp 17 (0x50) */ + .parent = 66, + .info = { SFF8436_INFO(&sff_8436_port[16]) }, + .client = NULL, + }, + { + /* qsfp 18 (0x50) */ + .parent = 67, + .info = { SFF8436_INFO(&sff_8436_port[17]) }, + .client = NULL, + }, + { + /* qsfp 19 (0x50) */ + .parent = 68, + .info = { SFF8436_INFO(&sff_8436_port[18]) }, + .client = NULL, + }, + { + /* qsfp 20 (0x50) */ + .parent = 69, + .info = { SFF8436_INFO(&sff_8436_port[19]) }, + .client = NULL, + }, + { + /* qsfp 21 (0x50) */ + .parent = 70, + .info = { SFF8436_INFO(&sff_8436_port[20]) }, + .client = NULL, + }, + { + /* qsfp 22 (0x50) */ + .parent = 71, + .info = { SFF8436_INFO(&sff_8436_port[21]) }, + .client = NULL, + }, + { + /* qsfp 23 (0x50) */ + .parent = 72, + .info = { SFF8436_INFO(&sff_8436_port[22]) }, + .client = NULL, + }, + { + /* qsfp 24 (0x50) */ + .parent = 73, + .info = { SFF8436_INFO(&sff_8436_port[23]) }, + .client = NULL, + }, + { + /* qsfp 25 (0x50) */ + .parent = 74, + .info = { SFF8436_INFO(&sff_8436_port[24]) }, + .client = NULL, + }, + { + /* qsfp 26 (0x50) */ + .parent = 75, + .info = { SFF8436_INFO(&sff_8436_port[25]) }, + .client = NULL, + }, + { + /* qsfp 27 (0x50) */ + .parent = 76, + .info = { SFF8436_INFO(&sff_8436_port[26]) }, + .client = NULL, + }, + { + /* qsfp 28 (0x50) */ + .parent = 77, + .info = { SFF8436_INFO(&sff_8436_port[27]) }, + .client = NULL, + }, + { + /* qsfp 29 (0x50) */ + .parent = 78, + .info = { SFF8436_INFO(&sff_8436_port[28]) }, + .client = NULL, + }, + { + /* qsfp 30 (0x50) */ + .parent = 79, + .info = { SFF8436_INFO(&sff_8436_port[29]) }, + .client = NULL, + }, + { + /* qsfp 31 (0x50) */ + .parent = 80, + .info = { SFF8436_INFO(&sff_8436_port[30]) }, + .client = NULL, + }, + { + /* qsfp 32 (0x50) */ + .parent = 81, + .info = { SFF8436_INFO(&sff_8436_port[31]) }, + .client = NULL, + }, +}; + + +static struct platform_device ag9032v1_i2c_device[] = { + ag9032v1_i2c_device_num(0), + ag9032v1_i2c_device_num(1), + ag9032v1_i2c_device_num(2), + ag9032v1_i2c_device_num(3), + ag9032v1_i2c_device_num(4), + ag9032v1_i2c_device_num(5), + ag9032v1_i2c_device_num(6), + ag9032v1_i2c_device_num(7), + ag9032v1_i2c_device_num(8), + ag9032v1_i2c_device_num(9), + ag9032v1_i2c_device_num(10), + ag9032v1_i2c_device_num(11), + ag9032v1_i2c_device_num(12), + ag9032v1_i2c_device_num(13), + ag9032v1_i2c_device_num(14), + ag9032v1_i2c_device_num(15), + ag9032v1_i2c_device_num(16), + ag9032v1_i2c_device_num(17), + ag9032v1_i2c_device_num(18), + ag9032v1_i2c_device_num(19), + ag9032v1_i2c_device_num(20), + ag9032v1_i2c_device_num(21), + ag9032v1_i2c_device_num(22), + ag9032v1_i2c_device_num(23), + ag9032v1_i2c_device_num(24), + ag9032v1_i2c_device_num(25), + ag9032v1_i2c_device_num(26), + ag9032v1_i2c_device_num(27), + ag9032v1_i2c_device_num(28), + ag9032v1_i2c_device_num(29), + ag9032v1_i2c_device_num(30), + ag9032v1_i2c_device_num(31), + ag9032v1_i2c_device_num(32), + ag9032v1_i2c_device_num(33), + ag9032v1_i2c_device_num(34), + ag9032v1_i2c_device_num(35), + ag9032v1_i2c_device_num(36), + ag9032v1_i2c_device_num(37), + ag9032v1_i2c_device_num(38), + ag9032v1_i2c_device_num(39), + ag9032v1_i2c_device_num(40), + ag9032v1_i2c_device_num(41), + ag9032v1_i2c_device_num(42), + ag9032v1_i2c_device_num(43), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ +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 = i2c_get_adapter(pdata->parent); + 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-ag9032v1-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +/* CPLD -- device */ + +enum cpld_type { + system_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data ag9032v1_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = SWPLD_REG, + }, +}; + +static struct platform_device ag9032v1_cpld = { + .name = "delta-ag9032v1-cpld", + .id = 0, + .dev = { + .platform_data = ag9032v1_cpld_platform_data, + .release = device_release + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_1); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data = (u32)reverse_8bits(ret) & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_2); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_3); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_4); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2, (u8)(reverse_8bits(data >> 8) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3, (u8)(reverse_8bits(data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4, (u8)(reverse_8bits(data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_1); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_2); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_3); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_4); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_2, (u8)reverse_8bits((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_3, (u8)reverse_8bits((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_4, (u8)reverse_8bits((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_response(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4); + if (ret < 0) + return sprintf(buf, "error number(%ld)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2, (u8)reverse_8bits((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3, (u8)reverse_8bits((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4, (u8)reverse_8bits((data >> 24) & 0xff)); + + return count; +} + +struct platform_led_status{ + int reg_data; + char *led_status; + int led_id; +}; + +static struct platform_led_status led_info[] = { + { + .reg_data = 0x40, + .led_status = "pwr1_green", + .led_id = 0, + }, + { + .reg_data = 0x80, + .led_status = "pwr1_amber", + .led_id = 0, + }, + { + .reg_data = 0x00, + .led_status = "pwr1_off", + .led_id = 0, + }, + { + .reg_data = 0xc0, + .led_status = "pwr1_off", + .led_id = 0, + }, + { + .reg_data = 0x10, + .led_status = "pwr2_green", + .led_id = 1, + }, + { + .reg_data = 0x20, + .led_status = "pwr2_amber", + .led_id = 1, + }, + { + .reg_data = 0x00, + .led_status = "pwr2_off", + .led_id = 1, + }, + { + .reg_data = 0x30, + .led_status = "pwr2_off", + .led_id = 1, + }, + { + .reg_data = 0x04, + .led_status = "sys_green", + .led_id = 2, + }, + { + .reg_data = 0x08, + .led_status = "sys_blinking_green", + .led_id = 2, + }, + { + .reg_data = 0x0c, + .led_status = "sys_red", + .led_id = 2, + }, + { + .reg_data = 0x00, + .led_status = "sys_off", + .led_id = 2, + }, + { + .reg_data = 0x01, + .led_status = "fan_green", + .led_id = 3, + }, + { + .reg_data = 0x02, + .led_status = "fan_amber", + .led_id = 3, + }, + { + .reg_data = 0x00, + .led_status = "fan_off", + .led_id = 3, + }, + { + .reg_data = 0x03, + .led_status = "fan_off", + .led_id = 3, + }, + { + .reg_data = 0x40, + .led_status = "fan1_green", + .led_id = 4, + }, + { + .reg_data = 0x80, + .led_status = "fan1_red", + .led_id = 4, + }, + { + .reg_data = 0x00, + .led_status = "fan1_off", + .led_id = 4, + }, + { + .reg_data = 0x10, + .led_status = "fan2_green", + .led_id = 5, + }, + { + .reg_data = 0x20, + .led_status = "fan2_red", + .led_id = 5, + }, + { + .reg_data = 0x00, + .led_status = "fan2_off", + .led_id = 5, + }, + { + .reg_data = 0x04, + .led_status = "fan3_green", + .led_id = 6, + }, + { + .reg_data = 0x08, + .led_status = "fan3_red", + .led_id = 6, + }, + { + .reg_data = 0x00, + .led_status = "fan3_off", + .led_id = 6, + }, + { + .reg_data = 0x01, + .led_status = "fan4_green", + .led_id = 7, + }, + { + .reg_data = 0x02, + .led_status = "fan4_red", + .led_id = 7, + }, + { + .reg_data = 0x00, + .led_status = "fan4_off", + .led_id = 7, + }, + { + .reg_data = 0x40, + .led_status = "fan5_green", + .led_id = 8, + }, + { + .reg_data = 0x80, + .led_status = "fan5_red", + .led_id = 8, + }, + { + .reg_data = 0x00, + .led_status = "fan5_off", + .led_id = 8, + }, +}; + +struct platform_led_data{ + int reg_addr; + int mask; +}; + +static struct platform_led_data led_data[] = { + { + .reg_addr = SYS_LED_REG, + .mask = 0xc0, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x30, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x0c, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x03, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0xc0, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x30, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x0c, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x03, + }, + { + .reg_addr = FAN2_LED_REG, + .mask = 0xc0, + }, +}; + + +static ssize_t get_led_color(struct device *dev, struct device_attribute *devattr, char *buf) +{ + char str[9][20] = {0}; + int board_data; + int led_data_number; + int led_info_number; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + board_data = i2c_smbus_read_byte_data(pdata[system_cpld].client, led_data[led_data_number].reg_addr); + if(board_data >= 0){ + board_data &= led_data[led_data_number].mask; + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + if (led_data_number == led_info[led_info_number].led_id){ + if(board_data == led_info[led_info_number].reg_data){ + sprintf(str[led_data_number], "%s", led_info[led_info_number].led_status); + } + } + } + } + else + printk( KERN_ERR "Missing LED board data\n"); + } + return sprintf(buf,"%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7],str[8]); +} + +static ssize_t set_led_color(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int led_info_number; + int led_data_number; + int str_compar; + int led_reg_value; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + str_compar = strncmp(buf,led_info[led_info_number].led_status,strlen(led_info[led_info_number].led_status)); + if(str_compar == 0){ + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + if(led_info[led_info_number].led_id == led_data_number){ + led_reg_value = i2c_smbus_read_byte_data(pdata[system_cpld].client, led_data[led_data_number].reg_addr); + if(led_reg_value >= 0){ + led_reg_value &= (~led_data[led_data_number].mask); + led_reg_value |= led_info[led_info_number].reg_data; + i2c_smbus_write_byte_data(pdata[system_cpld].client, (u8)(led_data[led_data_number].reg_addr & 0xff), (u8)(led_reg_value & 0xff)); + } + else + printk( KERN_ERR "Missing LED reg. data\n"); + } + } + } + } + return count; +} + + +static DEVICE_ATTR(sfp_present, S_IRUGO, get_present, NULL ); +static DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode ); +static DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset ); +static DEVICE_ATTR(sfp_response, S_IWUSR | S_IRUGO, get_response, set_response ); +static DEVICE_ATTR(led_control, S_IRUGO | S_IWUSR, get_led_color, set_led_color); + +static struct attribute *ag9032v1_cpld_attrs[] = { + &dev_attr_sfp_response.attr, + &dev_attr_sfp_present.attr, + &dev_attr_sfp_lpmode.attr, + &dev_attr_sfp_reset.attr, + &dev_attr_led_control.attr, + NULL, +}; + +static struct attribute_group ag9032v1_cpld_attr_grp = { + .attrs = ag9032v1_cpld_attrs, +}; + +/* CPLD -- driver */ +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS6); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS6); + return -ENODEV; + } + + pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr); + if (!pdata[system_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr); + goto error; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[system_cpld].client) { + if (!parent) { + parent = (pdata[system_cpld].client)->adapter; + } + i2c_unregister_device(pdata[system_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-cpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; +static struct swpld_mux_platform_data ag9032v1_swpld_mux_platform_data[] = { + { + .parent = BUS3, + .base_nr = BUS3_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS3_MUX_REG ,// the i2c register address which for select mux TEMP(FAN) + }, + { + .parent = BUS4, + .base_nr = BUS4_BASE_NUM , + .cpld = NULL, + .reg_addr = BUS4_MUX_REG , + }, + { + .parent = BUS5, + .base_nr = BUS5_BASE_NUM , + .cpld = NULL, + .reg_addr = BUS5_MUX_REG , + }, +}; + +static struct platform_device ag9032v1_swpld_mux[] = { + { + .name = "delta-ag9032v1-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v1-swpld-mux", + .id = 1, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[1], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v1-swpld-mux", + .id = 2, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[2], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) +{ + struct swpld_mux *mux = data; + u8 swpld_mux_val=0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = TEMP_FAN_VAL; + break; + case 1: + swpld_mux_val = FAN_EEPROM1_VAL; + break; + case 2: + swpld_mux_val = FAN_EEPROM2_VAL; + break; + case 3: + swpld_mux_val = FAN_EEPROM3_VAL; + break; + case 4: + swpld_mux_val = FAN_EEPROM4_VAL; + break; + case 5: + swpld_mux_val = FAN_EEPROM5_VAL; + break; + case 6: + swpld_mux_val = FANIO_CTL_VAL; + break; + case 7: + case 8: + swpld_mux_val = FAN_CTRL_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = PSU1_VAL; + break; + case 1: + swpld_mux_val = PSU2_VAL; + break; + case 2: + swpld_mux_val = HOT_SWAP1_VAL; + break; + case 3: + swpld_mux_val = HOT_SWAP2_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS5_BASE_NUM ){ + if (chan < 9){ + swpld_mux_val = (u8)(chan) + 0x01; + } + else if (8 < chan && chan < 19){ + swpld_mux_val = (u8)(chan - 9) + 0x10; + } + else if (18 < chan && chan < 29){ + swpld_mux_val = (u8)(chan - 19) + 0x20; + } + else if (28 < chan && chan < 39){ + swpld_mux_val = (u8)(chan - 29) + 0x30; + } + else{ + swpld_mux_val = 0x00; + } + } + else + { + swpld_mux_val = 0x00; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} + +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\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; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for mux\n"); + goto alloc_failed; + } + + mux->parent = parent; + mux->data = *pdata; + mux->child = kzalloc(sizeof(struct i2c_adapter *) * dev_num, GFP_KERNEL); + if (!mux->child) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for device on mux\n"); + goto alloc_failed2; + } + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + mux->child[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, class, + swpld_mux_select, NULL); + if (!mux->child[i]) { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + platform_set_drvdata(pdev, mux); + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->child[i - 1]); + kfree(mux->child); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} + + +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + int i; + struct swpld_mux *mux = platform_get_drvdata(pdev); + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\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; + } + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + for (i = 0; i < dev_num; i++) + i2c_del_mux_adapter(mux->child[i]); + + platform_set_drvdata(pdev, NULL); + i2c_put_adapter(mux->parent); + kfree(mux->child); + kfree(mux); + + return 0; +} + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-swpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ +static void __init delta_ag9032v1_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + struct swpld_mux_platform_data *swpld_pdata; + int ret,i = 0; + printk("ag9032v1_platform module initialization\n"); + + //Use pca9547 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + //client = i2c_new_device(adapter, &i2c_info_pca9547[0]); + i2c_client_9547 = i2c_new_device(adapter, &i2c_info_pca9547[0]); + + i2c_put_adapter(adapter); + + // set the CPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + // register the mux prob which call the CPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // 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; + } + + // register the CPLD + ret = platform_device_register(&ag9032v1_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_ag9032v1_cpld; + } + // link the CPLD and the Mux + cpld_pdata = ag9032v1_cpld.dev.platform_data; + + for (i = 0; i < ARRAY_SIZE(ag9032v1_swpld_mux); i++) + { + swpld_pdata = ag9032v1_swpld_mux[i].dev.platform_data; + swpld_pdata->cpld = cpld_pdata[system_cpld].client; + ret = platform_device_register(&ag9032v1_swpld_mux[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag9032v1_swpld_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(ag9032v1_i2c_device); i++) + { + ret = platform_device_register(&ag9032v1_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9032v1_i2c_device; + } + } + + if (ret) + goto error_ag9032v1_swpld_mux; + + return 0; + +error_ag9032v1_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v1_i2c_device[i]); + } + i = ARRAY_SIZE(ag9032v1_swpld_mux); +error_ag9032v1_swpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v1_swpld_mux[i]); + } + platform_driver_unregister(&ag9032v1_cpld); +error_ag9032v1_cpld: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag9032v1_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ag9032v1_i2c_device); i++ ) { + platform_device_unregister(&ag9032v1_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(ag9032v1_swpld_mux); i++) { + platform_device_unregister(&ag9032v1_swpld_mux[i]); + } + + platform_device_unregister(&ag9032v1_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&swpld_mux_driver); + + i2c_unregister_device(i2c_client_9547); +} + +module_init(delta_ag9032v1_platform_init); +module_exit(delta_ag9032v1_platform_exit); + +MODULE_DESCRIPTION("DNI ag9032v1 Platform Support"); +MODULE_AUTHOR("Neal Tai "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c new file mode 100644 index 000000000000..b9ddb979a29b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c @@ -0,0 +1,545 @@ +/* + * An hwmon driver for delta AG9032v1 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * Aries Lin + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_800ab_16_d_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_800ab_16_d_read_byte(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_800ab_16_d_data *dps_800ab_16_d_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_800ab_16_d_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_800ab_16_d_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_800ab_16_d_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_800ab_16_d_data *data = dps_800ab_16_d_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_800ab_16_d_data *data = dps_800ab_16_d_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_800ab_16_d_data *data = dps_800ab_16_d_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_800ab_16_d_data *data = dps_800ab_16_d_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_800ab_16_d_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_800ab_16_d_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_800ab_16_d_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_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_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_800ab_16_d_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_800ab_16_d_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x9a; /* PSU mfr_model */ + status = dps_800ab_16_d_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); + } + + command = 0x9e; /* PSU mfr_serial */ + status = dps_800ab_16_d_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->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_IWUGO | 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_IWUGO | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); + +static struct attribute *dps_800ab_16_d_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_800ab_16_d_group = { + .attrs = dps_800ab_16_d_attributes, +}; + +static int dps_800ab_16_d_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_800ab_16_d_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_800ab_16_d_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_800ab_16_d_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_800ab_16_d_remove(struct i2c_client *client) +{ + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); + kfree(data); + + return 0; +} + +enum id_name { + dni_ag9032v1_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ag9032v1_psu", dni_ag9032v1_psu }, + { "dps_800ab_16_d", dps_800ab_16_d }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_800ab_16_d_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_800ab_16_d_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_800ab_16_d", + }, + .probe = dps_800ab_16_d_probe, + .remove = dps_800ab_16_d_remove, + .id_table = dps_800ab_16_d_id, + .address_list = normal_i2c, +}; + +static int __init dps_800ab_16_d_init(void) +{ + return i2c_add_driver(&dps_800ab_16_d_driver); +} + +static void __exit dps_800ab_16_d_exit(void) +{ + i2c_del_driver(&dps_800ab_16_d_driver); +} + + +MODULE_AUTHOR("Aries Lin "); +MODULE_DESCRIPTION("DPS_800AB_16_D Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_800ab_16_d_init); +module_exit(dps_800ab_16_d_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c new file mode 100644 index 000000000000..73d9900af5b4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c @@ -0,0 +1,381 @@ +/* + * + * + * 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. + * + * + * + * + * + * A hwmon driver for the SMSC EMC2305 fan controller + * Complete datasheet is available (6/2013) at: + * http://www.smsc.com/media/Downloads_Public/Data_Sheets/2305.pdf + */ + +#include +#include +#include +#include +#include + + +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 EMC2305_REG_DEVICE 0xFD +#define EMC2305_REG_VENDOR 0xFE + +//#define FAN_MINIMUN 0x33 /*20%*/ +#define FAN_MINIMUN 0x0 /*0%*/ +#define FAN_RPM_BASED 0xAB + +#define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * n) +#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n) +#define EMC2305_REG_FAN_TACH(n) (0x3E + 0x10 * n) +#define EMC2305_REG_FAN_CONF(n) (0x32 + 0x10 * n) +#define EMC2305_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n) +#define EMC2305_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n) + +#define EMC2305_DEVICE 0x34 +#define EMC2305_VENDOR 0x5D +#define MAX_FAN_SPEED 23000 + +struct emc2305_data +{ + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; +}; + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int emc2305_remove(struct i2c_client *client); + +static const struct i2c_device_id emc2305_id[] = +{ + { "emc2305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +static struct i2c_driver emc2305_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, + .detect = emc2305_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(fan3_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 4); +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(fan3_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 2); +static SENSOR_DEVICE_ATTR(fan4_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 3); +static SENSOR_DEVICE_ATTR(fan5_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 4); +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 SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); + +static struct attribute *emc2305_attr[] = +{ + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_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_fan3_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan4_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan5_input_percentage.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.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 emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_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 emc2305_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, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_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 emc2305_data *data = i2c_get_clientdata(client); + int val; + + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_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 emc2305_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, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_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 emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_byte_data(client, + EMC2305_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 emc2305_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, + EMC2305_REG_FAN_DRIVE(attr->index), + val); + mutex_unlock(&data->lock); + return count; +} + +static int emc2305_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, EMC2305_REG_VENDOR); + if (vendor != EMC2305_VENDOR) + { + return -ENODEV; + } + + device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE); + if (device != EMC2305_DEVICE) + { + return -ENODEV; + } + + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + + return 0; +} + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int err; + int i; + + data = devm_kzalloc(&client->dev, sizeof(struct emc2305_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 = emc2305_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 < 5; i++) + { + /* set minimum drive to 0% */ + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_CONF(i), FAN_RPM_BASED); + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_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(emc2305_driver); + +MODULE_AUTHOR("Neal Tai"); +MODULE_DESCRIPTION("SMSC EMC2305 fan controller driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh new file mode 100755 index 000000000000..c5f897ff007f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +#platform init script for Delta ag9032v1 + +#fan speed monitol start +/usr/share/sonic/device/x86_64-delta_ag9032v1-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_ag9032v1-r0/fancontrol & + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh new file mode 100755 index 000000000000..5685bd71f58c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh @@ -0,0 +1,225 @@ +#!/bin/bash + +FAN1_EEPROM="-y 31 0x51 0x0a" +FAN2_EEPROM="-y 32 0x52 0x0a" +FAN3_EEPROM="-y 33 0x53 0x0a" +FAN4_EEPROM="-y 34 0x54 0x0a" +FAN5_EEPROM="-y 35 0x55 0x0a" +LED_CONTROL="/sys/devices/platform/delta-ag9032v1-cpld.0/led_control" +FAN1_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan5_input" +FAN1_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan5_input" +FAN2_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan4_input" +FAN2_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan4_input" +FAN3_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan3_input" +FAN3_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan3_input" +FAN4_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan2_input" +FAN4_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan2_input" +FAN5_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan1_input" +FAN5_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan1_input" + +PSU1_EEPROM="-y 40 0x50 0x00" +PSU2_EEPROM="-y 41 0x50 0x00" +PSU1_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-4/i2c-40/40-0058/fan1_input" +PSU2_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-4/i2c-41/41-0058/fan1_input" + +catfaneeprom(){ + fan_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num_num)) + fi + + i2cget $FAN3_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN4_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN5_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi +} + +catfanspeed(){ + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_front_rpm=`cat $FAN1_FRONT_RPM` + fan1_rear_rpm=`cat $FAN1_REAR_RPM` + if [ "${fan1_front_rpm}" -ne "960" ] && [ "${fan1_rear_rpm}" -ne "960" ] && [ "${fan1_front_rpm}" -ne "0" ] && [ "${fan1_rear_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_front_rpm}" -eq "960" ] || [ "${fan1_rear_rpm}" -eq "960" ] || [ "${fan1_front_rpm}" -eq "0" ] || [ "${fan1_rear_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_front_rpm=`cat $FAN2_FRONT_RPM` + fan2_rear_rpm=`cat $FAN2_REAR_RPM` + if [ "${fan2_front_rpm}" -ne "960" ] && [ "${fan2_rear_rpm}" -ne "960" ] && [ "${fan2_front_rpm}" -ne "0" ] && [ "${fan2_rear_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_front_rpm}" -eq "960" ] || [ "${fan2_rear_rpm}" -eq "960" ] || [ "${fan2_front_rpm}" -eq "0" ] || [ "${fan2_rear_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan3_rpm_normal_num=0 + fan3_front_rpm=`cat $FAN3_FRONT_RPM` + fan3_rear_rpm=`cat $FAN3_REAR_RPM` + if [ "${fan3_front_rpm}" -ne "960" ] && [ "${fan3_rear_rpm}" -ne "960" ] && [ "${fan3_front_rpm}" -ne "0" ] && [ "${fan3_rear_rpm}" -ne "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num+1)) + elif [ "${fan3_front_rpm}" -eq "960" ] || [ "${fan3_rear_rpm}" -eq "960" ] || [ "${fan3_front_rpm}" -eq "0" ] || [ "${fan3_rear_rpm}" -eq "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num)) + fi + + fan4_rpm_normal_num=0 + fan4_front_rpm=`cat $FAN4_FRONT_RPM` + fan4_rear_rpm=`cat $FAN4_REAR_RPM` + if [ "${fan4_front_rpm}" -ne "960" ] && [ "${fan4_rear_rpm}" -ne "960" ] && [ "${fan4_front_rpm}" -ne "0" ] && [ "${fan4_rear_rpm}" -ne "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num+1)) + elif [ "${fan4_front_rpm}" -eq "960" ] || [ "${fan4_rear_rpm}" -eq "960" ] || [ "${fan4_front_rpm}" -eq "0" ] || [ "${fan4_rear_rpm}" -eq "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num)) + fi + + fan5_rpm_normal_num=0 + fan5_front_rpm=`cat $FAN5_FRONT_RPM` + fan5_rear_rpm=`cat $FAN5_REAR_RPM` + if [ "${fan5_front_rpm}" -ne "960" ] && [ "${fan5_rear_rpm}" -ne "960" ] && [ "${fan5_front_rpm}" -ne "0" ] && [ "${fan5_rear_rpm}" -ne "0" ]; then + fan5_rpm_normal_num=$((fan5_rpm_normal_num+1)) + elif [ "${fan5_front_rpm}" -eq "960" ] || [ "${fan5_rear_rpm}" -eq "960" ] || [ "${fan5_front_rpm}" -eq "0" ] || [ "${fan5_rear_rpm}" -eq "0" ]; then + fan5_rpm_normal_num=$((fan5_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num+fan3_rpm_normal_num+fan4_rpm_normal_num+fan5_rpm_normal_num)) + +} + +catpsueeprom(){ + psu1_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu1_eeprom_num=$((psu1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu1_eeprom_num=$((psu1_eeprom_num)) + fi + + psu2_eeprom_num=0 + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu2_eeprom_num=$((psu2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu2_eeprom_num=$((psu2_eeprom_num)) + fi +} + +catpsufanspeed(){ + + psu1_rpm_normal_num=0 + psu1_rpm=`cat $PSU1_FAN_RPM` + + if [ "${psu1_rpm}" -ne "960" ] && [ "${psu1_rpm}" -ne "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num+1)) + elif [ "${psu1_rpm}" -eq "960" ] || [ "${psu1_rpm}" -eq "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num)) + fi + + psu2_rpm_normal_num=0 + psu2_rpm=`cat $PSU2_FAN_RPM` + + if [ "${psu2_rpm}" -ne "960" ] && [ "${psu2_rpm}" -ne "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num+1)) + elif [ "${psu2_rpm}" -eq "960" ] || [ "${psu2_rpm}" -eq "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num)) + fi + +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "5" ] && [ "${fan_rpm_normal_num}" -eq "5" ]; then + echo "fan_green" > $LED_CONTROL + elif [ "${fan_eeprom_num}" -lt "5" ] || [ "${fan_rpm_normal_num}" -lt "5" ]; then + echo "fan_amber" > $LED_CONTROL + fi +} + +setpsuled(){ + if [ "${psu1_eeprom_num}" -eq "1" ] && [ "${psu1_rpm_normal_num}" -eq "1" ]; then + echo "pwr1_green" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] || [ "${psu1_rpm_normal_num}" -eq "0" ]; then + echo "pwr1_amber" > $LED_CONTROL + fi + + if [ "${psu2_eeprom_num}" -eq "1" ] && [ "${psu2_rpm_normal_num}" -eq "1" ]; then + echo "pwr2_green" > $LED_CONTROL + elif [ "${psu2_eeprom_num}" -eq "0" ] || [ "${psu2_rpm_normal_num}" -eq "0" ]; then + echo "pwr2_amber" > $LED_CONTROL + fi +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "fan1_green" > $LED_CONTROL + else + echo "fan1_red" > $LED_CONTROL + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "fan2_green" > $LED_CONTROL + else + echo "fan2_red" > $LED_CONTROL + fi + + if [ "${fan3_rpm_normal_num}" -eq "1" ]; then + echo "fan3_green" > $LED_CONTROL + else + echo "fan3_red" > $LED_CONTROL + fi + + if [ "${fan4_rpm_normal_num}" -eq "1" ]; then + echo "fan4_green" > $LED_CONTROL + else + echo "fan4_red" > $LED_CONTROL + fi + + if [ "${fan5_rpm_normal_num}" -eq "1" ]; then + echo "fan5_green" > $LED_CONTROL + else + echo "fan5_red" > $LED_CONTROL + fi +} + +platformstatus(){ + + echo "sys_green" > $LED_CONTROL + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsufanspeed + setpsuled +} + +while true +do + platformstatus + sleep 1 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/changelog b/platform/broadcom/sonic-platform-modules-delta/debian/changelog new file mode 100644 index 000000000000..ec8327e8ae7a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/changelog @@ -0,0 +1,5 @@ +sonic-delta-platform-modules (1.1) unstable; urgency=low + + * Initial release + + -- Neal Tai Fri, 21 APR 2017 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/compat b/platform/broadcom/sonic-platform-modules-delta/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/control b/platform/broadcom/sonic-platform-modules-delta/debian/control new file mode 100644 index 000000000000..7ad1550415be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/control @@ -0,0 +1,11 @@ +Source: sonic-delta-platform-modules +Section: main +Priority: extra +Maintainer: Neal Tai +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-ag9032v1 +Architecture: amd64 +Depends: linux-image-3.16.0-4-amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/files b/platform/broadcom/sonic-platform-modules-delta/debian/files new file mode 100644 index 000000000000..ece02f8e80e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/files @@ -0,0 +1 @@ +platform-modules-ag9032v1_1.1_amd64.deb main extra diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init new file mode 100755 index 000000000000..9b829652fd57 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init @@ -0,0 +1,49 @@ +#!/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 ag9032v1 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_ag9032v1_psu + modprobe dni_emc2305 + modprobe at24 + modprobe delta_ag9032v1_platform + + /usr/local/bin/ag9032v1_platform_init.sh + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag9032v1.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install new file mode 100644 index 000000000000..40f7e56d832d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.install @@ -0,0 +1,3 @@ +ag9032v1/scripts/ag9032v1_platform_init.sh usr/local/bin +ag9032v1/scripts/led_status.sh usr/local/bin +ag9032v1/cfg/ag9032v1-modules.conf etc/modules-load.d diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/rules b/platform/broadcom/sonic-platform-modules-delta/debian/rules new file mode 100644 index 000000000000..ae590626c817 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ag9032v1 + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) +