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