blob: 4b0ec8a2ed82b102ab70459aa79b042f2e54fc8d [file] [log] [blame]
#!/bin/bash
#
# Power Control tool
# Enable/disable AC relay
# On/off System by step moter to press power key
export PATH=$PATH:/usr/sbin:/usr/libexec
DELAY_POWER_ON="0.5"
DELAY_POWER_OFF="5"
POWER_BTN_TIMEOUT_CNT=60
REV_EVT="EVT"
REV_DVT="DVT"
REV_UNKNOW="UNKNOW"
DBUS_HOST_ST_ON="xyz.openbmc_project.State.Host.HostState.Running"
DBUS_HOST_ST_OFF="xyz.openbmc_project.State.Host.HostState.Off"
HOST_ST_UNKNOW="Unknow"
HOST_ST_ON="On"
HOST_ST_OFF="Off"
HOST_AC_ON="AC On"
HOST_AC_OFF="AC Off"
function get_board_rev() {
local rev_id0
local rev_id1
local rev_id2
local rev_val
rev_id0=$(get_gpio "REV_ID0")
rev_id1=$(get_gpio "REV_ID1")
rev_id2=$(get_gpio "REV_ID2")
rev_val=$((rev_id0+(rev_id1<<1)+(rev_id2<<2)))
case $rev_val in
0)
echo "$REV_EVT"
;;
1)
echo "$REV_DVT"
;;
*)
echo "$REV_UNKNOW"
return 1
;;
esac
return 0
}
#Switch pull low while it be touched
function wait_for_switch() {
TARGET_PIN=$1
TARGET_SWITCH=1
TIME_CNT=0
while [ "$TARGET_SWITCH" -eq 1 ] ;do
TARGET_SWITCH=$(get_gpio "$TARGET_PIN")
sleep 0.1
TIME_CNT=$(( TIME_CNT +1))
if [ $TIME_CNT -gt $POWER_BTN_TIMEOUT_CNT ];then
echo "Error: Too long to get target switch, force exit" >&2
break
fi
done
}
function trigger_power_button() {
local sled_num=$1
local delay_time=$2
#SLED{N}_MS_DETECT1 (initial position)
GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1"
#SLED{N}_MS_DETECT0 (MAC position)
GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0"
echo "Motor go forward to press Power key"
motor-ctrl "sled${sled_num}" f >/dev/null
wait_for_switch "${GPIO_DETECT_PIN0}"
motor-ctrl "sled${sled_num}" s >/dev/null
if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then
echo "Power key switch triggered"
echo "Press power key for Sled${1} ${delay_time} seconds..."
sleep "$delay_time"
else
echo "Power key switch not trigger, back motor to initial position"
fi
motor-ctrl "sled${sled_num}" r >/dev/null
wait_for_switch "${GPIO_DETECT_PIN1}"
motor-ctrl "sled${sled_num}" s >/dev/null
if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then
echo "Motor reverse to initial position successful"
else
echo "Initial position switch not trigger, force stop motor"
fi
}
function release_power_button() {
local sled_num=$1
GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1"
if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ]; then
echo "Motor at initial position already"
return 0
fi
motor-ctrl "sled${sled_num}" r >/dev/null
wait_for_switch "${GPIO_DETECT_PIN1}"
motor-ctrl "sled${sled_num}" s >/dev/null
if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then
echo "Motor reverse to initial position successful"
return 0
fi
echo "Error: Initial position switch not trigger"
return 1
}
function press_power_button() {
local sled_num=$1
GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0"
echo "Motor go forward to press Power button"
motor-ctrl "sled${sled_num}" f >/dev/null
wait_for_switch "${GPIO_DETECT_PIN0}"
motor-ctrl "sled${sled_num}" s >/dev/null
if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then
echo "Power button switch triggered"
return 0
fi
echo "Error: Power button switch not trigger"
return 1
}
#Get i2c bus number for sledN
function get_bus_num() {
SLED_NUM=$1
local bus=0
#Mapping Sled number 1~6 to i2c bus number 0~5
if [[ "$SLED_NUM" = [1-6] ]]; then
bus=$(( SLED_NUM - 1 ))
fi
echo "$bus"
}
function set_gpio()
{
NET_NAME=$1
OUT_VAL=$2
mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME")
if [ "${#GPIO_INFO[@]}" -ne 2 ]; then
echo "set_gpio: can not find gpio, $NET_NAME"
return 1
fi
echo -n "set_gpio: set $NET_NAME = $OUT_VAL"
if ! gpioset "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}"="$OUT_VAL"; then
echo " failed"
return 1
fi
echo " success"
return 0
}
function get_gpio()
{
NET_NAME=$1
RET_VAL=2
mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME")
if [ "${#GPIO_INFO[@]}" -ne 2 ]; then
echo "get_gpio: can not find gpio, $NET_NAME" >&2
return 1
fi
if ! RET_VAL=$(gpioget "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}") ; then
echo "get_gpio: get ${NET_NAME} failed" >&2
return 1
fi
echo "${RET_VAL}"
return 0
}
function get_ac_status(){
i2c_bus=$(get_bus_num "$1")
p1_output_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x03)
p1_config_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x07)
host_pwr="$(( (p1_output_reg & 0x80)>>7 ))"
is_output="$(( (~p1_config_reg & 0x80)>>7 ))"
if [ "$(( host_pwr & is_output ))" -eq 1 ];then
echo "$HOST_AC_ON"
else
echo "$HOST_AC_OFF"
fi
}
function get_host_status_dbus()
{
local sled_num=$1
local object="/xyz/openbmc_project/state/host${sled_num}"
local service="xyz.openbmc_project.State.Host${sled_num}"
local interface="xyz.openbmc_project.State.Host"
local property="CurrentHostState"
local host_state
host_state=$(busctl get-property "$service" "$object" "$interface" "$property" | cut -d '"' -f2)
if [ "$host_state" = "$DBUS_HOST_ST_ON" ]; then
echo "$HOST_ST_ON"
elif [ "$host_state" = "$DBUS_HOST_ST_OFF" ]; then
echo "$HOST_ST_OFF"
else
echo "$HOST_ST_UNKNOW"
return 1
fi
return 0
}
function get_host_status_mdio()
{
SLED_NUM=$1
MDIO_BUS=0
declare -a PORT_MAP=(0 3 2 1 7 6 5)
# check /dev/mem
if ! create_dev_mem; then
return 1
fi
CHECK_CNT=0
MDIO_ERR_CNT=0
CUR_HOST_ST=$HOST_ST_UNKNOW
while true
do
if POST_ST_VAL=$(mdio-util c22 r $MDIO_BUS "${PORT_MAP[SLED_NUM]}" 0); then
if [ $((POST_ST_VAL&16#0800)) -eq $((16#0800)) ]; then
TMP_HOST_ST="$HOST_ST_ON"
else
TMP_HOST_ST="$HOST_ST_OFF"
fi
if [ "$CUR_HOST_ST" == "$TMP_HOST_ST" ]; then
CHECK_CNT=$((CHECK_CNT+1))
else
CUR_HOST_ST=$TMP_HOST_ST
CHECK_CNT=0
fi
if [ "$CHECK_CNT" -ge 5 ]; then
echo "$CUR_HOST_ST"
break
fi
else
MDIO_ERR_CNT=$((MDIO_ERR_CNT+1))
if [ "$MDIO_ERR_CNT" -ge 5 ]; then
echo "$HOST_ST_UNKNOW"
return 1
fi
fi
done
return 0
}
function get_host_status()
{
local sled_num=$1
local board_rev
board_rev=$(get_board_rev)
if [ "$board_rev" = "$REV_EVT" ]; then
get_host_status_dbus "$sled_num"
else
get_host_status_mdio "$sled_num"
fi
return $?
}
function create_dev_mem()
{
CHECK_CNT=0
while true
do
CHECK_CNT=$((CHECK_CNT+1))
if [ -c /dev/mem ]; then
# /dev/mem already exist
return 0
elif mknod /dev/mem c 1 1; then
# mknod success
return 0
elif [ "$CHECK_CNT" -ge 5 ]; then
break
fi
sleep 1
done
echo "create /dev/mem failed"
return 1
}
function show_usage(){
echo "Usage: power-ctrl [sled1 | sled2 | sled3 | sled4 | sled5 | sled6] [on off ac-on ac-off status dfu recovery]"
echo " power-ctrl chassis-cycle"
}
if [ $# -eq 1 ]; then
if [ "$1" = "chassis-cycle" ];then
echo "chassis cycle...."
i2cset -y -f 12 0x11 0xd9 c
exit 0
else
echo "Invalid argument: [ $1 ]"
show_usage
exit 1;
fi
fi
if [ $# -gt 2 ]; then
echo "Too many arguments"
show_usage
exit 1;
fi
if [[ "$1" =~ ^(sled[1-6]{1})$ ]]; then
SLED=$1
ACTION=$2
SLED_NUM=${SLED:4}
else
echo "invalid sled name: ${1}"
show_usage
exit 1;
fi
#Check if sled is present
SLED_PRESENT=$(get_gpio "presence-sled${SLED_NUM}")
if [ "$SLED_PRESENT" != 0 ];then
echo "${SLED} is not present!"
exit 1
fi
if [[ "$ACTION" == "on" ]]; then
if [ "$(get_ac_status "$SLED_NUM")" == "$HOST_AC_ON" ];then
host_power_st=$(get_host_status "$SLED_NUM")
if [ "$host_power_st" == "$HOST_ST_ON" ]; then
echo "${SLED} is already On"
elif [ "$host_power_st" == "$HOST_ST_OFF" ]; then
echo "Power on ${SLED}"
trigger_power_button "$SLED_NUM" "$DELAY_POWER_ON"
else
echo "${SLED} power state is $host_power_st"
exit 1
fi
else
echo "${SLED} is ac-off, please turn on ac before power on"
exit 1
fi
elif [[ "$ACTION" == "off" ]];then
if [ "$(get_ac_status "$SLED_NUM")" == "$HOST_AC_ON" ];then
host_power_st=$(get_host_status "$SLED_NUM")
if [ "$host_power_st" == "$HOST_ST_ON" ]; then
echo "Power off ${SLED}"
trigger_power_button "$SLED_NUM" "$DELAY_POWER_OFF"
elif [ "$host_power_st" == "$HOST_ST_OFF" ]; then
echo "${SLED} is already Off"
else
echo "${SLED} power state is $host_power_st"
exit 1
fi
else
echo "${SLED} is already ac-off"
exit 1
fi
elif [[ "$ACTION" == "status" ]];then
AC_ST=$(get_ac_status "$SLED_NUM")
if [ "$AC_ST" == "$HOST_AC_ON" ]; then
# check host power status if AC is on
get_host_status "$SLED_NUM" || exit 1
else
# AC off
echo "$HOST_AC_OFF"
fi
elif [[ "$ACTION" == "ac-on" ]];then
set_gpio "power-host${SLED_NUM}" 1
elif [[ "$ACTION" == "ac-off" ]];then
set_gpio "power-host${SLED_NUM}" 0
elif [[ "$ACTION" == "dfu" ]]; then
echo "Set host$SLED_NUM DFU mode"
# turn ac off, and hold for 25 seconds
echo "SLED$SLED_NUM: turn ac-off"
set_gpio "power-host${SLED_NUM}" 0
sleep 25
# press power button
echo "SLED$SLED_NUM: pressing power button"
if ! press_power_button "$SLED_NUM"; then
echo "SLED$SLED_NUM: press power button failed"
echo "SLED$SLED_NUM: releasing power button"
release_power_button "$SLED_NUM"
exit 1
fi
sleep 1
# turn ac on
echo "SLED$SLED_NUM: turn ac-on"
set_gpio "power-host${SLED_NUM}" 1
sleep 3
# release power button
echo "SLED$SLED_NUM: releasing host power button"
if ! release_power_button "$SLED_NUM"; then
echo "SLED$SLED_NUM: release power button failed"
exit 1
fi
elif [[ "$ACTION" == "recovery" ]]; then
if [ "$(get_ac_status "$SLED_NUM")" != "$HOST_AC_OFF" ]; then
echo "Please turn off host before trigger recovery mode"
exit 1
fi
echo "Set host$SLED_NUM Recovery mode"
# press power button
echo "SLED$SLED_NUM: pressing power button"
if ! press_power_button "$SLED_NUM"; then
echo "SLED$SLED_NUM: press power button failed"
echo "SLED$SLED_NUM: releasing power button"
release_power_button "$SLED_NUM"
exit 1
fi
sleep 10
# release power button
echo "SLED$SLED_NUM: releasing host power button"
if ! release_power_button "$SLED_NUM"; then
echo "SLED$SLED_NUM: release power button failed"
exit 1
fi
else
echo "Unknown action: [ ${ACTION} ]"
show_usage
fi