#!/bin/bash
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

# shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh

# Bus 0: Create i2c slave backend for ipmbd_0(BIC)
i2c_mslave_add 0 0x10

# Bus 4: Create i2c slave backend for ipmbd_4(Debug Card)
i2c_mslave_add 4 0x10

# Bus 16: i2c bus 1 mux, channel 0
i2c_device_add 16 0x4d ir35215              # ir35215
# Bus 17: i2c bus 1 mux, channel 1
i2c_device_add 17 0x40 xdpe132g5c           # xdpe132g5c
# Bus 18: i2c bus 1 mux, channel 2
i2c_device_add 18 0x3a powr1220             # powr1220
# Bus 19: i2c bus 1 mux, channel 3
i2c_device_add 19 0x68 xdpe12284            # xdpe12284
# Bus 20: i2c bus 1 mux, channel 4
i2c_device_add 20 0x0e pxe1211              # pxe1211
# Bus 21: i2c bus 1 mux, channel 5
i2c_device_add 21 0x47 ir35215              # ir35215
# Bus 22: i2c bus 1 mux, channel 6
i2c_device_add 22 0x60 xdpe12284            # xdpe12284
# Bus 23: i2c bus 1 mux, channel 7
# None

# Bus 2
i2c_device_add 2 0x3e scmcpld               # SCM CPLD

# Bus 24: i2c bus 2 mux, channel 0
i2c_device_add 24 0x10 adm1278              # adm1278
# Bus 26: i2c bus 2 mux, channel 2
# None
# Bus 27: i2c bus 2 mux, channel 3
i2c_device_add 27 0x52 24c64                # SCM EEPROM
# Bus 28: i2c bus 2 mux, channel 4
i2c_device_add 28 0x50 24c02                # SCM BCM546161S EEPROM
# Bus 29: i2c bus 2 mux, channel 5
# None
# Bus 30: i2c bus 2 mux, channel 6
# None
# Bus 31: i2c bus 2 mux, channel 7
# i2c_device_add 31 0x50 si53108            # si53108 do not enable this

# Bus 3
# Bus 35: i2c bus 3 mux, channel 3
i2c_device_add 35 0x4c tmp421               # tmp421
# Bus 36: i2c bus 3 mux, channel 4
i2c_device_add 36 0x4d tmp421               # tmp421
# Bus 38: i2c bus 3 mux, channel 6
i2c_device_add 38 0x2a net_asic             # GB switch i2c driver

# Bus 4
i2c_device_add 4 0x27 pca9555               # PCA9555 GPIO expander for debug card

# Bus 5
i2c_device_add 5 0x60 domfpga               # DOM FPGA 2

# Bus 6
i2c_device_add 6 0x51 24c64                 # SMB EEPROM
i2c_device_add 6 0x21 pca9534               # pca9534 GPIO expander

# Bus 7
# i2c_device_add 7 0x2e tpm_tis_i2c         # i2c tpm, driver binding in device tree

# Bus 8
i2c_device_add 8 0x51 24c64                 # i2c EEPROM
# Bus 40: i2c bus 8 mux, channel 0
# i2c_device_add 40 0xa0/0xb0 24c02/24c64   # PSU1 EEPROM
i2c_device_add 40 0x58 psu_driver           # PSU1 MCU
# Bus 41: i2c bus 8 mux, channel 1
# i2c_device_add 41 0xa0/0xb0 24c02/24c64   # PSU1 EEPROM
i2c_device_add 41 0x58 psu_driver           # PSU2 MCU
# Bus 42: i2c bus 8 mux, channel 2
i2c_device_add 42 0x50 24c02                # BMC BCM54616S EEPROM
# Bus 43: i2c bus 8 mux, channel 3
i2c_device_add 43 0x50 24c02                # BCM5389 BCM54616S EEPROM
# Bus 44: i2c bus 8 mux, channel 4
# None
# Bus 45: i2c bus 8 mux, channel 5
# pwr cpld upgrade interface
# Bus 46: i2c bus 8 mux, channel 6
# None
# Bus 47: i2c bus 8 mux, channel 7
i2c_device_add 47 0x3e smb_pwrcpld          # PWR CPLD

# Bus 9
# i2c_device_add 9 0x74 si5391b             # si5391b do not enable this
# i2c_device_add 9 TBD usb_hub              # usb_hub do not enable this

# Bus 10
# i2c_device_add 10 0x0d runbmc_fpga        # PFR FPGA

# Bus 12
i2c_device_add 12 0x3e smb_syscpld          # SMB CPLD

# Bus 13
i2c_device_add 13 0x60 domfpga              # DOM FPGA 1

# Bus 14
# disabled, multiple function pin, used as MDIO

# Bus 48: i2c bus 15 mux, channel 0
i2c_device_add 48 0x3e fcbcpld              # FCM CPLD
# Bus 49: i2c bus 15 mux, channel 1
i2c_device_add 49 0x51 24c64                # FCM EEPROM
# Bus 51: i2c bus 15 mux, channel 3
i2c_device_add 51 0x10 adm1278              # FCM Hotswap adm1278
# Bus 52: i2c bus 15 mux, channel 4
i2c_device_add 52 0x52 24c64                # FAN4 EEPROM
# Bus 53: i2c bus 15 mux, channel 5
i2c_device_add 53 0x52 24c64                # FAN3 EEPROM
# Bus 54: i2c bus 15 mux, channel 6
i2c_device_add 54 0x52 24c64                # FAN2 EEPROM
# Bus 55: i2c bus 15 mux, channel 7
i2c_device_add 55 0x52 24c64                # FAN1 EEPROM

# cloudripper will mix the NXP LM75 and TI TMP1075 sensor chips
# LM75 not support device id read, but TI TMP1075 support
# BMC can access TMP1075 0x0F address to get TMP1075 device id
TMP1075_ID=0x75
fixup_lm75_tmp1075_devices() {
    # Bus 25: i2c bus 2 mux, channel 1
    DEV_ID=$(i2cget -y -f 25 0x4c 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 25 0x4c tmp1075              # i2c tmp1075
    else
        i2c_device_add 25 0x4c lm75                 # i2c lm75
    fi

    DEV_ID=$(i2cget -y -f 25 0x4d 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 25 0x4d tmp1075              # i2c tmp1075
    else
        i2c_device_add 25 0x4d lm75                 # i2c lm75
    fi

    # Bus 3
    DEV_ID=$(i2cget -y -f 3 0x4a 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 3 0x4a tmp1075               # i2c tmp1075
    else
        i2c_device_add 3 0x4a lm75                  # i2c lm75
    fi

    # Bus 32: i2c bus 3 mux, channel 0
    DEV_ID=$(i2cget -y -f 32 0x48 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 32 0x48 tmp1075              # i2c tmp1075
    else
        i2c_device_add 32 0x48 lm75                 # i2c lm75
    fi
    # Bus 33: i2c bus 3 mux, channel 1
    DEV_ID=$(i2cget -y -f 33 0x49 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 33 0x49 tmp1075              # i2c tmp1075
    else
        i2c_device_add 33 0x49 lm75                 # i2c lm75
    fi
    # Bus 34: i2c bus 3 mux, channel 2
    DEV_ID=$(i2cget -y -f 34 0x4b 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 34 0x4b tmp1075              # tmp1075
    else
        i2c_device_add 34 0x4b lm75                 # i2c lm75
    fi

    # Bus 37: i2c bus 3 mux, channel 5
    DEV_ID=$(i2cget -y -f 37 0x4e 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 37 0x4e tmp1075              # i2c tmp1075
    else
        i2c_device_add 37 0x4e lm75                 # i2c lm75
    fi

    # Bus 39: i2c bus 3 mux, channel 7
    DEV_ID=$(i2cget -y -f 39 0x4f 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 39 0x4f tmp1075              # i2c tmp1075
    else
        i2c_device_add 39 0x4f lm75                 # i2c lm75
    fi

    # Bus 8
    DEV_ID=$(i2cget -y -f 8 0x4a 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 8 0x4a tmp1075               # i2c tmp1075
    else
        i2c_device_add 8 0x4a lm75                  # i2c lm75
    fi

    # Bus 50: i2c bus 15 mux, channel 2
    DEV_ID=$(i2cget -y -f 50 0x48 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 50 0x48 tmp1075              # FCM tmp1075
    else
        i2c_device_add 50 0x48 lm75                 # FCM lm75
    fi

    DEV_ID=$(i2cget -y -f 50 0x49 0x0f)
    if [ "$DEV_ID" = "$TMP1075_ID" ]; then
        i2c_device_add 50 0x49 tmp1075              # FCM tmp1075
    else
        i2c_device_add 50 0x49 lm75                 # FCM lm75
    fi
}

fixup_lm75_tmp1075_devices


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

#shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

COM_E_PWRGD=$(head -n 1 "${SCMCPLD_SYSFS_DIR}/pwrgd_pch_pwrok")

usage(){
    program=$(basename "$0")
    echo "Usage:"
    echo "     $program led"
}

if [ $# -ne 1 ]; then
    usage
    exit 1
fi

# When COM-e power is not ready, it doesn't work to set PHY register.
# Therefore, waiting for COM-e power ready, then start to set PHY register.
while [ "$COM_E_PWRGD" = "0x0" ];
do
    COM_E_PWRGD=$(head -n 1 "${SCMCPLD_SYSFS_DIR}/pwrgd_pch_pwrok")
    sleep 5
done

if [ "$1" = "led" ]; then
    echo "Wait a few seconds to setup management port LED..."
    # refer to BCM54616S Section 5, register 1C access
    # Register 1C (Shadow 00010): Spare Control 1
    # Bit0: 1: Enable link LED mode.
    mdio-util -m 2 -p 0xe -w 0x1c -d 0x8801
    # Register 1C (Shadow 01110): LED Selector 2
    # Bit7~4: LED4 Selector, b0011: Activity LED
    # Bit3~0: LED4 Selector, b0101: Slave
    mdio-util -m 2 -p 0xe -w 0x1c -d 0xb435
    echo "Done!"
else
    usage
    exit 1
fi


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

dev=$1
color=$2

usage(){
  program=$(basename "$0")
  echo "Usage:"
  echo "     $program <dev> <color>"
  echo ""
  echo "     <dev>: sys/fan/psu/scm"
  echo "     <color>: off/red/blue/green/amber"
}

led=""
case $dev in
  "sys" | "fan" | "psu" | "scm")
    led="/sys/class/leds/$dev"
  ;;
  *)
    usage
    exit 1
  ;;
esac

# color: red/blue/green value: 0-255
# brightness: 0-255
brightness="255"
case $color in
  "red")
    color="255 0 0"
  ;;
  "blue")
    color="0 255 0"
  ;;
  "green")
    color="0 0 255"
  ;;
  "amber")
    color="255 0 45"
  ;;
  "off")
    color="0 0 0"
    brightness=0
  ;;
  *)
    usage
    exit 1
  ;;
esac

echo "$color" > "$led/multi_intensity"
echo $brightness > "$led/brightness"


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

#shellcheck disable=SC1091
. /usr/local/bin/i2c-utils.sh

usage()
{
  echo "usage :"
  echo "   $0 <voltage in mv>"
  echo "   eg. $0 850"
  echo " limit : max 930 mV"
}

find_hwmon_path() {
  cd "$1"/hwmon/hwmon* 2> /dev/null || return 1
  pwd
}

if [ $# -ne 1 ]; then
  usage
  exit 255
fi

if [ $(($1)) -gt 931 ]; then
  usage
  exit 255
fi

vddcore_i2c_path=$(i2c_device_sysfs_abspath 17-0040)
vddcore_hwmon_path=$(find_hwmon_path "$vddcore_i2c_path")
if [ -z "$vddcore_hwmon_path" ]; then
  echo "device is not found"
  exit 1
fi
vddcore_sysfs_node="$vddcore_hwmon_path/vout0_value"

if echo "$1" > "$vddcore_sysfs_node"; then
  echo "$1"
  exit 0
else
  echo "setting error"
  exit 254
fi


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

#shellcheck disable=SC1091,SC2009
. /usr/local/bin/openbmc-utils.sh

CONSOLE_SH=/usr/local/bin/us_console.sh
FILE=/etc/us_pseudo_tty
TTY=/dev/ttyS4

mTerm_server_running() {
  pid=$(ps | grep -v grep | grep '/usr/local/bin/mTerm_server' -m 1 |
        awk '{print $1}')
  if [ "$pid" ] ; then
    return 0
  fi
  return 1
}

start_sol_session() {
  if [ -e $FILE ]; then
    read -r TTY<$FILE
  fi
  $CONSOLE_SH connect

  echo "You are in SOL session."
  echo "Use ctrl-x to quit."
  echo "-----------------------"
  echo

  trap '"$CONSOLE_SH" disconnect' INT TERM QUIT EXIT

  /usr/bin/microcom -s 57600 "$TTY"

  echo
  echo
  echo "-----------------------"
  echo "Exit from SOL session."
}

# if mTerm server is running use mTerm_client to connect to userver
# otherwise fallback to the old method
echo 0x3 > "$SMBCPLD_SYSFS_DIR/uart_selection"
if mTerm_server_running; then
  exec /usr/local/bin/mTerm_client wedge
else
  start_sol_session
fi


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
#shellcheck disable=SC1091
#shellcheck disable=SC2039
#shellcheck disable=SC2086
. /usr/local/bin/openbmc-utils.sh

ret=0
trap cleanup_spi INT TERM QUIT EXIT

PIDFILE="/var/run/spi_util.pid"
check_duplicate_process()
{
    exec 2>$PIDFILE
    flock -n 2 || (echo "Another process is running" && exit 1)
    ret=$?
    if [ $ret -eq 1 ]; then
      exit 1
    fi
    pid=$$
    echo $pid 1>&200
}

remove_pid_file()
{
    if [ -f $PIDFILE ]; then
        rm $PIDFILE
    fi
}

SPI1_MTD_INDEX=7
SPI1_DRIVER="1e630000.spi"
ASPEED_SMC_PATH="/sys/bus/platform/drivers/aspeed-smc/"

read_spi1_dev(){
    dev=$1
    file=$2
    echo "Reading ${dev} to $file..."
    flashrom -p linux_mtd:dev=$SPI1_MTD_INDEX -r "$file"
}

write_spi1_dev(){
    dev=$1
    file=$2
    echo "Writing $file to ${dev}..."

    tmpfile="$file"_ext
    flashsize=$(flashrom -p linux_mtd:dev=$SPI1_MTD_INDEX | grep -i kB | xargs echo | cut -d '(' -f 2 | cut -d ' ' -f 0)
    targetsize=$((flashsize * 1024))

    cp "$file" "$tmpfile"

    #extend the temp-file
    filesize=$(stat -c%s $tmpfile)
    add_size=$((targetsize - filesize))
    dd if=/dev/zero bs="$add_size" count=1 | tr "\000" "\377" >> "$tmpfile"
    flashrom -p linux_mtd:dev=$SPI1_MTD_INDEX -w "$tmpfile"
}

erase_spi1_dev(){
    flashrom -p linux_mtd:dev=$SPI1_MTD_INDEX -E
}

mtd_driver_unbind_spi1() {
    [ -e ${ASPEED_SMC_PATH}${SPI1_DRIVER} ] && echo ${SPI1_DRIVER} > ${ASPEED_SMC_PATH}unbind
}

mtd_driver_rebind_spi1() {
    # Sometime kernel may complain "vmap allocation for size 268439552 failed: use vmalloc=<size> to increase size"
    # until now the root cause is not clear, still need more investigation
    mtd_driver_unbind_spi1
    echo ${SPI1_DRIVER} > ${ASPEED_SMC_PATH}bind
}

config_spi1_pin_and_path(){
    dev=$1
    case ${dev} in
        "BIOS")
            echo "[Setup] BIOS"
            echo 0x01 > "$SMBCPLD_SYSFS_DIR/spi_1_sel"
        ;;
        "GB_PCIE_FLASH")
            echo "[Setup] GB_PCIE_FLASH"
            echo 0x03 > "$SMBCPLD_SYSFS_DIR/spi_1_sel"
        ;;
        "DOM_FPGA_FLASH1")
            echo "[Setup] DOM_FPGA_FLASH1"
            echo 0x04 > "$SMBCPLD_SYSFS_DIR/spi_1_sel"
        ;;
        "DOM_FPGA_FLASH2")
            echo "[Setup] DOM_FPGA_FLASH2"
            echo 0x05 > "$SMBCPLD_SYSFS_DIR/spi_1_sel"
        ;;
        *)
            echo "Please enter {BIOS, GB_PCIE_FLASH, DOM_FPGA_FLASH1, DOM_FPGA_FLASH2}"
            exit 1
        ;;
    esac
    echo "Config SPI1 Done."
}

