blob: d0453ec5ed3842413da8c9892d3347614d020932 [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
George Hungc1449692020-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 Hungc1449692020-09-02 22:20:04 +080030SATA0_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/entity/sata0_prsnt"
31
George Hung3a9aa272020-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 Hung18307552020-10-14 18:01:37 +080066get_hsbp_board_rev_id() {
George Hung3a9aa272020-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 Hung18307552020-10-14 18:01:37 +080071 | sed 's/ //g' > ~/hsbp_board_rev_id.txt
George Hung3a9aa272020-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.
George Hungac35d892020-11-16 20:31:04 +0800119 mapper wait ${SATA0_PRESENT_OBJPATH}
George Hung3a9aa272020-06-19 19:45:43 +0800120 sata_prsnt_n="$(busctl get-property $SERVICE_NAME ${SATA0_PRESENT_OBJPATH} \
George Hung18307552020-10-14 18:01:37 +0800121 $INTERFACE_NAME Present)"
George Hungac35d892020-11-16 20:31:04 +0800122
George Hung3a9aa272020-06-19 19:45:43 +0800123 # sata_prsnt_n is active low => value "true" means low
George Hung529a8df2020-11-09 11:20:08 +0800124 if [[ ${sata_prsnt_n} == "b true" ]]; then
George Hung3a9aa272020-06-19 19:45:43 +0800125 set_gpio_direction 'HDD_PRSNT_N' low
126 else
127 set_gpio_direction 'HDD_PRSNT_N' high
128 fi
129}
130
131KERNEL_FIU_ID="c0000000.fiu"
132KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU"
133
134bind_host_mtd() {
135 set_gpio_direction 'SPI_SW_SELECT' high
136 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
137 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
138 fi
139 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind
140}
141
142unbind_host_mtd() {
143 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
144 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
145 fi
146 set_gpio_direction 'SPI_SW_SELECT' low
147}
148trap unbind_host_mtd EXIT SIGHUP SIGINT SIGTERM
149
150# Taken from /run/initramfs/update
151# Given label name, return mtd node. e.g. `findmtd bmc` returns 'mtd0'
152findmtd() {
153 m=$(grep -xl "$1" /sys/class/mtd/*/name)
154 m=${m%/name}
155 m=${m##*/}
156 echo $m
157}
158
159verify_host_bios() {
160 echo "BIOS verification start!"
161
162 # placeholder for verifying host BIOS. For now time BIOS read
163 # with dd
164 bind_host_mtd || { echo "Failed to bind FIU driver for host MTD"; return 1; }
165
166 pnor_mtd=$(findmtd pnor)
167 [[ -z "${pnor_mtd}" ]] && { echo "Failed to find host MTD partition!"; return 1; }
168
169 # Test timing by computing SHA256SUM.
170 sha256sum /dev/${pnor_mtd}ro
171
172 echo "BIOS verification complete!"
173 unbind_host_mtd
174}
175
176reset_phy() {
177 ifconfig eth1 down
178 set_gpio_direction 'RST_BMC_PHY_N' low
179 set_gpio_direction 'RST_BMC_PHY_N' high
180 ifconfig eth1 up
181}
182
183parse_pe_fru() {
184 pe_fruid=3
185 for i in {1..2};
186 do
George Hungac35d892020-11-16 20:31:04 +0800187 mapper wait ${PE_PRESENT_OBJPATH[$(($i-1))]}
George Hung3a9aa272020-06-19 19:45:43 +0800188 pe_prsnt_n="$(busctl get-property $SERVICE_NAME ${PE_PRESENT_OBJPATH[$(($i-1))]} \
George Hung18307552020-10-14 18:01:37 +0800189 $INTERFACE_NAME Present)"
George Hung3a9aa272020-06-19 19:45:43 +0800190
George Hungac35d892020-11-16 20:31:04 +0800191 if [[ ${pe_prsnt_n} == "b false" ]]; then
George Hung3a9aa272020-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 Hung18307552020-10-14 18:01:37 +0800231 get_hsbp_board_rev_id
232 get_fan_board_rev_id
George Hung3a9aa272020-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 Hung3a9aa272020-06-19 19:45:43 +0800241 reset_phy
242
243 if [[ $(check_power_status) != \
244 'xyz.openbmc_project.State.Chassis.PowerState.On' ]]; then
245 verify_host_bios
246
247 echo "Release host from reset!" >&2
248 set_gpio_direction 'RST_BMC_RSMRST_N' high
249 set_gpio_direction 'RST_KBRST_BMC_CPLD_N' high
250 # TODO: remove the hack once kernel driver is ready
251 # Set the GPIO states to preserve across reboots
252 set_gpio_persistence
253
254 echo "Starting host power!" >&2
255 busctl set-property xyz.openbmc_project.State.Host \
256 /xyz/openbmc_project/state/host0 \
257 xyz.openbmc_project.State.Host \
258 RequestedHostTransition s \
259 xyz.openbmc_project.State.Host.Transition.On
260 else
261 echo "Host is already running, doing nothing!" >&2
262 fi
263
George Hungac35d892020-11-16 20:31:04 +0800264 set_hdd_prsnt
George Hung3a9aa272020-06-19 19:45:43 +0800265 parse_pe_fru
266}
267
268# Exit without running main() if sourced
269return 0 2>/dev/null
270
271main "$@"