xref: /openbmc/openbmc/meta-facebook/meta-harma/recipes-phosphor/state/phosphor-state-manager/power-cmd (revision a5915c00b50438dd8cccff22c628f790f43268d7)
1#!/bin/bash
2
3# shellcheck source=meta-facebook/recipes-fb/obmc_functions/files/fb-common-functions
4source /usr/libexec/fb-common-functions
5renice -10 $$
6
7check_valid_sgpio() {
8    sgpio_vaild0=$(get_gpio "power-card-enable")
9    sgpio_vaild1=$(get_gpio "power-12v-memory-good")
10    sgpio_vaild2=$(get_gpio "power-pvdd33-s5")
11
12    if [[ "$sgpio_vaild0" == "0" && "$sgpio_vaild1" == "0" && "$sgpio_vaild2" == "1" ]]; then
13        return 0  # true
14    else
15        return 1  # false
16    fi
17}
18
19# Power Good Status
20power_status() {
21    check_valid_sgpio
22    valid_sgpio=$?
23
24    if [ "$(get_gpio "host0-ready")" -eq 1 ] && [ "$valid_sgpio" -eq 0 ] ; then
25        echo "on"
26    else
27        echo "off"
28    fi
29}
30
31# Force DC off
32force_power_off() {
33    if [ "$(power_status)" == "on" ]; then
34        set_gpio power-host-control 0
35        sleep 6
36        set_gpio power-host-control 1
37        sleep 6
38    fi
39
40    # Workaround for AMD force shutdown failure.
41    if [ "$(power_status)" == "on" ]; then
42        set_gpio reset-control 0
43        sleep 1
44        set_gpio reset-control 1
45        sleep 3
46
47        set_gpio power-host-control 0
48        sleep 1
49        set_gpio power-host-control 1
50        sleep 1
51
52        for i in $(seq 1 10)
53        do
54            sleep 1
55            if [ "$(power_status)" == "off" ]; then
56               return 0
57            fi
58
59            if [ "$i" -eq 10 ]; then
60               return 1
61            fi
62        done
63    fi
64}
65
66# Graceful DC off
67graceful_power_off() {
68    if [ "$(power_status)" == "on" ]; then
69        set_gpio power-host-control 0
70        sleep 1
71        set_gpio power-host-control 1
72        sleep 1
73
74        # wait host power off
75        for i in $(seq 1 20)
76        do
77            sleep 1
78            if [ "$(power_status)" == "off" ]; then
79               break
80            fi
81        done
82    fi
83}
84
85# DC on
86power_on() {
87    if [ "$(power_status)" == "off" ]; then
88        set_gpio power-host-control 0
89        sleep 1
90        set_gpio power-host-control 1
91        sleep 1
92
93        for i in $(seq 1 10)
94        do
95            sleep 1
96            if [ "$(power_status)" == "on" ]; then
97               return 0
98            fi
99
100            if [ "$i" -eq 10 ]; then
101               return 1
102            fi
103        done
104    fi
105    return 0
106}
107
108# Host reset
109power_reset() {
110    set_gpio reset-control 0
111    sleep 1
112    set_gpio reset-control 1
113    sleep 1
114    return 0
115}
116
117# Sync power state to "off" for abnormal power loss.
118power_off_sync() {
119    local timeout=${1:-8}   # default 8 seconds if not provided
120    local delay=${2:-1}     # default 1 second interval if not provided
121
122    for ((i=0; i<timeout; i++)); do
123        local status
124        status=$(power_status)
125        if [ "$status" != "off" ]; then
126            return
127        fi
128        sleep "$delay"
129    done
130
131    local transition
132    transition=$(busctl get-property \
133        xyz.openbmc_project.State.Host0 \
134        /xyz/openbmc_project/state/host0 \
135        xyz.openbmc_project.State.Host \
136        RequestedHostTransition | awk '{print $2}' | tr -d '"')
137
138    if [ "$transition" != "xyz.openbmc_project.State.Host.Transition.Off" ] && [ "$(power_status)" == "off" ]; then
139        busctl set-property xyz.openbmc_project.State.Host0 \
140            /xyz/openbmc_project/state/host0 \
141            xyz.openbmc_project.State.Host \
142            RequestedHostTransition s \
143            xyz.openbmc_project.State.Host.Transition.Off
144    fi
145}
146
147# Sync power status to "On" for abnormal power-on scenarios.
148power_on_sync() {
149    local timeout=${1:-3}   # default 3 seconds if not provided
150    local delay=${2:-1}     # default 1 second interval if not provided
151
152    for ((i=0; i<timeout; i++)); do
153        local status
154        status=$(power_status)
155        if [ "$status" != "on" ]; then
156            return
157        fi
158        sleep "$delay"
159    done
160
161    local transition
162    transition=$(busctl get-property \
163        xyz.openbmc_project.State.Host0 \
164        /xyz/openbmc_project/state/host0 \
165        xyz.openbmc_project.State.Host \
166        RequestedHostTransition | awk '{print $2}' | tr -d '"')
167
168    if [ "$transition" != "xyz.openbmc_project.State.Host.Transition.On" ] && [ "$(power_status)" == "on" ]; then
169        busctl set-property xyz.openbmc_project.State.Host0 \
170            /xyz/openbmc_project/state/host0 \
171            xyz.openbmc_project.State.Host \
172            RequestedHostTransition s \
173            xyz.openbmc_project.State.Host.Transition.On
174    fi
175}
176
177# Main execution
178if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
179    case "$1" in
180        force_off)
181            force_power_off
182            ;;
183        graceful_off)
184            graceful_power_off
185            ;;
186        power_on)
187            power_on
188            ;;
189        power_reset)
190            power_reset
191            ;;
192        off_sync)
193            power_off_sync "$2" "$3"
194            ;;
195        on_sync)
196            power_on_sync "$2" "$3"
197            ;;
198        status)
199            power_status
200            ;;
201        *)
202            echo "Usage: $0 {force_off|graceful_off|power_on|power_reset|off_sync|on_sync|status}"
203            exit 0
204            ;;
205    esac
206fi
207
208