operate_spi1_dev(){
    op=$1
    dev=$2
    file=$3
    mtd_driver_rebind_spi1
    ## Operate devices ##
    case ${op} in
        "read")
                read_spi1_dev "$dev" "$file"
        ;;
        "write")
                write_spi1_dev "$dev" "$file"
        ;;
        "erase")
                erase_spi1_dev "$dev"
        ;;
        *)
            echo "Operation $op is not defined."
        ;;
    esac
    mtd_driver_unbind_spi1
}

read_spi2_dev(){
    dev=$1
    file=$2
    file_temp="$file"_temp
    echo -n "Reading ${dev} to $file ... "
    # Sometimes the read back BCM5389_EE image one bit fail.
    # still not found the real root cause
    for n in 1 2 3 4 5
    do
        echo "Reading $file $n times"
        dd if=/sys/bus/spi/devices/spi2.1/eeprom of="$file"
        sleep 1
        dd if=/sys/bus/spi/devices/spi2.1/eeprom of="$file_temp"
        if ! diff $file $file_temp >/dev/null; then
            # read-back file differ
            rm -rf "$file"*
        else
            # read-back file same
            rm -rf $file_temp;
            return;
        fi
    done
    logger -p user.err "Unable to read the correct $file after 5 retries"
    exit 1
}

write_spi2_dev(){
    dev=$1
    file=$2
    echo -n "Writing $file to ${dev} ... "
    dd if="$file" of=/sys/bus/spi/devices/spi2.1/eeprom
    echo "Done"
}

erase_spi2_dev(){
    echo -n "Erasing ${dev} ... "
    echo 1 > /sys/bus/spi/devices/spi2.1/erase
    echo "Done"
}

config_spi2_pin_and_path(){
    dev=$1

    case ${dev} in
        "BCM5389_EE")
            echo "[Setup] BCM5389_EE"
            echo 0x02 > "$SMBCPLD_SYSFS_DIR/spi_1_sel"
        ;;
        *)
            echo "Please enter {BCM5389_EE}"
            exit 1
        ;;
    esac
    echo "Config SPI2 Done."
}

operate_spi2_dev(){
    op=$1
    dev=$2
    file=$3
    ## Operate devices ##
    case ${op} in
        "read")
            read_spi2_dev "$dev" "$file"
        ;;
        "write")
            write_spi2_dev "$dev" "$file"
        ;;
        "erase")
            erase_spi2_dev "$dev"
        ;;
        *)
            echo "Operation $op is not defined."
        ;;
    esac
}

