blob: 9858404a032ca2b9f7fa3be53346eedb4f222185 [file] [log] [blame]
George Hung5f2142e2020-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
George Hungcad17882020-09-02 22:20:04 +080028PE_PRESENT_OBJPATH=("/xyz/openbmc_project/inventory/system/chassis/entity/pe_slot0_prsnt"
29"/xyz/openbmc_project/inventory/system/chassis/entity/pe_slot1_prsnt")
George Hungcad17882020-09-02 22:20:04 +080030SATA0_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/entity/sata0_prsnt"
31
George Hung5f2142e2020-06-19 19:45:43 +080032set_gpio_persistence() {
33 reg_val=$(devmem ${WD1RCR_ADDR} 32)
34 # Clear bit 16-23 to perserve all GPIO states across warm resets
35 reg_val=$(printf "0x%08x" $((reg_val & ~0xff0000)))
36 echo "Setting WD1RCR_ADDR to ${reg_val}"
37 devmem "${WD1RCR_ADDR}" 32 "${reg_val}"
38
39 reg_val=$(devmem ${CORSTC_ADDR} 32)
40 # Clear bit 16-23 of CORSTC
41 reg_val=$(printf "0x%08x" $((reg_val & ~0xff0000)))
42 echo "Setting CORSTC_ADDR to ${reg_val}"
43 devmem "${CORSTC_ADDR}" 32 "${reg_val}"
44}
45
46get_board_rev_id() {
47 echo $(get_gpio_value 'BMC_BRD_REV_ID7')\
48 $(get_gpio_value 'BMC_BRD_REV_ID6')\
49 $(get_gpio_value 'BMC_BRD_REV_ID5')\
50 $(get_gpio_value 'BMC_BRD_REV_ID4')\
51 $(get_gpio_value 'BMC_BRD_REV_ID3')\
52 $(get_gpio_value 'BMC_BRD_REV_ID2')\
53 $(get_gpio_value 'BMC_BRD_REV_ID1')\
54 $(get_gpio_value 'BMC_BRD_REV_ID0')\
55 | sed 's/ //g' > ~/board_rev_id.txt
56}
57
58get_board_sku_id() {
59 echo $(get_gpio_value 'BMC_BRD_SKU_ID3')\
60 $(get_gpio_value 'BMC_BRD_SKU_ID2')\
61 $(get_gpio_value 'BMC_BRD_SKU_ID1')\
62 $(get_gpio_value 'BMC_BRD_SKU_ID0')\
63 | sed 's/ //g' > ~/board_sku_id.txt
64}
65
George Hung90588792020-10-14 18:01:37 +080066get_hsbp_board_rev_id() {
George Hung5f2142e2020-06-19 19:45:43 +080067 echo $(get_gpio_value 'HSBP_BRD_REV_ID3')\
68 $(get_gpio_value 'HSBP_BRD_REV_ID2')\
69 $(get_gpio_value 'HSBP_BRD_REV_ID1')\
70 $(get_gpio_value 'HSBP_BRD_REV_ID0')\
George Hung90588792020-10-14 18:01:37 +080071 | sed 's/ //g' > ~/hsbp_board_rev_id.txt
George Hung5f2142e2020-06-19 19:45:43 +080072}
73
74get_fan_board_rev_id() {
75 echo $(get_gpio_value 'FAN_BRD_REV_ID1')\
76 $(get_gpio_value 'FAN_BRD_REV_ID0')\
77 | sed 's/ //g' > ~/fan_board_rev_id.txt
78}
79
80check_board_ver() {
81 # Sets BOARD_VER to either "PREPVT" or "PVT"
82 #
83 # BOARD_REV_ID[7:6] =
84 # 0x00 - EVT
85 # 0x01 - DVT
86 # 0x10 - PVT
87 # 0x11 - MP
88
89 rev7_val=$(get_gpio_value 'BMC_BRD_REV_ID7')
90 if (( rev7_val == 0 )); then
91 echo "EVT/DVT rev!"
92 BOARD_VER="PREPVT"
93 else
94 echo "PVT/MP rev!"
95 BOARD_VER="PVT"
96 fi
97}
98
99check_board_sku() {
100 sku1_val=$(get_gpio_value 'BMC_BRD_SKU_ID1')
101 if (( sku1_val == 1 )); then
102 echo "GBS SKU!"
103 BOARD_SKU="GBS"
104 else
105 echo "Other SKU!"
106 BOARD_SKU="TBD"
107 fi
108}
109
110set_uart_en_low() {
111 # GPIO76 UART_EN polarity inverted between DVT/PVT
112 # Pin direction was set high in the kernel.
113 set_gpio_direction 'FM_BMC_CPU_UART_EN' low
114}
115
116set_hdd_prsnt() {
117 # On PVT need to forward SATA0_PRSNT_N to HDD_PRSNT_N
118 # The signal is safe to set on DVT boards so just set universally.
119 sata_prsnt_n="$(busctl get-property $SERVICE_NAME ${SATA0_PRESENT_OBJPATH} \
George Hung90588792020-10-14 18:01:37 +0800120 $INTERFACE_NAME Present)"
121 if [[ "$?" == "0" && ${sata_prsnt_n} == "b false" ]]; then
George Hung5f2142e2020-06-19 19:45:43 +0800122 return 1
123 fi
124 # sata_prsnt_n is active low => value "true" means low
125 if [[ ${sata_prsnt_n} == "true" ]]; then
126 set_gpio_direction 'HDD_PRSNT_N' low
127 else
128 set_gpio_direction 'HDD_PRSNT_N' high
129 fi
130}
131
132KERNEL_FIU_ID="c0000000.fiu"
133KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU"
134
135bind_host_mtd() {
136 set_gpio_direction 'SPI_SW_SELECT' high
137 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
138 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
139 fi
140 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind
141}
142
143unbind_host_mtd() {
144 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
145 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
146 fi
147 set_gpio_direction 'SPI_SW_SELECT' low
148}
149trap unbind_host_mtd EXIT SIGHUP SIGINT SIGTERM
150
151# Taken from /run/initramfs/update
152# Given label name, return mtd node. e.g. `findmtd bmc` returns 'mtd0'
153findmtd() {
154 m=$(grep -xl "$1" /sys/class/mtd/*/name)
155 m=${m%/name}
156 m=${m##*/}
157 echo $m
158}
159
160verify_host_bios() {
161 echo "BIOS verification start!"
162
163 # placeholder for verifying host BIOS. For now time BIOS read
164 # with dd
165 bind_host_mtd || { echo "Failed to bind FIU driver for host MTD"; return 1; }
166
167 pnor_mtd=$(findmtd pnor)
168 [[ -z "${pnor_mtd}" ]] && { echo "Failed to find host MTD partition!"; return 1; }
169
170 # Test timing by computing SHA256SUM.
171 sha256sum /dev/${pnor_mtd}ro
172
173 echo "BIOS verification complete!"
174 unbind_host_mtd
175}
176
177reset_phy() {
178 ifconfig eth1 down
179 set_gpio_direction 'RST_BMC_PHY_N' low
180 set_gpio_direction 'RST_BMC_PHY_N' high
181 ifconfig eth1 up
182}
183
184parse_pe_fru() {
185 pe_fruid=3
186 for i in {1..2};
187 do
188 pe_prsnt_n="$(busctl get-property $SERVICE_NAME ${PE_PRESENT_OBJPATH[$(($i-1))]} \
George Hung90588792020-10-14 18:01:37 +0800189 $INTERFACE_NAME Present)"
George Hung5f2142e2020-06-19 19:45:43 +0800190
George Hung90588792020-10-14 18:01:37 +0800191 if [[ "$?" == "0" && ${pe_prsnt_n} == "b false" ]]; then
George Hung5f2142e2020-06-19 19:45:43 +0800192 pe_fruid=$(($pe_fruid+1))
193 continue
194 fi
195
196 # Output is the i2c bus number for the PCIE cards on PE0/PE1
197 # i2c-0 -> i2c mux (addr: 0x71) -> PE0/PE1
198 # PE0: channel 0
199 # PE1: channel 1
200 pe_fru_bus="$(ls -al /sys/bus/i2c/drivers/pca954x/0-0071/ | grep channel \
201 | awk -F "/" '{print $(NF)}' | awk -F "-" '{print $2}' | sed -n "${i}p")"
202
203 # If the PE FRU EEPROM syspath does not exist, create it ("24c02" is the
204 # EEPROM part number) and perform a phosphor-read-eeprom
205 for ((j=0; j < ${#pe_eeprom_addr[@]}; j++));
206 do
207 i2cget -f -y $pe_fru_bus "0x${pe_eeprom_addr[$j]}" 0x01 > /dev/null 2>&1
208 if [ $? -eq 0 ]; then
209 if [ ! -f "/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom" ]; then
210 echo 24c02 "0x${pe_eeprom_addr[$j]}" > "/sys/bus/i2c/devices/i2c-$pe_fru_bus/new_device"
211 fi
212 pe_fru_bus="/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom"
213 phosphor-read-eeprom --eeprom $pe_fru_bus --fruid $pe_fruid
214 break
215 fi
216 done
217 pe_fruid=$(($pe_fruid+1))
218 done
219}
220
221check_power_status() {
222 res0="$(busctl get-property -j xyz.openbmc_project.State.Chassis \
223 /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis \
224 CurrentPowerState | jq -r '.["data"]')"
225 echo $res0
226}
227
228main() {
229 get_board_rev_id
230 get_board_sku_id
George Hung90588792020-10-14 18:01:37 +0800231 get_hsbp_board_rev_id
232 get_fan_board_rev_id
George Hung5f2142e2020-06-19 19:45:43 +0800233
234 check_board_ver
235 if [[ "${BOARD_VER}" == "PREPVT" ]]; then
236 set_uart_en_low
237 fi
238
239 check_board_sku
240
George Hung5f2142e2020-06-19 19:45:43 +0800241 set_hdd_prsnt
242
243 reset_phy
244
245 if [[ $(check_power_status) != \
246 'xyz.openbmc_project.State.Chassis.PowerState.On' ]]; then
247 verify_host_bios
248
249 echo "Release host from reset!" >&2
250 set_gpio_direction 'RST_BMC_RSMRST_N' high
251 set_gpio_direction 'RST_KBRST_BMC_CPLD_N' high
252 # TODO: remove the hack once kernel driver is ready
253 # Set the GPIO states to preserve across reboots
254 set_gpio_persistence
255
256 echo "Starting host power!" >&2
257 busctl set-property xyz.openbmc_project.State.Host \
258 /xyz/openbmc_project/state/host0 \
259 xyz.openbmc_project.State.Host \
260 RequestedHostTransition s \
261 xyz.openbmc_project.State.Host.Transition.On
262 else
263 echo "Host is already running, doing nothing!" >&2
264 fi
265
266 parse_pe_fru
267}
268
269# Exit without running main() if sourced
270return 0 2>/dev/null
271
272main "$@"