blob: 4b0ec8a2ed82b102ab70459aa79b042f2e54fc8d [file] [log] [blame]
Allen.Wang4a0948d2021-12-15 13:41:18 +08001#!/bin/bash
2#
3# Power Control tool
4# Enable/disable AC relay
5# On/off System by step moter to press power key
6
7export PATH=$PATH:/usr/sbin:/usr/libexec
8
9DELAY_POWER_ON="0.5"
10DELAY_POWER_OFF="5"
11POWER_BTN_TIMEOUT_CNT=60
12
Potin Laibb91c1b2022-04-28 15:03:05 +080013REV_EVT="EVT"
14REV_DVT="DVT"
15REV_UNKNOW="UNKNOW"
16
17DBUS_HOST_ST_ON="xyz.openbmc_project.State.Host.HostState.Running"
18DBUS_HOST_ST_OFF="xyz.openbmc_project.State.Host.HostState.Off"
19
20HOST_ST_UNKNOW="Unknow"
21HOST_ST_ON="On"
22HOST_ST_OFF="Off"
23HOST_AC_ON="AC On"
24HOST_AC_OFF="AC Off"
25
26function get_board_rev() {
27 local rev_id0
28 local rev_id1
29 local rev_id2
30 local rev_val
31
32 rev_id0=$(get_gpio "REV_ID0")
33 rev_id1=$(get_gpio "REV_ID1")
34 rev_id2=$(get_gpio "REV_ID2")
35 rev_val=$((rev_id0+(rev_id1<<1)+(rev_id2<<2)))
36
37 case $rev_val in
38 0)
39 echo "$REV_EVT"
40 ;;
41 1)
42 echo "$REV_DVT"
43 ;;
44 *)
45 echo "$REV_UNKNOW"
46 return 1
47 ;;
48 esac
49
50 return 0
51}
52
Allen.Wang4a0948d2021-12-15 13:41:18 +080053#Switch pull low while it be touched
54function wait_for_switch() {
55 TARGET_PIN=$1
56 TARGET_SWITCH=1
57 TIME_CNT=0
58 while [ "$TARGET_SWITCH" -eq 1 ] ;do
59 TARGET_SWITCH=$(get_gpio "$TARGET_PIN")
60 sleep 0.1
61 TIME_CNT=$(( TIME_CNT +1))
62 if [ $TIME_CNT -gt $POWER_BTN_TIMEOUT_CNT ];then
63 echo "Error: Too long to get target switch, force exit" >&2
64 break
65 fi
66 done
67}
68
69function trigger_power_button() {
70 local sled_num=$1
Allen.Wang6af0dff2021-12-28 20:23:05 +080071 local delay_time=$2
Allen.Wang4a0948d2021-12-15 13:41:18 +080072
73 #SLED{N}_MS_DETECT1 (initial position)
74 GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1"
75 #SLED{N}_MS_DETECT0 (MAC position)
76 GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0"
77
78 echo "Motor go forward to press Power key"
79 motor-ctrl "sled${sled_num}" f >/dev/null
80 wait_for_switch "${GPIO_DETECT_PIN0}"
81 motor-ctrl "sled${sled_num}" s >/dev/null
82
83 if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then
84 echo "Power key switch triggered"
85 echo "Press power key for Sled${1} ${delay_time} seconds..."
86 sleep "$delay_time"
87 else
Allen.Wang6af0dff2021-12-28 20:23:05 +080088 echo "Power key switch not trigger, back motor to initial position"
Allen.Wang4a0948d2021-12-15 13:41:18 +080089 fi
90
91 motor-ctrl "sled${sled_num}" r >/dev/null
92 wait_for_switch "${GPIO_DETECT_PIN1}"
93 motor-ctrl "sled${sled_num}" s >/dev/null
94 if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then
95 echo "Motor reverse to initial position successful"
96 else
Allen.Wang6af0dff2021-12-28 20:23:05 +080097 echo "Initial position switch not trigger, force stop motor"
Allen.Wang4a0948d2021-12-15 13:41:18 +080098 fi
99}
100
Potin Laidb5648e2022-02-16 00:57:55 +0800101function release_power_button() {
102 local sled_num=$1
103 GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1"
104
105 if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ]; then
106 echo "Motor at initial position already"
107 return 0
108 fi
109
110 motor-ctrl "sled${sled_num}" r >/dev/null
111 wait_for_switch "${GPIO_DETECT_PIN1}"
112 motor-ctrl "sled${sled_num}" s >/dev/null
113 if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then
114 echo "Motor reverse to initial position successful"
115 return 0
116 fi
117
118 echo "Error: Initial position switch not trigger"
119 return 1
120}
121
122function press_power_button() {
123 local sled_num=$1
124
125 GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0"
126
127 echo "Motor go forward to press Power button"
128 motor-ctrl "sled${sled_num}" f >/dev/null
129 wait_for_switch "${GPIO_DETECT_PIN0}"
130 motor-ctrl "sled${sled_num}" s >/dev/null
131
132 if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then
133 echo "Power button switch triggered"
134 return 0
135 fi
136
137 echo "Error: Power button switch not trigger"
138 return 1
139}
140
Allen.Wang4a0948d2021-12-15 13:41:18 +0800141#Get i2c bus number for sledN
142function get_bus_num() {
143 SLED_NUM=$1
144 local bus=0
Allen.Wang5ff992e2022-01-04 21:00:38 +0800145 #Mapping Sled number 1~6 to i2c bus number 0~5
146 if [[ "$SLED_NUM" = [1-6] ]]; then
147 bus=$(( SLED_NUM - 1 ))
Allen.Wang4a0948d2021-12-15 13:41:18 +0800148 fi
149 echo "$bus"
150}
151
152function set_gpio()
153{
154 NET_NAME=$1
155 OUT_VAL=$2
156 mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME")
157 if [ "${#GPIO_INFO[@]}" -ne 2 ]; then
158 echo "set_gpio: can not find gpio, $NET_NAME"
159 return 1
160 fi
161 echo -n "set_gpio: set $NET_NAME = $OUT_VAL"
162 if ! gpioset "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}"="$OUT_VAL"; then
163 echo " failed"
164 return 1
165 fi
166 echo " success"
167 return 0
168}
169
170function get_gpio()
171{
172 NET_NAME=$1
173 RET_VAL=2
174
175 mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME")
176 if [ "${#GPIO_INFO[@]}" -ne 2 ]; then
177 echo "get_gpio: can not find gpio, $NET_NAME" >&2
178 return 1
179 fi
180 if ! RET_VAL=$(gpioget "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}") ; then
181 echo "get_gpio: get ${NET_NAME} failed" >&2
182 return 1
183 fi
184 echo "${RET_VAL}"
185 return 0
186}
187
188function get_ac_status(){
189 i2c_bus=$(get_bus_num "$1")
190 p1_output_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x03)
191 p1_config_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x07)
192 host_pwr="$(( (p1_output_reg & 0x80)>>7 ))"
193 is_output="$(( (~p1_config_reg & 0x80)>>7 ))"
194
195 if [ "$(( host_pwr & is_output ))" -eq 1 ];then
Potin Laibb91c1b2022-04-28 15:03:05 +0800196 echo "$HOST_AC_ON"
Allen.Wang4a0948d2021-12-15 13:41:18 +0800197 else
Potin Laibb91c1b2022-04-28 15:03:05 +0800198 echo "$HOST_AC_OFF"
Allen.Wang4a0948d2021-12-15 13:41:18 +0800199 fi
200}
201
Potin Laibb91c1b2022-04-28 15:03:05 +0800202function get_host_status_dbus()
203{
204 local sled_num=$1
205 local object="/xyz/openbmc_project/state/host${sled_num}"
206 local service="xyz.openbmc_project.State.Host${sled_num}"
207 local interface="xyz.openbmc_project.State.Host"
208 local property="CurrentHostState"
209 local host_state
210
211 host_state=$(busctl get-property "$service" "$object" "$interface" "$property" | cut -d '"' -f2)
212
213 if [ "$host_state" = "$DBUS_HOST_ST_ON" ]; then
214 echo "$HOST_ST_ON"
215 elif [ "$host_state" = "$DBUS_HOST_ST_OFF" ]; then
216 echo "$HOST_ST_OFF"
217 else
218 echo "$HOST_ST_UNKNOW"
219 return 1
220 fi
221
222 return 0
223}
224
225function get_host_status_mdio()
Potin Laidc251662022-04-01 11:16:50 +0800226{
227 SLED_NUM=$1
228 MDIO_BUS=0
Potin Laibb91c1b2022-04-28 15:03:05 +0800229
Potin Laidc251662022-04-01 11:16:50 +0800230 declare -a PORT_MAP=(0 3 2 1 7 6 5)
231
232 # check /dev/mem
233 if ! create_dev_mem; then
234 return 1
235 fi
236
237 CHECK_CNT=0
238 MDIO_ERR_CNT=0
239 CUR_HOST_ST=$HOST_ST_UNKNOW
240
241 while true
242 do
243 if POST_ST_VAL=$(mdio-util c22 r $MDIO_BUS "${PORT_MAP[SLED_NUM]}" 0); then
244 if [ $((POST_ST_VAL&16#0800)) -eq $((16#0800)) ]; then
245 TMP_HOST_ST="$HOST_ST_ON"
246 else
247 TMP_HOST_ST="$HOST_ST_OFF"
248 fi
249
250 if [ "$CUR_HOST_ST" == "$TMP_HOST_ST" ]; then
251 CHECK_CNT=$((CHECK_CNT+1))
252 else
253 CUR_HOST_ST=$TMP_HOST_ST
254 CHECK_CNT=0
255 fi
256
257 if [ "$CHECK_CNT" -ge 5 ]; then
258 echo "$CUR_HOST_ST"
259 break
260 fi
261 else
262 MDIO_ERR_CNT=$((MDIO_ERR_CNT+1))
263 if [ "$MDIO_ERR_CNT" -ge 5 ]; then
264 echo "$HOST_ST_UNKNOW"
265 return 1
266 fi
267 fi
268 done
269
270 return 0
271}
272
Potin Laibb91c1b2022-04-28 15:03:05 +0800273function get_host_status()
274{
275 local sled_num=$1
276 local board_rev
277
278 board_rev=$(get_board_rev)
279
280 if [ "$board_rev" = "$REV_EVT" ]; then
281 get_host_status_dbus "$sled_num"
282 else
283 get_host_status_mdio "$sled_num"
284 fi
285
286 return $?
287}
288
Potin Laidc251662022-04-01 11:16:50 +0800289function create_dev_mem()
290{
291 CHECK_CNT=0
292 while true
293 do
294 CHECK_CNT=$((CHECK_CNT+1))
295 if [ -c /dev/mem ]; then
296 # /dev/mem already exist
297 return 0
298 elif mknod /dev/mem c 1 1; then
299 # mknod success
300 return 0
301 elif [ "$CHECK_CNT" -ge 5 ]; then
302 break
303 fi
304 sleep 1
305 done
306
307 echo "create /dev/mem failed"
308 return 1
309}
310
Allen.Wang4a0948d2021-12-15 13:41:18 +0800311function show_usage(){
Potin Lai035ff462022-04-28 17:02:21 +0800312 echo "Usage: power-ctrl [sled1 | sled2 | sled3 | sled4 | sled5 | sled6] [on off ac-on ac-off status dfu recovery]"
Allen.Wang4a0948d2021-12-15 13:41:18 +0800313 echo " power-ctrl chassis-cycle"
314}
315
316if [ $# -eq 1 ]; then
317 if [ "$1" = "chassis-cycle" ];then
318 echo "chassis cycle...."
319 i2cset -y -f 12 0x11 0xd9 c
320 exit 0
321 else
322 echo "Invalid argument: [ $1 ]"
323 show_usage
324 exit 1;
325 fi
326fi
327
328if [ $# -gt 2 ]; then
329 echo "Too many arguments"
330 show_usage
331 exit 1;
332fi
333
Allen.Wang5ff992e2022-01-04 21:00:38 +0800334if [[ "$1" =~ ^(sled[1-6]{1})$ ]]; then
Allen.Wang4a0948d2021-12-15 13:41:18 +0800335 SLED=$1
336 ACTION=$2
337 SLED_NUM=${SLED:4}
338else
339 echo "invalid sled name: ${1}"
340 show_usage
341 exit 1;
342fi
343
344#Check if sled is present
345SLED_PRESENT=$(get_gpio "presence-sled${SLED_NUM}")
346if [ "$SLED_PRESENT" != 0 ];then
347 echo "${SLED} is not present!"
348 exit 1
349fi
350
351if [[ "$ACTION" == "on" ]]; then
Potin Laibb91c1b2022-04-28 15:03:05 +0800352 if [ "$(get_ac_status "$SLED_NUM")" == "$HOST_AC_ON" ];then
Potin Laidc251662022-04-01 11:16:50 +0800353 host_power_st=$(get_host_status "$SLED_NUM")
Potin Laibb91c1b2022-04-28 15:03:05 +0800354 if [ "$host_power_st" == "$HOST_ST_ON" ]; then
Potin Laidc251662022-04-01 11:16:50 +0800355 echo "${SLED} is already On"
Potin Laibb91c1b2022-04-28 15:03:05 +0800356 elif [ "$host_power_st" == "$HOST_ST_OFF" ]; then
Potin Laidc251662022-04-01 11:16:50 +0800357 echo "Power on ${SLED}"
358 trigger_power_button "$SLED_NUM" "$DELAY_POWER_ON"
359 else
360 echo "${SLED} power state is $host_power_st"
361 exit 1
362 fi
Allen.Wang787c9c62022-03-02 14:55:03 +0800363 else
364 echo "${SLED} is ac-off, please turn on ac before power on"
365 exit 1
366 fi
Allen.Wang4a0948d2021-12-15 13:41:18 +0800367elif [[ "$ACTION" == "off" ]];then
Potin Laibb91c1b2022-04-28 15:03:05 +0800368 if [ "$(get_ac_status "$SLED_NUM")" == "$HOST_AC_ON" ];then
Potin Laidc251662022-04-01 11:16:50 +0800369 host_power_st=$(get_host_status "$SLED_NUM")
Potin Laibb91c1b2022-04-28 15:03:05 +0800370 if [ "$host_power_st" == "$HOST_ST_ON" ]; then
Potin Laidc251662022-04-01 11:16:50 +0800371 echo "Power off ${SLED}"
372 trigger_power_button "$SLED_NUM" "$DELAY_POWER_OFF"
Potin Laibb91c1b2022-04-28 15:03:05 +0800373 elif [ "$host_power_st" == "$HOST_ST_OFF" ]; then
Potin Laidc251662022-04-01 11:16:50 +0800374 echo "${SLED} is already Off"
375 else
376 echo "${SLED} power state is $host_power_st"
377 exit 1
378 fi
Allen.Wang787c9c62022-03-02 14:55:03 +0800379 else
380 echo "${SLED} is already ac-off"
381 exit 1
382 fi
Allen.Wang4a0948d2021-12-15 13:41:18 +0800383elif [[ "$ACTION" == "status" ]];then
Potin Laidc251662022-04-01 11:16:50 +0800384 AC_ST=$(get_ac_status "$SLED_NUM")
Potin Laibb91c1b2022-04-28 15:03:05 +0800385 if [ "$AC_ST" == "$HOST_AC_ON" ]; then
Potin Laidc251662022-04-01 11:16:50 +0800386 # check host power status if AC is on
387 get_host_status "$SLED_NUM" || exit 1
388 else
389 # AC off
Potin Laibb91c1b2022-04-28 15:03:05 +0800390 echo "$HOST_AC_OFF"
Potin Laidc251662022-04-01 11:16:50 +0800391 fi
Allen.Wang4a0948d2021-12-15 13:41:18 +0800392elif [[ "$ACTION" == "ac-on" ]];then
393 set_gpio "power-host${SLED_NUM}" 1
394elif [[ "$ACTION" == "ac-off" ]];then
395 set_gpio "power-host${SLED_NUM}" 0
Potin Laidb5648e2022-02-16 00:57:55 +0800396elif [[ "$ACTION" == "dfu" ]]; then
397 echo "Set host$SLED_NUM DFU mode"
398
Allen.Wang787c9c62022-03-02 14:55:03 +0800399 # turn ac off, and hold for 25 seconds
Potin Laidb5648e2022-02-16 00:57:55 +0800400 echo "SLED$SLED_NUM: turn ac-off"
401 set_gpio "power-host${SLED_NUM}" 0
Allen.Wang787c9c62022-03-02 14:55:03 +0800402 sleep 25
Potin Laidb5648e2022-02-16 00:57:55 +0800403
Allen.Wang787c9c62022-03-02 14:55:03 +0800404 # press power button
Potin Laidb5648e2022-02-16 00:57:55 +0800405 echo "SLED$SLED_NUM: pressing power button"
406 if ! press_power_button "$SLED_NUM"; then
407 echo "SLED$SLED_NUM: press power button failed"
408 echo "SLED$SLED_NUM: releasing power button"
409 release_power_button "$SLED_NUM"
410 exit 1
411 fi
Allen.Wang787c9c62022-03-02 14:55:03 +0800412 sleep 1
Potin Laidb5648e2022-02-16 00:57:55 +0800413
414 # turn ac on
415 echo "SLED$SLED_NUM: turn ac-on"
416 set_gpio "power-host${SLED_NUM}" 1
417 sleep 3
418
419 # release power button
420 echo "SLED$SLED_NUM: releasing host power button"
421 if ! release_power_button "$SLED_NUM"; then
422 echo "SLED$SLED_NUM: release power button failed"
423 exit 1
424 fi
Potin Lai035ff462022-04-28 17:02:21 +0800425elif [[ "$ACTION" == "recovery" ]]; then
426 if [ "$(get_ac_status "$SLED_NUM")" != "$HOST_AC_OFF" ]; then
427 echo "Please turn off host before trigger recovery mode"
428 exit 1
429 fi
430 echo "Set host$SLED_NUM Recovery mode"
431
432 # press power button
433 echo "SLED$SLED_NUM: pressing power button"
434 if ! press_power_button "$SLED_NUM"; then
435 echo "SLED$SLED_NUM: press power button failed"
436 echo "SLED$SLED_NUM: releasing power button"
437 release_power_button "$SLED_NUM"
438 exit 1
439 fi
440 sleep 10
441
442 # release power button
443 echo "SLED$SLED_NUM: releasing host power button"
444 if ! release_power_button "$SLED_NUM"; then
445 echo "SLED$SLED_NUM: release power button failed"
446 exit 1
447 fi
Allen.Wang4a0948d2021-12-15 13:41:18 +0800448else
449 echo "Unknown action: [ ${ACTION} ]"
450 show_usage
451fi