cleanup_spi(){
    if [ $ret -eq 1 ]; then
        exit 1
    fi
    echo 0 > "$SMBCPLD_SYSFS_DIR/spi_1_sel"

    rm -rf /tmp/*_spi*_tmp
    remove_pid_file
}

ui(){
    . /usr/local/bin/openbmc-utils.sh
    op=$1
    spi=$2
    ## Open the path to device ##
    case ${spi} in
        "spi1")
            dev=$3
            file=$4
            config_spi1_pin_and_path "$dev"
            operate_spi1_dev "$op" "$dev" "$file"
        ;;
        "spi2")
            dev=$3
            file=$4
            config_spi2_pin_and_path "$dev"
            operate_spi2_dev "$op" "$dev" "$file"
        ;;
        *)
            echo "No such SPI bus."
            return 1
        ;;
    esac
}

usage(){
    program=$(basename "$0")
    echo "Usage:"
    echo "  $program <op> <spi1> <spi device> <file>"
    echo "    <op>          : read, write, erase"
    echo "    <spi1 device> : BIOS, GB_PCIE_FLASH, DOM_FPGA_FLASH1, DOM_FPGA_FLASH2"
    echo "    <spi2 device> : BCM5389_EE"
    echo ""
    echo "Examples:"
    echo "  $program write spi1 BIOS bios.bin"
    echo ""
}

check_parameter(){
    program=$(basename "$0")
    op=$1
    spi=$2

    # check operations.
    case ${op} in
        "read" | "write" | "erase")
            ;;
        *)
            return 1
            ;;
    esac

    case ${spi} in
        # check spi 1 device and parameters.
        "spi1")
            dev=$3
            file=$4
            case ${dev} in
                "BIOS"|"GB_PCIE_FLASH"|"DOM_FPGA_FLASH1"|"DOM_FPGA_FLASH2")
                    case ${op} in
                        "read" | "write")
                            if [ $# -ne 4 ]; then
                                return 1
                            fi
                            ;;
                    "erase")
                            if [ $# -ne 3 ]; then
                                return 1
                            fi
                            ;;
                    esac
                    ;;
                *)
                    return 1
                    ;;
            esac
            ;;
        # check spi 2 device and parameters.
        "spi2")
            dev=$3
            file=$4
            case ${dev} in
                "BCM5389_EE")
                    case ${op} in
                        "read" | "write")
                            if [ $# -ne 4 ]; then
                                return 1
                            fi
                            ;;
                        "erase")
                            if [ $# -ne 3 ]; then
                                return 1
                            fi
                            ;;
                    esac
                    ;;
                *)
                    return 1
                    ;;
            esac
            ;;
        # check device and parameters fail.
        *)
            return 1
            ;;
    esac

    return 0
}

# check_duplicate_process - to check if there is the duplicate spi util process, will return fail and stop execute command.
check_duplicate_process

# check_parameter - to check command parameters
check_parameter "$@"

is_par_ok=$?

if [ $is_par_ok -eq 0 ]; then
    ui "$@"
    exit 0
else
    usage
    exit 1
fi


#!/bin/bash
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

#shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh

SMB_CPLD_I2C_BUS="12"
SMB_CPLD_I2C_ADDR="0x3e"

i2c_wr() {
    i2cset "$@"; sleep 0.01;
}

# Wedge400-C GB switch reset commands collection
gb_reset() {
    if [ "$1" = "cycle" ];then
        # gb power off
        i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x42 0x0e
        sleep 0.5
        # gb power on
        i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x42 0x0f
        sleep 1
    fi

    # [3] mux_ps=1, ps=1, scan=0, tri_l=1
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0xd
    # [0] a_rstn=0
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x05 0xfe
    # [0] tri_l=0
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0xc
    # [1] scan_mode=1
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0xe
    # [1] scan_mode=0
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0xc
    # [0] tri_l=1
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0xd
    # [0] a_rstn=1
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x05 0xff
    # [0] a_rstn=0
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x05 0xfe
    # [2] ps=0
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0x9
    # [2] ps=1
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0xd
    sleep 0.5
    # [0] a_rstn=1
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x05 0xff
    # [3] mux_ps=0
    i2c_wr -f -y $SMB_CPLD_I2C_BUS $SMB_CPLD_I2C_ADDR 0x60 0x5
}

case "$1" in
    "--help" | "?" | "-h")
        program=$(basename "$0")
        echo "Usage: switch chip reset command"
        echo "  <$program> only reset switch without switch power cycle"
        echo "  <$program cycle> to reset switch after switch power cycle"
    ;;

    *)
        shift
        gb_reset "$1"
    ;;
esac


#!/bin/bash
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

#shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh

prog="$0"

PWR_USRV_RST_SYSFS="${SCMCPLD_SYSFS_DIR}/iso_com_rst_n"
PWR_CYCLE_SYSFS="${PWRCPLD_SYSFS_DIR}/power_cycle_go"
PWR_TIMER_BASE_1S_SYSFS="${PWRCPLD_SYSFS_DIR}/timer_base_1s"
PWR_TIMER_BASE_10S_SYSFS="${PWRCPLD_SYSFS_DIR}/timer_base_10s"
PWR_TIMER_COUNTER_SETTING_SYSFS="${PWRCPLD_SYSFS_DIR}/timer_counter_setting"
PWR_TIMER_COUNTER_SETTING_UPDATE_SYSFS="${PWRCPLD_SYSFS_DIR}/timer_counter_setting_update"

usage() {
    echo "Usage: $prog <command> [command options]"
    echo
    echo "Commands:"
    echo "  status: Get the current microserver power status"
    echo
    echo "  on: Power on microserver if not powered on already"
    echo "    options:"
    echo "      -f: Re-do power on sequence no matter if microserver has "
    echo "          been powered on or not."
    echo
    echo "  off: Power off microserver ungracefully"
    echo
    echo "  reset: Power reset microserver ungracefully"
    echo "    options:"
    echo "      -s: Power reset whole wedge400 system ungracefully"
    echo "      -s -t [1-2550]: Setting boot up time."
    echo "            From 1 to 249 the step is 1 second."
    echo "            From 250 to 2550 the step is 10 seconds"
    echo "            and don't care ones-digits."
    echo
    echo
}

main_power_status() {
    return 0
}

do_status() {
    echo -n "Microserver power is "
    return_code=0

    if wedge_is_us_on; then
        echo "on"
    else
        echo "off"
        return_code=1
    fi

    return $return_code
}

do_on_com_e() {
    echo 1 > "$PWR_USRV_SYSFS"
    echo 1 > "$PWR_USRV_FORCE_OFF"
    return $?
}

do_on() {
    local force opt ret
    force=0
    while getopts "f" opt; do
        case $opt in
            f)
                force=1
                ;;
            *)
                usage
                exit 1
                ;;
        esac
    done
    echo -n "Power on microserver ..."
    if [ $force -eq 0 ]; then
        # need to check if uS is on or not
        if wedge_is_us_on; then
            echo " Already on. Skip!"
            return 1
        fi
    fi

    # reset TH
    # reset_brcm.sh
    # power on sequence
    do_on_com_e
    ret=$?
    if [ $ret -eq 0 ]; then
        echo " Done"
	logger "Successfully power on micro-server"
    else
        echo " Failed"
        logger "Failed to power on micro-server"
    fi
    return $ret
}

do_off_com_e() {
    echo 0 > "$PWR_USRV_FORCE_OFF"
    return $?
}

do_off() {
    local ret
    echo -n "Power off microserver ..."
    do_off_com_e
    ret=$?
    if [ $ret -eq 0 ]; then
        echo " Done"
    else
        echo " Failed"
    fi
    return $ret
}

do_config_reset_timer() {
    # Check numeric
    wake_t=$1
    echo "$wake_t" | grep -E -q '^[0-9]+$'
    ret=$?
    if [ $ret -ne 0 ]; then
        usage
        exit 1
    else
        if [ "$wake_t" -ge 1 ] && [ "$wake_t" -lt 250 ];then
            echo 1 > "$PWR_TIMER_BASE_1S_SYSFS"
            echo 0 > "$PWR_TIMER_BASE_10S_SYSFS"
            logger "Waiting $wake_t seconds for the system boot up"
            echo "Waiting $wake_t seconds for the system boot up"
        elif [ "$wake_t" -ge 250 ] && [ "$wake_t" -le 2550 ];then
            echo 0 > "$PWR_TIMER_BASE_1S_SYSFS"
            echo 1 > "$PWR_TIMER_BASE_10S_SYSFS"
            wake_t=$((wake_t/10))
            logger "Waiting $((wake_t * 10)) seconds for the system boot up"
            echo "Waiting $((wake_t * 10)) seconds for the system boot up"
        else
            usage
            exit 1
        fi
        echo $wake_t > "$PWR_TIMER_COUNTER_SETTING_SYSFS"
        echo 1 > "$PWR_TIMER_COUNTER_SETTING_UPDATE_SYSFS"
    fi
}

do_reset() {
    local system timer wake_t opt
    system=0
    timer=0
    wake_t=0
    while getopts "st:" opt; do
        case $opt in
            s)
                system=1
                ;;
            t)
                timer=1
                wake_t=$OPTARG
                ;;
            *)
                usage
                exit 1
                ;;
        esac
    done

    if [ $system -eq 1 ]; then
        if [ $timer -eq 1 ]; then
            do_config_reset_timer "$wake_t"
        fi
        # Synchronize cached writes to persistent storage
        # We found somethimes /mnt/data data lost after wedge_power.sh reset -s,
        # add sync in case of file system will be broken by random power cycle.
        sync
        logger "Power reset the whole system ..."
        echo  "Power reset the whole system ..."
        echo 1 > "$PWR_CYCLE_SYSFS"
        sleep 3
        # Control should not reach here, but if it failed to reset
        # the system through PSU, then run a workaround to reset
        # most of the system instead (if not all)
        logger "Failed to reset the system. Will sleep for 3 sec then running a workaround"
        echo "Failed to reset the system. Will sleep for 3 sec then running a workaround"
        i2cset -f -y 1 0x3a 0x12 0
    else
        if ! wedge_is_us_on; then
            echo "Power resetting microserver that is powered off has no effect."
            echo "Use '$prog on' to power the microserver on"
            return 1
        fi
        # reset TH first
        # reset_brcm.sh
        echo -n "Power reset microserver ..."
        echo 0 > "$PWR_USRV_RST_SYSFS"
        sleep 1
        echo 1 > "$PWR_USRV_RST_SYSFS"
        logger "Successfully power reset micro-server"
    fi
    echo " Done"
    return 0
}

if [ $# -lt 1 ]; then
    usage
    exit 1
fi

command="$1"
shift

set_bic=0
case "$command" in
    status)
        do_status "$@"
        ;;
    on)
        do_on "$@"
        set_bic=1
        ;;
    off)
        do_off "$@"
        ;;
    reset)
        do_reset "$@"
        set_bic=1
        ;;
    *)
        usage
        exit 1
        ;;
esac

if [ $set_bic -ne 0 ]; then
    # sleep 10 seconds to wait BIC ready
    (sleep 10; setup_bic.sh) &
fi

exit $?


#!/bin/bash
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

# Get output from bic-util
bic_output=$(bic-util scm --read_mac)

# Check if the read was successful and output matches with our format
match=$(echo "$bic_output" | grep -c 'MAC address: [0-9a-f][0-9a-f]:')
if [ "$match" = "1" ]; then
    # Mac address: xx:xx:xx:xx:xx:xx
    echo "$bic_output" | cut -d ' ' -f 3
    exit 0
else
    echo "Cannot find out the microserver MAC" 1>&2
    exit 1
fi


#!/bin/bash
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

# Provides:          xdpe12284 setup on EVT3
# Short-Description: Some EVT3 units xdpe12284 has uncorrect firmware, BMC need
#                    to set xdpe12284 registers to change max power supply as
#                    power required.

# shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh

# Only some EVT3 need to set xdpe12284 power
[ "$(wedge_board_type_rev)" != "Cloudripper_EVT3" ] && exit 0

echo -n "Setup xdpe12284 on EVT3 unit ..."

# set register value n~m bits as expected
# $1: current value
# $2: start bit
# $3: end bit
# $4: start-end bits expect value
update_reg() {
    reg=$1
    startbit=$2
    endbit=$3
    data=$4

    ((lsb_mask = ((0xffff) >> startbit) << startbit))
    ((msb_mask = ((0xffff) >> (15 - endbit)) ))
    ((mask = lsb_mask & msb_mask))

    reg=$((reg & ~mask))
    reg=$((reg | ((data << startbit) & mask)))

    printf 0x%x $reg
}

for i in $(seq 1 2)
do
    if [ "$i" -eq 1 ]; then
        XPDE_BUS="19"
        XPDE_ADDR="0x68"
    elif [ "$i" -eq 2 ]; then
        XPDE_BUS="22"
        XPDE_ADDR="0x60"
    fi

    # We need to use i2c get/set instead of sysfs nodes because the pmbus driver not support.
    # set page to 0x20
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x00 0x20
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x9 w)      #   page addr start end expect
    val=$(update_reg "$val" 10 15 0x14)                 #   0x20  0x9   10   15  0x14
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x9 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0xA w)
    val=$(update_reg "$val" 10 15 0x24)                 #   0x20  0xA   10   15  0x24
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0xA "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0xB w)
    val=$(update_reg "$val" 6 11 0x14)                  #   0x20  0xB   6    11  0x14
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0xB "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x11 w)
    val=$(update_reg "$val" 6 10 0x2)                   #   0x20  0x11  6    10  0x2
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x11 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x25 w)
    val=$(update_reg "$val" 0 5  0x1E)                  #   0x20  0x25  0    5   0x1E
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x25 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x26 w)
    val=$(update_reg "$val" 0 6  0x75)                  #   0x20  0x26  0    6   0x75
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x26 "$val" w

    # set page to 0x21
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x00 0x21
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x2 w)
    val=$(update_reg "$val" 0 9  0x50)                  #   0x21  0x2   0    9   0x50
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x2 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x5 w)
    val=$(update_reg "$val" 8 10 0x6)                   #   0x21  0x5   8    10  0x6
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x5 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x9 w)
    val=$(update_reg "$val" 10 15 0x1E)                 #   0x21  0x9   10   15  0x1E
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x9 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0xA w)
    val=$(update_reg "$val" 10 15 0x1E)                 #   0x21  0xA   10   15  0x1E
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0xA "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0xB w)
    val=$(update_reg "$val" 6 11 0x14)                  #   0x21  0xB   6    11  0x14
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0xB "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0xE w)
    val=$(update_reg "$val" 0 5  0x29)                  #   0x21  0xE   0    5   0x29
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0xE "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x1E w)
    val=$(update_reg "$val" 4 7  0x2)                   #   0x21  0x1E  4    7   0x2
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x1E "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x23 w)
    val=$(update_reg "$val" 6 15 0x3C)                  #   0x21  0x23  6    15  0x3C
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x23 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x25 w)
    val=$(update_reg "$val" 0 5  0x14)                  #   0x21  0x25  0    5   0x14
    val=$(update_reg "$val" 6 15 0x50)                  #   0x21  0x25  6    15  0x50
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x25 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x27 w)
    val=$(update_reg "$val" 0 7  0x2A)                  #   0x21  0x27  0    7   0x2A
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x27 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x2C w)
    val=$(update_reg "$val" 0 3  0x2)                   #   0x21  0x2C  0    3   0x2
    val=$(update_reg "$val" 4 7  0x2)                   #   0x21  0x2C  4    7   0x2
    val=$(update_reg "$val" 8 11 0x2)                   #   0x21  0x2C  8    11  0x2
    val=$(update_reg "$val" 12 15 0x2)                  #   0x21  0x2C  12   15  0x2
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x2C "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x37 w)
    val=$(update_reg "$val" 0 7  0x28)                  #   0x21  0x37  0    7   0x28
    val=$(update_reg "$val" 8 11 0x0)                   #   0x21  0x37  8    11  0x0
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x37 "$val" w
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x53 w)
    val=$(update_reg "$val" 0 6  0xC)                   #   0x21  0x53  0    6   0xC
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x53 "$val" w

    # set page to 0x22
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x00 0x22
    val=$(i2cget -f -y $XPDE_BUS $XPDE_ADDR 0x45 w)
    val=$(update_reg "$val" 0 3  0x0)                   #   0x22  0x45  0    3   0x0
    i2cset -y -f $XPDE_BUS $XPDE_ADDR 0x45 "$val" w

    # reset page to 0x0
    i2cset -f -y $XPDE_BUS $XPDE_ADDR 0x0 0x0
done

echo "done."


#!/bin/bash
#
# Copyright 2021-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#

# This script is a workaround for the I2C PMBUS vout sensor reading issue given
# the root cause has not been found. When the issue happens, reload the pmbus
# device driver will fix the issue.

# shellcheck disable=SC1091
source /usr/local/bin/openbmc-utils.sh

printf "Check special sensors and rebind driver..."

i2c_check_driver_binding "fix-binding"

/usr/local/bin/xdpe12284-hack.sh

retry=0
# ir35215 chip enabled by COMe power on,
# so need sleep some time to wait COMe Power on
sleep 5
#
# We have seen intermittent ir35215 voltage reading value unreasonable and root cause is
# not clear as of now. Testing shows below retry will help to mitigate
# such error.
#
fixup_i2c_ir35215() {
    while [ $retry -lt 5 ]; do
        sensor1_ok=$(/usr/local/bin/sensor-util smb 0x12 --force | grep ok &> /dev/null; echo $?)
        sensor2_ok=$(/usr/local/bin/sensor-util smb 0x20 --force | grep ok &> /dev/null; echo $?)
        if [ $((sensor1_ok)) -eq 0 ] && [ $((sensor2_ok)) -eq 0 ]; then
            echo "Check ir35215 done"
            return
        fi
        retry=$((retry + 1))
        echo "trying fixup driver ir35215 for i2c device 16-4d, time $retry"
        i2c_device_delete 16 0x4d
        i2c_device_add 16 0x4d ir35215
    done
    logger -p user.err "Unable to fix ir35215 sensor reading after 5 retries"
}
#
# We have seen intermittent pxe1211 voltage reading value unreasonable and root cause is
# not clear as of now. Testing shows below retry will help to mitigate
# such error.
#
retry=0
fixup_i2c_pxe1211() {
    while [ $retry -lt 5 ]; do
        sensor1_ok=$(/usr/local/bin/sensor-util smb 0x6e --force | grep ok &> /dev/null; echo $?)
        sensor2_ok=$(/usr/local/bin/sensor-util smb 0x75 --force | grep ok &> /dev/null; echo $?)
        sensor3_ok=$(/usr/local/bin/sensor-util smb 0x7c --force | grep ok &> /dev/null; echo $?)
        if [ $((sensor1_ok)) -eq 0 ] && [ $((sensor2_ok)) -eq 0 ]  && [ $((sensor3_ok)) -eq 0 ]; then
            echo "Check pxe1211 done"
            return
        fi
        retry=$((retry + 1))
        echo "trying fixup driver pxe1211 for i2c device 20-0e, time $retry"
        i2c_device_delete 20 0x0e
        i2c_device_add 20 0x0e pxe1211
    done
    logger -p user.err "Unable to fix pxe1211 sensor reading after 5 retries"
}
#
# We have seen intermittent xdpe132g5c voltage reading value unreasonable and root cause is
# not clear as of now. Testing shows below retry will help to mitigate
# such error.
#
retry=0
fixup_i2c_xdpe132g5c() {
    while [ $retry -lt 5 ]; do
        sensor1_ok=$(/usr/local/bin/sensor-util smb 0x35 --force | grep ok &> /dev/null; echo $?)
        sensor2_ok=$(/usr/local/bin/sensor-util smb 0x2e --force | grep ok &> /dev/null; echo $?)
        if [ $((sensor1_ok)) -eq 0 ] && [ $((sensor2_ok)) -eq 0 ]; then
            echo "Check xdpe132g5c done"
            return
        fi
        retry=$((retry + 1))
        echo "trying fixup driver xdpe132g5c for i2c device 17-40, time $retry"
        i2c_device_delete 17 0x40
        i2c_device_add 17 0x40 xdpe132g5c
    done
    logger -p user.err "Unable to fix xdpe132g5c sensor reading after 5 retries"
}

fixup_i2c_ir35215
fixup_i2c_pxe1211
fixup_i2c_xdpe132g5c


#!/bin/sh
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

### BEGIN INIT INFO
# Provides:          setup-fan
# Required-Start:    board-id
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Set fan speed
### END INIT INFO

echo -n "Setup fan speed... "
/usr/local/bin/set_fan_speed.sh 50
/usr/local/bin/fand -v
echo "done."


# Copyright 2015-present Facebook. All Rights Reserved.

SYSCPLD_SYSFS_DIR="/sys/class/i2c-dev/i2c-13/device/13-003e"
SLOTID_SYSFS="${SYSCPLD_SYSFS_DIR}/slotid"

wedge_board_type() {
    echo 'CMM'
}

wedge_slot_id() {
    val=$(head -n 1 $SLOTID_SYSFS)
    if [ "${val}" = "0x1" ]; then
        echo c1
    else
        echo c2
    fi
}


#!/bin/bash
#
# Copyright 2019-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

declare -a DEVICES
DEVICES=(
  I2C:0x1
  SCM-BMC:0x2
)

declare -a MODULES
MODULES=(
  LC101:0x40
  LC102:0x50
  LC201:0x41
  LC202:0x51
  LC301:0x42
  LC302:0x52
  LC401:0x43
  LC402:0x53
  FC1:0x88
  FC2:0x89
  FC3:0x8a
  FC4:0x8b
  SCM-FC1-LEFT:0xc2
  SCM-FC1-RIGHT:0xd2
  SCM-FC2-LEFT:0xc3
  SCM-FC2-RIGHT:0xd3
  SCM-LC101:0xc4
  SCM-LC102:0xd4
  SCM-LC201:0xc5
  SCM-LC202:0xd5
  SCM-LC301:0xc6
  SCM-LC302:0xd6
  SCM-LC401:0xc7
  SCM-LC402:0xd7
  SCM-FC3-LEFT:0xc8
  SCM-FC3-RIGHT:0xd8
  SCM-FC4-LEFT:0xc9
  SCM-FC4-RIGHT:0xd9
)

#Resetting all the devices of a module
resetModuleDeviceAll(){
    for key in ${MODULES[*]}; do
        module=${key%%:*}
        m_value=${key##*:}
        if [[ "${module}" = "$1" || -z "$1" ]]; then
            echo "Resetting ${module} module and the device on SCM-BMC and the i2c endpoints"
            for dev in ${DEVICES[*]}; do
                device=${dev%%:*}
                d_value=${dev##*:}
                echo "Resetting ${device} devices of ${module} module."
                sleep 1
                echo ${d_value} > /sys/bus/i2c/drivers/cmmcpld/13-003e/one_wire_rst_device
                echo ${m_value} > /sys/bus/i2c/drivers/cmmcpld/13-003e/one_wire_rst_trig
            done
            #Only reset one LC/FC
            if [ -n "$1" ]; then
                break
            fi
        fi
    done

    if [[ -n "$1" && ${module} != "$1" ]]; then
        echo "Error: unsupported module name <$1>!"
        usage
    fi
    unset module value
}

#Resetting a specific device from a module
resetModuleDevice(){
    for key in ${MODULES[*]}; do
        module=${key%%:*}
        m_value=${key##*:}
        if [ "${module}" = "$1" ]; then
            if [ "$2" = "all" ]; then
                resetModuleDeviceAll $module
                unset module m_value
                return
            else
                for dev in ${DEVICES[*]}; do
                    device=${dev%%:*}
                    d_value=${dev##*:}
                    if [ "${device}" = $2 ]; then
                        echo "Resetting ${device} devices of ${module} module."
                        sleep 1
                        echo ${d_value} > /sys/bus/i2c/drivers/cmmcpld/13-003e/one_wire_rst_device
                        echo ${m_value} > /sys/bus/i2c/drivers/cmmcpld/13-003e/one_wire_rst_trig
                        unset module m_value device d_value
                        return
                    fi
                done
            fi
        fi
    done

    if  [[ ${module} != "$1" || ${device} != "$2" ]]; then
        echo "Error: unsupported module/device name!"
        usage
    fi
    unset module m_value device d_value
}

#List supported modules and devices for the user
viewModuleDevices(){
    echo "Available modules:"
    for key in ${MODULES[*]}; do
        module=${key%%:*}
        echo "$module"
    done
    echo -e "\nAvailable devices:"

    for key in ${DEVICES[*]}; do
        device=${key%%:*}
        echo "$device"
    done
    unset module device
}

usage() {
    echo "Usage: cmm-modules-devices-reset.sh <module> [device] | all"
    echo ""

    viewModuleDevices

    echo ""
    echo "Example: cmm-modules-devices-reset.sh LC101"
    echo "Example reset all LC/FC: cmm-modules-devices-reset.sh all"
}

#parse command line arguments
if [ $# == 0 ]; then
    echo "Error: <module> parameter is missing!"
    usage
elif [ $# == 1 ]; then
    if [ "$1" = "view-modules-devices" ]; then
        viewModuleDevices
    elif [ "$1" = "all" ]; then
        resetModuleDeviceAll
    else
        resetModuleDeviceAll "$1"
    fi
elif [ $# == 2 ]; then
    resetModuleDevice "$1" "$2"
else
    echo "Error: invalid command line arguments!"
    usage
    exit 1
fi


#!/bin/bash
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

if [ $# -ne 1 ]; then
    exit -1
fi

img="$1"

source /usr/local/bin/openbmc-utils.sh

# change CPLD_JTAG_SEL to 0 to connect BMC_CPLD pins
gpio_set CPLD_JTAG_SEL 0

ispvm dll /usr/lib/libcpldupdate_dll_gpio.so "${img}" \
    --tms BMC_CPLD_TMS \
    --tdo BMC_CPLD_TDO \
    --tdi BMC_CPLD_TDI \
    --tck BMC_CPLD_TCK


#!/bin/bash
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

source /usr/local/bin/gpio-utils.sh

if [ $# -ne 2 ]; then
    exit -1
fi

# Convert card string to upper case
card="${1^^}"
if [ ${card} != "FCB1" && ${card} != "FCB2" && \
     ${card} != "FCB3" && ${card} != "FCB4" ]; then
    echo "${1} is not a correct FCB card name."
    exit -1
fi
img="$2"

ispvm dll /usr/lib/libcpldupdate_dll_gpio.so "${img}" \
    --tms ${card}_CPLD_TMS \
    --tck ${card}_CPLD_TCK \
    --tdi ${card}_CPLD_TDI \
    --tdo ${card}_CPLD_TDO


#!/bin/bash
#
# Copyright 2015-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
usage() {
  echo "Usage: $0 [Fan Unit (1...12)]" >&2
}

# map the output of the command into an array
mapfile -t FAN_ARRAY < <(sensors fancpld-*|grep ^Fan)

show_rpm(){
  front_fan_idx=$(( ($1 - 1) * 2 ))
  rear_fan_idx=$((( ( $1 - 1) * 2) + 1))
  IFS=' ' read -r -a fan_front <<< "${FAN_ARRAY[$front_fan_idx]}"
  IFS=' ' read -r -a fan_rear <<< "${FAN_ARRAY[$rear_fan_idx]}"

  if [ "${#fan_front[@]}" -ne 5 ] || [ "${#fan_rear[@]}" -ne 5 ]; then
      echo "wrong sensors fan reading input. Exiting ..."
      exit 1
  fi

  echo "${fan_front[3]}, ${fan_rear[3]}"
}

# Return appropriate value based on the argument passed to it.
if [ "$#" -eq 0 ]; then
  FANS="1 2 3 4 5 6 7 8 9 10 11 12"
elif [ "${#}" -eq 1 ]; then
    if [ "${1}" -lt 1 ] || [ "${1}" -gt 12 ]; then
        usage
        exit 1
    fi
    FANS="$1"
else
    usage
    exit 1
fi

for fan in $FANS; do
  echo "Fan $fan RPMs: $(show_rpm "${fan}")"
done


#!/bin/bash
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

source /usr/local/bin/openbmc-utils.sh

SYSFS_I2C_DEVICES='/sys/bus/i2c/devices'

CMD="${SYSFS_I2C_DEVICES}/13-003e/*present"
FAN_CMD1="${SYSFS_I2C_DEVICES}/171-0033/"
FAN_CMD2="${SYSFS_I2C_DEVICES}/179-0033/"
FAN_CMD3="${SYSFS_I2C_DEVICES}/187-0033/"
FAN_CMD4="${SYSFS_I2C_DEVICES}/195-0033/"

# Will return <key> : <val>
# eg :- cmm : 1
function get_presence
{
  local file=$1 key=$2
  val=$(head -n1 $file | awk '{print substr($0,0,3) }' | sed 's/.x//')
  if [ $val -eq 0 ]; then
    val=1
  else
    val=0
  fi
  echo $key ":" $val
}

# CMMs, FCs, LCs, SCMs
function get_card_presence
{
  for file in $CMD
  do
    key=$(echo $file | sed 's/.*003e\///' | sed 's/_present.*//')
    get_presence $file $key
  done
}

