blob: 17074ddaff9954cc35068b3d8542427f2d6c8cf5 [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.
George Hung0a2c1052020-11-16 20:31:04 +0800119 mapper wait ${SATA0_PRESENT_OBJPATH}
George Hung5f2142e2020-06-19 19:45:43 +0800120 sata_prsnt_n="$(busctl get-property $SERVICE_NAME ${SATA0_PRESENT_OBJPATH} \
George Hung90588792020-10-14 18:01:37 +0800121 $INTERFACE_NAME Present)"
George Hung0a2c1052020-11-16 20:31:04 +0800122
George Hung5f2142e2020-06-19 19:45:43 +0800123 # sata_prsnt_n is active low => value "true" means low
George Hung947b9a42020-11-09 11:20:08 +0800124 if [[ ${sata_prsnt_n} == "b true" ]]; then
George Hung5f2142e2020-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
George Hung8350dd72021-07-01 12:22:16 +0800131KERNEL_FIU_ID="c0000000.spi"
George Hung5f2142e2020-06-19 19:45:43 +0800132KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU"
133
George Hung8350dd72021-07-01 12:22:16 +0800134# the node of FIU is spi for kernel 5.10, but
135# for less than or equal kernel 5.4, the node
136# is fiu
Brandon Kimcbe8a9f2021-07-07 15:08:13 -0700137shopt -s nullglob
138for fiu in "$KERNEL_SYSFS_FIU"/*.fiu; do
139 KERNEL_FIU_ID="c0000000.fiu"
140 break
George Hung8350dd72021-07-01 12:22:16 +0800141done
142
George Hung5f2142e2020-06-19 19:45:43 +0800143bind_host_mtd() {
144 set_gpio_direction 'SPI_SW_SELECT' high
145 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
146 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
147 fi
148 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind
149}
150
151unbind_host_mtd() {
152 if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then
153 echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
154 fi
155 set_gpio_direction 'SPI_SW_SELECT' low
156}
157trap unbind_host_mtd EXIT SIGHUP SIGINT SIGTERM
158
159# Taken from /run/initramfs/update
160# Given label name, return mtd node. e.g. `findmtd bmc` returns 'mtd0'
161findmtd() {
162 m=$(grep -xl "$1" /sys/class/mtd/*/name)
163 m=${m%/name}
164 m=${m##*/}
165 echo $m
166}
167
168verify_host_bios() {
169 echo "BIOS verification start!"
170
171 # placeholder for verifying host BIOS. For now time BIOS read
172 # with dd
173 bind_host_mtd || { echo "Failed to bind FIU driver for host MTD"; return 1; }
174
175 pnor_mtd=$(findmtd pnor)
176 [[ -z "${pnor_mtd}" ]] && { echo "Failed to find host MTD partition!"; return 1; }
177
178 # Test timing by computing SHA256SUM.
179 sha256sum /dev/${pnor_mtd}ro
180
181 echo "BIOS verification complete!"
182 unbind_host_mtd
183}
184
George Hung5f2142e2020-06-19 19:45:43 +0800185parse_pe_fru() {
186 pe_fruid=3
187 for i in {1..2};
188 do
George Hung0a2c1052020-11-16 20:31:04 +0800189 mapper wait ${PE_PRESENT_OBJPATH[$(($i-1))]}
George Hung5f2142e2020-06-19 19:45:43 +0800190 pe_prsnt_n="$(busctl get-property $SERVICE_NAME ${PE_PRESENT_OBJPATH[$(($i-1))]} \
George Hung90588792020-10-14 18:01:37 +0800191 $INTERFACE_NAME Present)"
George Hung5f2142e2020-06-19 19:45:43 +0800192
George Hung0a2c1052020-11-16 20:31:04 +0800193 if [[ ${pe_prsnt_n} == "b false" ]]; then
George Hung5f2142e2020-06-19 19:45:43 +0800194 pe_fruid=$(($pe_fruid+1))
195 continue
196 fi
197
198 # Output is the i2c bus number for the PCIE cards on PE0/PE1
199 # i2c-0 -> i2c mux (addr: 0x71) -> PE0/PE1
200 # PE0: channel 0
201 # PE1: channel 1
202 pe_fru_bus="$(ls -al /sys/bus/i2c/drivers/pca954x/0-0071/ | grep channel \
203 | awk -F "/" '{print $(NF)}' | awk -F "-" '{print $2}' | sed -n "${i}p")"
204
205 # If the PE FRU EEPROM syspath does not exist, create it ("24c02" is the
206 # EEPROM part number) and perform a phosphor-read-eeprom
207 for ((j=0; j < ${#pe_eeprom_addr[@]}; j++));
208 do
209 i2cget -f -y $pe_fru_bus "0x${pe_eeprom_addr[$j]}" 0x01 > /dev/null 2>&1
210 if [ $? -eq 0 ]; then
211 if [ ! -f "/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom" ]; then
212 echo 24c02 "0x${pe_eeprom_addr[$j]}" > "/sys/bus/i2c/devices/i2c-$pe_fru_bus/new_device"
213 fi
214 pe_fru_bus="/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom"
215 phosphor-read-eeprom --eeprom $pe_fru_bus --fruid $pe_fruid
216 break
217 fi
218 done
219 pe_fruid=$(($pe_fruid+1))
220 done
221}
222
223check_power_status() {
George Hung97466ae2021-07-28 10:47:49 +0800224 res0="$(busctl get-property -j xyz.openbmc_project.State.Chassis0 \
George Hung5f2142e2020-06-19 19:45:43 +0800225 /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis \
226 CurrentPowerState | jq -r '.["data"]')"
227 echo $res0
228}
229
George Hung8350dd72021-07-01 12:22:16 +0800230clk_buf_bus_switch="11-0076"
231clk_buf_driver="/sys/bus/i2c/drivers/pca954x/"
232
233bind_clk_buf_switch() {
234 echo "Re-bind i2c bus 11 clk_buf_switch"
235 echo "${clk_buf_bus_switch}" > "${clk_buf_driver}"/bind
236}
237
George Hung5f2142e2020-06-19 19:45:43 +0800238main() {
239 get_board_rev_id
240 get_board_sku_id
George Hung90588792020-10-14 18:01:37 +0800241 get_hsbp_board_rev_id
242 get_fan_board_rev_id
George Hung5f2142e2020-06-19 19:45:43 +0800243
244 check_board_ver
245 if [[ "${BOARD_VER}" == "PREPVT" ]]; then
246 set_uart_en_low
247 fi
248
249 check_board_sku
250
George Hung5f2142e2020-06-19 19:45:43 +0800251 if [[ $(check_power_status) != \
252 'xyz.openbmc_project.State.Chassis.PowerState.On' ]]; then
253 verify_host_bios
254
255 echo "Release host from reset!" >&2
256 set_gpio_direction 'RST_BMC_RSMRST_N' high
257 set_gpio_direction 'RST_KBRST_BMC_CPLD_N' high
258 # TODO: remove the hack once kernel driver is ready
259 # Set the GPIO states to preserve across reboots
260 set_gpio_persistence
261
262 echo "Starting host power!" >&2
George Hung97466ae2021-07-28 10:47:49 +0800263 busctl set-property xyz.openbmc_project.State.Host0 \
George Hung5f2142e2020-06-19 19:45:43 +0800264 /xyz/openbmc_project/state/host0 \
265 xyz.openbmc_project.State.Host \
266 RequestedHostTransition s \
267 xyz.openbmc_project.State.Host.Transition.On
George Hung8350dd72021-07-01 12:22:16 +0800268
269 sleep 1
270 bind_clk_buf_switch
George Hung5f2142e2020-06-19 19:45:43 +0800271 else
272 echo "Host is already running, doing nothing!" >&2
273 fi
274
George Hung0a2c1052020-11-16 20:31:04 +0800275 set_hdd_prsnt
George Hung5f2142e2020-06-19 19:45:43 +0800276 parse_pe_fru
277}
278
279# Exit without running main() if sourced
280return 0 2>/dev/null
281
282main "$@"