summaryrefslogtreecommitdiff
path: root/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/power-ctrl
blob: b27ca323e08266451583558720fc29b387f27123 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
#!/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]"
    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
else
    echo "Unknown action: [ ${ACTION} ]"
    show_usage
fi