# If fc1 is present fcb1 is present, same for other fcbs
# Fans
function get_fan_presence
{
  local num=1 fan_cmd=$1 count=$((($2 * 3) - 2))
  while [ $num -lt 4 ]; do
    key='fan'$count
    file=$fan_cmd'fantray'$num'_present'
    get_presence $file $key
    (( num++ ))
    (( count++ ))
  done
}

# Power supplies
function get_psu_presence
{
  local num=1
  while [ $num -lt 5 ]; do
    key='psu'$num
    cmd='gpio_get PSU'$num'_PRESENT'
    val=$($cmd)
    if [ $val -eq 0 ]; then
      val=1
    else
      val=0
    fi
    echo $key ":" $val
    (( num++ ))
  done
}

# get all info
echo "CARDS"
get_card_presence

echo "FANS"
get_fan_presence $FAN_CMD1 1
get_fan_presence $FAN_CMD2 2
get_fan_presence $FAN_CMD3 3
get_fan_presence $FAN_CMD4 4

echo "POWER SUPPLIES"
get_psu_presence


#!/bin/sh
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

# channel 0: r1: 17.8K; r2:  2.2K; v2: 0mv
# channel 1: r1:  3.3K; r2:  1.0K; v2: 0mv
# channel 2: r1:  3.3K; r2:  2.2K; v2: 0mv
# channel 3: r1:  3.3K; r2:  3.3K; v2: 0mv
# channel 4: r1:  0.0K; r2:  1.0K; v2: 0mv
# channel 5: r1:  0.0K; r2:  1.0K; v2: 0mv
# channel 6: r1: 17.8K; r2:  2.2K; v2: 0mv
# channel 7: r1:  3.3K; r2:  1.0K; v2: 0mv
# channel 8-15: not used by cmm.

