blob: 7b45710910209136c45f6053d449b1597fe29482 [file] [log] [blame]
George Hung3a9aa272020-06-19 19:45:43 +08001#!/bin/bash
2# Copyright 2020 Google LLC
3# Copyright 2020 Quanta Computer Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17
18source /usr/libexec/gbs-gpio-common.sh
19
20WD1RCR_ADDR=0xf080103c
21CORSTC_ADDR=0xf080105c
22BOARD_VER="" # Set by check_board_ver
23pe_eeprom_addr=( 50 54 )
24
25SERVICE_NAME="xyz.openbmc_project.Inventory.Manager"
26INTERFACE_NAME="xyz.openbmc_project.Inventory.Item"
27
28PE_PRESENT_OBJPATH=("/xyz/openbmc_project/inventory/system/chassis/gpios/pe_slot0_prsnt"
29"/xyz/openbmc_project/inventory/system/chassis/gpios/pe_slot1_prsnt")
30HSBP_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/hsbp_cab_prsnt"
31FANBD_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/fanbd_cab_prsnt"
32BP12V_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/bp12v_cab_prsnt"
33SATA0_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/sata0_prsnt"
34
35set_gpio_persistence() {
36 reg_val=$(devmem ${WD1RCR_ADDR} 32)
37 # Clear bit 16-23 to perserve all GPIO states across warm resets
38 reg_val=$(printf "0x%08x" $((reg_val & ~0xff0000)))
39 echo "Setting WD1RCR_ADDR to ${reg_val}"
40 devmem "${WD1RCR_ADDR}" 32 "${reg_val}"
41
42 reg_val=$(devmem ${CORSTC_ADDR} 32)
43 # Clear bit 16-23 of CORSTC
44 reg_val=$(printf "0x%08x" $((reg_val & ~0xff0000)))
45 echo "Setting CORSTC_ADDR to ${reg_val}"
46 devmem "${CORSTC_ADDR}" 32 "${reg_val}"
47}
48
49get_board_rev_id() {
50 echo $(get_gpio_value 'BMC_BRD_REV_ID7')\
51 $(get_gpio_value 'BMC_BRD_REV_ID6')\
52 $(get_gpio_value 'BMC_BRD_REV_ID5')\
53 $(get_gpio_value 'BMC_BRD_REV_ID4')\
54 $(get_gpio_value 'BMC_BRD_REV_ID3')\
55 $(get_gpio_value 'BMC_BRD_REV_ID2')\
56 $(get_gpio_value 'BMC_BRD_REV_ID1')\
57 $(get_gpio_value 'BMC_BRD_REV_ID0')\
58 | sed 's/ //g' > ~/board_rev_id.txt
59}
60
61get_board_sku_id() {
62 echo $(get_gpio_value 'BMC_BRD_SKU_ID3')\
63 $(get_gpio_value 'BMC_BRD_SKU_ID2')\
64 $(get_gpio_value 'BMC_BRD_SKU_ID1')\
65 $(get_gpio_value 'BMC_BRD_SKU_ID0')\
66 | sed 's/ //g' > ~/board_sku_id.txt
67}
68
69get_hsp_board_rev_id() {
70 echo $(get_gpio_value 'HSBP_BRD_REV_ID3')\
71 $(get_gpio_value 'HSBP_BRD_REV_ID2')\
72 $(get_gpio_value 'HSBP_BRD_REV_ID1')\
73 $(get_gpio_value 'HSBP_BRD_REV_ID0')\
74 | sed 's/ //g' > ~/hsp_board_rev_id.txt
75}
76
77get_fan_board_rev_id() {
78 echo $(get_gpio_value 'FAN_BRD_REV_ID1')\
79 $(get_gpio_value 'FAN_BRD_REV_ID0')\
80 | sed 's/ //g' > ~/fan_board_rev_id.txt
81}
82
83check_board_ver() {
84 # Sets BOARD_VER to either "PREPVT" or "PVT"
85 #
86 # BOARD_REV_ID[7:6] =
87 # 0x00 - EVT
88 # 0x01 - DVT
89 # 0x10 - PVT
90 # 0x11 - MP
91
92 rev7_val=$(get_gpio_value 'BMC_BRD_REV_ID7')
93 if (( rev7_val == 0 )); then
94 echo "EVT/DVT rev!"
95 BOARD_VER="PREPVT"
96 else
97 echo "PVT/MP rev!"
98 BOARD_VER="PVT"
99 fi
100}
101
102check_board_sku() {
103 sku1_val=$(get_gpio_value 'BMC_BRD_SKU_ID1')
104 if (( sku1_val == 1 )); then
105 echo "GBS SKU!"
106 BOARD_SKU="GBS"
107 else
108 echo "Other SKU!"
109 BOARD_SKU="TBD"
110 fi
111}
112
113set_uart_en_low() {
114 # GPIO76 UART_EN polarity inverted between DVT/PVT
115 # Pin direction was set high in the kernel.
116 set_gpio_direction 'FM_BMC_CPU_UART_EN' low
117}
118
119set_hdd_prsnt() {
120 # On PVT need to forward SATA0_PRSNT_N to HDD_PRSNT_N
121 # The signal is safe to set on DVT boards so just set universally.
122 sata_prsnt_n="$(busctl get-property $SERVICE_NAME ${SATA0_PRESENT_OBJPATH} \
123 $INTERFACE_NAME Present | awk '{print $2}')"
124 if [[ ${sata_prsnt_n} != "true" ]]; then
125 return 1
126 fi
127 # sata_prsnt_n is active low => value "true" means low
128 if [[ ${sata_prsnt_n} == "true" ]]; then
129 set_gpio_direction 'HDD_PRSNT_N' low
130 else
131 set_gpio_direction 'HDD_PRSNT_N' high
132 fi
133}
134
135KERNEL_FIU_ID="c0000000.fiu"
136KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU"
137
138bind_host_mtd() {
139 set_gpio_direction 'SPI_SW_SELECT' high
140 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
141 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
142 fi
143 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind
144}
145
146unbind_host_mtd() {
147 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
148 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
149 fi
150 set_gpio_direction 'SPI_SW_SELECT' low
151}
152trap unbind_host_mtd EXIT SIGHUP SIGINT SIGTERM
153
154# Taken from /run/initramfs/update
155# Given label name, return mtd node. e.g. `findmtd bmc` returns 'mtd0'
156findmtd() {
157 m=$(grep -xl "$1" /sys/class/mtd/*/name)
158 m=${m%/name}
159 m=${m##*/}
160 echo $m
161}
162
163verify_host_bios() {
164 echo "BIOS verification start!"
165
166 # placeholder for verifying host BIOS. For now time BIOS read
167 # with dd
168 bind_host_mtd || { echo "Failed to bind FIU driver for host MTD"; return 1; }
169
170 pnor_mtd=$(findmtd pnor)
171 [[ -z "${pnor_mtd}" ]] && { echo "Failed to find host MTD partition!"; return 1; }
172
173 # Test timing by computing SHA256SUM.
174 sha256sum /dev/${pnor_mtd}ro
175
176 echo "BIOS verification complete!"
177 unbind_host_mtd
178}
179
180reset_phy() {
181 ifconfig eth1 down
182 set_gpio_direction 'RST_BMC_PHY_N' low
183 set_gpio_direction 'RST_BMC_PHY_N' high
184 ifconfig eth1 up
185}
186
187parse_pe_fru() {
188 pe_fruid=3
189 for i in {1..2};
190 do
191 pe_prsnt_n="$(busctl get-property $SERVICE_NAME ${PE_PRESENT_OBJPATH[$(($i-1))]} \
192 $INTERFACE_NAME Present | awk '{print $2}')"
193
194 if [[ ${pe_prsnt_n} != "true" ]]; then
195 pe_fruid=$(($pe_fruid+1))
196 continue
197 fi
198
199 # Output is the i2c bus number for the PCIE cards on PE0/PE1
200 # i2c-0 -> i2c mux (addr: 0x71) -> PE0/PE1
201 # PE0: channel 0
202 # PE1: channel 1
203 pe_fru_bus="$(ls -al /sys/bus/i2c/drivers/pca954x/0-0071/ | grep channel \
204 | awk -F "/" '{print $(NF)}' | awk -F "-" '{print $2}' | sed -n "${i}p")"
205
206 # If the PE FRU EEPROM syspath does not exist, create it ("24c02" is the
207 # EEPROM part number) and perform a phosphor-read-eeprom
208 for ((j=0; j < ${#pe_eeprom_addr[@]}; j++));
209 do
210 i2cget -f -y $pe_fru_bus "0x${pe_eeprom_addr[$j]}" 0x01 > /dev/null 2>&1
211 if [ $? -eq 0 ]; then
212 if [ ! -f "/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom" ]; then
213 echo 24c02 "0x${pe_eeprom_addr[$j]}" > "/sys/bus/i2c/devices/i2c-$pe_fru_bus/new_device"
214 fi
215 pe_fru_bus="/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom"
216 phosphor-read-eeprom --eeprom $pe_fru_bus --fruid $pe_fruid
217 break
218 fi
219 done
220 pe_fruid=$(($pe_fruid+1))
221 done
222}
223
224check_power_status() {
225 res0="$(busctl get-property -j xyz.openbmc_project.State.Chassis \
226 /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis \
227 CurrentPowerState | jq -r '.["data"]')"
228 echo $res0
229}
230
231main() {
232 get_board_rev_id
233 get_board_sku_id
234
235 check_board_ver
236 if [[ "${BOARD_VER}" == "PREPVT" ]]; then
237 set_uart_en_low
238 fi
239
240 check_board_sku
241
242 hsbp_prsnt="$(busctl get-property $SERVICE_NAME ${HSBP_PRESENT_OBJPATH} \
243 $INTERFACE_NAME Present | awk '{print $2}')"
244 if [[ ${hsbp_prsnt} == "true" ]]; then
245 get_hsp_board_rev_id
246 hsbp_12v_prsnt="$(busctl get-property $SERVICE_NAME ${BP12V_PRESENT_OBJPATH} \
247 $INTERFACE_NAME Present | awk '{print $2}')"
248 if [[ ${hsbp_12v_prsnt} != "true" ]]; then
249 echo "HSBP board power cable(12V) not present !!"
250 fi
251 else
252 echo "HSBP board sideband cable not present !!"
253 echo "Stop NVMe Power/LED control Service "
254 systemctl stop xyz.openbmc_project.Control.Nvme.Power
255 systemctl stop xyz.openbmc_project.nvme.manager
256 fi
257
258 fan_prsnt="$(busctl get-property $SERVICE_NAME ${FANBD_PRESENT_OBJPATH} \
259 $INTERFACE_NAME Present | awk '{print $2}')"
260 if [[ ${fan_prsnt} == "true" ]]; then
261 get_fan_board_rev_id
262 else
263 echo "Fan board sideband cable not present !!"
264 fi
265
266 set_hdd_prsnt
267
268 reset_phy
269
270 if [[ $(check_power_status) != \
271 'xyz.openbmc_project.State.Chassis.PowerState.On' ]]; then
272 verify_host_bios
273
274 echo "Release host from reset!" >&2
275 set_gpio_direction 'RST_BMC_RSMRST_N' high
276 set_gpio_direction 'RST_KBRST_BMC_CPLD_N' high
277 # TODO: remove the hack once kernel driver is ready
278 # Set the GPIO states to preserve across reboots
279 set_gpio_persistence
280
281 echo "Starting host power!" >&2
282 busctl set-property xyz.openbmc_project.State.Host \
283 /xyz/openbmc_project/state/host0 \
284 xyz.openbmc_project.State.Host \
285 RequestedHostTransition s \
286 xyz.openbmc_project.State.Host.Transition.On
287 else
288 echo "Host is already running, doing nothing!" >&2
289 fi
290
291 parse_pe_fru
292}
293
294# Exit without running main() if sourced
295return 0 2>/dev/null
296
297main "$@"