#!/bin/bash
#
# Copyright 2019-present Huaqin. All Rights Reserved.
#
# This program file 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; version 2 of the License.
#
# 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.
#
#
PART1="/dev/mmcblk0p1"
PART2="/dev/mmcblk0p2"
PART1_MOUNT_POINT="/overlay/rw"
PART2_MOUNT_POINT="/var/volatile/log/"
DEV="/dev/mmcblk0"
prog=$(basename "$0")
usage() {
echo "Usage: ${prog} "
echo
echo "Note:"
echo " configuration : System configurations and user data"
echo " all : All disk data,include user data, syslog and system configurations"
echo
echo "Examples:"
echo " $prog configuration "
echo " $prog all "
echo
exit 1
}
check_parameter() {
if [ $# -ne 1 ]; then
usage
fi
obj="$1"
if [ "${obj}" != "configuration" ] && [ "${obj}" != "all" ]; then
usage
fi
}
format_fs_1() {
mkfs.ext4 $PART1 << EOF
y
EOF
}
partition_rm_1() {
fdisk $DEV << EOF
d
1
w
EOF
}
format_fs_2() {
mkfs.ext4 $PART2 << EOF
y
EOF
}
partition_rm_2() {
fdisk $DEV << EOF
d
2
w
EOF
}
format_emmc() {
if [ "$format_flag" = 1 ]; then
case $obj in
configuration)
umount -lf $PART1_MOUNT_POINT || (echo "umount $PART1 fail !" && exit 1)
format_fs_1
sleep 3
partition_rm_1
sleep 3
partprobe $DEV
;;
all)
umount -lf $PART2_MOUNT_POINT || (echo "umount $PART2 fail !" && exit 1)
format_fs_2
sleep 3
partition_rm_2
sleep 3
partprobe $DEV
;;
*)
usage
;;
esac
fi
echo "reboot after 10S"
sleep 10
reboot
}
confirm_prompt() {
case $obj in
configuration)
read -r -p $'This operaion will restore system configurations.\x0aPlease confirm. [Y/N] ' input
;;
all)
read -r -p $'This operaion will format emmc and discard all system configurations.\x0aPlease confirm. [Y/N] ' input
;;
*)
usage
;;
esac
case $input in
[yY][eE][sS] | [yY])
echo "Start to perform restore default command."
format_flag=1
;;
[nN][oO] | [nN])
echo "Abort execution and exit."
exit 1
;;
*)
echo "Invalid input..."
exit 1
;;
esac
}
check_parameter "$@"
confirm_prompt
format_emmc
#!/bin/bash
. /usr/local/bin/openbmc-utils.sh
BLACKBOX_ADDRESS=0xdc
BLACKBOX_PAGE_ADDRESS=0xdb
OUTPUTFILE=/var/log/dump_acbel_psu_blackbox.txt
program=$(basename "$0")
usage() {
echo "Usage:"
echo " $program -i "
echo
echo "PSU index:"
echo " 1-4"
echo
echo "Examples:"
echo " $program -i 4"
exit 1
}
decompose_iic_addr()
{
bus=$(echo "$1" | awk -F "-" '{print $1}')
str=$(echo "$1" | awk -F "-" '{print $2}')
address=${str/00/0x}
}
check_parameter()
{
if [ "$#" -ne 2 ];then
usage
fi
device="$2"
if [ "$device" != "1" ] && [ "$device" != "2" ] && [ "$device" != "3" ] && [ "$device" != "4" ];then
usage
fi
}
linear11_convert()
{
if [ $((($1 >> 10) & 0x1)) == 1 ] ; then
mantissa=$(($1 & 0x3FF))
mantissa=$(($mantissa ^ 0x3ff))
mantissa=$((~$mantissa))
else
mantissa=$(((((($1 & 0x7ff)) << 5)) >> 5))
fi
if [ $((($1 >> 15) & 0x1)) == 1 ] ; then
exponent=$(((($1 & 0x7FFF)) >> 11))
exponent=$(($exponent ^ 0xf))
exponent=$((~$exponent))
else
exponent=$(($1>> 11))
fi
val_x=$((mantissa * 1000))
if [ $exponent -ge 0 ]; then
val_x=$(($val_x<<$exponent))
else
val_x=$(($val_x>>$((-$exponent))))
fi
echo $val_x
}
linear11_convert $1
linear11_convert()
{
mantissa=$(((((($1 & 0x7ff)) << 5)) >> 5))
if [ $((($1 >> 15) & 0x1)) == 1 ] ; then
exponent=$(((($1 & 0x7FFF)) >> 11))
exponent=$(($exponent ^ 0xf))
exponent=$((~$exponent))
else
exponent=$(($1>> 11))
fi
val_x=$((mantissa * 1000))
if [ $exponent -ge 0 ]; then
val_x=$(($val_x<<$exponent))
else
val_x=$(($val_x>>$((-$exponent))))
fi
echo $val_x
}
linear16_convert()
{
mantissa=$(printf %d "$1")
if [ $((($2 >> 4) & 0x1)) == 1 ] ; then
exponent=$(((((($2 << 11)) >> 11)) & 0xf))
exponent=$(($exponent ^ 0xf))
exponent=$((~$exponent))
else
exponent=$(printf %d "$2")
fi
val_x=$((mantissa * 1000))
if [ $exponent -ge 0 ]; then
val_x=$(($val_x<<$exponent))
else
val_x=$(($val_x>>$((-$exponent))))
fi
echo $val_x
}
do_action()
{
value=$(i2ctransfer -f -y $bus w1@$address $BLACKBOX_ADDRESS r52)
present_psu_on_time_l=${value:7:2}
present_psu_on_time_m=${value:12:2}
present_psu_on_time_h=${value:17:2}
present_psu_on_time="0x""$present_psu_on_time_h""$present_psu_on_time_m""$present_psu_on_time_l"
present_psu_on_time=$(printf %d "$present_psu_on_time")
echo "Present total PSU ON time: $present_psu_on_time min" >> $OUTPUTFILE
present_num_ac_cycles_l=${value:22:2}
present_num_ac_cycles_h=${value:27:2}
present_num_ac_cycles="0x""$present_num_ac_cycles_h""$present_num_ac_cycles_l"
present_num_ac_cycles=$(printf %d "$present_num_ac_cycles")
echo "Present number of AC power cycles: $present_num_ac_cycles" >> $OUTPUTFILE
present_num_pson_cycles_l=${value:32:2}
present_num_pson_cycles_h=${value:37:2}
present_num_pson_cycles="0x""$present_num_pson_cycles_h""$present_num_pson_cycles_l"
present_num_pson_cycles=$(printf %d "$present_num_pson_cycles")
echo "Present number of PSON power cycles: $present_num_pson_cycles" >> $OUTPUTFILE
power_on_time_l=${value:42:2}
power_on_time_m=${value:47:2}
power_on_time_h=${value:52:2}
power_on_time="0x""$power_on_time_h""$power_on_time_m""$power_on_time_l"
power_on_time=$(printf %d "$power_on_time")
echo "Power supply total power on time: $power_on_time" >> $OUTPUTFILE
clock_data_l=${value:57:2}
clock_data_m1=${value:62:2}
clock_data_m2=${value:67:2}
clock_data_h=${value:72:2}
clock_data="0x""$clock_data_h""$clock_data_m2""$clock_data_m1""$clock_data_l"
clock_data=$(printf %d "$clock_data")
echo "Real Time Clock Data from System: $clock_data" >> $OUTPUTFILE
num_ac_cycles_l=${value:77:2}
num_ac_cycles_h=${value:82:2}
num_ac_cycles="0x""$num_ac_cycles_h""$num_ac_cycles_l"
num_ac_cycles=$(printf %d "$num_ac_cycles")
echo "Number of AC power cycles: $num_ac_cycles" >> $OUTPUTFILE
num_pson_cycles_l=${value:87:2}
num_pson_cycles_h=${value:92:2}
num_pson_cycles="0x""$num_pson_cycles_h""$num_pson_cycles_l"
num_pson_cycles=$(printf %d "$num_pson_cycles")
echo "Number of PSON power cycles: $num_pson_cycles" >> $OUTPUTFILE
status_word_l=${value:97:2}
status_word_h=${value:102:2}
status_word="0x""$status_word_h""$status_word_l"
if [ $((($status_word >> 1) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: CML: A communications, memory or logic fault has occurred Refer to STATUS_CML" >> $OUTPUTFILE
elif [ $((($status_word >> 2) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: TEMPERATURE: A temperature fault or warning has occurred Refer to STATUS_TEMPER ATURE" >> $OUTPUTFILE
elif [ $((($status_word >> 3) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: VIN_UV_FAULT: An input under voltage fault has occurred Refer to STATUS_INPUT" >> $OUTPUTFILE
elif [ $((($status_word >> 4) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: IOUT_OC_FAULT: An output over current fault has occurred Refer to STATUS_IOUT" >> $OUTPUTFILE
elif [ $((($status_word >> 5) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: VOUT_OV_FAULT: An output overvoltage fault has occurred Refer to STATUS_VOUT" >> $OUTPUTFILE
elif [ $((($status_word >> 6) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: OFF: This bit is asserted if the unit is not providing power to the output " >> $OUTPUTFILE
elif [ $((($status_word >> 10) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: FANS: A fan or airflow fault or warning has occurred Refer to STATUS_FANS" >> $OUTPUTFILE
elif [ $((($status_word >> 11) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: POWER_GOOD: The POWER_GOOD signal, if present, is negated Reflects real time state of PSU" >> $OUTPUTFILE
elif [ $((($status_word >> 13) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: INPUT: An input voltage, input current, or input power fault or warning has occurred Refer to STATUS_INPUT" >> $OUTPUTFILE
elif [ $((($status_word >> 14) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: IOUT/POUT: An output current or output power fault or warning has occurred Refer to STATUS_IOUT" >> $OUTPUTFILE
elif [ $((($status_word >> 15) & 0x1)) == 1 ] ; then
echo "STATUS_WORD: VOUT: An output voltage fault or warning has occurred Refer to STATUS_VOUT" >> $OUTPUTFILE
fi
status_vout_l=${value:107:2}
status_vout="0x""$status_vout_l"
if [ $((($status_vout >> 4) & 0x1)) == 1 ] ; then
echo "STATUS_VOUT: VOUT_UV_FAULT: Output Under voltage Fault STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
elif [ $((($status_vout >> 7) & 0x1)) == 1 ] ; then
echo "STATUS_VOUT: VOUT_OV_FAULT: Output Overvoltage Fault STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
fi
status_iout_l=${value:112:2}
status_iout="0x""$status_iout_l"
if [ $(($status_iout & 0x1)) == 1 ] ; then
echo "STATUS_IOUT: POUT_OP_WARNING: Predictive failure STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_iout >> 1) & 0x1)) == 1 ] ; then
echo "STATUS_IOUT: POUT_OP_FAULT: Failure STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
elif [ $((($status_iout >> 5) & 0x1)) == 1 ] ; then
echo "STATUS_IOUT: IOUT_OC_WARNING: Predictive failure STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_iout >> 7) & 0x1)) == 1 ] ; then
echo "STATUS_IOUT: IOUT_OC_FAULT : Failure STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): OFF">> $OUTPUTFILE
fi
status_input_l=${value:117:2}
status_input="0x""$status_input_l"
if [ $(($status_input & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: PIN_OP_WARNING: Predictive failure STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_input >> 1) & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: IIN_OC_WARNING: Predictive failure STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_input >> 2) & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: IIN_OC_FAULT: Input Overcurrent Fault STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
elif [ $((($status_input >> 3) & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: Unit Off for Low Input Voltage : Either the input voltage has never exceeded the input turn-on threshold or if the unit did start,\
the input voltage decreased below the turn-off threshold STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
elif [ $((($status_input >> 4) & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: VIN_UV_FAULT: Input Under voltage Fault STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
elif [ $((($status_input >> 5) & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: VIN_UV_WARNING: Predictive failure STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_input >> 7) & 0x1)) == 1 ] ; then
echo "STATUS_INPUT: VIN_OV_FAULT: Input Overvoltage Fault STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
fi
status_temp_l=${value:122:2}
status_temp="0x""$status_temp_l"
if [ $((($status_temp >> 6) & 0x1)) == 1 ] ; then
echo "STATUS_TEMPERATURE: OT_WARNING: Over Temperature Warning STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_temp >> 7) & 0x1)) == 1 ] ; then
echo "STATUS_TEMPERATURE: OT_FAULT: Over Temperature Fault STATUS bit Auto Recovery: Yes PSU state when bit is asserted('1'): OFF" >> $OUTPUTFILE
fi
status_cml_l=${value:127:2}
status_cml="0x""$status_cml_l"
if [ $((($status_cml >> 5) & 0x1)) == 1 ] ; then
echo "STATUS_CML: Packet Error Check Failed: Packet Error Check Failed STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_cml >> 6) & 0x1)) == 1 ] ; then
echo "STATUS_CML: Invalid/Unsupported Data: Invalid Or Unsupported Data Received STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
elif [ $((($status_cml >> 7) & 0x1)) == 1 ] ; then
echo "STATUS_CML: Invalid/Unsupported Command: Invalid Or Unsupported Command Received STATUS bit Auto Recovery: No PSU state when bit is asserted('1'): ON" >> $OUTPUTFILE
fi
status_fan_1_2_l=${value:132:2}
status_fan_1_2="0x""$status_fan_1_2_l"
if [ $((($status_fan_1_2 >> 3) & 0x1)) == 1 ] ; then
echo "STATUS_FAN_1_2: Fan 1 Speed Overridden : Fan 1 overridden occurred STATUS bit Auto Recovery: Yes" >> $OUTPUTFILE
elif [ $((($status_fan_1_2 >> 5) & 0x1)) == 1 ] ; then
echo "STATUS_FAN_1_2: Fan 1 Warning : Fan 1 warning occurred STATUS bit Auto Recovery: Yes" >> $OUTPUTFILE
elif [ $((($status_fan_1_2 >> 7) & 0x1)) == 1 ] ; then
echo "STATUS_FAN_1_2: Fan 1 Fault : Fan 1 fault occurred STATUS bit Auto Recovery: Yes" >> $OUTPUTFILE
fi
read_vin_l=${value:137:2}
read_vin_h=${value:142:2}
read_vin="0x""$read_vin_h""$read_vin_l"
read_vin=$(linear11_convert $read_vin)
read_vin=$(awk 'BEGIN{printf "%.2f\n",'$read_vin'/1000}')
echo "READ_VIN: $read_vin V" >> $OUTPUTFILE
read_iin_l=${value:147:2}
read_iin_h=${value:152:2}
read_iin="0x""$read_iin_h""$read_iin_l"
read_iin=$(linear11_convert $read_iin)
read_iin=$(awk 'BEGIN{printf "%.2f\n",'$read_iin'/1000}')
echo "READ_IIN: $read_iin A" >> $OUTPUTFILE
read_vout_l=${value:157:2}
read_vout_h=${value:162:2}
read_vout="0x""$read_vout_h""$read_vout_l"
mode_vout=$(i2cget -f -y $bus $address 0x20)
read_vout=$(linear16_convert $read_vout $mode_vout)
read_vout=$(awk 'BEGIN{printf "%.2f\n",'$read_vout'/1000}')
echo "READ_VOUT: $read_vout V" >> $OUTPUTFILE
read_iout_l=${value:167:2}
read_iout_h=${value:172:2}
read_iout="0x""$read_iout_h""$read_iout_l"
read_iout=$(linear11_convert $read_iout)
read_iout=$(awk 'BEGIN{printf "%.2f\n",'$read_iout'/1000}')
echo "READ_IOUT: $read_iout A" >> $OUTPUTFILE
read_temp_1_l=${value:177:2}
read_temp_1_h=${value:182:2}
read_temp_1="0x""$read_temp_1_h""$read_temp_1_l"
read_temp_1=$(linear11_convert $read_temp_1)
read_temp_1=$(awk 'BEGIN{printf "%.2f\n",'$read_temp_1'/1000}')
echo "READ_TEMPERATURE_1 (Ambient): $read_temp_1 C" >> $OUTPUTFILE
read_temp_2_l=${value:187:2}
read_temp_2_h=${value:192:2}
read_temp_2="0x""$read_temp_2_h""$read_temp_2_l"
read_temp_2=$(linear11_convert $read_temp_2)
read_temp_2=$(awk 'BEGIN{printf "%.2f\n",'$read_temp_2'/1000}')
echo "READ_TEMPERATURE_2 (Hot Spot): $read_temp_2 C" >> $OUTPUTFILE
read_temp_3_l=${value:197:2}
read_temp_3_h=${value:202:2}
read_temp_3="0x""$read_temp_3_h""$read_temp_3_l"
read_temp_3=$(linear11_convert $read_temp_3)
read_temp_3=$(awk 'BEGIN{printf "%.2f\n",'$read_temp_3'/1000}')
echo "READ_TEMPERATURE_3 (Primary): $read_temp_3 C" >> $OUTPUTFILE
read_fan_speed_1_l=${value:207:2}
read_fan_speed_1_h=${value:212:2}
read_fan_speed_1="0x""$read_fan_speed_1_h""$read_fan_speed_1_l"
read_fan_speed_1=$(linear11_convert $read_fan_speed_1)
read_fan_speed_1=$(awk 'BEGIN{printf "%.2f\n",'$read_fan_speed_1'/1000}')
echo "READ_FAN_SPEED_1: $read_fan_speed_1 RPM" >> $OUTPUTFILE
read_pout_l=${value:217:2}
read_pout_h=${value:222:2}
read_pout="0x""$read_pout_h""$read_pout_l"
read_pout=$(linear11_convert $read_pout)
read_pout=$(awk 'BEGIN{printf "%.2f\n",'$read_pout'/1000}')
echo "READ_POUT: $read_pout W" >> $OUTPUTFILE
read_pin_l=${value:227:2}
read_pin_h=${value:232:2}
read_pin="0x""$read_pin_h""$read_pin_l"
read_pin=$(linear11_convert $read_pin)
read_pin=$(awk 'BEGIN{printf "%.2f\n",'$read_pin'/1000}')
echo "READ_PIN: $read_pin W" >> $OUTPUTFILE
ac_shutdown=${value:237:2}
ac_shutdown="0x""$ac_shutdown"
ac_shutdown_l=$(($ac_shutdown & 0xf))
ac_shutdown_l=$(printf %d "$ac_shutdown_l")
echo "AC shutdown due to under voltage on input: $ac_shutdown_l" >> $OUTPUTFILE
thermal_shutdown_h=$((($ac_shutdown >> 4) & 0xf))
thermal_shutdown_h=$(printf %d "$thermal_shutdown_h")
echo "Thermal shutdown: $thermal_shutdown_h" >> $OUTPUTFILE
output_shutdown=${value:242:2}
output_shutdown="0x""$output_shutdown"
output_shutdown_l=$(($output_shutdown & 0xf))
output_shutdown_l=$(printf %d "$output_shutdown_l")
echo "Over current or over power shutdown on output: $output_shutdown_l" >> $OUTPUTFILE
general_shutdown_h=$((($output_shutdown >> 4) & 0xf))
general_shutdown_h=$(printf %d "$general_shutdown_h")
echo "General failure shutdown: $general_shutdown_h" >> $OUTPUTFILE
fan_fail_shutdown=${value:247:2}
fan_fail_shutdown="0x""$fan_fail_shutdown"
fan_fail_shutdown_l=$(($fan_fail_shutdown & 0xf))
fan_fail_shutdown_l=$(printf %d "$fan_fail_shutdown_l")
echo "Fan failure shutdown: $fan_fail_shutdown_l" >> $OUTPUTFILE
voltage_shutdown_h=$((($fan_fail_shutdown >> 4) & 0xf))
voltage_shutdown_h=$(printf %d "$voltage_shutdown_h")
echo "Shutdown due to over voltage on output: $voltage_shutdown_h" >> $OUTPUTFILE
voltage_warning_no_shutdown=${value:252:2}
voltage_warning_no_shutdown="0x""$voltage_warning_no_shutdown"
voltage_warning_no_shutdown_l=$(($voltage_warning_no_shutdown & 0xf))
voltage_warning_no_shutdown_l=$(printf %d "$voltage_warning_no_shutdown_l")
echo "Input voltage warning; no shutdown: $voltage_warning_no_shutdown_l" >> $OUTPUTFILE
thermal_warning_no_shutdown_h=$((($voltage_warning_no_shutdown >> 4) & 0xf))
thermal_warning_no_shutdown_h=$(printf %d "$thermal_warning_no_shutdown_h")
echo "Thermal warning; no shutdown: $thermal_warning_no_shutdown_h" >> $OUTPUTFILE
current_power_warning_no_shutdown=${value:257:2}
current_power_warning_no_shutdown="0x""$current_power_warning_no_shutdown"
current_power_warning_no_shutdown_l=$(($current_power_warning_no_shutdown & 0xf))
current_power_warning_no_shutdown_l=$(printf %d "$current_power_warning_no_shutdown_l")
echo "Output current power warning; no shutdown: $current_power_warning_no_shutdown_l" >> $OUTPUTFILE
fan_slow_warning_no_shutdown_h=$((($current_power_warning_no_shutdown >> 4) & 0xf))
fan_slow_warning_no_shutdown_h=$(printf %d "$fan_slow_warning_no_shutdown_h")
echo "Fan slow warning; no shutdown: $fan_slow_warning_no_shutdown_h" >> $OUTPUTFILE
}
do_action_all()
{
prn_sta=$(get_psu_present "$device")
if [ "$prn_sta" -eq 0 ];then
echo "psu$device absent , please dump present psu"
exit 1
fi
full_addr=${PSU_PMBUS_SLAVE_ADDR_ARRAY[$device-1]}
decompose_iic_addr "${full_addr}"
echo "MFR_BLACKBOX_PAGE = 0x00 " >> $OUTPUTFILE
i2cset -f -y $bus $address $BLACKBOX_PAGE_ADDRESS 0x00
do_action
echo " " >> $OUTPUTFILE
echo "MFR_BLACKBOX_PAGE = 0x01 " >> $OUTPUTFILE
i2cset -f -y $bus $address $BLACKBOX_PAGE_ADDRESS 0x01
do_action
echo " " >> $OUTPUTFILE
echo "MFR_BLACKBOX_PAGE = 0x02 " >> $OUTPUTFILE
i2cset -f -y $bus $address $BLACKBOX_PAGE_ADDRESS 0x02
do_action
echo " " >> $OUTPUTFILE
echo "MFR_BLACKBOX_PAGE = 0x03 " >> $OUTPUTFILE
i2cset -f -y $bus $address $BLACKBOX_PAGE_ADDRESS 0x03
do_action
echo " " >> $OUTPUTFILE
echo "MFR_BLACKBOX_PAGE = 0x04 " >> $OUTPUTFILE
i2cset -f -y $bus $address $BLACKBOX_PAGE_ADDRESS 0x04
do_action
echo "dump psu$psu_num blackbox data to $OUTPUTFILE ok."
}
check_parameter "$@"
do_action_all
#!/bin/bash
source /usr/local/bin/openbmc-utils.sh
COME_CPLD_FW="0.01.06_COMe.vme"
PROGRAM=$(basename "$0")
LCNUM=2
SET_COME_HEART_VALUE_1=0x3
SET_COME_HEART_VALUE_2=0x4
COME_HEART_FAILED_COUNTS_LIMIT=3
COME_UPGRADE_FAILED_COUNTS_LIMIT=3
come_heart_failed_counts=()
come_upgrade_failed_counts=()
come_cpld_hotswap_flag=()
check_file_ok()
{
if [ ! -f "$COME_CPLD_FW" ]; then
logger -p user.err -t "$PROGRAM" "$COME_CPLD_FW doesnot exist, exit!!!"
echo "$PROGRAM:" "$COME_CPLD_FW doesnot exist, exit!!!"
exit 255
fi
}
init_failed_counts()
{
for((index=1;index<="${LCNUM}";index++));
do
come_heart_failed_counts[$index]=0
come_upgrade_failed_counts[$index]=0
done
}
check_come_cpld_hotswap()
{
come_cpld_hotswap_flag[$index]=false
}
check_come_cpld_status()
{
if "${come_cpld_hotswap_flag[$index]}" ; then
come_upgrade_failed_counts[$index]=0
fi
lc_prnt=$(get_lc_present "${index}")
if [ "${lc_prnt}" -eq 1 ];then
come_sta=$(is_come_power_ok "${index}")
if [ "${come_sta}" -eq 1 ];then
if [[ "${come_upgrade_failed_counts[$index]}" < "$COME_UPGRADE_FAILED_COUNTS_LIMIT" ]] ; then
check_heart_failed_count
fi
fi
else
come_upgrade_failed_counts[$index]=0
fi
}
check_heart_failed_count()
{
for((come_heart_failed_counts[$index]=0 ; ${come_heart_failed_counts[$index]}<"$COME_HEART_FAILED_COUNTS_LIMIT" ; come_heart_failed_counts[$index]++));
do
come_scratch_path="${LCCOME_PATH_DICT[$index]}/come_scratch"
echo "$SET_COME_HEART_VALUE_1" > "$come_scratch_path"
read_value_1=$(head -n 1 < "$come_scratch_path")
sleep 5
echo "$SET_COME_HEART_VALUE_2" > "$come_scratch_path"
read_value_2=$(head -n 1 < "$come_scratch_path")
if [ "$read_value_1" == "$SET_COME_HEART_VALUE_1" ] && [ "$read_value_2" == "$SET_COME_HEART_VALUE_2" ]; then
come_heart_failed_counts[$index]=0
come_upgrade_failed_counts[$index]=0
break
fi
done
if [ "${come_heart_failed_counts[$index]}" == "$COME_HEART_FAILED_COUNTS_LIMIT" ] ; then
come_heart_failed_counts[$index]=0
check_upgrade_failed_count
fi
}
check_upgrade_failed_count()
{
for((come_upgrade_failed_counts[$index]=0 ; ${come_upgrade_failed_counts[$index]}<"$COME_UPGRADE_FAILED_COUNTS_LIMIT" ; come_upgrade_failed_counts[$index]++));
do
if ! /usr/local/bin/upgrade_cpld -d come -f $COME_CPLD_FW -i $index; then
reboot_str=$(reboot_cpu -i $index -o cycle)
if echo "$reboot_str" | grep Success > /dev/null 2>&1 ; then
echo "$SET_COME_HEART_VALUE_1" > "$come_scratch_path"
read_value=$(head -n 1 < "$come_scratch_path")
if [ "$read_value" == "$SET_COME_HEART_VALUE_1" ];then
come_heart_failed_counts[$index]=0
come_upgrade_failed_counts[$index]=0
break
fi
fi
fi
done
if [ "${come_upgrade_failed_counts[$index]}" == "$COME_UPGRADE_FAILED_COUNTS_LIMIT" ] ; then
logger -p user.err -t "$PROGRAM:" "come$index cpld upgrade failed times has exceeded limit value $COME_UPGRADE_FAILED_COUNTS_LIMIT"
fi
}
check_file_ok
init_failed_counts
while true
do
for((index=1;index<="${LCNUM}";index++));
do
check_come_cpld_hotswap
check_come_cpld_status
sleep 5
done
sleep 6
done
test.sh
#!/bin/bash
function help_usage(){
echo "Usage: test.sh [OPTIONS]"
echo "Available options:"
echo "-h [options help] help"
echo "-d [value] device num"
echo "-p [value] power"
echo "-f [value] fine-tuning enble"
echo "-o [value] offset"
echo "-c [value] channle"
echo "-n [value] freq_n_value"
echo "-l [value] laser on/off"
echo "-m [messages] messages"
echo "-s [status] status"
}
ARGS=`getopt -o hd:p:sc:mn:f:o:l: -n "$0" -- "$@"`
PRAM="flase"
POWER="flase"
STATUS="flase"
CHANNLE="flase"
FREQ="flase"
MESSAGES="flase"
LASER="flase"
FINETUNING="flase"
OFFSET="flase"
while true
do
case "$1" in
-h)
help_usage
exit 0
;;
-d)
case "$2" in
"")
echo -e "ERROR:NO device number please input 0-15"
help_usage
exit 1
;;
*)
val=$2
PRAM="true"
shift 2
;;
esac
;;
-p)
case "$2" in
"")
echo -e "Woring: NO value,please input low or high"
;;
*)
value=$2
POWER="true"
shift 2
;;
esac
;;
-s)
STATUS="true"
break
;;
-m)
MESSAGES="true"
break
;;
-f)
case "$2" in
"")
echo -e "ERROR:NO param please input enble or disable"
help_usage
exit 1
;;
*)
FINETUNING="true"
finetuning=$2
shift 2
;;
esac
;;
-o)
case "$2" in
"")
echo -e "ERROR:NO param please input offset of fine-tuning"
echo -e "fine-tuning offset range low:-5000 high:5000"
help_usage
exit 1
;;
*)
OFFSET="true"
offset=$2
shift 2
;;
esac
;;
-c)
case "$2" in
"")
echo -e "ERROR:NO channle module please input"
echo -e "channle module support 3.125 6.25 12.5 25 50 75 100ghz,33ghz not support "
help_usage
exit 1
;;
*)
CHANNLE="true"
channle=$2
shift 2
;;
esac
;;
-n)
case "$2" in
"")
echo -e "ERROR:NO frequency param please input"
help_usage
exit 1
;;
*)
FREQ="true"
frequency=$2
shift 2
;;
esac
;;
-l)
case "$2" in
"")
echo -e "ERROR:NO param please input on or off"
help_usage
exit 1
;;
*)
LASER="true"
laser=$2
shift 2
;;
esac
;;
"")
if [ "$PRAM" = "true" ] ;then
break
else
help_usage
exit 0
fi
;;
*)
help_usage
exit 0
;;
esac
done
BASE_INFO="base_info"
WAVE_SWITCH="wavelength_switch"
dev=14
bus=`expr ${val} + ${dev}`
if [ $bus -ge 14 ] && [ $bus -le 29 ] && [ "$PRAM" = "true" ];then
device_path="/sys/bus/i2c/drivers/zr_optoe/$bus-0050/"
else
echo " input port num is error"
exit 0
fi
if [ -d "$device_path" ];then
module_type=`cd $device_path$BASE_INFO && cat module_type`
if [ $module_type != 0x1 ];then
echo " the port nmmber $val is not color module"
exit 0
fi
fi
if [ -d "$device_path" ] && [ "$FINETUNING" = "true" ] && [ "$OFFSET" = "true" ] ;then
datapath_status=`cd $device_path$BASE_INFO && cat lane1_host_status`
if [ $offset -gt 5000 ] || [ $offset -lt -5000 ];then
echo "fine-tuning offset out of range, low:-5000 high:5000"
exit 0
fi
if [ $datapath_status = 0x1 ] || [ $datapath_status = 0x4 ] || [ $datapath_status = 0x7 ];then
if [ $finetuning != "enble" ] && [ $finetuning != "disable" ];then
echo " fine-tuning switch value is error,enble or disable"
exit 1
elif [ $finetuning = "enble" ];then
cd $device_path$WAVE_SWITCH && echo 0x1 > lane1_ftg_enable && echo $offset > lane1_ftg_offset
old_freq=`cd $device_path$WAVE_SWITCH && cat lane1_cha_num`
cd $device_path$WAVE_SWITCH && echo $old_freq > lane1_cha_num
echo "fine-tuning change success"
else
cd $device_path$WAVE_SWITCH && echo 0x0 > lane1_ftg_enable && echo $offset > lane1_ftg_offset
echo "fine-tuning turn off success"
fi
else
echo "the color module datapath status can't change frequency "
exit 0
fi
else
if [ "$FINETUNING" = "true" ];then
echo "device is not exist"
exit 1
fi
fi
if [ -d "$device_path" ] && [ "$POWER" = "true" ];then
oldvalue=`cd $device_path$BASE_INFO && cat ctrl_power`
if [ $value != "high" ] && [ $value != "low" ];then
echo " power value is error,high or low"
exit 1
elif [ $oldvalue = 0x0 ] && [ $value = "high" ];then
echo "It's already high power"
exit 1
elif [ $oldvalue != 0x0 ] && [ $value = "low" ];then
echo "it's already low power"
exit 1
elif [ $oldvalue != 0x0 ] && [ $value = "high" ];then
cd $device_path$BASE_INFO && echo 0x0 > ctrl_power
sleep 0.5
high_power=`cd $device_path$BASE_INFO && cat ctrl_power`
if [ $high_power = 0x0 ];then
echo "change high power success"
echo "high power"
else
echo "change high power fail"
fi
exit 0
else
cd $device_path$BASE_INFO && echo 0x40 > ctrl_power
sleep 0.5
low_power=`cd $device_path$BASE_INFO && cat ctrl_power`
if [ $low_power = 0x40 ];then
echo "change low power success"
echo "low power"
else
echo "change low power fail"
fi
exit 0
fi
else
if [ "$POWER" = "true" ];then
echo "device is not exist"
exit 1
fi
fi
if [ -d "$device_path" ] && [ "$CHANNLE" = "true" ] && [ "$FREQ" = "true" ];then
datapath_status=`cd $device_path$BASE_INFO && cat lane1_host_status`
if [ $datapath_status = 0x1 ] || [ $datapath_status = 0x4 ] || [ $datapath_status = 0x7 ];then
case $channle in
3.125)
cd $device_path$WAVE_SWITCH && echo 0x0 > lane1_grid_spac
if [ $frequency -ge -576 ] && [ $frequency -le 960 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 3.125ghz frequency success"
else
echo " freqency param n is out of range,check or cmd -m"
exit 0
fi
;;
6.25)
cd $device_path$WAVE_SWITCH && echo 0x1 > lane1_grid_spac
if [ $frequency -ge -288 ] && [ $frequency -le 480 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 6.25ghz frequency success"
else
echo " freqency param n is out of range,check or cmd -m"
exit 0
fi
;;
12.5)
cd $device_path$WAVE_SWITCH && echo 0x2 > lane1_grid_spac
if [ $frequency -ge -144 ] && [ $frequency -le 240 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 12.5ghz frequency fail"
else
echo " freqency param n is out of range,check or cmd -m"
exit 0
fi
;;
25)
cd $device_path$WAVE_SWITCH && echo 0x3 > lane1_grid_spac
if [ $frequency -ge -72 ] && [ $frequency -le 120 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 25ghz frequency success"
else
echo " freqency param n is out of range,check or cmd -m"
exit 0
fi
;;
50)
cd $device_path$WAVE_SWITCH && echo 0x4 > lane1_grid_spac
if [ $frequency -ge -36 ] && [ $frequency -le 60 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 50ghz frequency success"
else
echo " freqency param n is out of range,check or cmd -m"
exit 0
fi
;;
75)
cd $device_path$WAVE_SWITCH && echo 0x6 > lane1_grid_spac
right_param=`expr $frequency % 3`
if [ $frequency -ge -72 ] && [ $frequency -le 120 ] && [ $right_param = 0 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 75ghz frequency success"
else
echo " freqency param n is out of range,or param error,check or cmd -m"
exit 0
fi
;;
100)
cd $device_path$WAVE_SWITCH && echo 0x5 > lane1_grid_spac
if [ $frequency -ge -18 ] && [ $frequency -le 30 ];then
cd $device_path$WAVE_SWITCH && echo $frequency > lane1_cha_num
echo "change 100ghz frequency success"
else
echo " freqency param n is out of range,check or cmd -m for detail messages"
exit 0
fi
;;
*) echo "channle param is error ,check or cmd -m for detail messages"
;;
esac
else
echo "the color module datapath status can't change frequency "
exit 0
fi
else
if [ "$CHANNNLE" = "true" ];then
echo "device is not exist"
exit 1
fi
fi
if [ -d "$device_path" ] && [ "$LASER" = "true" ];then
if [ $laser != "on" ] && [ $laser != "off" ];then
echo " laser switch value is error,on or off"
exit 1
elif [ $laser = "on" ];then
cd $device_path$BASE_INFO && echo 0x0 > laser_on_off && echo 0x0 > tx1_disable
echo "laser turn on success"
else
cd $device_path$BASE_INFO && echo 0xff > laser_on_off && echo 0x1 > tx1_disable
echo "laser turn off success"
fi
else
if [ "$LASER" = "true" ];then
echo "device is not exist"
fi
fi
if [ -d "$device_path" ] && [ "$STATUS" = "true" ];then
echo "QDD$val is color module and exist,following detail messages"
ftg_enble=`cd $device_path$WAVE_SWITCH && cat lane1_ftg_enable`
ftg_offset=`cd $device_path$WAVE_SWITCH && cat lane1_ftg_offset`
if [ $ftg_enble = 0x1 ];then
echo "current fine-tuning is turn on,the offset is $ftg_offset"
else
echo "current fine-tuning is turn off,the offset is $ftg_offset"
fi
grid_spac=`cd $device_path$WAVE_SWITCH && cat lane1_grid_spac`
if [ $grid_spac = 0x0 ];then
echo "current channle is 3.125ghz"
grid_spac=3.125
elif [ $grid_spac = 0x1 ];then
echo "current channle is 6.25ghz"
grid_spac=6.25
elif [ $grid_spac = 0x2 ];then
echo "current channle is 12.5ghz"
grid_spac=12.5
elif [ $grid_spac = 0x3 ];then
echo "current channle is 25ghz"
grid_spac=25
elif [ $grid_spac = 0x4 ];then
echo "current channle is 50ghz"
grid_spac=50
elif [ $grid_spac = 0x5 ];then
echo "current channle is 100ghz"
grid_spac=100
elif [ $grid_spac = 0x6 ];then
echo "current channle is 75ghz"
grid_spac=75
else
echo "current channle is not support"
fi
cha_value=`cd $device_path$WAVE_SWITCH && cat lane1_cha_num`
echo "the $grid_spac ghz n value is $cha_value"
current_freq=`cd $device_path$WAVE_SWITCH && cat lane1_cur_freq`
echo "the $grid_spac ghz current frequency is $current_freq"
laser_on=`cd $device_path$BASE_INFO && cat laser_on_off`
laser_enble=`cd $device_path$BASE_INFO && cat tx1_disable`
if [ $laser_on = 0x0 ] && [ $laser_enble = 0x0 ];then
echo "current laser status turn on already"
else
echo "current laser status is turn off "
fi
high_power=`cd $device_path$BASE_INFO && cat ctrl_power`
if [ $high_power = 0x0 ];then
echo "current device status high power"
else
echo "current device status low power"
fi
tx1_power=`cd $device_path$BASE_INFO && cat tx1_power`
echo "QDD$val tx1_power is $tx1_power"
rx1_power=`cd $device_path$BASE_INFO && cat rx1_power`
echo "QDD$val rx1_power is $rx1_power"
datapath_status=`cd $device_path$BASE_INFO && cat lane1_host_status`
if [ $datapath_status = 0x1 ];then
echo "datapath status is DataPathDeactivated"
elif [ $datapath_status = 0x2 ];then
echo "datapath status is DataPathInit"
elif [ $datapath_status = 0x3 ];then
echo "datapath status is DataPathDeinit"
elif [ $datapath_status = 0x4 ];then
echo "datapath status is DataPathActivated"
elif [ $datapath_status = 0x5 ];then
echo "datapath status is DataPathTxTurnOn"
elif [ $datapath_status = 0x6 ];then
echo "datapath status is DataPathTxTurnOff"
elif [ $datapath_status = 0x7 ];then
echo "datapath status is DataPathInitialized"
else
echo "datapath status is Reserved"
fi
else
if [ "$STATUS" = "true" ];then
echo "device is not exist"
exit 1
fi
fi
if [ -d "$device_path" ] && [ "$MESSAGES" = "true" ];then
echo "here are funetuning offset range low:-5000 high:5000"
echo "here are channle whether support and channle frequency n range!"
echo "3.125G SUPPORT: channle n low = -576,channle n high = 960"
echo "3.125G FREQ =193.1 + n*0.003125"
echo "6.25G SUPPORT: channle n low = -288,channle n high = 480"
echo "6.25G FREQ =193.1 + n*0.00625"
echo "12.5G SUPPORT: channle n low = -144,channle n high = 240"
echo "12.5G FREQ =193.1 + n*0.0125"
echo "25G SUPPORT: channle n low = -72, channle n high = 120"
echo "25G FREQ =193.1 + n*0.025"
echo "50G SUPPORT: channle n low = -36, channle n high = 60"
echo "50G FREQ =193.1 + n*0.05"
echo "75G SUPPORT: channle n low = -72, channle n high = 120"
echo "75G FREQ =193.1 + n*0.025 n%3=0"
echo "100G SUPPORT: channle n low = -18, channle n high = 30"
echo "100G FREQ =193.1 + n*0.1"
echo "33G NOT SUPPORT: channle n low = -54, channle n high = 90"
else
if [ "$MESSAGES" = "true" ];then
echo "device is not exist"
exit 1
fi
fi
def.h
hwmon-sysfs.h
#ifndef _LINUX_HWMON_SYSFS_H
#define _LINUX_HWMON_SYSFS_H
#include
struct sensor_device_attribute {
struct device_attribute dev_attr;
int index;
};
#define to_sensor_dev_attr(_dev_attr) \
container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \
{ \
.dev_attr = __ATTR(_name, _mode, _show, _store), \
.index = _index \
}
#define SENSOR_ATTR_RO(_name, _func, _index) \
SENSOR_ATTR(_name, 0444, _func##_show, NULL, _index)
#define SENSOR_ATTR_RW(_name, _func, _index) \
SENSOR_ATTR(_name, 0644, _func##_show, _func##_store, _index)
#define SENSOR_ATTR_WO(_name, _func, _index) \
SENSOR_ATTR(_name, 0200, NULL, _func##_store, _index)
#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
struct sensor_device_attribute sensor_dev_attr_##_name \
= SENSOR_ATTR(_name, _mode, _show, _store, _index)
#define SENSOR_DEVICE_ATTR_RO(_name, _func, _index) \
SENSOR_DEVICE_ATTR(_name, 0444, _func##_show, NULL, _index)
#define SENSOR_DEVICE_ATTR_RW(_name, _func, _index) \
SENSOR_DEVICE_ATTR(_name, 0644, _func##_show, _func##_store, _index)
#define SENSOR_DEVICE_ATTR_WO(_name, _func, _index) \
SENSOR_DEVICE_ATTR(_name, 0200, NULL, _func##_store, _index)
struct sensor_device_attribute_2 {
struct device_attribute dev_attr;
u8 index;
u8 nr;
};
#define to_sensor_dev_attr_2(_dev_attr) \
container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr)
#define SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) \
{ \
.dev_attr = __ATTR(_name, _mode, _show, _store), \
.index = _index, \
.nr = _nr \
}
#define SENSOR_ATTR_2_RO(_name, _func, _nr, _index) \
SENSOR_ATTR_2(_name, 0444, _func##_show, NULL, _nr, _index)
#define SENSOR_ATTR_2_RW(_name, _func, _nr, _index) \
SENSOR_ATTR_2(_name, 0644, _func##_show, _func##_store, _nr, _index)
#define SENSOR_ATTR_2_WO(_name, _func, _nr, _index) \
SENSOR_ATTR_2(_name, 0200, NULL, _func##_store, _nr, _index)
#define SENSOR_DEVICE_ATTR_2(_name, _mode, _show, _store, _nr, _index) \
struct sensor_device_attribute_2 sensor_dev_attr_##_name \
= SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index)
#define SENSOR_DEVICE_ATTR_2_RO(_name, _func, _nr, _index) \
SENSOR_DEVICE_ATTR_2(_name, 0444, _func##_show, NULL, _nr, _index)
#define SENSOR_DEVICE_ATTR_2_RW(_name, _func, _nr, _index) \
SENSOR_DEVICE_ATTR_2(_name, 0644, _func##_show, _func##_store, _nr, _index)
#define SENSOR_DEVICE_ATTR_2_WO(_name, _func, _nr, _index) \
SENSOR_DEVICE_ATTR_2(_name, 0200, NULL, _func##_store, _nr, _index)
#endif
Makefile
obj-m := cpld_lpc.o cpld_i2c.o i2c-ocores.o mc24lc64t.o optoe.o fpga_i2c_adapter.o switchboard.o \
ina2xx.o pxe1410.o i2c_dev_sysfs.o i2c_kobj_sysfs.o sn1701022.o xdpe12284.o zr_optoe.o
all:
#make -C /mnt/sda/daili/haishen/lcj/wangjian/header/usr/src/linux-headers-4.9.0-14-2-amd64 M=$(PWD) modules
make -C /home/4.9-head/header/usr/src/linux-headers-4.9.0-14-2-amd64 M=$(PWD) modules
clean:
#make -C /mnt/sda/daili/haishen/lcj/wangjian/header/usr/src/linux-headers-4.9.0-14-2-amd64 M=$(PWD) clean
make -C /home/4.9-head/header/usr/src/linux-headers-4.9.0-14-2-amd64 M=$(PWD) clean
mc24lc64t.c
#include
#include
#include
#include
#include
#include
#include
#include
#define EEPROM_SIZE 8192
struct mc24lc64t_data {
struct mutex update_lock;
};
static ssize_t mc24lc64t_read(
struct file *filp,
struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf,
loff_t off,
size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
size_t timeout, read_time, i = 0;
int32_t status;
if (drvdata == NULL)
return -ENODEV;
if (i2c_smbus_write_byte_data(client, off >> 8, off)) {
status = -EIO;
goto exit;
}
msleep(1);
mutex_lock(&drvdata->update_lock);
begin:
if (i < count) {
timeout = jiffies + msecs_to_jiffies(25);
do {
read_time = jiffies;
status = i2c_smbus_read_byte(client);
if (status >= 0) {
buf[i++] = status;
goto begin;
}
} while (time_before(read_time, timeout));
status = -ETIMEDOUT;
goto exit;
}
status = count;
exit:
mutex_unlock(&drvdata->update_lock);
return status;
}
static ssize_t mc24lc64t_write(
struct file *filp,
struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf,
loff_t off,
size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
size_t timeout, write_time, i = 0;
int32_t status;
u16 value;
if (drvdata == NULL)
return -ENODEV;
mutex_lock(&drvdata->update_lock);
begin:
if (i < count) {
timeout = jiffies + msecs_to_jiffies(25);
value = (buf[i] << 8 | (off & 0xff));
do {
write_time = jiffies;
status = i2c_smbus_write_word_data(client, off >> 8, value);
if (status == 0) {
off++;
i++;
goto begin;
}
} while (time_before(write_time, timeout));
status = -ETIMEDOUT;
goto exit;
}
status = count;
exit:
mutex_unlock(&drvdata->update_lock);
return status;
}
static struct bin_attribute mc24lc64t_bit_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO | S_IWUGO,
},
.size = EEPROM_SIZE,
.read = mc24lc64t_read,
.write = mc24lc64t_write,
};
static int32_t mc24lc64t_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct mc24lc64t_data *drvdata;
int32_t err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_READ_BYTE))
return -EPFNOSUPPORT;
if (!(drvdata = devm_kzalloc(&client->dev, sizeof(struct mc24lc64t_data), GFP_KERNEL)))
return -ENOMEM;
i2c_set_clientdata(client, drvdata);
mutex_init(&drvdata->update_lock);
err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
return err;
}
static int32_t mc24lc64t_remove(struct i2c_client *client)
{
sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
return 0;
}
static const struct i2c_device_id mc24lc64t_id[] = {{"24lc64t", 0}, {}};
MODULE_DEVICE_TABLE(i2c, mc24lc64t_id);
static struct i2c_driver mc24lc64t_driver = {
.driver = {
.name = "mc24lc64t",
.owner = THIS_MODULE,
},
.probe = mc24lc64t_probe,
.remove = mc24lc64t_remove,
.id_table = mc24lc64t_id,
};
module_i2c_driver(mc24lc64t_driver);
MODULE_AUTHOR("Huaqin Technology Co.,Ltd.");
MODULE_DESCRIPTION("Hua Qin 24LC64T Driver");
MODULE_VERSION("0.0.1");
MODULE_LICENSE("GPL");
optoe.c
#undef EEPROM_CLASS
#ifdef CONFIG_EEPROM_CLASS
#define EEPROM_CLASS
#endif
#ifdef CONFIG_EEPROM_CLASS_MODULE
#define EEPROM_CLASS
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "i2c_kobj_sysfs.h"
#ifdef EEPROM_CLASS
#include
#endif
#include
#define MAX_PORT_NAME_LEN 20
struct optoe_platform_data {
uint32_t byte_len;
uint16_t page_size;
uint8_t flags;
void *dummy1;
void *dummy2;
#ifdef EEPROM_CLASS
struct eeprom_platform_data *eeprom_data;
#endif
char port_name[MAX_PORT_NAME_LEN];
};
#define OPTOE_PAGE_SIZE 128
#define OPTOE_ARCH_PAGES 256
#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE)
#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE)
#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE)
#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE)
#define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE)
#define OPTOE_PAGE_SELECT_REG 0x7F
#define ONE_ADDR_PAGEABLE_REG 0x02
#define QSFP_NOT_PAGEABLE BIT(2)
#define CMIS_NOT_PAGEABLE BIT(7)
#define TWO_ADDR_PAGEABLE_REG 0x40
#define TWO_ADDR_PAGEABLE BIT(4)
#define TWO_ADDR_0X51_REG 92
#define TWO_ADDR_0X51_SUPP BIT(6)
#define OPTOE_ID_REG 0
#define OPTOE_READ_OP 0
#define OPTOE_WRITE_OP 1
#define OPTOE_EOF 0
#define HEX2DEC_2_BYTE_LEN 7
#define NODE_DIR "optoe_test_node"
struct optoe_data {
struct optoe_platform_data chip;
int32_t use_smbus;
char port_name[MAX_PORT_NAME_LEN];
struct mutex lock;
struct bin_attribute bin;
struct attribute_group attr_group;
uint8_t *writebuf;
uint32_t write_max;
uint32_t num_addresses;
#ifdef EEPROM_CLASS
struct eeprom_device *eeprom_dev;
#endif
int32_t dev_class;
struct i2c_client *client[];
};
static uint32_t io_limit = OPTOE_PAGE_SIZE;
static uint32_t write_timeout = 25;
#define ONE_ADDR 1
#define TWO_ADDR 2
#define CMIS_ADDR 3
static const struct i2c_device_id optoe_ids[] = {{"optoe1", ONE_ADDR}, {"optoe2", TWO_ADDR}, {"optoe3", CMIS_ADDR}, {"sff8436", ONE_ADDR}, {"24c04", TWO_ADDR}, {}};
MODULE_DEVICE_TABLE(i2c, optoe_ids);
static uint8_t optoe_translate_offset(struct optoe_data *optoe, loff_t *offset, struct i2c_client **client)
{
uint32_t page = 0;
*client = optoe->client[0];
if (optoe->dev_class == TWO_ADDR) {
if (*offset > 255) {
*client = optoe->client[1];
*offset -= 256;
}
}
if (*offset < OPTOE_PAGE_SIZE)
return page;
page = (*offset >> 7) - 1;
*offset = OPTOE_PAGE_SIZE + (*offset & 0x7f);
return page;
}
static ssize_t
optoe_eeprom_read(struct optoe_data *optoe, struct i2c_client *client, char *buf, uint32_t offset, size_t count)
{
struct i2c_msg msg[2];
uint8_t msgbuf[2];
size_t timeout, read_time;
int32_t status, i;
memset(msg, 0, sizeof(msg));
switch (optoe->use_smbus) {
case I2C_SMBUS_I2C_BLOCK_DATA:
if (count > I2C_SMBUS_BLOCK_MAX)
count = I2C_SMBUS_BLOCK_MAX;
break;
case I2C_SMBUS_WORD_DATA:
count = (count == 1) ? 1 : 2;
break;
case I2C_SMBUS_BYTE_DATA:
count = 1;
break;
default:
i = 0;
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;
}
timeout = jiffies + msecs_to_jiffies(write_timeout);
do {
read_time = jiffies;
switch (optoe->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, "eeprom read %zu@%d --> %d (%ld)\n", count, offset, status, jiffies);
if (status == count)
return count;
if (status == -ENXIO)
return status;
usleep_range(1000, 2000);
} while (time_before(read_time, timeout));
return -ETIMEDOUT;
}
static ssize_t
optoe_eeprom_write(struct optoe_data *optoe, struct i2c_client *client, const char *buf, uint32_t offset, size_t count)
{
struct i2c_msg msg;
ssize_t status;
size_t timeout, write_time;
uint32_t next_page_start;
int32_t i = 0;
if (count > optoe->write_max)
count = optoe->write_max;
next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE);
if (offset + count > next_page_start)
count = next_page_start - offset;
switch (optoe->use_smbus) {
case I2C_SMBUS_I2C_BLOCK_DATA:
if (count > I2C_SMBUS_BLOCK_MAX)
count = I2C_SMBUS_BLOCK_MAX;
break;
case I2C_SMBUS_WORD_DATA:
count = (count == 1) ? 1 : 2;
break;
case I2C_SMBUS_BYTE_DATA:
count = 1;
break;
default:
msg.addr = client->addr;
msg.flags = 0;
msg.buf = optoe->writebuf;
msg.buf[i++] = offset;
memcpy(&msg.buf[i], buf, count);
msg.len = i + count;
break;
}
timeout = jiffies + msecs_to_jiffies(write_timeout);
do {
write_time = jiffies;
switch (optoe->use_smbus) {
case I2C_SMBUS_I2C_BLOCK_DATA:
status = i2c_smbus_write_i2c_block_data(client, offset, count, buf);
if (status == 0)
status = count;
break;
case I2C_SMBUS_WORD_DATA:
if (count == 2) {
status = i2c_smbus_write_word_data(client, offset, (uint16_t)((buf[0]) | (buf[1] << 8)));
} else {
status = i2c_smbus_write_byte_data(client, offset, buf[0]);
}
if (status == 0)
status = count;
break;
case I2C_SMBUS_BYTE_DATA:
status = i2c_smbus_write_byte_data(client, offset, buf[0]);
if (status == 0)
status = count;
break;
default:
status = i2c_transfer(client->adapter, &msg, 1);
if (status == 1)
status = count;
break;
}
dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", count, offset, (long int)status, jiffies);
if (status == count)
return count;
usleep_range(1000, 2000);
} while (time_before(write_time, timeout));
return -ETIMEDOUT;
}
static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, char *buf, loff_t off, size_t count, int32_t opcode)
{
struct i2c_client *client;
ssize_t retval = 0;
uint8_t page = 0;
loff_t phy_offset = off;
int32_t ret = 0;
page = optoe_translate_offset(optoe, &phy_offset, &client);
dev_dbg(
&client->dev, "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", __func__, off, page, phy_offset,
(long int)count, opcode);
if (page > 0) {
ret = optoe_eeprom_write(optoe, client, &page, OPTOE_PAGE_SELECT_REG, 1);
if (ret < 0) {
dev_dbg(&client->dev, "Write page register for page %d failed ret:%d!\n", page, ret);
return ret;
}
}
while (count) {
ssize_t status;
if (opcode == OPTOE_READ_OP) {
status = optoe_eeprom_read(optoe, client, buf, phy_offset, count);
} else {
status = optoe_eeprom_write(optoe, client, buf, phy_offset, count);
}
if (status <= 0) {
if (retval == 0)
retval = status;
break;
}
buf += status;
phy_offset += status;
count -= status;
retval += status;
}
if (page > 0) {
page = 0;
ret = optoe_eeprom_write(optoe, client, &page, OPTOE_PAGE_SELECT_REG, 1);
if (ret < 0) {
dev_err(&client->dev, "Restore page register to 0 failed:%d!\n", ret);
if (retval == 0)
retval = ret;
}
}
return retval;
}
static ssize_t optoe_page_legal(struct optoe_data *optoe, loff_t off, size_t len)
{
struct i2c_client *client = optoe->client[0];
uint8_t regval;
int32_t not_pageable;
int32_t status;
size_t maxlen;
if (off < 0)
return -EINVAL;
if (optoe->dev_class == TWO_ADDR) {
if ((off + len) <= TWO_ADDR_NO_0X51_SIZE)
return len;
if (off >= TWO_ADDR_EEPROM_SIZE)
return OPTOE_EOF;
status = optoe_eeprom_read(optoe, client, ®val, TWO_ADDR_PAGEABLE_REG, 1);
if (status < 0)
return status;
if (regval & TWO_ADDR_PAGEABLE) {
maxlen = TWO_ADDR_EEPROM_SIZE - off;
} else {
if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE)
return OPTOE_EOF;
status = optoe_eeprom_read(optoe, client, ®val, TWO_ADDR_0X51_REG, 1);
if (status < 0)
return status;
if (regval & TWO_ADDR_0X51_SUPP) {
maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off;
} else {
if (off >= TWO_ADDR_NO_0X51_SIZE)
return OPTOE_EOF;
maxlen = TWO_ADDR_NO_0X51_SIZE - off;
}
}
len = (len > maxlen) ? maxlen : len;
dev_dbg(&client->dev, "page_legal, SFP, off %lld len %ld\n", off, (long int)len);
} else {
if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE)
return len;
if (off >= ONE_ADDR_EEPROM_SIZE)
return OPTOE_EOF;
status = optoe_eeprom_read(optoe, client, ®val, ONE_ADDR_PAGEABLE_REG, 1);
if (status < 0)
return status;
if (optoe->dev_class == ONE_ADDR) {
not_pageable = QSFP_NOT_PAGEABLE;
} else {
not_pageable = CMIS_NOT_PAGEABLE;
}
dev_dbg(&client->dev, "Paging Register: 0x%x; not_pageable mask: 0x%x\n", regval, not_pageable);
if (regval & not_pageable) {
if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE)
return OPTOE_EOF;
maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off;
} else {
maxlen = ONE_ADDR_EEPROM_SIZE - off;
}
len = (len > maxlen) ? maxlen : len;
dev_dbg(&client->dev, "page_legal, QSFP, off %lld len %ld\n", off, (long int)len);
}
return len;
}
static ssize_t optoe_read_write(struct optoe_data *optoe, char *buf, loff_t off, size_t len, int32_t opcode)
{
struct i2c_client *client = optoe->client[0];
int32_t chunk;
int32_t status = 0;
ssize_t retval;
size_t pending_len = 0, chunk_len = 0;
loff_t chunk_offset = 0, chunk_start_offset = 0;
loff_t chunk_end_offset = 0;
dev_dbg(
&client->dev, "%s: off %lld len:%ld, opcode:%s\n", __func__, off, (long int)len,
(opcode == OPTOE_READ_OP) ? "r" : "w");
if (unlikely(!len))
return len;
mutex_lock(&optoe->lock);
status = optoe_page_legal(optoe, off, len);
if ((status == OPTOE_EOF) || (status < 0)) {
mutex_unlock(&optoe->lock);
return status;
}
len = status;
pending_len = len;
retval = 0;
for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) {
chunk_start_offset = chunk * OPTOE_PAGE_SIZE;
chunk_end_offset = chunk_start_offset + OPTOE_PAGE_SIZE;
if (chunk_start_offset < off) {
chunk_offset = off;
if ((off + pending_len) < chunk_end_offset)
chunk_len = pending_len;
else
chunk_len = chunk_end_offset - off;
} else {
chunk_offset = chunk_start_offset;
if (pending_len < OPTOE_PAGE_SIZE)
chunk_len = pending_len;
else
chunk_len = OPTOE_PAGE_SIZE;
}
dev_dbg(
&client->dev,
"sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n",
off, (long int)len, chunk_start_offset, chunk_offset, (long int)chunk_len, (long int)pending_len);
status = optoe_eeprom_update_client(optoe, buf, chunk_offset, chunk_len, opcode);
if (status != chunk_len) {
dev_dbg(
&client->dev, "o_u_c: chunk %d c_offset %lld c_len %ld failed %d!\n", chunk, chunk_offset,
(long int)chunk_len, status);
if (status > 0)
retval += status;
if (retval == 0)
retval = status;
break;
}
buf += status;
pending_len -= status;
retval += status;
}
mutex_unlock(&optoe->lock);
return retval;
}
static ssize_t
optoe_bin_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count)
{
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
struct optoe_data *optoe = i2c_get_clientdata(client);
if (!client || !optoe) {
return -ENODEV;
}
return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP);
}
static ssize_t optoe_bin_write(
struct file *filp,
struct kobject *kobj,
struct bin_attribute *attr,
char *buf,
loff_t off,
size_t count)
{
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
struct optoe_data *optoe = i2c_get_clientdata(client);
return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP);
}
static int32_t optoe_remove(struct i2c_client *client)
{
struct optoe_data *optoe;
int32_t i;
optoe = i2c_get_clientdata(client);
sysfs_remove_group(&client->dev.kobj, &optoe->attr_group);
sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin);
for (i = 1; i < optoe->num_addresses; i++)
i2c_unregister_device(optoe->client[i]);
#ifdef EEPROM_CLASS
eeprom_device_unregister(optoe->eeprom_dev);
#endif
kfree(optoe->writebuf);
kfree(optoe);
return 0;
}
static ssize_t show_dev_class(struct device *dev, struct device_attribute *dattr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct optoe_data *optoe = i2c_get_clientdata(client);
ssize_t count;
if (!client || !optoe) {
return -ENODEV;
}
mutex_lock(&optoe->lock);
count = snprintf(buf, PAGE_SIZE, "%d\n", optoe->dev_class);
mutex_unlock(&optoe->lock);
return count;
}
static ssize_t set_dev_class(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct optoe_data *optoe = i2c_get_clientdata(client);
int32_t dev_class;
if (!client || !optoe) {
return -ENODEV;
}
if (kstrtoint(buf, 0, &dev_class) != 0 || dev_class < 1 || dev_class > 3)
return -EINVAL;
mutex_lock(&optoe->lock);
if (dev_class == TWO_ADDR) {
if (!optoe->client[1]) {
optoe->client[1] = i2c_new_dummy(client->adapter, 0x51);
if (!optoe->client[1]) {
dev_err(&client->dev, "address 0x51 unavailable\n");
mutex_unlock(&optoe->lock);
return -EADDRINUSE;
}
}
optoe->bin.size = TWO_ADDR_EEPROM_SIZE;
optoe->num_addresses = 2;
} else {
if (optoe->client[1])
i2c_unregister_device(optoe->client[1]);
optoe->bin.size = ONE_ADDR_EEPROM_SIZE;
optoe->num_addresses = 1;
}
optoe->dev_class = dev_class;
mutex_unlock(&optoe->lock);
return count;
}
static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class);
#ifndef EEPROM_CLASS
static ssize_t show_port_name(struct device *dev, struct device_attribute *dattr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct optoe_data *optoe = i2c_get_clientdata(client);
ssize_t count;
if (!client || !optoe)
return -ENODEV;
mutex_lock(&optoe->lock);
count = snprintf(buf, MAX_PORT_NAME_LEN, "%s\n", optoe->port_name);
mutex_unlock(&optoe->lock);
return count;
}
static ssize_t set_port_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct optoe_data *optoe = i2c_get_clientdata(client);
char port_name[MAX_PORT_NAME_LEN];
if (sscanf(buf, "%19s", port_name) != 1)
return -EINVAL;
mutex_lock(&optoe->lock);
strncpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN);
mutex_unlock(&optoe->lock);
return count;
}
static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name);
#endif
static struct attribute *optoe_attrs[] = {
#ifndef EEPROM_CLASS
&dev_attr_port_name.attr,
#endif
&dev_attr_dev_class.attr,
NULL,
};
static struct attribute_group optoe_attr_group = {
.attrs = optoe_attrs,
};
static ssize_t default_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct i2c_client *client = kobj_to_i2c_client(kobj->parent);
struct optoe_data *optoe = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_kobj_attr_st *dev_attr;
ssize_t retval;
char val, val_mask, reg_val;
const size_t len = 1;
if (!client || !optoe) {
return -ENODEV;
}
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -ENODEV;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr->ida_show) {
return -EINVAL;
}
optoe->use_smbus = I2C_SMBUS_BYTE_DATA;
retval = optoe_read_write(optoe, ®_val, dev_attr->ida_reg, len, OPTOE_READ_OP);
if (retval != len) {
return -EINVAL;
}
val_mask = (1 << (dev_attr->ida_n_bits)) - 1;
val = (reg_val >> dev_attr->ida_bit_offset) & val_mask;
return snprintf(buf, PAGE_SIZE, "%#x\n", val);
}
static ssize_t default_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj->parent);
struct optoe_data *optoe = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_kobj_attr_st *dev_attr;
ssize_t retval;
char val;
size_t req_val;
size_t req_val_mask;
const size_t len = 1;
if (!client || !optoe) {
return -ENODEV;
}
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -ENODEV;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -ENODEV;
retval = kstrtoul(buf, 0, &req_val);
if (retval < 0) {
return -EINVAL;
}
req_val_mask = ~(((-1) >> (dev_attr->ida_n_bits)) << (dev_attr->ida_n_bits));
req_val &= req_val_mask;
optoe->use_smbus = I2C_SMBUS_BYTE_DATA;
retval = optoe_read_write(optoe, &val, dev_attr->ida_reg, len, OPTOE_READ_OP);
if (retval != len) {
return -EINVAL;
}
val &= ~(req_val_mask << dev_attr->ida_bit_offset);
val |= req_val << dev_attr->ida_bit_offset;
retval = optoe_read_write(optoe, &val, dev_attr->ida_reg, len, OPTOE_WRITE_OP);
if (retval != len) {
return -EINVAL;
}
return count;
}
static ssize_t freq_span_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct i2c_client *client = kobj_to_i2c_client(kobj->parent);
struct optoe_data *optoe = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_kobj_attr_st *dev_attr;
ssize_t retval;
size_t value = 0;
char buffer[HEX2DEC_2_BYTE_LEN] = {};
char reg_val[2] = {};
const size_t len = 2;
if (!client || !optoe) {
return -ENODEV;
}
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -ENODEV;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -ENODEV;
optoe->use_smbus = I2C_SMBUS_BYTE_DATA;
retval = optoe_read_write(optoe, reg_val, dev_attr->ida_reg, len, OPTOE_READ_OP);
if (retval != len) {
return -EINVAL;
}
retval = snprintf(buffer, HEX2DEC_2_BYTE_LEN, "0x%x%x\n", reg_val[0], reg_val[1]);
if (retval == 0) {
return -EINVAL;
}
retval = kstrtoul(buffer, 0, &value);
if (retval < 0) {
return -EINVAL;
}
return snprintf(buf, PAGE_SIZE, "%zu\n", value);
}
static const i2c_kobj_attr_st optoe_attr_table[] = {
{
"low_power",
NULL,
default_show,
default_store,
26,
6,
1,
},
{
"freq_span_range_3_125_low",
NULL,
freq_span_range_show,
NULL,
0x04 * OPTOE_PAGE_SIZE + 130,
0,
16,
},
{
"channel_number_lan1",
NULL,
default_show,
default_store,
0x12 * OPTOE_PAGE_SIZE + 128,
4,
4,
}};
static i2c_kobj_data_st optoe_data;
static int32_t optoe_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int32_t err;
int32_t use_smbus = 0;
struct optoe_platform_data chip;
struct optoe_data *optoe;
int32_t num_addresses = 0;
char port_name[MAX_PORT_NAME_LEN];
int n_attrs = sizeof(optoe_attr_table) / sizeof(optoe_attr_table[0]);
if (client->addr != 0x50) {
dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr);
err = -EINVAL;
goto exit;
}
if (client->dev.platform_data) {
chip = *(struct optoe_platform_data *)client->dev.platform_data;
#ifdef EEPROM_CLASS
strncpy(port_name, chip.eeprom_data->label, MAX_PORT_NAME_LEN);
#else
memcpy(port_name, chip.port_name, MAX_PORT_NAME_LEN);
#endif
dev_dbg(&client->dev, "probe, chip provided, flags:0x%x; name: %s\n", chip.flags, client->name);
} else {
if (!id->driver_data) {
err = -ENODEV;
goto exit;
}
dev_dbg(&client->dev, "probe, building chip\n");
strncpy(port_name, "unitialized", 12);
chip.flags = 0;
#ifdef EEPROM_CLASS
chip.eeprom_data = NULL;
#endif
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
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 {
err = -EPFNOSUPPORT;
goto exit;
}
}
num_addresses = 2;
optoe = kzalloc(sizeof(struct optoe_data) + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
if (!optoe) {
err = -ENOMEM;
goto exit;
}
mutex_init(&optoe->lock);
if ((strcmp(client->name, "optoe1") == 0) || (strcmp(client->name, "sff8436") == 0)) {
optoe->dev_class = ONE_ADDR;
chip.byte_len = ONE_ADDR_EEPROM_SIZE;
num_addresses = 1;
} else if ((strcmp(client->name, "optoe2") == 0) || (strcmp(client->name, "24c04") == 0)) {
optoe->dev_class = TWO_ADDR;
chip.byte_len = TWO_ADDR_EEPROM_SIZE;
num_addresses = 2;
} else if (strcmp(client->name, "optoe3") == 0) {
optoe->dev_class = CMIS_ADDR;
chip.byte_len = ONE_ADDR_EEPROM_SIZE;
num_addresses = 1;
} else {
err = -EINVAL;
goto exit_kfree;
}
dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class);
optoe->use_smbus = use_smbus;
optoe->chip = chip;
optoe->num_addresses = num_addresses;
memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN);
sysfs_bin_attr_init(&optoe->bin);
optoe->bin.attr.name = "eeprom";
optoe->bin.attr.mode = 0444;
optoe->bin.read = optoe_bin_read;
optoe->bin.size = chip.byte_len;
if (!use_smbus || (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA) || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
uint32_t write_max = 1;
optoe->bin.write = optoe_bin_write;
optoe->bin.attr.mode |= 0200;
if (write_max > io_limit)
write_max = io_limit;
if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
write_max = I2C_SMBUS_BLOCK_MAX;
optoe->write_max = write_max;
optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL);
if (!optoe->writebuf) {
err = -ENOMEM;
goto exit_kfree;
}
} else {
dev_warn(&client->dev, "cannot write due to controller restrictions.");
}
optoe->client[0] = client;
if (num_addresses == 2) {
optoe->client[1] = i2c_new_dummy(client->adapter, 0x51);
if (!optoe->client[1]) {
dev_err(&client->dev, "address 0x51 unavailable\n");
err = -EADDRINUSE;
goto err_struct;
}
}
err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin);
if (err)
goto err_struct;
optoe->attr_group = optoe_attr_group;
err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group);
if (err) {
dev_err(&client->dev, "failed to create sysfs attribute group.\n");
goto err_struct;
}
i2c_kobj_sysfs_data_complex_init(client, &optoe_data, optoe_attr_table, n_attrs, NODE_DIR);
#ifdef EEPROM_CLASS
optoe->eeprom_dev = eeprom_device_register(&client->dev, chip.eeprom_data);
if (IS_ERR(optoe->eeprom_dev)) {
dev_err(&client->dev, "error registering eeprom device.\n");
err = PTR_ERR(optoe->eeprom_dev);
goto err_sysfs_cleanup;
}
#endif
i2c_set_clientdata(client, optoe);
dev_info(
&client->dev, "%zu byte %s EEPROM, %s\n", optoe->bin.size, client->name,
optoe->bin.write ? "read/write" : "read-only");
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");
}
return 0;
#ifdef EEPROM_CLASS
err_sysfs_cleanup:
sysfs_remove_group(&client->dev.kobj, &optoe->attr_group);
sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin);
#endif
err_struct:
if (num_addresses == 2) {
if (optoe->client[1])
i2c_unregister_device(optoe->client[1]);
}
kfree(optoe->writebuf);
exit_kfree:
kfree(optoe);
exit:
dev_dbg(&client->dev, "probe error %d\n", err);
return err;
}
static struct i2c_driver optoe_driver = {
.driver = {
.name = "optoe",
.owner = THIS_MODULE,
},
.probe = optoe_probe,
.remove = optoe_remove,
.id_table = optoe_ids,
};
static int32_t __init optoe_init(void)
{
if (!io_limit) {
pr_err("optoe: io_limit must not be 0!\n");
return -EINVAL;
}
io_limit = rounddown_pow_of_two(io_limit);
return i2c_add_driver(&optoe_driver);
}
module_init(optoe_init);
static void __exit optoe_exit(void)
{
i2c_del_driver(&optoe_driver);
}
module_exit(optoe_exit);
MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs");
MODULE_AUTHOR("DON BOLLINGER ");
MODULE_LICENSE("GPL");
pmbus.h
#ifndef PMBUS_H
#define PMBUS_H
#include
#include
enum pmbus_regs
{
PMBUS_PAGE = 0x00,
PMBUS_OPERATION = 0x01,
PMBUS_ON_OFF_CONFIG = 0x02,
PMBUS_CLEAR_FAULTS = 0x03,
PMBUS_PHASE = 0x04,
PMBUS_CAPABILITY = 0x19,
PMBUS_QUERY = 0x1A,
PMBUS_VOUT_MODE = 0x20,
PMBUS_VOUT_COMMAND = 0x21,
PMBUS_VOUT_TRIM = 0x22,
PMBUS_VOUT_CAL_OFFSET = 0x23,
PMBUS_VOUT_MAX = 0x24,
PMBUS_VOUT_MARGIN_HIGH = 0x25,
PMBUS_VOUT_MARGIN_LOW = 0x26,
PMBUS_VOUT_TRANSITION_RATE = 0x27,
PMBUS_VOUT_DROOP = 0x28,
PMBUS_VOUT_SCALE_LOOP = 0x29,
PMBUS_VOUT_SCALE_MONITOR = 0x2A,
PMBUS_COEFFICIENTS = 0x30,
PMBUS_POUT_MAX = 0x31,
PMBUS_FAN_CONFIG_12 = 0x3A,
PMBUS_FAN_COMMAND_1 = 0x3B,
PMBUS_FAN_COMMAND_2 = 0x3C,
PMBUS_FAN_CONFIG_34 = 0x3D,
PMBUS_FAN_COMMAND_3 = 0x3E,
PMBUS_FAN_COMMAND_4 = 0x3F,
PMBUS_VOUT_OV_FAULT_LIMIT = 0x40,
PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41,
PMBUS_VOUT_OV_WARN_LIMIT = 0x42,
PMBUS_VOUT_UV_WARN_LIMIT = 0x43,
PMBUS_VOUT_UV_FAULT_LIMIT = 0x44,
PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45,
PMBUS_IOUT_OC_FAULT_LIMIT = 0x46,
PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47,
PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48,
PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
PMBUS_IOUT_OC_WARN_LIMIT = 0x4A,
PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B,
PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C,
PMBUS_OT_FAULT_LIMIT = 0x4F,
PMBUS_OT_FAULT_RESPONSE = 0x50,
PMBUS_OT_WARN_LIMIT = 0x51,
PMBUS_UT_WARN_LIMIT = 0x52,
PMBUS_UT_FAULT_LIMIT = 0x53,
PMBUS_UT_FAULT_RESPONSE = 0x54,
PMBUS_VIN_OV_FAULT_LIMIT = 0x55,
PMBUS_VIN_OV_FAULT_RESPONSE = 0x56,
PMBUS_VIN_OV_WARN_LIMIT = 0x57,
PMBUS_VIN_UV_WARN_LIMIT = 0x58,
PMBUS_VIN_UV_FAULT_LIMIT = 0x59,
PMBUS_IIN_OC_FAULT_LIMIT = 0x5B,
PMBUS_IIN_OC_WARN_LIMIT = 0x5D,
PMBUS_POUT_OP_FAULT_LIMIT = 0x68,
PMBUS_POUT_OP_WARN_LIMIT = 0x6A,
PMBUS_PIN_OP_WARN_LIMIT = 0x6B,
PMBUS_STATUS_BYTE = 0x78,
PMBUS_STATUS_WORD = 0x79,
PMBUS_STATUS_VOUT = 0x7A,
PMBUS_STATUS_IOUT = 0x7B,
PMBUS_STATUS_INPUT = 0x7C,
PMBUS_STATUS_TEMPERATURE = 0x7D,
PMBUS_STATUS_CML = 0x7E,
PMBUS_STATUS_OTHER = 0x7F,
PMBUS_STATUS_MFR_SPECIFIC = 0x80,
PMBUS_STATUS_FAN_12 = 0x81,
PMBUS_STATUS_FAN_34 = 0x82,
PMBUS_READ_VIN = 0x88,
PMBUS_READ_IIN = 0x89,
PMBUS_READ_VCAP = 0x8A,
PMBUS_READ_VOUT = 0x8B,
PMBUS_READ_IOUT = 0x8C,
PMBUS_READ_TEMPERATURE_1 = 0x8D,
PMBUS_READ_TEMPERATURE_2 = 0x8E,
PMBUS_READ_TEMPERATURE_3 = 0x8F,
PMBUS_READ_FAN_SPEED_1 = 0x90,
PMBUS_READ_FAN_SPEED_2 = 0x91,
PMBUS_READ_FAN_SPEED_3 = 0x92,
PMBUS_READ_FAN_SPEED_4 = 0x93,
PMBUS_READ_DUTY_CYCLE = 0x94,
PMBUS_READ_FREQUENCY = 0x95,
PMBUS_READ_POUT = 0x96,
PMBUS_READ_PIN = 0x97,
PMBUS_REVISION = 0x98,
PMBUS_MFR_ID = 0x99,
PMBUS_MFR_MODEL = 0x9A,
PMBUS_MFR_REVISION = 0x9B,
PMBUS_MFR_LOCATION = 0x9C,
PMBUS_MFR_DATE = 0x9D,
PMBUS_MFR_SERIAL = 0x9E,
PMBUS_VIRT_BASE = 0x100,
PMBUS_VIRT_READ_TEMP_AVG,
PMBUS_VIRT_READ_TEMP_MIN,
PMBUS_VIRT_READ_TEMP_MAX,
PMBUS_VIRT_RESET_TEMP_HISTORY,
PMBUS_VIRT_READ_VIN_AVG,
PMBUS_VIRT_READ_VIN_MIN,
PMBUS_VIRT_READ_VIN_MAX,
PMBUS_VIRT_RESET_VIN_HISTORY,
PMBUS_VIRT_READ_IIN_AVG,
PMBUS_VIRT_READ_IIN_MIN,
PMBUS_VIRT_READ_IIN_MAX,
PMBUS_VIRT_RESET_IIN_HISTORY,
PMBUS_VIRT_READ_PIN_AVG,
PMBUS_VIRT_READ_PIN_MIN,
PMBUS_VIRT_READ_PIN_MAX,
PMBUS_VIRT_RESET_PIN_HISTORY,
PMBUS_VIRT_READ_POUT_AVG,
PMBUS_VIRT_READ_POUT_MIN,
PMBUS_VIRT_READ_POUT_MAX,
PMBUS_VIRT_RESET_POUT_HISTORY,
PMBUS_VIRT_READ_VOUT_AVG,
PMBUS_VIRT_READ_VOUT_MIN,
PMBUS_VIRT_READ_VOUT_MAX,
PMBUS_VIRT_RESET_VOUT_HISTORY,
PMBUS_VIRT_READ_IOUT_AVG,
PMBUS_VIRT_READ_IOUT_MIN,
PMBUS_VIRT_READ_IOUT_MAX,
PMBUS_VIRT_RESET_IOUT_HISTORY,
PMBUS_VIRT_READ_TEMP2_AVG,
PMBUS_VIRT_READ_TEMP2_MIN,
PMBUS_VIRT_READ_TEMP2_MAX,
PMBUS_VIRT_RESET_TEMP2_HISTORY,
PMBUS_VIRT_READ_VMON,
PMBUS_VIRT_VMON_UV_WARN_LIMIT,
PMBUS_VIRT_VMON_OV_WARN_LIMIT,
PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
PMBUS_VIRT_STATUS_VMON,
};
#define PB_OPERATION_CONTROL_ON BIT(7)
#define PB_CAPABILITY_SMBALERT BIT(4)
#define PB_CAPABILITY_ERROR_CHECK BIT(7)
#define PB_VOUT_MODE_MODE_MASK 0xe0
#define PB_VOUT_MODE_PARAM_MASK 0x1f
#define PB_VOUT_MODE_LINEAR 0x00
#define PB_VOUT_MODE_VID 0x20
#define PB_VOUT_MODE_DIRECT 0x40
#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1))
#define PB_FAN_2_RPM BIT(2)
#define PB_FAN_2_INSTALLED BIT(3)
#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5))
#define PB_FAN_1_RPM BIT(6)
#define PB_FAN_1_INSTALLED BIT(7)
#define PB_STATUS_NONE_ABOVE BIT(0)
#define PB_STATUS_CML BIT(1)
#define PB_STATUS_TEMPERATURE BIT(2)
#define PB_STATUS_VIN_UV BIT(3)
#define PB_STATUS_IOUT_OC BIT(4)
#define PB_STATUS_VOUT_OV BIT(5)
#define PB_STATUS_OFF BIT(6)
#define PB_STATUS_BUSY BIT(7)
#define PB_STATUS_UNKNOWN BIT(8)
#define PB_STATUS_OTHER BIT(9)
#define PB_STATUS_FANS BIT(10)
#define PB_STATUS_POWER_GOOD_N BIT(11)
#define PB_STATUS_WORD_MFR BIT(12)
#define PB_STATUS_INPUT BIT(13)
#define PB_STATUS_IOUT_POUT BIT(14)
#define PB_STATUS_VOUT BIT(15)
#define PB_POUT_OP_WARNING BIT(0)
#define PB_POUT_OP_FAULT BIT(1)
#define PB_POWER_LIMITING BIT(2)
#define PB_CURRENT_SHARE_FAULT BIT(3)
#define PB_IOUT_UC_FAULT BIT(4)
#define PB_IOUT_OC_WARNING BIT(5)
#define PB_IOUT_OC_LV_FAULT BIT(6)
#define PB_IOUT_OC_FAULT BIT(7)
#define PB_VOLTAGE_UV_FAULT BIT(4)
#define PB_VOLTAGE_UV_WARNING BIT(5)
#define PB_VOLTAGE_OV_WARNING BIT(6)
#define PB_VOLTAGE_OV_FAULT BIT(7)
#define PB_PIN_OP_WARNING BIT(0)
#define PB_IIN_OC_WARNING BIT(1)
#define PB_IIN_OC_FAULT BIT(2)
#define PB_TEMP_UT_FAULT BIT(4)
#define PB_TEMP_UT_WARNING BIT(5)
#define PB_TEMP_OT_WARNING BIT(6)
#define PB_TEMP_OT_FAULT BIT(7)
#define PB_FAN_AIRFLOW_WARNING BIT(0)
#define PB_FAN_AIRFLOW_FAULT BIT(1)
#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2)
#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3)
#define PB_FAN_FAN2_WARNING BIT(4)
#define PB_FAN_FAN1_WARNING BIT(5)
#define PB_FAN_FAN2_FAULT BIT(6)
#define PB_FAN_FAN1_FAULT BIT(7)
#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0)
#define PB_CML_FAULT_OTHER_COMM BIT(1)
#define PB_CML_FAULT_PROCESSOR BIT(3)
#define PB_CML_FAULT_MEMORY BIT(4)
#define PB_CML_FAULT_PACKET_ERROR BIT(5)
#define PB_CML_FAULT_INVALID_DATA BIT(6)
#define PB_CML_FAULT_INVALID_COMMAND BIT(7)
enum pmbus_sensor_classes
{
PSC_VOLTAGE_IN = 0,
PSC_VOLTAGE_OUT,
PSC_CURRENT_IN,
PSC_CURRENT_OUT,
PSC_POWER,
PSC_TEMPERATURE,
PSC_FAN,
PSC_NUM_CLASSES
};
#define PMBUS_PAGES 32
#define PMBUS_HAVE_VIN BIT(0)
#define PMBUS_HAVE_VCAP BIT(1)
#define PMBUS_HAVE_VOUT BIT(2)
#define PMBUS_HAVE_IIN BIT(3)
#define PMBUS_HAVE_IOUT BIT(4)
#define PMBUS_HAVE_PIN BIT(5)
#define PMBUS_HAVE_POUT BIT(6)
#define PMBUS_HAVE_FAN12 BIT(7)
#define PMBUS_HAVE_FAN34 BIT(8)
#define PMBUS_HAVE_TEMP BIT(9)
#define PMBUS_HAVE_TEMP2 BIT(10)
#define PMBUS_HAVE_TEMP3 BIT(11)
#define PMBUS_HAVE_STATUS_VOUT BIT(12)
#define PMBUS_HAVE_STATUS_IOUT BIT(13)
#define PMBUS_HAVE_STATUS_INPUT BIT(14)
#define PMBUS_HAVE_STATUS_TEMP BIT(15)
#define PMBUS_HAVE_STATUS_FAN12 BIT(16)
#define PMBUS_HAVE_STATUS_FAN34 BIT(17)
#define PMBUS_HAVE_VMON BIT(18)
#define PMBUS_HAVE_STATUS_VMON BIT(19)
enum pmbus_data_format
{
linear = 0,
direct,
vid
};
enum vrm_version
{
vr11 = 0,
vr12,
vr13,
imvp9,
amd625mv
};
struct pmbus_driver_info {
int pages;
enum pmbus_data_format format[PSC_NUM_CLASSES];
enum vrm_version vrm_version[PMBUS_PAGES];
int m[PSC_NUM_CLASSES];
int b[PSC_NUM_CLASSES];
int R[PSC_NUM_CLASSES];
u32 func[PMBUS_PAGES];
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int reg);
int (*write_word_data)(struct i2c_client *client, int page, int reg, u16 word);
int (*write_byte)(struct i2c_client *client, int page, u8 value);
int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
int num_regulators;
const struct regulator_desc *reg_desc;
};
extern const struct regulator_ops pmbus_regulator_ops;
#define PMBUS_REGULATOR(_name, _id) \
[_id] = { \
.name = (_name #_id), \
.id = (_id), \
.of_match = of_match_ptr(_name #_id), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &pmbus_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
void pmbus_clear_cache(struct i2c_client *client);
int pmbus_set_page(struct i2c_client *client, u8 page);
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, u8 value);
int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, u8 mask, u8 value);
void pmbus_clear_faults(struct i2c_client *client);
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, struct pmbus_driver_info *info);
int pmbus_do_remove(struct i2c_client *client);
const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
*client);
#endif
pxe1410.c
#include
#include
#include
#include
#include
#include "i2c_dev_sysfs.h"
#include "pmbus.h"
#define MAX_RETRY_COUNT 10
static int32_t linear_convert(int32_t data)
{
int16_t exponent;
int32_t mantissa;
int32_t val_x;
mantissa = (((data & 0x7ff) << 5)) >> 5;
exponent = ((int16_t)data) >> 11;
val_x = mantissa * 1000L;
if (exponent >= 0)
val_x <<= exponent;
else
val_x >>= -exponent;
return val_x;
}
static int32_t i2c_set_page(struct i2c_client *client, int32_t page)
{
int32_t rv;
rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
if (rv == 0) {
rv = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
if (rv < 0)
return rv;
if (rv != page)
return -EIO;
else
return 0;
}
return rv;
}
static ssize_t chip_vout_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = 500 + (result - 1) * 10;
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_vin_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result);
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_pin_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result);
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_pout_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result) * 1000;
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_iout_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result);
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_iin_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result);
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_limit_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result);
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static ssize_t chip_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_dev_data_st *data = i2c_get_clientdata(client);
i2c_sysfs_attr_st *i2c_attr;
const i2c_dev_attr_st *dev_attr;
int32_t result = -1;
int32_t i = 0;
if (!data)
return -EINVAL;
i2c_attr = TO_I2C_SYSFS_ATTR(attr);
if (!i2c_attr)
return -EINVAL;
dev_attr = i2c_attr->isa_i2c_attr;
if (!dev_attr)
return -EINVAL;
mutex_lock(&data->idd_lock);
while ((result < 0) && (i < MAX_RETRY_COUNT)) {
result = i2c_set_page(client, 0);
if (result == 0)
result = i2c_smbus_read_word_data(client, (dev_attr->ida_reg));
i++;
}
mutex_unlock(&data->idd_lock);
if (result >= 0)
result = linear_convert(result);
return scnprintf(buf, PAGE_SIZE, "%d\n", result);
}
static const i2c_dev_attr_st chip_attr_table[] = {
{
"in1_input",
NULL,
chip_vin_show,
NULL,
0x88,
0,
8,
},
{
"in2_input",
NULL,
chip_vout_show,
NULL,
0x8b,
0,
8,
},
{
"curr1_input",
NULL,
chip_iin_show,
NULL,
0x89,
0,
8,
},
{
"curr2_input",
NULL,
chip_iout_show,
NULL,
0x8c,
0,
8,
},
{
"power1_input",
NULL,
chip_pin_show,
NULL,
0x97,
0,
8,
},
{
"power2_input",
NULL,
chip_pout_show,
NULL,
0x96,
0,
8,
},
{
"temp1_input",
NULL,
chip_temp_show,
NULL,
0x8d,
0,
8,
},
{
"in1_max",
NULL,
chip_limit_show,
NULL,
0x55,
0,
8,
},
{
"in1_min",
NULL,
chip_limit_show,
NULL,
0x59,
0,
8,
},
{
"in2_max",
NULL,
chip_limit_show,
NULL,
0x40,
0,
8,
},
{
"in2_min",
NULL,
chip_limit_show,
NULL,
0x44,
0,
8,
},
{
"curr2_max",
NULL,
chip_limit_show,
NULL,
0x46,
0,
8,
},
};
static i2c_dev_data_st chip_data;
static const struct i2c_device_id chip_id[] = {
{"pxe1410", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, chip_id);
static int32_t chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int32_t n_attrs = sizeof(chip_attr_table) / sizeof(chip_attr_table[0]);
return i2c_dev_sysfs_data_init(client, &chip_data, chip_attr_table, n_attrs);
}
static int32_t chip_remove(struct i2c_client *client)
{
i2c_dev_sysfs_data_clean(client, &chip_data);
return 0;
}
static struct i2c_driver chip_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "pxe1410",
},
.probe = chip_probe,
.remove = chip_remove,
.id_table = chip_id,
};
static int32_t __init chip_mod_init(void)
{
return i2c_add_driver(&chip_driver);
}
static void __exit chip_mod_exit(void)
{
i2c_del_driver(&chip_driver);
}
MODULE_AUTHOR("[email protected]");
MODULE_DESCRIPTION("PXE1410 Driver");
MODULE_LICENSE("GPL");
module_init(chip_mod_init);
module_exit(chip_mod_exit);
reset_driver.sh
#!/bin/sh
sudo rmmod switchboard
sudo rmmod pxe1410
sudo rmmod optoe
sudo rmmod mc24lc64t
sudo rmmod ina2xx
sudo rmmod i2c-ocores
sudo rmmod i2c_dev_sysfs
sudo rmmod fpga_i2c_adapter
sudo rmmod cpld_lpc
sudo rmmod cpld_i2c
sleep 1
sudo modprobe i2c-i801
sudo modprobe i2c-dev
sleep 1
sudo insmod cpld_i2c.ko
sudo insmod cpld_lpc.ko
sudo insmod fpga_i2c_adapter.ko
sudo insmod i2c_dev_sysfs.ko
sudo insmod i2c-ocores.ko
sudo insmod ina2xx.ko
sudo insmod mc24lc64t.ko
sudo insmod i2c_kobj_sysfs.ko
sudo insmod pxe1410.ko
sudo insmod switchboard.ko
setup.py
import os
import sys
def new_device(driver, addr, bus, devdir):
if not os.path.exists(os.path.join(bus, devdir)):
try:
with open("%s/new_device" % bus, "w") as f:
f.write("%s 0x%x\n" % (driver, addr))
except Exception, e:
print "Unexpected error initialize device %s:0x%x:%s: %s" % (driver, addr, bus, e)
else:
print("Device %s:%x:%s already exists." % (driver, addr, bus))
def new_i2c_device(driver, addr, bus_number):
bus = '/sys/bus/i2c/devices/i2c-%d' % bus_number
devdir = "%d-%4.4x" % (bus_number, addr)
return new_device(driver, addr, bus, devdir)
def baseconfig():
print("Initialize EEPROM driver")
new_i2c_device('24lc64t', 0x56, 0)
new_i2c_device('sn1701022', 0x66, 4)
new_i2c_device('sn1701022', 0x64, 4)
new_i2c_device('lm75', 0x48, 3)
new_i2c_device('lm75', 0x49, 3)
new_i2c_device('lm75', 0x48, 5)
new_i2c_device('lm75', 0x49, 6)
new_i2c_device('lm75', 0x4a, 7)
new_i2c_device('lm75', 0x4b, 8)
new_i2c_device('xdpe132g5c', 0x4d, 9)
new_i2c_device('pxe1410', 0x60, 10)
new_i2c_device('ads7830', 0x48, 11)
new_i2c_device('ads7830', 0x49, 12)
new_i2c_device('ads7830', 0x4a, 13)
new_i2c_device('tpa620', 0x41, 30)
for y in range(16):
new_i2c_device('optoe1', 0x50, 14 + y)
def main():
baseconfig()
if __name__ == "__main__":
sys.exit(main())
sn1701022.c
#include
#include
#include
#include
#include
#include
#include "pmbus.h"
#define MAX_SUPPORT_PAGE 2
static struct pmbus_driver_info sn1701022_info = {
.pages = MAX_SUPPORT_PAGE,
.format[PSC_VOLTAGE_IN] = linear,
.format[PSC_VOLTAGE_OUT] = vid,
.vrm_version[0] = vr12,
.vrm_version[1] = vr12,
.format[PSC_CURRENT_IN] = linear,
.format[PSC_CURRENT_OUT] = linear,
.format[PSC_TEMPERATURE] = linear,
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT,
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT,
};
static int32_t sn1701022_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
return pmbus_do_probe(client, id, &sn1701022_info);
}
static const struct i2c_device_id sn1701022_id[] = {{"sn1701022", 0}, {}};
MODULE_DEVICE_TABLE(i2c, sn1701022_id);
static struct i2c_driver sn1701022_driver = {
.driver = {
.name = "sn1701022",
},
.probe = sn1701022_probe,
.remove = pmbus_do_remove,
.id_table = sn1701022_id,
};
module_i2c_driver(sn1701022_driver);
MODULE_AUTHOR("[email protected]");
MODULE_DESCRIPTION("PMBus driver for SN1701022");
MODULE_LICENSE("GPL");
fpga驱动,设备在fpga_i2c_adapter.c