config_adc() {
    channel=$1
    r1=$2
    r2=$3
    v2=$4
    sysfs_adc_path="/sys/devices/platform/ast_adc.0"

    echo $r1 > ${sysfs_adc_path}/adc${channel}_r1
    echo $r2 > ${sysfs_adc_path}/adc${channel}_r2
    echo $v2 > ${sysfs_adc_path}/adc${channel}_v2
    echo 1 > ${sysfs_adc_path}/adc${channel}_en
}

bulk_setup_adc() {
    config_adc 0 178 22 0
    config_adc 1  33 10 0
    config_adc 2  33 22 0
    config_adc 3  33 33 0
    config_adc 4   0 10 0
    config_adc 5   0 10 0
    config_adc 6 178 22 0
    config_adc 7  33 10 0
}

#
# Passing R1, R2 and V2 values to kernel is only needed in kernel 4.1;
# In kernel 4.17 (or newer versions), voltage computation formulas are
# defined in lm_sensors config file.
#
KERNEL_VERSION=`uname -r`
if [[ ${KERNEL_VERSION} == 4.1.* ]]; then
    bulk_setup_adc
fi


#!/bin/sh
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

source /usr/local/bin/openbmc-utils.sh

#
# Setup gpios managed by the given i2c IO Expander.
# $1 - sysfs path of the i2c io expander. For example, 30-0020
# $2 - offset (within the gpio chip)
# $3 - list of symbolic links for the gpio pins
#
setup_i2c_gpios() {
    local i2c_path=${1}
    local offset=${2}
    shift 2
    local symlinks="$*"
    local gpio_chip=$(gpiochip_lookup_by_i2c_path ${i2c_path})
    local gpio_base=$(gpiochip_get_base ${gpio_chip})
    local pin link_name

    if [ -z "${gpio_base}" ]; then
        echo "unable to export pins of io expander ${i2c_path}"
        return
    fi

    for link_name in ${symlinks}; do
        pin=$((gpio_base + offset))
        gpio_export ${pin} ${link_name}
        offset=$((offset + 1))
    done
}

#
# Explicitly disable other functions so the pins function as gpio.
# NOTE: the function is only needed in kernel 4.1: pinctrl is handled
# in device tree in kernel 4.18 and future versions.
#
pinctrl_request_gpios() {
    # GPIOM0|M1|M2|M3
    # SCU84[24|25|26|27] must be 0 to disable UART2 function pins.
    for bit in 24 25 26 27; do
        devmem_clear_bit $(scu_addr 84) $bit
    done

    # GPIOF0
    # SCU90[30] must be 0 to disable LPC LHAD0 function.
    # SCU80[24] must be 0 to disable UART4 NCTS function.
    devmem_clear_bit $(scu_addr 90) 30
    devmem_clear_bit $(scu_addr 80) 24
}

#
# Test if the pins are functions as gpio pins.
#
pinctrl_check_gpios() {
    # GPIOM0|M1|M2|M3
    # SCU84[24|25|26|27] must be 0 to disable UART2 function pins.
    for bit in 24 25 26 27; do
        if devmem_test_bit $(scu_addr 84) $bit; then
            echo "pinctrl error: GPIOM# pins are claimed by UART2 functions"
        fi
    done

    # GPIOF0
    # SCU90[30] must be 0 to disable LPC LHAD0 function.
    # SCU80[24] must be 0 to disable UART4 NCTS function.
    if devmem_test_bit $(scu_addr 90) 30; then
        echo "pinctrl error: GPIOF0 pin is claimed by LPC function"
    fi
    if devmem_test_bit $(scu_addr 80) 24; then
        echo "pinctrl error: GPIOF0 pin is claimed by UART4 function"
    fi
}

# The gpio pins managed by aspeed gpio controller always start
# from 0 in kernel 4.1, but it's dynamically allocated in kernel
# 4.17, thus we need to read the base from sysfs.
KERNEL_VERSION=`uname -r`
if [[ ${KERNEL_VERSION} == 4.1.* ]]; then
    ASPEED_GPIO_BASE=0
    pinctrl_request_gpios
else
    ASPEED_GPIOCHIP=$(gpiochip_lookup_by_label 1e780000.gpio)
    ASPEED_GPIO_BASE=$(gpiochip_get_base ${ASPEED_GPIOCHIP})
    if [ -z "${ASPEED_GPIO_BASE}" ]; then
        echo "unable to find base pin of aspeed gpio controller"
        exit 1
    fi
fi

pinctrl_check_gpios

# GPIOM0: BMC_CPLD_TMS
# GPIOM1: BMC_CPLD_TDI
# GPIOM2: BMC_CPLD_TCK
# GPIOM3: BMC_CPLD_TDO
IDX=0
SYMLINKS="BMC_CPLD_TMS BMC_CPLD_TDI BMC_CPLD_TCK BMC_CPLD_TDO"
for LINK_NAME in ${SYMLINKS}; do
    OFFSET=$(gpio_name2value M${IDX})
    PIN=$((ASPEED_GPIO_BASE + OFFSET))
    gpio_export ${PIN} ${LINK_NAME}
    IDX=$((IDX + 1))
done

# GPIOF0: CPLD_JTAG_SEL (needs to be low)
OFFSET=$(gpio_name2value F0)
PIN=$((ASPEED_GPIO_BASE + OFFSET))
gpio_export ${PIN} CPLD_JTAG_SEL

# SYSTEM LED GPIOs
SYSLED_SYMLINKS="SYS_LED_RED SYS_LED_GREEN SYS_LED_BLUE
                 FAN_LED_RED FAN_LED_GREEN FAN_LED_BLUE
                 PSU_LED_RED PSU_LED_GREEN PSU_LED_BLUE
                 FAB_LED_RED FAB_LED_GREEN FAB_LED_BLUE"
setup_i2c_gpios "30-0021" 0 ${SYSLED_SYMLINKS}

# PSU PRESENCE GPIOs
PSU_SYMLINKS="PSU4_PRESENT PSU3_PRESENT PSU2_PRESENT PSU1_PRESENT"
setup_i2c_gpios "29-0020" 8 ${PSU_SYMLINKS}

# FCB1 GPIOs
FCB1_SYMLINKS="FCB1_CPLD_TMS FCB1_CPLD_TCK FCB1_CPLD_TDI FCB1_CPLD_TDO"
setup_i2c_gpios "172-0022" 0 ${FCB1_SYMLINKS}

# FCB2 GPIOs
FCB2_SYMLINKS="FCB2_CPLD_TMS FCB2_CPLD_TCK FCB2_CPLD_TDI FCB2_CPLD_TDO"
setup_i2c_gpios "180-0022" 0 ${FCB2_SYMLINKS}

# FCB3 GPIOs
FCB3_SYMLINKS="FCB3_CPLD_TMS FCB3_CPLD_TCK FCB3_CPLD_TDI FCB3_CPLD_TDO"
setup_i2c_gpios "188-0022" 0 ${FCB3_SYMLINKS}

# FCB4 GPIOs
FCB4_SYMLINKS="FCB4_CPLD_TMS FCB4_CPLD_TCK FCB4_CPLD_TDI FCB4_CPLD_TDO"
setup_i2c_gpios "196-0022" 0 ${FCB4_SYMLINKS}


#!/bin/sh
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

##### NOTE #########################################################
# - When adding new devices, always add to end of the list here
#   so any other dependencies that are hard coded with GPIO
#   will not break.
# - Although technically all the i2c devices can be created by using
#   device tree, we prefer to do it here, mainly because:
#     * it's easier to control the order of device creation.
#     * a majority of i2c devices are located on line/fabric cards,
#       and it's easier to control device creation/removal and add
#       hot-plug support in the future.
####################################################################

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

