1#!/bin/bash
2
3# Disable check for usage of the definitions within mori-lib.sh
4#shellcheck disable=SC2034
5
6# get_gpio_num
7# Dynamically obtains GPIO number from chip base and I2C expanders
8# line-name
9function get_gpio_num() {
10    #shellcheck disable=SC2207
11    CHIP_PIN=($(gpiofind "$1" | awk '{print substr ($1, 9 ), $2 }'))
12    #shellcheck disable=SC2128
13    if [ -z "$CHIP_PIN" ]; then
14        echo "Could not find GPIO with name: $1"
15        return 1
16    fi
17
18    if [ "${CHIP_PIN[0]}" -gt 7 ]; then
19        BUS_ADDR=$(gpiodetect | grep gpiochip"${CHIP_PIN[0]}" | \
20                   grep -o '\[.*]' | tr -d ' \[\]')
21        GPIO_BASE_DIR=$(cd /sys/bus/i2c/devices/"$BUS_ADDR"/gpio/ || \
22                        exit; ls -1 -v)
23        # Check that there is a single gpiobank per i2c device
24        GPIO_BANKS=$(cd /sys/bus/i2c/devices/"$BUS_ADDR"/ || \
25                     exit ;  ls -1 -d -v gpiochip*)
26        # Determine which GPIO_BASE to use based on the place of the GPIO_BANK
27        # in comparision to GPIO_BANKS
28        # gpiochip# is set in reverse order of numbering for location of
29        # GPIO_BASE_DIR
30        count=$(echo "$GPIO_BANKS" | wc -w)
31        for X in ${GPIO_BANKS}
32        do
33            if [[ $(gpiofind "$1" | cut -d " " -f 1) == "$X" ]]; then
34                # Used to select the correct GPIO_BASE value
35                #shellcheck disable=SC2086
36                GPIO_BASE_DIR=("$(echo ${GPIO_BASE_DIR} | cut -d " " -f $count)")
37                break
38            fi
39            count=$((count-1))
40        done
41        tmp="/sys/bus/i2c/devices/$BUS_ADDR/gpio/${GPIO_BASE_DIR[0]}/base"
42        GPIO_BASE=$(cat "$tmp")
43        echo "$((GPIO_BASE+CHIP_PIN[1]))"
44    else
45        echo "$((CHIP_PIN[0]*32+CHIP_PIN[1]))"
46    fi
47}
48
49# set_gpio_ctrl
50# line-name, high(1)/low(0)
51function set_gpio_ctrl() {
52    #shellcheck disable=SC2046
53    gpioset $(gpiofind "$1")="$2"
54}
55
56# get_gpio_ctrl
57# line-name
58function get_gpio_ctrl() {
59    GPIO_NUM=$(get_gpio_num "$1")
60    echo "$GPIO_NUM" > /sys/class/gpio/export
61    # GPIOs added by drivers use different path for value most but not all
62    # drivers follow this trend
63    # Try reading like traditional GPIO, if fails, try reading in driver format
64    if ! cat /sys/class/gpio/gpio"$GPIO_NUM"/value 2> /dev/null ; then
65        cat /sys/class/gpio/"$1"/value
66    fi
67    echo "$GPIO_NUM" > /sys/class/gpio/unexport
68}
69
70
71function Does_File_Exist() {
72  local FILE=$1
73
74  if [[ ! -f "${FILE}" ]]; then
75    echo "${FILE} file does not exist" >&2
76    return 1
77  fi
78}
79
80function cleanup_bios_access() {
81  # Run only if setup_bios_access was previously ran
82  if Does_File_Exist /run/bios_access &> /dev/null ; then
83    # switch the SPI mux from BMC to Host
84    if [ -d "${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID}" ]; then
85      echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
86    fi
87    set_gpio_ctrl FM_BIOS_FLASH_SPI_MUX_R_SEL 0
88
89    # Indicate to host that BMC is finished accessing SPI
90    set_gpio_ctrl S0_BMC_SPI_NOR_ACCESS 0
91
92    rm /run/bios_access
93  fi
94}
95
96function setup_bios_access() {
97  # Run only if setup_bios_access was not previously ran without cleanup
98  if ! Does_File_Exist /run/bios_access &> /dev/null ; then
99    echo "BMC is accessing BIOS" > /run/bios_access
100
101    # rescan the spi bus
102    if [ -d "${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID}" ]; then
103      echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
104      usleep 100
105    fi
106
107    # Wait until the host is finished accessing the SPI
108    while [[ $(get_gpio_ctrl S0_SOC_SPI_NOR_ACCESS) == 1 ]]
109    do
110      sleep 1
111    done
112    # Indicate to host that BMC is accessing SPI
113    set_gpio_ctrl S0_BMC_SPI_NOR_ACCESS 1
114
115    # switch the SPI mux from Host to BMC
116    set_gpio_ctrl FM_BIOS_FLASH_SPI_MUX_R_SEL 1
117
118    echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind
119  fi
120}
121
122# Start definitions
123
124# I2C Definitions
125# The array is (<bus> <address>), where address is in hexadecimal.
126I2C_BMC_CPLD=(13 76)
127I2C_MB_CPLD=(0 76)
128I2C_FANCTRL=(35 2c)
129I2C_BMC_PWRSEQ=(48 59)
130I2C_MB_PWRSEQ=(40 40)
131I2C_CPU_EEPROM=(19 50)
132
133# File Path Definition
134# File path used to prevent hotswapping
135RST_LOCK_FILE="/etc/FW_FLASH_ONGOING"
136
137# Device name and driver path used for BIOS SPI
138KERNEL_FIU_ID="c0000000.spi"
139KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU"
140