. /usr/local/bin/i2c-utils.sh

#
# instantiate all the i2c-muxes.
# Note:
#   - the function may be skipped if i2c switches were already created
#     in kernel space.
#   - please do not modify the order of i2c-mux creation unless you've
#     decided to fix bus-number of leaf i2c-devices.
#
bulk_create_i2c_mux() {
    i2c_mux_name="pca9548"
    mux_channels=8

    # The first-level i2c-muxes which are directly connected to aspeed
    # i2c adapters are described in device tree, and the bus number of
    # these i2c-muxes' channels are hardcoded (as below) to avoid
    # breaking the existing applications.
    #    i2c-mux 1-0077: child bus 16-23
    #    i2c-mux 2-0071: child bus 24-31
    #    i2c-mux 8-0077: child bus 32-39

    # Create second-level i2c-muxes which are connected to first level
    # mux "1-0077". "1-0077" has 8 channels and each channel is connected
    # with 2 more i2c-muxes (@ address 0x70 & 0x73), thus total 128 i2c
    # buses (40-167) will be registered.
    parent_buses="18 19 20 21 16 17 22 23"
    mux_addresses="0x70 0x73"
    for bus in ${parent_buses}; do
        for addr in ${mux_addresses}; do
            i2c_mux_add_sync "$bus" "$addr" "$i2c_mux_name" "$mux_channels"
        done
    done

    # Create second-level i2c-muxes which are connected to first level
    # mux "8-0077". "8-0077" has 8 channels and the first 4 channels are
    # connected with 1 extra level of i2c-mux (@ address 0x70), thus
    # totally 32 i2c buses (168-199) will be registered.
    parent_buses="32 33 34 35"
    for bus in ${parent_buses}; do
        i2c_mux_add_sync "$bus" 0x70 "$i2c_mux_name" "$mux_channels"
    done
}

#
# We've seen some intermittent i2c transaction failures on i2c8 because
# some slaves (on Fan Control Boards) NACK the address stage.
# We are not quite clear if it's caused by flaw(s) in i2c switch channel
# selection, or due to the "longer" distance between BMC SoC and Fan
# Control Boards (compared with other i2c buses on Galaxy Chassis), but
# increasing base clock divisor (which impacts bus free time as well as
# data setup/hold time) helps to fix/mitigate the issue.
#
# Below line updates i2c8 (0-based) I2CD04: Clock and AC Timing Control
# Register #1 value from default 0xFFFFE003 to 0xFFF77004.
#
devmem 0x1E78A344 32 0xFFF77004

#
# Let's check a few i2c switches on fabric cards to determine if these
# switches were already created in kernel space.
#
I2C_MUX_FAB1="${SYSFS_I2C_DEVICES}/16-0070"
I2C_MUX_FAB2="${SYSFS_I2C_DEVICES}/17-0070"
I2C_MUX_FAB3="${SYSFS_I2C_DEVICES}/22-0070"
I2C_MUX_FAB4="${SYSFS_I2C_DEVICES}/23-0070"
if [ ! -e "${I2C_MUX_FAB1}" ] && [ ! -e "${I2C_MUX_FAB2}" ] && \
   [ ! -e "${I2C_MUX_FAB3}" ] && [ ! -e "${I2C_MUX_FAB4}" ]; then
    bulk_create_i2c_mux
fi

# EEPROM
i2c_device_add 6 0x51 24c64

#PCB EEPROM
i2c_device_add 28 0x50 24c64

# Two temperature sensors on CMM
i2c_device_add 3 0x48 tmp75 # inlet
i2c_device_add 3 0x49 tmp75 # outlet

# CMM CPLD
i2c_device_add 13 0x3e cmmcpld

# FAN CPLD
fancpld_busses="171 179 187 195"
for bus in ${fancpld_busses}; do
    i2c_device_add ${bus} 0x33 fancpld
done

# Temperature sensors
# FAB1: 106   0x48 - 0x4b
# SCM-FAB1: 113 0x48, 114 0x49

# FAB2: 122
# SCM-FAB2: 129 0x48, 130 0x49

# LC101: 42, 0x48-0x4b
# LC102: 45, 0x48-0x4b
# SCM-LC1: 49 0x48, 50 0x49

# LC201: 58
# LC202: 61
# SCM-LC2: 65 0x48, 66, 0x49

# LC301: 74
# LC302: 77
# SCM-LC3: 81 0x48, 82, 0x49

# LC401: 90
# LC401: 93
# SCM-LC4: 97 0x48, 98 0x49

# FAB3: 138
# SCM-FAB3: 145 0x48, 146 0x49

# FAB4: 154
# SCM-FAB4: 161 0x48, 162 0x49

# Temperature sensors on LC/FC
temp_busses="42 45 58 61 74 77 90 93 106 122 138 154"
temp_addrs="0x48 0x49 0x4a 0x4b"
for bus in ${temp_busses}; do
    for addr in ${temp_addrs}; do
        i2c_device_add ${bus} ${addr} tmp75
    done
done

# Temperature sensors on SCM
temp_busses="113 129 49 65 81 97 145 161"
for bus in ${temp_busses}; do
    i2c_device_add ${bus} 0x48 tmp75
    i2c_device_add $((bus + 1)) 0x49 tmp75
done

# FCB PCA9534
# GPIOs are allocated backwards.
# So, list the bus list in reverse order,
# so that GPIO numbers are increasing from FCB1-FCB4
fcb_busses="196 188 180 172"
for bus in ${fcb_busses}; do
    i2c_device_add ${bus} 0x22 pca9534
done

# PSU PRESENCE
# Spec says pca9506 but this kernel version supports only 9505
# which works for us
i2c_device_add 29 0x20 pca9505

# PFE modules
i2c_device_add 27 0x10 pfe3000 # psu1
i2c_device_add 26 0x10 pfe3000 # psu2
i2c_device_add 25 0x10 pfe3000 # psu3
i2c_device_add 24 0x10 pfe3000 # psu4

# LEDs
i2c_device_add 30 0x21 pca9535

#
# Go through all i2c devices and trigger manual driver binding if needed.
#
if [[ ${KERNEL_VERSION} != 4.1.* ]]; then
    # sleep 50 milliseconds just in case driver binding is "delayed".
    usleep 50000

    i2c_check_driver_binding "fix-binding"
fi


#!/bin/sh
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

### BEGIN INIT INFO
# Provides:          system monitoring
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Set system monitoring
### END INIT INFO

echo -n "Setup system monitoring "
/usr/local/bin/system_monitor.sh >/dev/null 2>&1 &
echo "done."


#!/bin/sh
#
# Copyright 2015-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

# There are 4 busses and 3 fans on each bus. The fans are labeled 1-12 in the
# following order: Bus 171 fan 1,2,3; Bus 179 fan 4,5,6; Bus 187 fan 7,8,9; and
# Bus 195 fan 10,11,12.
usage() {
    echo "Usage: $0 <PERCENT (0..100)>  <Fan ID (1..12)>" >&2
}

set -e

if [ "$#" -ne 2 ] && [ "$#" -ne 1 ]; then
    usage
    exit 1
fi

busses="171 179 187 195"
if [ "$#" -eq 1 ]; then
    ids="1 2 3"
else
    if [ "$2" -le 0 ] || [ "$2" -ge 13 ]; then
        echo "Fan id $2: not a valid id"
        exit 1
    fi
    FAN="$2"
    FAN=$((${FAN} - 1))
    busIndex=$((${FAN} / 3))
    temp=$((${FAN} - ( ${FAN} / 3 * 3 )))
    ids=$((${temp} + 1))
    if [ ${busIndex} -eq 0 ]; then
        busses="171"
    elif [ ${busIndex} -eq 1 ]; then
        busses="179"
    elif [ ${busIndex} -eq 2 ]; then
        busses="187"
    else
        busses="195"
    fi
fi

# Convert the percentage to our 1/32th unit (0-31).
unit=$(( ( $1 * 31 ) / 100 ))

for bus in ${busses}; do
    for id in ${ids}; do
        pwm="/sys/class/i2c-dev/i2c-${bus}/device/${bus}-0033/fantray${id}_pwm"
        echo "$unit" > "${pwm}"
        echo "Successfully set fan ${id} on bus ${bus} speed to $1%"
    done
done


#!/bin/bash
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

usage() {
    echo "Usage: $0 <card name>"
    echo "    card name: lc101, lc102, ..., fc3, fc4, cmm"
}

if [ $# -ne 1 ]; then
    usage "$0"
    exit -1
fi

declare -A card_uart_map
card_uart_map[fc1]=0x1
card_uart_map[fc2]=0x2
card_uart_map[fc3]=0x3
card_uart_map[fc4]=0x4
card_uart_map[lc101]=0x5
card_uart_map[lc102]=0x9
card_uart_map[lc201]=0x6
card_uart_map[lc202]=0xa
card_uart_map[lc301]=0x7
card_uart_map[lc302]=0xb
card_uart_map[lc401]=0x8
card_uart_map[lc402]=0xc
card_uart_map[cmm]=0xd

value=${card_uart_map[${1,,}]}
if [ -z "$value" ]; then
    usage "$0"
    exit -1
fi

sysfs_path="/sys/class/i2c-dev/i2c-13/device/13-003e/uart3_mux_ctrl"

echo "You are in SOL session."
echo "Use ctrl-x to quit."
echo "-----------------------"
echo

trap 'echo 0 > "$sysfs_path"' INT TERM QUIT EXIT

echo $value > "$sysfs_path"

/usr/bin/microcom -s 9600 /dev/ttyS2

echo
echo
echo "-----------------------"
echo "Exit from SOL session."


#!/bin/bash
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.

# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
source /usr/local/bin/openbmc-utils.sh

function set_led_color
{
  local component=$1 color=$2

  if [ "$color" = 'yellow' ]; then
    echo out > /tmp/gpionames/${component}_RED/direction
    echo 0 > /tmp/gpionames/${component}_RED/value

    echo out > /tmp/gpionames/${component}_GREEN/direction
    echo 0 > /tmp/gpionames/${component}_GREEN/value

    echo in > /tmp/gpionames/${component}_BLUE/direction
    echo 1 > /tmp/gpionames/${component}_BLUE/value

  elif [ "$color" = 'red' ]; then
    echo out > /tmp/gpionames/${component}_RED/direction
    echo 0 > /tmp/gpionames/${component}_RED/value

    echo in > /tmp/gpionames/${component}_GREEN/direction
    echo 1 > /tmp/gpionames/${component}_GREEN/value

    echo in > /tmp/gpionames/${component}_BLUE/direction
    echo 1 > /tmp/gpionames/${component}_BLUE/value

  else
    echo in > /tmp/gpionames/${component}_RED/direction
    echo 1 > /tmp/gpionames/${component}_RED/value

    echo in > /tmp/gpionames/${component}_GREEN/direction
    echo 1 > /tmp/gpionames/${component}_GREEN/value

    echo out > /tmp/gpionames/${component}_BLUE/direction
    echo 0 > /tmp/gpionames/${component}_BLUE/value
  fi
}
# System led:
# If atleast 1 card is not present = yellow (red+green)
# otherwise = blue
# note presence util reads peer cmm =0
function set_sys_led
{
  local ret=0
  ret=$('/usr/local/bin/presence_util.sh' | grep ": 0" | wc -l)
  if [ $ret -gt 1 ]; then
    set_led_color 'SYS_LED' 'yellow'
  else
    set_led_color 'SYS_LED' 'blue'
  fi
}

# Fabric LED:
# all present = blue
# atleast 1 missing = yellow
# more than 1 missing = red
function set_fab_led
{
  local count=0
  count=$(/usr/local/bin/presence_util.sh | sed -n "/^fc.*: 0/p" | wc -l)
  if [ $count -eq 1 ]; then
    set_led_color 'FAB_LED' 'yellow'
  elif [ $count -gt 1 ]; then
    set_led_color 'FAB_LED' 'red'
  else
    set_led_color 'FAB_LED' 'blue'
  fi
}

function check_psu_alarm
{
  local sensor=$1
  local vout_low_th=11 vout_high_th=13 vin_low_th=100 vin_high_th=250 vin=0 vout=0

  readarray pfe1 < <(/usr/bin/sensors $sensor | grep -e vin -e vout1)
  vin=$(echo "${pfe1}" | sed -e 's/vin:\s*+\(.*\)[.].*$/\1/')
  vout=$(echo "${pfe1[1]}" | sed -e 's/vout1:\s*+\(.*\)[.].*$/\1/')
  if [ $vin -lt $vin_low_th ] || [ $vin -gt $vin_high_th ] ; then
    return 0
  fi
  if [ $vout -lt $vout_low_th ] || [ $vout -gt $vout_high_th ]; then
    return 0
  fi
  return 1
}

function set_psu_led
{
  local ret=0
  sensors=( "pfe3000-i2c-24-10" "pfe3000-i2c-25-10" "pfe3000-i2c-26-10" "pfe3000-i2c-27-10" )
  for i in "${sensors[@]}"
  do
    if check_psu_alarm $i; then
      set_led_color 'PSU_LED' 'red'
      return
    fi
  done
  ret=$(/usr/local/bin/presence_util.sh | sed -n "/psu.*: 0/p" | wc -l)
  if [ $ret -gt 0 ]; then
    set_led_color 'PSU_LED' 'yellow'
  else
    set_led_color 'PSU_LED' 'blue'
  fi
}

function set_fan_led
{
  local ret=0
  ret=$(/usr/bin/sensors fancpld-* | sed -n "/^Fan.*: 0 RPM/p" | wc -l)
  if [ $ret -gt 0 ]; then
    set_led_color 'FAN_LED' 'red'
    return
  fi
  ret=$(/usr/local/bin/presence_util.sh | sed -n "/fan.*: 0/p" | wc -l)
  if [ $ret -gt 0 ]; then
    set_led_color 'FAN_LED' 'yellow'
  else
    set_led_color 'FAN_LED' 'blue'
  fi
}

while :
do
  set_sys_led
  sleep 1s
  set_fab_led
  sleep 1s
  set_psu_led
  sleep 1s
  set_fan_led
  sleep 10m
done


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
TTY=/dev/ttyS1

mTerm_server_running() {
  # shellcheck disable=SC2009
  pid=$(ps | grep -v grep | grep '/usr/local/bin/mTerm_server' -m 1 |
      awk '{print $1}')
  if [ "$pid" ] ; then
    return 0
  fi
  return 1
}

start_sol_session() {
  echo "You are in SOL session."
  echo "Use ctrl-x to quit."
  echo "-----------------------"
  echo

  /usr/bin/microcom -s 57600 $TTY

  echo
  echo
  echo "-----------------------"
  echo "Exit from SOL session."
}

# if mTerm server is running use mTerm_client to connect to userver
# otherwise fallback to the old method

if mTerm_server_running; then
  exec /usr/local/bin/mTerm_client wedge
else
  start_sol_session
fi


#!/bin/sh
#
# Copyright 2021-present Facebook. All Rights Reserved.
#
exec /usr/local/bin/front-paneld


#!/bin/bash
#
# Copyright 2021-present Facebook. All Rights Reserved.
#
### BEGIN INIT INFO
# Provides:          setup-front-paneld
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Start front panel control daemon
### END INIT INFO

echo -n "Setup Front Panel Daemon..."
runsv /etc/sv/front-paneld > /dev/null 2>&1 &
echo "done."


#!/bin/sh
#
# Copyright 2015-present Facebook. All Rights Reserved.
#
### BEGIN INIT INFO
# Provides:          setup-front-paneld
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Start front panel control daemon
### END INIT INFO

echo "Setup Front Panel Daemon.."
runsv /etc/sv/led-controld > /dev/null 2>&1 &
echo "done."


#!/bin/sh
#shellcheck disable=SC1091
. /usr/local/fbpackages/utils/ast-functions

ARGS="scm smb pim2 pim3 pim4 pim5 pim6 pim7 pim8 pim9 psu1 psu2 psu3 psu4 fan"
#shellcheck disable=SC2086
exec /usr/local/bin/sensord $ARGS


#!/bin/bash
#
# Copyright 2021-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

### BEGIN INIT INFO
# Provides:          setup-sensord
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Setup sensor monitoring
### END INIT INFO
#shellcheck disable=SC1091
source /usr/local/fbpackages/utils/ast-functions

echo -n "Setup sensor monitoring for ELBERT... "

runsv /etc/sv/sensord > /dev/null 2>&1 &

echo "done."


#!/bin/sh
#
# Copyright 2014-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

### BEGIN INIT INFO
# Provides:          sensor-setup
# Required-Start:    power-on
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Power on micro-server
### END INIT INFO

# Eventually, this will be used to configure the various (mostly
# i2c-based) sensors, once we have a kernel version that supports
# doing this more dynamically.
#
# For now, we're using it to install the lm75 and pmbus module so that it
# can detect the fourth temperature sensor, which is located
# on the uServer, which doesn't get power until power-on executes.
#
# Similarly, the pmbus sensor seems to have an easier time of
# detecting the NCP4200 buck converters after poweron.  This has not
# been carefully explored.

modprobe lm75
modprobe lm90
modprobe max6697
modprobe pmbus
modprobe ucd9000


#!/bin/sh

### BEGIN INIT INFO
# Provides:		tcsd trousers
# Required-Start:	$local_fs $remote_fs $network
# Required-Stop:	$local_fs $remote_fs $network
# Should-Start:
# Should-Stop:
# Default-Start:	2 3 4 5
# Default-Stop:		0 1 6
# Short-Description:	starts tcsd
# Description:		tcsd belongs to the TrouSerS TCG Software Stack
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/tcsd
NAME=tcsd
DESC="Trusted Computing daemon"
USER="root"

test -x "${DAEMON}" || exit 0

# Read configuration variable file if it is present
# shellcheck source=/dev/null
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

case "${1}" in
	start)
		echo "Starting $DESC: "

    # For ELBERT platform, it has separate TPM for BMC only - it's probed during
    # BMC start up. So there is no need for additional device probe / addition

    # Generate symlink for tcsd
    rm -f /dev/tpm
		if [ -e /dev/tpm0 ]
    then
      ln -s /dev/tpm0 /dev/tpm
    else
      ln -s /dev/tpm1 /dev/tpm
    fi

		start-stop-daemon --start --quiet --oknodo --pidfile /var/run/"${NAME}".pid --user "${USER}" --chuid "${USER}" --exec "${DAEMON}" -- "${DAEMON_OPTS}"
		RETVAL="$?"
		echo "$NAME."
		[ "$RETVAL" = 0 ] && pidof $DAEMON > /var/run/${NAME}.pid
		exit $RETVAL
		;;

	stop)
		echo "Stopping $DESC: "

		start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/${NAME}.pid --user ${USER} --exec ${DAEMON}
		RETVAL="$?"
                echo  "$NAME."
		rm -f /var/run/${NAME}.pid
		exit $RETVAL
		;;

	restart|force-reload)
		"${0}" stop
		sleep 1
		"${0}" start
		exit $?
		;;
	*)
		echo "Usage: ${NAME} {start|stop|restart|force-reload|status}" >&2
		exit 3
		;;
esac

exit 0


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

usage() {
    echo "Usage: $0 [Fan Unit (1..5)]" >&2
}

FCMCPLD="/sys/bus/i2c/drivers/fancpld/6-0060"

show_pwm()
{
    pwm="$FCMCPLD/fan$1_pwm"
    val="$(head -n 1 "$pwm")"
    # Val is [0,255], so let's scale the value down to [0,100]
    float_val=$(echo "$val 100 * 255 / p" | dc)
    rounded="$(printf '%.*f' 0 "$float_val")"
    echo "$rounded%"
}

show_rpm()
{
    rpm="$(head -n 1 "$FCMCPLD"/fan"$1"_input)"
    # Keep the output in the same format as Minipack
    echo "$rpm, $rpm"
}

set -e

# If user input is given, use it as FAN TRAY instance
# Otherwise, read all
if [ "$#" -eq 0 ]; then
    FANS="1 2 3 4 5"
elif [ "$#" -eq 1 ]; then
    if [ "$1" -le 0 ] || [ "$1" -ge 6 ]; then
        echo "Fan $1: Should be between 1 and 5"
        exit 1
    fi
    FANS="$1"
else
    usage
    exit 1
fi

for fan in $FANS; do
    echo "Fan $fan RPMs: $(show_rpm "$fan"), ($(show_pwm "$fan"))"
done


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

### BEGIN INIT INFO
# Provides:          setup-fan
# Required-Start:    board-id
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Set fan speed
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

# shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh

if ! wedge_is_bmc_personality; then
    echo "uServer is not in BMC personality. Skipping all fan control"
    return
fi

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
# shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh
default_fsc_config="/etc/fsc-config.json"

if ! wedge_is_bmc_personality; then
    echo "uServer is not in BMC personality. Skipping all fan control"
    return
fi

num_pim16q=0
num_pim8ddm=0

pim_list="2 3 4 5 6 7 8 9"
for pim in ${pim_list}; do
     fru="$(peutil "$pim" 2>&1)"
     # PIM 16CD and 16CD2 are equivilant for FSCD
     if echo "$fru" | grep -q '88-16CD'; then
         num_pim16q=$((num_pim16q+1))
     elif echo "$fru" | grep -q '88-8D'; then
         num_pim8ddm=$((num_pim8ddm+1))
     fi
done

if [ $num_pim16q -eq 8 ]; then
    # 8xPIM16Q
    cp /etc/FSC-8-PIM16Q-config.json ${default_fsc_config}
elif [ $num_pim16q -eq 5 ] && [ $num_pim8ddm -eq 3 ]; then
    cp /etc/FSC-5-PIM16Q-3-PIM8DDM-config.json ${default_fsc_config}
elif [ $num_pim16q -eq 2 ] && [ $num_pim8ddm -eq 6 ]; then
    cp /etc/FSC-2-PIM16Q-6-PIM8DDM-config.json ${default_fsc_config}
else
    # Assume highest power configuration otherwise
    cp /etc/FSC-8-PIM8DDM-config.json ${default_fsc_config}
fi

# Create dummy sensors which host will write
echo 0 > /tmp/.PIM_QSFP200
echo 0 > /tmp/.PIM_QSFP400
echo 0 > /tmp/.PIM_F104

echo "Setup fan speed..."
/usr/local/bin/set_fan_speed.sh 30
runsv /etc/sv/fscd > /dev/null 2>&1 &
echo "done."


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

# ELBERT fan set utility for fscd.

usage() {
  echo "Usage: $0 <PWM_PERCENT> [FAN_TRAY] "
  echo "<PWM_PERCENT> : From 0 to 100 "
  echo "[FAN_TRAY] : 1, 2, 3, 4 or 5."
  echo "If no FAN_TRAY is specified, all FANs will be programmed"
}

set -e

# Make sure we only have 1 or 2 arguments
if [ "$#" -ne 2 ] && [ "$#" -ne 1 ]; then
    usage
    exit 1
fi

# Also make sure that percent value is really between 0 and 100
if [ "$1" -lt 0 ] || [ "$1" -gt 100 ]; then
    echo "PWM_PERCENT $1: should be between 0 and 100"
    exit 1
fi

# Read FAN_TRAY value from user argument.
# If no FAN_TRAY is given, configure all FANs
if [ "$#" -eq 1 ]; then
    FAN_UNIT="1 2 3 4 5"
else
    if [ "$2" -le 0 ] || [ "$2" -ge 6 ]; then
        echo "Fan $2: should be between 1 and 5"
        exit 1
    fi
    FAN_UNIT="$2"
fi

# Convert input (0-100%) to PWM (0-255)
# Multiple by 2.5
float_step=$(echo "$1 255 * 100 / p" | dc)
step="$(printf '%.*f' 0 "$float_step")"

for unit in ${FAN_UNIT}; do
    pwm="/sys/bus/i2c/drivers/fancpld/6-0060/fan${unit}_pwm"
    echo "$step" > "${pwm}"
    echo "$step will be set to ${pwm} !!!!"
    echo "Successfully set fan ${unit} speed to $1%"
done


#!/bin/bash
#
# Copyright 2021-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#

# led-controld looks for this file; if found, beacon LED will be on.
BEACON_FILE="/tmp/.elbert_beacon"

# This enum is defined in led-controld.h; do not make changes here without
# also updating that file.
BEACON_MODE_OFF=-1
BEACON_MODE_LOCATOR=0
BEACON_MODE_NETSTATE=1
BEACON_MODE_DRAINED=2
BEACON_MODE_AUDIT=3

beacon_stoi() {
     # Translate mode to int for file storage.
     mode_str=$1
     mode_int="$BEACON_MODE_OFF"
     case "$mode_str" in
          locator)
               mode_int="$BEACON_MODE_LOCATOR"
               ;;
          netstate)
               mode_int="$BEACON_MODE_NETSTATE"
               ;;
          drained)
               mode_int="$BEACON_MODE_DRAINED"
               ;;
          audit)
               mode_int="$BEACON_MODE_AUDIT"
               ;;
          *)
               usage
               ;;
     esac

     echo "$mode_int"
}

beacon_led_on() {
     mode_str=$1

     if [ -z "$mode_str" ]; then
          mode_str="locator"
     fi

     mode_int=$(beacon_stoi "$mode_str")
     if [ -f "$BEACON_FILE" ]; then
          curr_mode=$(<"$BEACON_FILE")
          if [[ "$mode_int" == "$curr_mode" ]]; then
               echo "Beacon LED: already ON in $mode_str mode"
               exit 1
          fi
     fi

     echo "$mode_int" > "$BEACON_FILE"
     echo "Beacon LED: now ON in $mode_str mode"
}

beacon_led_off() {
     if [ ! -f "$BEACON_FILE" ]; then
          echo "Beacon LED: already OFF"
          exit 1
     fi

     rm -rf "$BEACON_FILE"
     echo "Beacon LED: now OFF"
}

beacon_led_status() {
     # Print beacon status for every mode.
     curr_mode="$BEACON_MODE_OFF"
     if [ -f "$BEACON_FILE" ]; then
          curr_mode=$(<"$BEACON_FILE")
     fi

     for mode_str in locator netstate drained audit; do
          mode_int=$(beacon_stoi "$mode_str")
          if [[ "$mode_int" == "$curr_mode" ]]; then
             echo "$mode_str: ON"
          else
             echo "$mode_str: OFF"
          fi
     done
}

usage() {
     program=$(basename "$0")
     echo "Usage:"
     echo "$program <on|off|status> [locator | netstate | drained | audit]"
     exit 1
}

command="$1"
shift

case "$command" in
     on)
          beacon_led_on "$1"
          ;;
     off)
          beacon_led_off
          ;;
     status)
          beacon_led_status
          ;;
     *)
          usage
          ;;
esac


#!/bin/bash

# shellcheck disable=SC1091
# shellcheck disable=SC2012
# shellcheck disable=SC2039
. /usr/local/bin/openbmc-utils.sh

# Check if another fw upgrade is ongoing
check_fwupgrade_running

trap cleanup INT TERM QUIT EXIT

SCM_SPI="spi1.0"
SCM_SPIDEV="spidev1.0"
SCM_MTD=""
ABOOT_CONF_START=$((0x9FA000))
FLASH_SIZE=$((0x1000000))
ABOOT_CONF_SIZE=$((0x5000))
SECTION_BLOCK_SIZE=$((0x1000))

# Temp files for storing bios file.
TEMP_BIOS_IMAGE="/tmp/tmp_bios_image"
# Temp file for storing aboot_conf data
TEMP_ABOOT_CONF="/tmp/aboot_conf.bin"

DEFAULT_ABOOT_CONF="BOOT_METHOD1=IPV6_PXE,BOOT_METHOD2=LOCAL,BOOT_METHOD3=ARISTA"

cleanup() {
    disconnect_spi
    rm -f $TEMP_ABOOT_CONF $TEMP_BIOS_IMAGE
}

bind_spi_nor() {
    # Unbind spidev
    if [ -e /dev/"$SCM_SPIDEV" ]; then
        echo "$SCM_SPI" > /sys/bus/spi/drivers/spidev/unbind
    fi

    # Bind
    echo spi-nor  > /sys/bus/spi/devices/"$SCM_SPI"/driver_override
    if [ ! -e /sys/bus/spi/drivers/spi-nor/"$SCM_SPI" ]; then
        echo Binding "$SCM_SPI" to ...
        echo "$SCM_SPI" > /sys/bus/spi/drivers/spi-nor/bind
        sleep 0.5
    fi
    SCM_MTD="$(grep "$SCM_SPI" /proc/mtd |awk '{print$1}' | tr -d : | tr -d mtd)"
    if test -z "$SCM_MTD"; then
        echo "Failed to locate mtd partition for SPI Flash!"
        exit 1
    fi
}

unbind_spi_nor() {
    # Method for unloading spi-nor driver dynamically back to spidev
    echo > /sys/bus/spi/devices/"$SCM_SPI"/driver_override
    if grep "$SCM_SPI" /proc/mtd > /dev/null 2>&1 ; then
        echo "Unbinding spi-nor from $SCM_SPI"
        echo "$SCM_SPI" > /sys/bus/spi/drivers/spi-nor/unbind
    fi
    if [ ! -e /dev/"$SCM_SPIDEV" ]; then
        echo "Binding spidev back to $SCM_SPI"
        echo "$SCM_SPI" > /sys/bus/spi/drivers/spidev/bind
    fi
}

usage() {
    program=$(basename "$0")
    echo "Usage:"
    echo "$program <OP> <bios file>"
    echo "      <OP> : read, write, erase, verify"
    exit 1
}

disconnect_spi() {
    # connect through CPLD
    echo 0x0 > "${SCMCPLD_SYSFS_DIR}"/bios_select
    # Set GPIOV0 to 0 (default GPIO state)
    gpio_set_value BMC_SPI1_CS0_MUX_SEL 0
    unbind_spi_nor
}

connect_spi() {
    # Set GPIOV0 to 0
    gpio_set_value BMC_SPI1_CS0_MUX_SEL 0
    # connect through CPLD
    echo 0x1 > "${SCMCPLD_SYSFS_DIR}"/bios_select
    bind_spi_nor
}

connect_spi

read_flash() {
    echo "Reading flash content..."
    flashrom -f -p linux_mtd:dev="$SCM_MTD" -r "$1" || return 1
    sleep 1
    echo "Verifying flash content..."
    flashrom -f -p linux_mtd:dev="$SCM_MTD" -v "$1" || return 1
    return 0
}

create_bios_image() {
    start_block="$(($1 / SECTION_BLOCK_SIZE))"
    num_blocks="$(($2 / SECTION_BLOCK_SIZE))"
    rm -f "$TEMP_BIOS_IMAGE"
    dd if="$3" of="$TEMP_BIOS_IMAGE" bs="$SECTION_BLOCK_SIZE" count="$start_block" \
       2> /dev/null
    dd if="$4" bs="$SECTION_BLOCK_SIZE" count="$num_blocks" >> "$TEMP_BIOS_IMAGE" \
       2> /dev/null
    end_blocks=$(( (FLASH_SIZE / SECTION_BLOCK_SIZE) - start_block - num_blocks ))
    dd if="$3" bs="$SECTION_BLOCK_SIZE" count="$end_blocks" skip=$((start_block + num_blocks)) \
       >> "$TEMP_BIOS_IMAGE" 2> /dev/null
}

create_aboot_conf() {
    echo "Using Aboot conf: $1"

    nvs="$1,"

    rm -f "$TEMP_ABOOT_CONF"
    touch "$TEMP_ABOOT_CONF"
    while [ -n "${nvs%%,*}" ]; do
        nv="${nvs%%,*}"
        name="${nv%%=*}"
        if [ "$name" = "$nv" ]; then
            echo "Invalid name-value argument $nv" >&2
            return 1
        fi
        echo -n "${nv%%=*}=" >> "$TEMP_ABOOT_CONF"
        echo -n "${nv#*=}" | base64 >> "$TEMP_ABOOT_CONF"
        nvs="${nvs#*,}"
    done

    size="$(ls -l "$TEMP_ABOOT_CONF" | awk '{print $5}')"
    pad_size="$((ABOOT_CONF_SIZE - size))"
    dd if=/dev/zero bs=1 count="$pad_size" >> "$TEMP_ABOOT_CONF" 2> /dev/null
}

aboot_version() {
    grep -a CONFIG_LOCALVERSION "$1" 2> /dev/null | awk -F'"' '{print $2}'
}

if [ "$1" = "erase" ]; then
    echo "Erasing flash content ..."
    flashrom -f -p linux_mtd:dev="$SCM_MTD" -E || exit 1
elif [ "$1" = "read" ]; then
    retry_command 5 read_flash "$2" || exit 1
elif [ "$1" = "verify" ]; then
    bios_image="$2"
    if [ -n "$(aboot_version "$bios_image")" ]; then
        create_aboot_conf "$DEFAULT_ABOOT_CONF" || exit 1
        create_bios_image "$ABOOT_CONF_START" "$ABOOT_CONF_SIZE" \
                          "$bios_image" "$TEMP_ABOOT_CONF" || exit 1
        bios_image="$TEMP_BIOS_IMAGE"
    fi
    echo "Verifying flash content..."
    flashrom -f -p linux_mtd:dev="$SCM_MTD" -v "$bios_image" || exit 1
elif [ "$1" = "write" ]; then
    bios_image="$2"
    if [ -n "$(aboot_version "$bios_image")" ]; then
        create_aboot_conf "$DEFAULT_ABOOT_CONF" || exit 1
        create_bios_image "$ABOOT_CONF_START" "$ABOOT_CONF_SIZE" \
                          "$bios_image" "$TEMP_ABOOT_CONF" || exit 1
        bios_image="$TEMP_BIOS_IMAGE"
    fi
    echo "Writing flash content..."
    retry_command 5 flashrom -n -f -p linux_mtd:dev="$SCM_MTD" -w "$bios_image" || exit 1
    sleep 1
    echo "Verifying flash content..."
    # Retry verification up to 5 times
    retry_command 5 flashrom -f -p linux_mtd:dev="$SCM_MTD" -v "$bios_image" || exit 1
else
    usage
fi


#!/bin/bash

# Read AST2620 register SCU014 [23:16] to retrieve the board hardware revision.

SCU014_REG=0x1e6e2014
HW_REV_BIT=16
BOARD_REV=$(($(($(devmem "${SCU014_REG}") >> "${HW_REV_BIT}")) & 0xff))
echo "BMC Board Revision: A${BOARD_REV}"