#!/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=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"
if [ -e /sys/bus/platform/drivers/spi-aspeed-smc ]; then
    ASPEED_SMC_PATH="/sys/bus/platform/drivers/spi-aspeed-smc/"
else
    ASPEED_SMC_PATH="/sys/bus/platform/drivers/aspeed-smc/"
fi

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
}

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

read_spi2_dev(){
    dev=$1
    file=$2
    file_temp="$file"_temp
    echo "Reading ${dev} to $file..."
    # Sometimes the read back BCM5387_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/devices/platform/spi-gpio/spi_master/spi2/spi2.2/spi2.20/nvmem of="$file"
        sleep 1
        dd if=/sys/devices/platform/spi-gpio/spi_master/spi2/spi2.2/spi2.20/nvmem 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_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))

    case ${dev} in
        "PCIE_SW"|"TH4_PCIE_FLASH"|"COME_BIOS"|"DOM_FPGA_ALL"|"DOM_FPGA_PIM1"|"DOM_FPGA_PIM2"|"DOM_FPGA_PIM3"|"DOM_FPGA_PIM4"|"DOM_FPGA_PIM5"|"DOM_FPGA_PIM6"|"DOM_FPGA_PIM7"|"DOM_FPGA_PIM8")
        # store to the temp-file
        cp "$file" "$tmpfile"
        ;;

	"IOB_FPGA")
        # remove fpga header size 112 and then store to the temp-file
        dd if="$file" skip=1 bs=112 of="$tmpfile"
        ;;
    esac

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

    echo flashrom -p linux_mtd:dev=$SPI1_MTD_INDEX -w "$tmpfile"

    flashrom -p linux_mtd:dev=$SPI1_MTD_INDEX -w "$tmpfile"

    case ${dev} in
        "IOB_FPGA")
            echo 0 > /sys/bus/i2c/devices/12-003e/sys_cpld_fpga_rst_n
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/sys_cpld_fpga_rst_n
        ;;

        "DOM_FPGA_PIM1")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim1_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim1_smb_pg
        ;;
        "DOM_FPGA_PIM2")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim2_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim2_smb_pg
        ;;
        "DOM_FPGA_PIM3")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim3_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim3_smb_pg
        ;;
        "DOM_FPGA_PIM4")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim4_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim4_smb_pg
        ;;
        "DOM_FPGA_PIM5")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim5_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim5_smb_pg
        ;;
        "DOM_FPGA_PIM6")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim6_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim6_smb_pg
        ;;
        "DOM_FPGA_PIM7")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim7_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim7_smb_pg
        ;;
        "DOM_FPGA_PIM8")
            echo 0 > /sys/bus/i2c/devices/12-003e/pim8_smb_pg
            sleep 1
            echo 1 > /sys/bus/i2c/devices/12-003e/pim8_smb_pg
        ;;
    esac
}

write_spi2_dev(){
    dev=$1
    file=$2
    echo "Writing $file to ${dev}..."
    dd if="$file" of=/sys/devices/platform/spi-gpio/spi_master/spi2/spi2.2/spi2.20/nvmem
}

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

erase_spi2_dev(){
    echo 1 > /sys/devices/platform/spi-gpio/spi_master/spi2/spi2.2/erase
}

setup_pims_switch_mux(){

#
# This function is used to bypass the command through FPGA to PCA9534, to switch the mux from PIM FPGA to IOB FPGA that BMC can access PIM Flash through IOB FPGA via SPI protocol.
#
# The registers at address 0XF0 and above defined in this section is dedicated for BMC only.
# CPU canâ€™t access 0XF0-0XFF registers in this section. BMC can use the address/data/command registers defined in address 0XF0- 0XFC to access FPGA full memory space.
# 0xFF is a debug register.
#
# 0xF0	RW	Indirect Access Address register [31:24]
# 0xF1	RW	Indirect Access Address register [23:16]
# 0xF2	RW	Indirect Access Address register [15:8]
# 0xF3	RW	Indirect Access Address register [7:0]
#
# 0xF4  RW      Indirect Access Write data register [31:24]
# 0xF5  RW      Indirect Access Write data [23:16]
# 0xF6  RW      Indirect Access Write data [15:8]
# 0xF7  RW      Indirect Access Write data [7:0]
#
# 0xFC	RW	Indirect Access Command Register.
# bit0 = 1 is for write; bit0 = 0 is for read.
# Writing to this register will trigger an indirect access.
#
# Set 0x0000148c to 0x00000003
#
    # Set Indirect Access Address 0x0000148c
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x8c
    # Set Write Data 0x00000003
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0x0
    i2cset -y -f 13 0x35 0xf7 0x3
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001484 to 0x80220200
#

    # Set Indirect Access Address 0x00001484
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x84
    # Set Write Data 0x80220200
    i2cset -y -f 13 0x35 0xf4 0x80
    i2cset -y -f 13 0x35 0xf5 0x22
    i2cset -y -f 13 0x35 0xf6 0x2
    i2cset -y -f 13 0x35 0xf7 0x0
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001500 to 0x0000fc03
#

    # Set Indirect Access Address 0x00001500
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x15
    i2cset -y -f 13 0x35 0xf3 0x0
    # Set Write Data 0x0000fc03
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0xfc
    i2cset -y -f 13 0x35 0xf7 0x3
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

    sleep 1

#
# Set 0x0000148c to 0x00000003
#

    # Set Indirect Access Address 0x0000148c
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x8c
    # Set Write Data 0x00000003
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0x0
    i2cset -y -f 13 0x35 0xf7 0x3
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001484 to 0x80220200
#

    # Set Indirect Access Address 0x00001484
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x84
    # Set Write Data 0x80220200
    i2cset -y -f 13 0x35 0xf4 0x80
    i2cset -y -f 13 0x35 0xf5 0x22
    i2cset -y -f 13 0x35 0xf6 0x2
    i2cset -y -f 13 0x35 0xf7 0x0
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001500 to 0x0000d501
#

    # Set Indirect Access Address 0x00001500
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x15
    i2cset -y -f 13 0x35 0xf3 0x0
    # Set Write Data 0x0000d501
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0xd5
    i2cset -y -f 13 0x35 0xf7 0x01
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

    sleep 1

#
# Set 0x0000148c to 0x00000003
#

    # Set Indirect Access Address 0x0000148c
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x8c
    # Set Write Data 0x00000003
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0x0
    i2cset -y -f 13 0x35 0xf7 0x3
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001484 to 0x80220200
#

    # Set Indirect Access Address 0x00001484
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x84
    # Set Write Data 0x80220200
    i2cset -y -f 13 0x35 0xf4 0x80
    i2cset -y -f 13 0x35 0xf5 0x22
    i2cset -y -f 13 0x35 0xf6 0x2
    i2cset -y -f 13 0x35 0xf7 0x0
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001500 to 0x0000fc03
#

    # Set Indirect Access Address 0x00001500
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x15
    i2cset -y -f 13 0x35 0xf3 0x0
    # Set Write Data 0x0000fc03
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0xfc
    i2cset -y -f 13 0x35 0xf7 0x3
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

    sleep 1

#
# Set 0x0000148c to 0x00000003
#

    # Set Indirect Access Address 0x0000148c
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x8c
    # Set Write Data 0x00000003
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0x0
    i2cset -y -f 13 0x35 0xf7 0x3
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001484 to 0x80220200
#

    # Set Indirect Access Address 0x00001484
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x14
    i2cset -y -f 13 0x35 0xf3 0x84
    # Set Write Data 0x80220200
    i2cset -y -f 13 0x35 0xf4 0x80
    i2cset -y -f 13 0x35 0xf5 0x22
    i2cset -y -f 13 0x35 0xf6 0x2
    i2cset -y -f 13 0x35 0xf7 0x0
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

#
# Set 0x00001500 to 0x0000d501
#

    # Set Indirect Access Address 0x00001500
    i2cset -y -f 13 0x35 0xf0 0x0
    i2cset -y -f 13 0x35 0xf1 0x0
    i2cset -y -f 13 0x35 0xf2 0x15
    i2cset -y -f 13 0x35 0xf3 0x0
    # Set Write Data 0x0000d501
    i2cset -y -f 13 0x35 0xf4 0x0
    i2cset -y -f 13 0x35 0xf5 0x0
    i2cset -y -f 13 0x35 0xf6 0xd5
    i2cset -y -f 13 0x35 0xf7 0x01
    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

}

config_spi1_pin_and_path(){
    dev=$1

    case ${dev} in
        "TH4_PCIE_FLASH")
            echo "[Setup] TH4_PCIE_FLASH"
            echo 0x00 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 1 - enable FPGA internal SPI masters
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0 - select none
            i2cset -y -f 13 0x35 0x76 0x80 b
            i2cset -y -f 13 0x35 0x77 0x00 b
        ;;
        "IOB_FPGA")
            echo "[Setup] IOB_FPGA"
            echo 0x01 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 1 - enable FPGA internal SPI masters
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0 - select none
            i2cset -y -f 13 0x35 0x76 0x80 b
            i2cset -y -f 13 0x35 0x77 0x00 b
        ;;
        "PCIE_SW")
            echo "[Setup] PCIE_SW"
            echo 0x02 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 1 - enable FPGA internal SPI masters
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0 - select none
            i2cset -y -f 13 0x35 0x76 0x80 b
            i2cset -y -f 13 0x35 0x77 0x00 b
        ;;
        "COME_BIOS")
            echo "[Setup] COME_BIOS"
            echo 0x03 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 1 - enable FPGA internal SPI masters
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0 - select none
            i2cset -y -f 13 0x35 0x76 0x80 b
            i2cset -y -f 13 0x35 0x77 0x00 b
        ;;
        "DOM_FPGA_ALL")
            echo "[Setup] DOM_FPGA_ALL"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x100 - Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            i2cset -y -f 13 0x35 0x76 0x01 b
            i2cset -y -f 13 0x35 0x77 0x00 b
        ;;
        "DOM_FPGA_PIM1")
            echo "[Setup] DOM_FPGA_PIM1"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x01 - Bit0 is for PIM#1
            i2cset -y -f 13 0x35 0x76 0x00 b
            i2cset -y -f 13 0x35 0x77 0x01 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM2")
            echo "[Setup] DOM_FPGA_PIM2"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x02 - Bit1 is for PIM#2
            i2cset -y -f 13 0x35 0x76 0x10 b
            i2cset -y -f 13 0x35 0x77 0x02 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM3")
            echo "[Setup] DOM_FPGA_PIM3"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x04 - Bit2 is for PIM#3
            i2cset -y -f 13 0x35 0x76 0x20 b
            i2cset -y -f 13 0x35 0x77 0x04 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM4")
            echo "[Setup] DOM_FPGA_PIM4"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x08 - Bit3 is for PIM#4
            i2cset -y -f 13 0x35 0x76 0x30 b
            i2cset -y -f 13 0x35 0x77 0x08 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM5")
            echo "[Setup] DOM_FPGA_PIM5"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x10 - Bit4 is for PIM#5
            i2cset -y -f 13 0x35 0x76 0x40 b
            i2cset -y -f 13 0x35 0x77 0x10 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM6")
            echo "[Setup] DOM_FPGA_PIM6"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x20 - Bit5 is for PIM#6
            i2cset -y -f 13 0x35 0x76 0x50 b
            i2cset -y -f 13 0x35 0x77 0x20 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM7")
            echo "[Setup] DOM_FPGA_PIM7"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x40 - Bit6 is for PIM#7
            i2cset -y -f 13 0x35 0x76 0x60 b
            i2cset -y -f 13 0x35 0x77 0x40 b
            setup_pims_switch_mux
        ;;
        "DOM_FPGA_PIM8")
            echo "[Setup] DOM_FPGA_PIM8"
            echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel
            #
            # FPGA 0x0074, [31:0] is 4 bytes address offset from 0x74 to 0x77 offset
            #
            # Set FPGA register offset 74h bit[15] SPI master mode to 0 - SPI legacy mode, SPI master is BMC.
            #
            # Bit0 is for PIM#1; bit7 is for PIM#8.
            # Bit8 is for the SPI Flash attached on IOB FPGA. For testing
            #
            # Set FPGA register offset 74h bit[8:0] SPI selection bitmap to 0x80 - Bit7 is for PIM#8
            i2cset -y -f 13 0x35 0x76 0x70 b
            i2cset -y -f 13 0x35 0x77 0x80 b
            setup_pims_switch_mux
        ;;

        *)
            echo "Please enter {TH4_PCIE_FLASH, IOB_FPGA, PCIE_SW, COME_BIOS, DOM_FPGA_ALL, DOM_FPGA_PIM1, DOM_FPGA_PIM2, DOM_FPGA_PIM3, DOM_FPGA_PIM4, DOM_FPGA_PIM5, DOM_FPGA_PIM6, DOM_FPGA_PIM7, DOM_FPGA_PIM8}"
            exit 1
        ;;
    esac

    mtd_driver_rebind_spi1
    echo "Config SPI1 Done."
}

config_spi2_pin_and_path(){
    dev=$1

    case ${dev} in
        "BCM5387_EE")
            echo "[Setup] BCM5387_EE"
            echo 0x05 > /sys/bus/i2c/devices/12-003e/spi2_sel
        ;;
        "SMB_EE")
            echo "[Setup] SMB_EE"
            echo 0x04 > /sys/bus/i2c/devices/12-003e/spi2_sel
        ;;

        *)
            echo "Please enter {BCM5387_EE, SMB_EE}"
            exit 1
        ;;
    esac
    echo "Config SPI2 Done."
}

operate_spi1_dev(){
    op=$1
    dev=$2
    file=$3
    ## Operate devices ##
    case ${op} in
        "read")
                read_spi1_dev "$dev" "$file"
        ;;
        "write")
                if [ ! -f "$file" ]; then
                    echo "$file not exist!!!"
                    exit 1
                fi
                write_spi1_dev "$dev" "$file"
        ;;
        "erase")
                erase_spi1_dev "$dev"
        ;;
        *)
            echo "Operation $op is not defined."
        ;;
    esac
    mtd_driver_unbind_spi1
}

operate_spi2_dev(){
    op=$1
    dev=$2
    file=$3
    ## Operate devices ##
    case ${op} in
        "read")
                read_spi2_dev "$dev" "$file"
        ;;
        "write")
                if [ ! -f "$file" ]; then
                    echo "$file not exist!!!"
                    exit 1
                fi
                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|spi2> <spi device> <file>"
    echo "    <op>          : read, write, erase"
    echo "    <spi1 device> : TH4_PCIE_FLASH, IOB_FPGA, PCIE_SW, COME_BIOS, DOM_FPGA_ALL, DOM_FPGA_PIM1 ~ DOM_FPGA_PIM8"
    echo "    <spi2 device> : BCM5387_EE, SMB_EE"
    echo ""
    echo "Examples:"
    echo "  $program write spi1 DOM_FPGA_PIM7 domfpga.bit"
    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
                "TH4_PCIE_FLASH"|"IOB_FPGA"|"PCIE_SW"|"COME_BIOS"|"DOM_FPGA_ALL"|"DOM_FPGA_PIM1"|"DOM_FPGA_PIM2"|"DOM_FPGA_PIM3"|"DOM_FPGA_PIM4"|"DOM_FPGA_PIM5"|"DOM_FPGA_PIM6"|"DOM_FPGA_PIM7"|"DOM_FPGA_PIM8")
                    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
                "BCM5387_EE"|"SMB_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/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
#
# This tool is used to setup the SPI mux on the PIM from connecting to DOM FPGA to connecting to IOB FPGA,
# so that IOB FPGA has the ability to read and write Flash on PIM.
# Before updating the DOM FPGA, we must set the SPI mux of PIM to access the Flash of DOM FPGA.
#

set_pca9534_register(){

    register=$1
    value=$2

    # Set IOB FPGA indirect Access Address 0x00001500
    i2cset -y -f 13 0x35 0xf0 0x00 0x00 0x15 0x00 i
    # Set IOB FPGA Write Data 0x0000fc03
    i2cset -y -f 13 0x35 0xf4 0x00 0x00 "$value" "$register" i

    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1 b
}

flush_ucd_register(){

    # Set IOB FPGA indirect Access Address 0x0000148c
    i2cset -y -f 13 0x35 0xf0 0x00 0x00 0x14 0x8c i
    # Set IOB FPGA Write Data 0x00000003
    i2cset -y -f 13 0x35 0xf4 0x00 0x00 0x00 0x03 i

    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1

    # Set IOB FPGA indirect Access Address 0x00001484
    i2cset -y -f 13 0x35 0xf0 0x00 0x00 0x14 0x84 i
    # Set IOB FPGA Write Data 0x80220200
    i2cset -y -f 13 0x35 0xf4 0x80 0x22 0x02 0x00 i

    # Set Command Write Action
    i2cset -y -f 13 0x35 0xfc 0x1
}

setup_pims_switch_mux(){

    flush_ucd_register

    # Register 3 -  Configuration Register
    set_pca9534_register "0x03" "0xc0"

    flush_ucd_register

    #
    # Set Register 1 - Output Port Register bit[1] - O1
    #
    # Register 1 -  Output Port Register
    set_pca9534_register "0x01" "0xd5"

    flush_ucd_register
}

echo 0x06 > /sys/bus/i2c/devices/12-003e/spi1_sel

for i in 0 1 2 3 4 5 6 7
do
    cmd=$(printf "i2cset -y -f 13 0x35 0x76 0x%02x 0x%02x i\n" "$(((i+8)<<4))" "$((1<<i))")
    $cmd
    setup_pims_switch_mux
done


#!/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
source /usr/local/bin/openbmc-utils.sh

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

prog="$0"
#board_rev=$(wedge_board_rev)

PWR_USRV_RST_SYSFS="${SCMCPLD_SYSFS_DIR}/sys_reset_n"
PWR_L_CYCLE_SYSFS="${LEFT_PDBCPLD_SYSFS_DIR}/power_cycle_go"
PWR_R_CYCLE_SYSFS="${RIGHT_PDBCPLD_SYSFS_DIR}/power_cycle_go"
PWR_L_TIMER_BASE_1S_SYSFS="${LEFT_PDBCPLD_SYSFS_DIR}/timer_base_1s"
PWR_R_TIMER_BASE_1S_SYSFS="${RIGHT_PDBCPLD_SYSFS_DIR}/timer_base_1s"
PWR_L_TIMER_BASE_10S_SYSFS="${LEFT_PDBCPLD_SYSFS_DIR}/timer_base_10s"
PWR_R_TIMER_BASE_10S_SYSFS="${RIGHT_PDBCPLD_SYSFS_DIR}/timer_base_10s"
PWR_L_TIMER_COUNTER_SETTING_SYSFS="${LEFT_PDBCPLD_SYSFS_DIR}/timer_counter_setting"
PWR_R_TIMER_COUNTER_SETTING_SYSFS="${RIGHT_PDBCPLD_SYSFS_DIR}/timer_counter_setting"
PWR_L_TIMER_COUNTER_SETTING_UPDATE_SYSFS="${LEFT_PDBCPLD_SYSFS_DIR}/timer_counter_setting_update"
PWR_R_TIMER_COUNTER_SETTING_UPDATE_SYSFS="${RIGHT_PDBCPLD_SYSFS_DIR}/timer_counter_setting_update"

PIM_NAME="${PIM_RST_SYSFS}/pim"
CPLD_RESET="_hw_rst_l"
CPLD_PG="_smb_pg"

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 fuji 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 "  pimreset: Power-cycle one or all PIM(s)"
    echo "    options:"
    echo "      -a  : Reset all PIMs or "
    echo "      -2 , -3 , ... , -9 : Reset a single PIM (2, 3 ... 9) "
    echo
    echo "  pim_power_on/off: Power-on/off one or all PIM(s)"
    echo "    options:"
    echo "      -a  : Power-on/off all PIMs or "
    echo "      -2 , -3 , ... , -9 : Power-on/off a single PIM (2, 3 ... 9) "
    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

    # 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_L_TIMER_BASE_1S_SYSFS"
            echo 1 > "$PWR_R_TIMER_BASE_1S_SYSFS"
            echo 0 > "$PWR_L_TIMER_BASE_10S_SYSFS"
            echo 0 > "$PWR_R_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_L_TIMER_BASE_1S_SYSFS"
            echo 0 > "$PWR_R_TIMER_BASE_1S_SYSFS"
            echo 1 > "$PWR_L_TIMER_BASE_10S_SYSFS"
            echo 1 > "$PWR_R_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_L_TIMER_COUNTER_SETTING_SYSFS"
        echo $wake_t > "$PWR_R_TIMER_COUNTER_SETTING_SYSFS"
        echo 1 > "$PWR_L_TIMER_COUNTER_SETTING_UPDATE_SYSFS"
        echo 1 > "$PWR_R_TIMER_COUNTER_SETTING_UPDATE_SYSFS"
        echo 0 > "$PWR_L_TIMER_COUNTER_SETTING_UPDATE_SYSFS"
        echo 0 > "$PWR_R_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_L_CYCLE_SYSFS"
            echo 1 > "$PWR_R_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. Running a workaround"
            echo "Failed to reset the system. 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
        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
}

toggle_pim_reset() {
    retval=0
    pim=$1
    for slot in 2 3 4 5 6 7 8 9; do
      if [ "$pim" -eq 0 ] || [ $slot -eq "$pim" ]; then
        index=$((slot - 1))
         echo Power-cycling PIM in slot $slot
         #i2cset -f -y ${PIM_CPLD_BUS[$index]} $CPLD_ADDR $CPLD_RESET_CMD
         echo 0 > "$PIM_NAME$index$CPLD_RESET"
         sleep 1
         echo 1 > "$PIM_NAME$index$CPLD_RESET"
         result=$?
         if [ $result -ne 0 ]; then
           retval=$result
         fi
      fi
    done
    return $retval
}

toggle_pim_power_onoff() {
	retval=0
	action=$1
	pim=$2
	for slot in 2 3 4 5 6 7 8 9; do
		if [ "$pim" -eq 0 ] || [ $slot -eq "$pim" ]; then
			index=$((slot - 1))
			if [ "$action" = "on" ]; then
				echo Power-on PIM in slot $slot
				echo 1 > "$PIM_NAME$index$CPLD_PG"
				result=$?
			elif [ "$action" = "off" ]; then
				echo Power-off PIM in slot $slot
				echo 0 > "$PIM_NAME$index$CPLD_PG"
				result=$?
			fi
			if [ "$result" -ne 0 ]; then
				retval=$result
			fi
		fi
	done
	return $retval
}

do_pimreset() {
    local pim opt retval
    retval=0
    pim=-1
    while getopts "23456789a" opt; do
        case $opt in
            a)
                pim=0
                ;;
            2)
                pim=2
                ;;
            3)
                pim=3
                ;;
            4)
                pim=4
                ;;
            5)
                pim=5
                ;;
            6)
                pim=6
                ;;
            7)
                pim=7
                ;;
            8)
                pim=8
                ;;
            9)
                pim=9
                ;;
            *)
                usage
                exit 1
                ;;
        esac
    done
    if [ $pim -eq -1 ]; then
      usage
      exit 1
    fi

    toggle_pim_reset $pim
    retval=$?

    return $retval
}

do_pim_power_on() {
	local pim opt retval
	retval=0
	pim=-1
	while getopts "23456789a" opt; do
		case $opt in
			a)
				pim=0
				;;
			2)
				pim=2
				;;
			3)
				pim=3
				;;
			4)
				pim=4
				;;
			5)
				pim=5
				;;
			6)
				pim=6
				;;
			7)
				pim=7
				;;
			8)
				pim=8
				;;
			9)
				pim=9
				;;
			*)
				usage
				exit 1
				;;
		esac
	done
	if [ $pim -eq -1 ]; then
		usage
		exit 1
	fi

	toggle_pim_power_onoff on $pim
	retval=$?

	return $retval
}

do_pim_power_off() {
	local pim opt retval
	retval=0
	pim=-1
	while getopts "23456789a" opt; do
		case $opt in
			a)
				pim=0
				;;
			2)
				pim=2
				;;
			3)
				pim=3
				;;
			4)
				pim=4
				;;
			5)
				pim=5
				;;
			6)
				pim=6
				;;
			7)
				pim=7
				;;
			8)
				pim=8
				;;
			9)
				pim=9
				;;
			*)
				usage
				exit 1
				;;
		esac
	done
	if [ $pim -eq -1 ]; then
		usage
		exit 1
	fi

	toggle_pim_power_onoff off $pim
	retval=$?

	return $retval
}

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
        ;;
    pimreset)
        do_pimreset "$@"
        exit $?
        ;;
	pim_power_on)
		do_pim_power_on "$@"
		exit $?
		;;
	pim_power_off)
		do_pim_power_off "$@"
		exit $?
		;;
    *)
        usage
        exit 1
        ;;
esac

if [ $set_bic -ne 0 ]; then
# sleep 10 second to wait BIC & COMe 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/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

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

#
# Main entry starts here
#
/usr/local/bin/setup_avs.sh


#!/bin/sh

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

#At this way, it uses to GPIO mode
devmem_clear_bit 0x1e6e2070 12
devmem_clear_bit 0x1e6e2070 13

if [ ! -L "${SHADOW_GPIO}/BMC_EEPROM1_SPI_SS" ]; then
    gpio_export_by_name "$ASPEED_GPIO" GPIOI4 BMC_EEPROM1_SPI_SS
    gpio_export_by_name "$ASPEED_GPIO" GPIOI5 BMC_EEPROM1_SPI_SCK
    gpio_export_by_name "$ASPEED_GPIO" GPIOI6 BMC_EEPROM1_SPI_MOSI
    gpio_export_by_name "$ASPEED_GPIO" GPIOI7 BMC_EEPROM1_SPI_MISO
fi

gpio_set_value SWITCH_EEPROM1_WRT 1

/usr/local/bin/at93cx6_util_py3.py --cs BMC_EEPROM1_SPI_SS \
                                   --clk BMC_EEPROM1_SPI_SCK \
                                   --mosi BMC_EEPROM1_SPI_MOSI \
                                   --miso BMC_EEPROM1_SPI_MISO $@

#resolve to SPI mode for another flash using(backup flash)
devmem_set_bit 0x1e6e2070 12


#!/bin/sh

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

status_switch() {
	prompt=1
	while getopts "f" opts; do
		case $opts in
			f)
				prompt=0
				shift
				;;
			*)
				prompt=1
				;;
		esac
	done
	if [ "$1" = "mdio" ]; then
		gpio_set_value SWITCH_EEPROM1_WRT 1
	elif [ "$1" = "eeprom" ]; then
		gpio_set_value SWITCH_EEPROM1_WRT 0
	else
		echo "Mode doesn't support!"
		return 1
	fi
	if [ $prompt -eq 1 ]; then
		printf "Need to reset BCM5389(Y/n) "
		read confirm
		if [ "$confirm" = "Y" ] || [ "$confirm" = "y" ]; then
			printf "Reset......"
			i2cset -f -y 12 0x31 0x14 0xfb
			sleep 1
			i2cset -f -y 12 0x31 0x14 0xff
			printf "OK\n"
		fi
	else
		printf "Reset......"
		i2cset -f -y 12 0x31 0x14 0xfb
		sleep 1
		i2cset -f -y 12 0x31 0x14 0xff
		printf "OK\n"
	fi

	return 0
}

command="$1"
case "$command" in
	--mode)
		shift
		status_switch $@
		;;
	*)
		bcm5396_util.py $@
		;;
esac


#!/bin/sh
i2cset -f -y 0 0x3e 0x16 0x01
if [ ! -f /dev/spidev5 ]
then
	mknod /dev/spidev5.0 c 153 0
	modprobe spidev
fi
flashrom -p linux_spi:dev=/dev/spidev5.0 -c W25Q64.V
#flashrom -p linux_spi:dev=/dev/spidev5.0 -r bios


# Copyright 2015-present Facebook. All Rights Reserved.

SYSCPLD_SYSFS_DIR=$(i2c_device_sysfs_abspath 12-0031)
SCMCPLD_SYSFS_DIR=$(i2c_device_sysfs_abspath 0-003e)
GALAXY_EC_SYSFS_DIR=$(i2c_device_sysfs_abspath 0-0033)
SCM_EEPROM_SYSFS_DIR=$(i2c_device_sysfs_abspath 0-0052)
MB_EEPROM_SYSFS_DIR=$(i2c_device_sysfs_abspath 6-0051)
SCM_EEPROM="${SCM_EEPROM_SYSFS_DIR}/eeprom"
MB_EEPROM="${MB_EEPROM_SYSFS_DIR}/eeprom"
PWR_MAIN_SYSFS="${SYSCPLD_SYSFS_DIR}/pwr_main_n"
SCM_PRESENT_SYSFS="${SYSCPLD_SYSFS_DIR}/micro_srv_present"
PWR_BOARD_VER="${SYSCPLD_SYSFS_DIR}/board_ver"
SLOTID_SYSFS="${SYSCPLD_SYSFS_DIR}/slotid"
PWR_USRV_SYSFS="${SCMCPLD_SYSFS_DIR}/pwr_come_en"
repower=0

wedge_iso_buf_enable() {
    # TODO, no isolation buffer
    return 0
}

wedge_iso_buf_disable() {
    # TODO, no isolation buffer
    return 0
}

wedge_is_us_on() {
    local val n retries prog
    if [ $# -gt 0 ]; then
        retries="$1"
    else
        retries=1
    fi
    if [ $# -gt 1 ]; then
        prog="$2"
    else
        prog=""
    fi
    if [ $# -gt 2 ]; then
        default=$3              # value 0 means defaul is 'ON'
    else
        default=1
    fi
    #val=$(cat $PWR_USRV_SYSFS 2> /dev/null | head -n 1)
	((val=$(i2cget -f -y 0 0x3e 0x10 2> /dev/null | head -n 1)))
    if [ -z "$val" ]; then
        return $default
    elif [ `expr $val % 2` == "1" ]; then
        return 0            # powered on
    else
        return 1
    fi
}

wedge_board_type() {
    echo 'Galaxy100'
}

wedge_slot_id() {
    printf "%d\n" $(cat $SLOTID_SYSFS)
}

wedge_board_rev() {
    local val
    val=$(cat $PWR_BOARD_VER 2> /dev/null | head -n 1)
    echo $val
}

# Should we enable OOB interface or not
wedge_should_enable_oob() {
    # wedge100 uses BMC MAC since beginning
    return -1
}

galaxy100_scm_is_present() {
	#check scm if is present
	present=$(cat $SCM_PRESENT_SYSFS | head -n 1)
	if [ "$present" != "0x0" ]; then
		return 1
	fi
	return 0
}

wedge_power_on_board() {
    local val present
    # power on main power, uServer power
    val=$(cat $PWR_MAIN_SYSFS | head -n 1)
    if [ "$val" != "0x1" ]; then
        echo 1 > $PWR_MAIN_SYSFS
        sleep 2
    fi
}

wedge_power_off_board() {
    # power off main power, uServer power
    echo 0 > $PWR_MAIN_SYSFS
    sleep 2
}

come_recovery() {
	#repeater config
	repeater_config
	KR10G_repeater_config
	wedge_power_on_board
	#disable the I2C buffer to EC first
	i2cset -f -y 0 0x3e 0x18 0x07 2> /dev/null
	sleep 1
	i2cset -f -y 0 0x3e 0x10 0xfd 2> /dev/null
	usleep 11000
	i2cset -f -y 0 0x3e 0x0b 0xff 2> /dev/null
	sleep 15
	i2cset -f -y 0 0x3e 0x0b 0xfe 2> /dev/null
	usleep 11000
	i2cset -f -y 0 0x3e 0x10 0xfe 2> /dev/null
	sleep 10
	i2cset -f -y 0 0x3e 0x10 0xff 2> /dev/null
	usleep 11000
	#enable I2c buffer to EC
	i2cset -f -y 0 0x3e 0x18 0x01 2> /dev/null

	return 0
}

restore_us_com() {
	repeater_config
	KR10G_repeater_config
	wedge_power_on_board
	#reset LPC bridge
	i2cset -f -y 0 0x3e 0x31 0x0 2> /dev/null
	usleep 10000
	i2cset -f -y 0 0x3e 0x31 0x1 2> /dev/null

	i2cset -f -y 0 0x3e 0x10 0xff 2> /dev/null
	#enable I2c buffer to EC
	i2cset -f -y 0 0x3e 0x18 0x01 2> /dev/null
}

get_power_flag() {
	return $repower
}
set_power_flag() {
	repower=$1
}

i2c_write() {
	local count=0
	while [ $count -lt 10 ]; do
		i2cset -f -y $1 $2 $3 $4
		if [ $? -eq 0 ]; then
			return 0
		fi
		count=$(($count+1))
		usleep 11000
	done
	return -1
}

i2c_read() {
	local count=0
	while [ $count -lt 10 ]; do
		temp=`i2cget -f -y $1 $2 $3`
		if [ $? -eq 0 ]; then
			return $(($temp))
		fi
		count=$(($count+1))
		usleep 11000
	done
	return -1
}
#$1: bus
#$2: addr
#$3: reg
#$4: value
#$5: mask
i2c_write_verify() {
	count=0
	while [ $count -lt 10 ]; do
		#echo "i2c write $1 $2 $3 $4"
		i2c_write $1 $2 $3 $4 2> /dev/null
		if [ $? -eq 255 ]; then
			count=$(($count+1))
			continue
		fi
		((val=$4))
		((mask=$5))
		#echo -n "i2c read $1 $2 $3  "
		i2c_read $1 $2 $3 2> /dev/null
		temp=$?
		#echo -n "=$temp val=$val    "
		if [ $temp -eq 255 ]; then
			count=$(($count+1))
			continue
		fi
		((ret=temp))
		#echo -n "ret=$ret  mask=$mask  "
		if (((($ret & $mask)) == (($val)))); then
			#echo "equal"
			return 0
		fi
		count=$(($count+1))
	done
	#echo "Write bus $1 addr $2 reg $3 value $4 error!"
	return 1
}
repeater_config() {
	((val=$(i2cget -f -y 12 0x31 0x3 2> /dev/null | head -n 1)))
	((left=$(i2cget -f -y 12 0x31 0x5 2> /dev/null | head -n 1)))
	if [ $val -lt 8  -a $left -eq 0 ] || [ $val -ge 8 ]; then
		i2c_write_verify 0 0x58 0x01 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x0a 0x0 0x0
		usleep 11000
		i2c_write_verify 0 0x58 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x2c 0x00 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x33 0x00 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x3a 0x00 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x41 0x00 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x2d 0xa8 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x34 0xa8 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x3b 0xa9 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x42 0xa9 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x2e 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x35 0x01 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x3c 0x02 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x43 0x02 0x1f
		usleep 11000

		i2c_write_verify 0 0x58 0x0f 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x16 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x1d 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x24 0x0 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x10 0xaf 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x17 0xaf 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x1e 0xaf 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x25 0xaf 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x11 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x18 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x1f 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x26 0x0 0x1f
		usleep 11000
	else

		i2c_write_verify 0 0x58 0x01 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x0a 0x0 0x0
		usleep 11000
		i2c_write_verify 0 0x58 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x2c 0x04 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x33 0x04 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x3a 0x00 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x41 0x00 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x2d 0xab 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x34 0xab 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x3b 0xab 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x42 0xab 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x2e 0x01 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x35 0x01 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x3c 0x02 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x43 0x02 0x1f
		usleep 11000

		i2c_write_verify 0 0x58 0x0f 0x01 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x16 0x01 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x1d 0x01 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x24 0x01 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x10 0xaf 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x17 0xaf 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x1e 0xaf 0xff
		usleep 11000
		i2c_write_verify 0 0x58 0x25 0xaf 0xff
		usleep 11000

		i2c_write_verify 0 0x58 0x11 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x18 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x1f 0x0 0x1f
		usleep 11000
		i2c_write_verify 0 0x58 0x26 0x0 0x1f
		usleep 11000
	fi
}

KR10G_repeater_config() {
	((val=$(i2cget -f -y 12 0x31 0x3 2> /dev/null | head -n 1)))
	((left=$(i2cget -f -y 12 0x31 0x5 2> /dev/null | head -n 1)))
	if [ $val -lt 8  -a $left -eq 0 ] || [ $val -ge 8 ]; then
		i2c_write_verify 0 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x0f 0x01 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x11 0x02 0x1f
		usleep 11000
		i2c_write_verify 0 0x59 0x23 0x04 0xff
		usleep 11000

		i2c_write_verify 0 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x16 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x18 0x02 0x1f
		usleep 11000
		i2c_write_verify 0 0x59 0x2d 0x04 0xff
		usleep 11000

		i2c_write_verify 1 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x0f 0x02 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x11 0x02 0x1f
		usleep 11000
		i2c_write_verify 1 0x59 0x23 0x04 0xff
		usleep 11000

		i2c_write_verify 1 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x16 0x04 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x18 0x02 0x1f
		usleep 11000
		i2c_write_verify 1 0x59 0x2d 0x04 0xff
		usleep 11000
	else
		i2c_write_verify 0 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x0f 0x01 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x11 0x04 0x1f
		usleep 11000
		i2c_write_verify 0 0x59 0x23 0x04 0xff
		usleep 11000

		i2c_write_verify 0 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x16 0x0 0xff
		usleep 11000
		i2c_write_verify 0 0x59 0x18 0x04 0x1f
		usleep 11000
		i2c_write_verify 0 0x59 0x2d 0x04 0xff
		usleep 11000

		i2c_write_verify 1 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x0f 0x02 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x11 0x02 0x1f
		usleep 11000
		i2c_write_verify 1 0x59 0x23 0x04 0xff
		usleep 11000

		i2c_write_verify 1 0x59 0x06 0x18 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x16 0x0 0xff
		usleep 11000
		i2c_write_verify 1 0x59 0x18 0x02 0x1f
		usleep 11000
		i2c_write_verify 1 0x59 0x2d 0x04 0xff
		usleep 11000
	fi
}


#!/bin/bash
#
# Copyright 2017-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
#

#
# A simple script to flush i2c clock signals to recover from I2C stuck issue.
#

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

#
# Initialize variables, and define a helper function
#

iteration=0
rc=0
I2C_CMD="${SYSCPLD_SYSFS_DIR}/i2c_sta_rst_raw"

force_stop() {
	echo "Sending out START condition through I2C bus"
	echo 0x07 > $I2C_CMD
  usleep 5000
  echo 0x0F > $I2C_CMD
  usleep 5000
}

#
# Step 1. Hold both SDA and SCL high
#
echo "Holding SDA and SCL high"
echo 0x0F > $I2C_CMD

#
# Step 2. Toggle SCL up to 10 times, until bus recovers
#
while [ $iteration -lt 10 ];
do
	echo "Toggling SCL for clock flushing. Iteration : $iteration"
  # SCL low
	echo 0x0B > $I2C_CMD
  usleep 5000
  # SCL high
	echo 0x0F > $I2C_CMD
	usleep 5000
  # Check if bus recovered by looking at bit [5:4]
	rc=$(cat $I2C_CMD | head -n 1 | awk -F "0x" '{print $2}')
	if (($rc & 0x30)); then
		echo "Bus recovery successful"
		rc=0
		break
	fi
	echo "I2C BUS not yet recovered"
	iteration=$(($iteration+1))
done

#
# Step 3. Handle the result, and run force_stop if asked to do so
#         Setting return code to -1, if recovery is not successful
#
if [ $(($rc)) -ne 0 ]; then
	echo "Bus recovery failure"
  rc=-1
fi
if [ $# -eq 1 ] && [ $1 == "-f" ]; then
	force_stop
fi

#
# Step 4. Put the I2C block in normal operation mode
#
echo "Putting I2C master back to normal operation mode"
echo 0x0D > $I2C_CMD

#
# Step 5. Finally, toggle reset CP2112, no matter recovery successful or not
#
echo "Toggle resetting CP2112"
/bin/bash /usr/local/bin/reset_cp2112.sh

#
# Step 6. Exit with the return code
#
echo "Exiting with rc $rc"
exit $rc


#!/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
#

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

EC_VERSION=$(head -n 1 "${GALAXY_EC_SYSFS_DIR}/version")

r=$(echo "$EC_VERSION" | awk '{print substr ($1, 2, 2)}')
e=$(echo "$EC_VERSION" | awk '{print substr ($1, 5, 2)}')

released_date=$(head -n 1 "${GALAXY_EC_SYSFS_DIR}/build_date_input")

echo "EC Released Version: R$(printf '%02d' $r).E$(printf '%02d' $e)"
echo "EC Released Date: $released_date"


#!/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.
#

### BEGIN INIT INFO
# Provides:          power-on
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Power on micro-server
### END INIT INFO
. /usr/local/bin/openbmc-utils.sh

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

devmem_clear_bit 0x1e6e2080 20
devmem_clear_bit 0x1e6e208c 14

i2cset -f -y 12 0x31 0x06 0x4 2>/dev/null #sysled light blue
i2cset -f -y 0 0x3e 0x18 0x1 2>/dev/null #open EC buffer

devmem 0x1e78a044 32 0x77776f05 #increase thDDAT

/usr/local/bin/us_refresh.sh &

val=$(i2cget -f -y 12 0x31 0x22 2> /dev/null)
if [ "$val" = "0x11" ] ; then
	i2cset -f -y 12 0x31 0x22 0x0
	soft_reboot=0
else
	soft_reboot=1
	echo "System boot by software reboot"
fi

if galaxy100_scm_is_present && [ $soft_reboot -eq 0 ] ; then
	# First power on TH, and if Panther+ is used,
	# provide standby power to Panther+.
	repeater_config
	wedge_power_on_board

	echo -n "Checking microserver present status ... "
	if wedge_is_us_on 10 "."; then
		echo "on"
	    on=1
	    # microsever reset
	    wedge_power.sh reset
	else
	    echo "off"
		on=0
	fi

	if [ $on -eq 0 ]; then
	    # Power on now
	    wedge_power.sh on -f
	fi
	KR10G_repeater_config
elif ! galaxy100_scm_is_present ; then
	echo "SCM isn't present..."
fi

if galaxy100_scm_is_present ; then
	echo -n "SCM CPLD access "
	ver=$(i2cget -f -y 0 0x3e 0x1 2> /dev/null)
	if [ $? -ne 0 ] || [ $ver = "0xff" ]; then
		echo "[Fail]"
	else
		echo "[OK]"
	fi
	if [ $soft_reboot -eq 1 ]; then
		echo -n "Checking microserver present status ... "
		if wedge_is_us_on 10 "."; then
			echo "on"
		    on=1
		else
		    echo "off"
			on=0
		fi
		if [ $on -eq 0 ]; then
			repeater_config
			wedge_power_on_board
		    # Power on now
		    wedge_power.sh on -f
			KR10G_repeater_config
			#reset LPC bridge
			i2cset -f -y 0 0x3e 0x31 0x0 2> /dev/null
			usleep 10000
			i2cset -f -y 0 0x3e 0x31 0x1 2> /dev/null
		fi

		mac=$(/usr/local/bin/wedge_us_mac.sh)
		echo -n "COM-e MAC: $mac "
		if [ $mac = "00:00:00:00:00:00" ]; then
			echo "[Warning]"
		else
			echo "[OK]"
		fi
		/usr/local/bin/repeater_verify.sh
	fi
fi


#!/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.
#

lc_qsfp_cpld_ver() {
  card_type=$(weutil  | grep 'Product Name' | awk -F ':' '{print $2}')
  card_type=${card_type,,}

  major_rev=0
  sub_rev=0
  if [ $card_type == 'lc' ] || [ $card_type == 'galaxy-lc' ]; then
    #QSFP CPLD version
    ((val=$(i2cget -f -y 12 0x31 0x3 2> /dev/null | head -n 1)))
    if [ $val -lt 8 ]; then
      old=$((`i2cget -f -y 12 0x74 0x01`))
      if [ $old -eq 9 ] || [ $old -eq 12 ] || [ $old -eq 13 ]; then
        i2cset -f -y 12 0x74 0x01 0x0
      elif [ $old -eq 10 ] || [ $old -eq 14 ] || [ $old -eq 15 ]; then
        i2cset -f -y 12 0x74 0x01 0x1
      elif [ $old -eq 0 ] || [ $old -eq 1 ] || [ $old -eq 5 ]; then
        i2cset -f -y 12 0x74 0x01 0x4
      elif [ $old -eq 2 ] || [ $old -eq 3 ] || [ $old -eq 6 ]; then
        i2cset -f -y 12 0x74 0x01 0x5
      fi
      temp=$((`i2cget -f -y 12 0x39 0x01 2> /dev/null`))
      major_rev=$(($temp & 0x3f))
      sub_rev=$(i2cget -f -y 12 0x39 0x02 2> /dev/null | awk -F "0x" '{print $2}')
    fi
  fi
    printf "%02x,%02d\n" ${major_rev} ${sub_rev}
}

lc_qsfp_cpld_ver


#!/bin/bash

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

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

i2c_read() {
	local count=0
	while [ $count -lt 10 ]; do
		temp=`i2cget -f -y $1 $2 $3`
		if [ $? -eq 0 ]; then
			return $(($temp))
		fi
		count=$(($count+1))
		usleep 11000
	done
	return -1
}

#$1: bus
#$2: addr
#$3: reg
#$4: value
#$5: mask
i2c_read_verify() {
	((val=$4))
	((mask=$5))
	#echo -n "i2c read $1 $2 $3  "
	i2c_read $1 $2 $3 2> /dev/null
	temp=$?
	printf "Verify bus:%d addr:0x%02x reg:0x%02x value:0x%02x (expect 0x%02x)   " $1 $2 $3 $(($temp&$mask)) $4
	#echo -n "=$temp val=$val    "
	if [ $temp -eq 255 ]; then
		echo -e "\033[41;37m[FAIL]\033[0m"
		return 1
	fi
	((ret=temp))
	#echo -n "ret=$ret  mask=$mask  "
	if (((($ret & $mask)) == (($val)))); then
		echo -e "\033[42;37m[PASS]\033[0m"
		return 0
	else
		echo -e "\033[41;37m[FAIL]\033[0m"
		return 1
	fi
	return 1
}

repeater_config() {
	((val=$(i2cget -f -y 12 0x31 0x3 2> /dev/null | head -n 1)))
	((left=$(i2cget -f -y 12 0x31 0x5 2> /dev/null | head -n 1)))
	if [ $val -lt 8  -a $left -eq 0 ] || [ $val -ge 8 ]; then
		i2c_read_verify 0 0x58 0x01 0x0 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x0a 0x0 0x0
		usleep 11000
		i2c_read_verify 0 0x58 0x06 0x18 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x2c 0x00 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x33 0x00 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x3a 0x00 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x41 0x00 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x2d 0xa8 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x34 0xa8 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x3b 0xa9 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x42 0xa9 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x2e 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x35 0x01 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x3c 0x02 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x43 0x02 0x1f
		usleep 11000

		i2c_read_verify 0 0x58 0x0f 0x0 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x16 0x0 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x1d 0x0 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x24 0x0 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x10 0xaf 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x17 0xaf 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x1e 0xaf 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x25 0xaf 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x11 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x18 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x1f 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x26 0x0 0x1f
		usleep 11000
	else

		i2c_read_verify 0 0x58 0x01 0x0 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x0a 0x0 0x0
		usleep 11000
		i2c_read_verify 0 0x58 0x06 0x18 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x2c 0x04 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x33 0x04 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x3a 0x00 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x41 0x00 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x2d 0xab 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x34 0xab 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x3b 0xab 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x42 0xab 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x2e 0x01 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x35 0x01 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x3c 0x02 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x43 0x02 0x1f
		usleep 11000

		i2c_read_verify 0 0x58 0x0f 0x01 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x16 0x01 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x1d 0x01 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x24 0x01 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x10 0xaf 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x17 0xaf 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x1e 0xaf 0xff
		usleep 11000
		i2c_read_verify 0 0x58 0x25 0xaf 0xff
		usleep 11000

		i2c_read_verify 0 0x58 0x11 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x18 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x1f 0x0 0x1f
		usleep 11000
		i2c_read_verify 0 0x58 0x26 0x0 0x1f
		usleep 11000
	fi
}

repeater_config


#!/bin/bash
#
# Copyright 2017-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

#
# A simple script to toggle reset CP2112 device
#

CP2112_RESET_CMD="${SYSCPLD_SYSFS_DIR}/cp2112_rst"

#
# Toggle reset CP2112, with enough time in-between for chip status settle down
#
echo 0x0 > $CP2112_RESET_CMD
usleep 50000
echo 0x1 > $CP2112_RESET_CMD
usleep 50000

#
# If the execution reached here, that means all writes went through
# return 0.
#
exit 0


#!/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
#

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

rev=$(head -n 1 "${SCMCPLD_SYSFS_DIR}/cpld_rev")
sub_rev=$(head -n 1 "${SCMCPLD_SYSFS_DIR}/cpld_sub_rev")

echo $(($rev)).$(($sub_rev))


#!/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.
#

((val=$(i2cget -f -y 12 0x31 0x3 2> /dev/null | head -n 1)))
if [ $val -ge 8 ]; then
	mv /etc/sensors.d/galaxy100_fab.conf /etc/sensors.d/galaxy100.conf
	rm /etc/sensors.d/galaxy100_lc.conf
else
	mv /etc/sensors.d/galaxy100_lc.conf /etc/sensors.d/galaxy100.conf
	rm /etc/sensors.d/galaxy100_fab.conf
fi


#!/bin/sh
#
# Copyright 2018-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

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

# Bus 0
i2c_device_add 0 0x10 adm1278
i2c_device_add 0 0x18 ds110df111
i2c_device_add 0 0x21 pca9534
i2c_device_add 0 0x33 galaxy100_ec
i2c_device_add 0 0x3e scmcpld
i2c_device_add 0 0x54 24c02
i2c_device_add 0 0x52 24c02

# Bus 1
i2c_device_add 1 0x18 ds110df111
i2c_device_add 1 0x70 IR3581
i2c_device_add 1 0x72 IR3584

# Bus 2
i2c_device_add 2 0x40 pwr1014a

# Bus 5
i2c_device_add 5 0x20 slb9645tt

# Bus 6
i2c_device_add 6 0x27 pcf8574
i2c_device_add 6 0x51 24c64

# Bus 9
i2c_device_add 9 0x50 24c02

# Bus 11
i2c_device_add 11 0x10 adm1278

# Bus 12
i2c_device_add 12 0x31 syscpld
i2c_device_add 12 0x39 qsfp_cpld

#
# setup ADC channels
# This step is only needed in legacy kernel (v4.1), because the ADC
# controller is configured in device tree in the latest kernel.
#
if uname -r | grep "4\.1\.*" > /dev/null 2>&1; then
    modprobe ast_adc
    # channel 3: r1:  2.0K; r2:  1.0K; v2: 0mv
    # channel 4: r1:  4.7K; r2:  1.0K; v2: 0mv
    # channel 8: r1:  1.0K; r2:  1.0K; v2: 0mv
    # channel 9: r1:  1.0K; r2:  1.0K; v2: 0mv
    ast_config_adc 3  2 1 0
    ast_config_adc 4  47 10 0
    ast_config_adc 8  1 1 0
    ast_config_adc 9  1 1 0
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
#

usage() {
    echo "$0 <connect | disconnect>"
}

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

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

if [ "$1" == "connect" ]; then
    VALUE=1
elif [ "$1" == "disconnect" ]; then
    VALUE=0
else
    usage
    exit 1
fi

#reset MUX that uS console connects to UART1.
i2cset -f -y 0 0x3e 0x30 0xfe 2>/dev/null
usleep 100000
i2cset -f -y 0 0x3e 0x30 0xff 2>/dev/null


#!/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.
#

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

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

# Because the voltage leak from uS COM pins could cause uS to struck when
# transitting from S5 to S0, we will need to explicitely pull down uS COM
# pins before powering off/reset and restoring COM pins after

TH_SHUTDOWN_VOL=949
TH_RESTORE_VOL=1028
th_shutdown=0

restore_us_com() {
    repeater_config
    KR10G_repeater_config
    wedge_power_on_board
    i2cset -f -y 0 0x3e 0x10 0xff 2> /dev/null
    logger "Power on micro-server after inserting SCM"
}

lm57_monitor() {
    vol=$(cat /sys/devices/platform/ast_adc.0/in0_input 2> /dev/null)
    if [ $vol -le ${TH_SHUTDOWN_VOL} ] && [ $th_shutdown -eq 0 ] ; then
        echo "Shut down TH power by LM57 over temperature..."
        echo "ADC=$vol, standard=$TH_SHUTDOWN_VOL"
        wedge_power_off_board
        th_shutdown=1
        logger "Power off micro-server due to LM57 over temperature (${vol} vs ${TH_SHUTDOWN_VOL})"
    fi
    if [ $vol -ge ${TH_RESTORE_VOL} ] && [ $th_shutdown -eq 1 ] ; then
        echo "restore TH power by LM57 temperature drop..."
        echo "ADC=$vol, standard=$TH_RESTORE_VOL"
        wedge_power_on_board
        th_shutdown=0
        logger "Power on micro-server after LM57 temperature drop (${vol} vs ${TH_SHUTDOWN_VOL})"
    fi
    cpld_val=$(i2cget -f -y 12 0x31 0x15 2> /dev/null)
    if [ $vol -ge ${TH_RESTORE_VOL} ] && [ "$cpld_val" = "0x11" ] ; then
        echo "restore TH power which shutdown by CPLD..."
        i2cset -f -y 12 0x31 0x15 0x0 2> /dev/null
        wedge_power_on_board
        th_shutdown=0
        logger "Power on micro-server caused by CPLD (${cpld_val}, ${vol} vs ${TH_SHUTDOWN_VOL})"
    fi
}

val=0
ret=0
echo 1 > /sys/devices/platform/ast_adc.0/adc0_en
come_check=0
wait_count=0
power_ok=0
scm_removed=0
th_reset_delay=0
((card_val=$(i2cget -f -y 12 0x31 0x0 2> /dev/null | head -n 1)))
card_val=$(($card_val % 16))
if [ $card_val -le 1 ]; then
    #EVT or DVT1 board
    TH_SHUTDOWN_VOL=1296
    TH_RESTORE_VOL=1402
fi
while true; do
    galaxy100_scm_is_present
    ret=$?
    if [ $ret -eq 0 ] && [ $val -eq 1 ]; then
        echo "SCM is inserted, Power ON!"
		    come_check=1
		    power_ok=1
		    wait_count=0
		    scm_removed=0
		    th_reset_delay=0
	  elif [ $ret -eq 0 ] && [ $come_check -eq 1 ] && [ $power_ok -eq 0 ]; then
		    ((temp=$(i2cget -f -y 0 0x3e 0x12 2> /dev/null | head -n 1)))
		    if [ $temp != 15 ] ; then
			      echo "Power on COM-e fail, recovery..."
			      come_recovery
			      wait_count=0
			      power_ok=0
			      come_check=0
			      logger "Recovered COMe failed to power on"
		    else
			      come_check=0
			      power_ok=1
			      echo "Power on COM-e OK"
		    fi
	  elif [ $ret -eq 1 -a $val -eq 0 ] || [ $scm_removed -eq 1 ]; then
		    scm_removed=1
		    if [ $th_reset_delay -ge 20 ]; then
			      #reset TH
			      i2cset -f -y 12 0x31 0x12 0xf2 2> /dev/null
			      usleep 500000
			      i2cset -f -y 12 0x31 0x12 0xf3 2> /dev/null
			      scm_remove=0
			      logger "Reset Tomahawk after removing SCM"
		    fi
		    th_reset_delay=$(($th_reset_delay + 1))
	  else
		    wait_count=$(($wait_count + 1))
		    if [ $ret -eq 0 ] && [ $wait_count -ge 30 ] && [ $come_check -eq 1 ] && [ $power_ok -eq 1 ]; then
			      if [ $wait_count -eq 30 ]; then
				        #after 15s, power on
				        restore_us_com
			      elif [ $wait_count -ge 70 ]; then
				        #after 20s, check status
				        power_ok=0
			      fi
		    fi
		    if [ $wait_count -ge 360 ]; then
			      wait_count=0
			      if [ $power_ok -eq 0 ]; then
				        #echo "Check again"
				        come_check=1
			      fi
		    fi
    fi
    val=$ret
    lm57_monitor
    usleep 500000
done


#!/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.
#

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

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

# Because the voltage leak from uS COM pins could cause uS to struck when
# transitting from S5 to S0, we will need to explicitely pull down uS COM
# pins before powering off/reset and restoring COM pins after

lc_r=0
((val=$(i2cget -f -y 12 0x31 0x3 2> /dev/null | head -n 1)))
((right=$(i2cget -f -y 12 0x31 0x5 2> /dev/null | head -n 1)))
if [ $val -lt 8  -a $right -eq 1 ]; then
	lc_r=1
fi
lc_r_rec_msg() {
	if [ $lc_r -eq 1 ]; then
		i2cset -f -y 12 0x31 0x28 0x0 2> /dev/null
		tmp=$(i2cget -f -y 12 0x31 0x28 2> /dev/null)
		val=$(($tmp & 0x70))
		tmp2=$(i2cget -f -y 12 0x31 0x28 2> /dev/null) #double check
		if [ $val -eq $((0x50)) -a $tmp = $tmp2 ]; then
			echo "Receive msg to power on COMe because of SCM CPLD upgrading"
			i2cset -f -y 12 0x31 0x28 0x05 2> /dev/null
			#power off COMe
			#i2cset -f -y 0 0x3e 0x10 0xfd 2> /dev/null
			#sleep 2
			#i2cset -f -y 0 0x3e 0x10 0xfe 2> /dev/null

			#reset TH
			#i2cset -f -y 12 0x31 0x12 0xf2 2> /dev/null
			#sleep 1
			#i2cset -f -y 12 0x31 0x12 0xf3 2> /dev/null

			i2cset -f -y 12 0x31 0x10 0xfd

			power_status=1
			count=0
			delay_flag=0
		fi
	fi
}

power_status=0
count=0
delay_flag=0
while true; do
	lc_r_rec_msg
	if [ $power_status -eq 1 -a $delay_flag -eq 1 ]; then
		i2cset -f -y 12 0x31 0x10 0xff
		restore_us_com
		power_status=2
	elif [ $power_status -eq 2 -a $delay_flag -eq 2 ]; then
		((temp=$(i2cget -f -y 0 0x3e 0x12 2> /dev/null | head -n 1)))
		if [ $temp != 15 ] ; then
			echo "Power on COM-e fail, recovery..."
			come_recovery
		else
			echo "Power on COM-e OK"
			power_status=0
			delay_flag=0
		fi
	fi
	if [ $power_status -ne 0 ]; then
		if [ $count -eq 30 ]; then
			delay_flag=1
		elif [ $count -eq 70 ]; then
			delay_flag=2
		elif [ $count -ge 430 ]; then
			delay_flag=2
			count=71
		else
			delay_flag=0
		fi
		count=$(($count+1))
	fi
	usleep 500000
done


#!/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.
#
#

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

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

prog="$0"

PWR_SYSTEM_SYSFS="${SYSCPLD_SYSFS_DIR}/pwr_cyc_all_n"
#PWR_USRV_RST_SYSFS="${SCMCPLD_SYSFS_DIR}/come_rst_n"
ALT_SYSRESET_SYSFS="/sys/bus/i2c/drivers/pwr1014a/2-0040/mod_hard_powercycle"

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 wedge system ungracefully"
    echo
}

do_status() {
    echo -n "Microserver power is "
    if wedge_is_us_on; then
        echo "on"
    else
        echo "off"
    fi
    return 0
}

do_on_com_e() {
    #echo 1 > $PWR_USRV_SYSFS
    i2cset -f -y 0 0x3e 0x10 0xff 2> /dev/null
    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 10 "."; then
            echo " Already on. Skip!"
            return 1
        fi
    fi

    # power on sequence
    do_on_com_e
    ret=$?
    if [ $ret -eq 0 ]; then
        #enable I2c buffer to EC
        i2cset -f -y 0 0x3e 0x18 0x01 2> /dev/null
        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_SYSFS
    i2cset -f -y 0 0x3e 0x10 0xfd 2> /dev/null
    sleep 15
    i2cset -f -y 0 0x3e 0x10 0xfe 2> /dev/null
    sleep 10
    return 0
}

do_off() {
    local ret
    echo -n "Power off microserver(about 30s) ..."
    #disable the I2C buffer to EC first
    i2cset -f -y 0 0x3e 0x18 0x07 2> /dev/null
    sleep 1
    do_off_com_e
    ret=$?
    if [ $ret -eq 0 ]; then
        echo " Done"
        logger "Successfully power off micro-server"
    else
        echo " Failed"
        logger "Failed to power off micro-server"
    fi
    return $ret
}

do_reset() {
    local system opt
    system=0
    while getopts "s" opt; do
        case $opt in
            s)
                system=1
                ;;
            *)
                usage
                exit -1
                ;;
        esac
    done
    if [ $system -eq 1 ]; then
        logger "Power reset the whole system ..."
        echo -n "Power reset whole system ..."
        sleep 1
        echo 0 > $PWR_SYSTEM_SYSFS
        # In case the previous reset attempt fails, we try the alternative
        # way - reset the entire module through PWR1014A
        logger -s "wedge_power.sh reset -s through CPLD failed. Using pwr1014a instead."
        # Give rsyslog enough time to flush the log
        sleep 5
        echo 0 > $ALT_SYSRESET_SYSFS
        sleep 1
    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
        echo -n "Power reset microserver ..."
        #echo 0 > $PWR_USRV_RST_SYSFS
        i2cset -f -y 0 0x3e 0x11 0x0 2> /dev/null
        sleep 1
        #echo 1 > $PWR_USRV_RST_SYSFS
        i2cset -f -y 0 0x3e 0x11 0x1 2> /dev/null
        logger "Successfully power reset micro-server"
    fi
    echo " Done"
    return 0
}

do_recovery() {
    local ret
    echo -n "Power on microserver recovery(about 30s) ..."
    come_recovery
    echo " Done"
    logger "Successfully power recover micro-server"
    return 0
}

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

command="$1"
shift

case "$command" in
    status)
        do_status $@
        ;;
    on)
        do_on $@
        ;;
    off)
        do_off $@
        ;;
    reset)
        do_reset $@
        ;;
    recovery)
        do_recovery $@
        ;;
    *)
        usage
        exit -1
        ;;
esac

exit $?


#!/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
#

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

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

if ! wedge_is_us_on; then
    echo "Cannot retrive microserver MAC when microserver is powered off." 1>&2
    exit -2
fi

count=0
while [ $count -lt 10 ]
do
  mac=$(cat "${GALAXY_EC_SYSFS_DIR}/mac_addr")

	if [ -n "$mac" -a "${mac/X/}" = "${mac}" ]; then
	    echo $mac
	    exit 0
	fi
	count=$(($count + 1))
	sleep 1
done

if [ $count -ge 10 ]; then
	echo "Cannot find out the microserver MAC" 1>&2
	exit -1
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:          setup-watchdogd
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Set watchdogd handler
### END INIT INFO

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

# Disable the dual boot watch dog
devmem_clear_bit 0x1e78502c 0

#
# "watchdogd" is only needed in legacy kernel (v4.1), and the watchdog can
# be automatically kicked by a kernel thread in the latest kernel.
#
if uname -r | grep "4\.1\.*" > /dev/null 2>&1; then
    /usr/bin/watchdogd.sh > /dev/null 2>&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
#

function watchdog_handler
{
  while true; do
    /usr/local/bin/wdtcli kick
    sleep 5 # secs
  done
}

echo "Watchdog pinging enabled"
watchdog_handler


#!/bin/bash

# NC-SI version (0x15) field 52 contains the IANA of the vendor.
# If this is 00000000, then we are running in QEMU and there is no point
# to wait.
if [[ "$(ncsi-util 0x15 | grep 52:)" == *"0x00 0x00 0x00 0x00"* ]]; then
    exit 0
fi

logger "Update eth0 IPv6 link local address after NC-SI MAC address configured"

# shellcheck disable=SC2086
mac_to_ll() {
  IFS=':'; set $1; unset IFS
  echo "fe80::$(printf %x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6" | \
    sed -E 's/:0+/:/g; s/:{3,}/::/; s/:$/:0/'
}

exp_ll=
ll=

for _ in {1..30}; do
  # wait getting address from NC-SI
  if [ "$(cat /sys/class/net/eth0/addr_assign_type)" = "3" ]; then
    exp_ll=$(mac_to_ll "$(cat /sys/class/net/eth0/address)")
    ll=$(ip -6 addr show dev eth0 scope link | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d')
    if [ "$ll" = "$exp_ll" ]; then
      break
    fi
    # re-generate link-local address
    ip -6 addr flush dev eth0 scope link
    echo 1 > /proc/sys/net/ipv6/conf/eth0/addr_gen_mode
    echo 0 > /proc/sys/net/ipv6/conf/eth0/addr_gen_mode
    break;
  fi
  sleep 1
done

if [ "$ll" != "$exp_ll" ]; then
  for _ in {1..100}; do
    usleep 10000
    ll=$(ip -6 addr show dev eth0 scope link | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d')
    if [ "$ll" = "$exp_ll" ]; then
      break;
    fi
  done
fi

logger "restart eth0 after MAC and Linklock addr update"
ifdown eth0
sleep 1
ifup eth0 &


#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
### BEGIN INIT INFO
# Provides:          setup-bic-cached
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Set Cachcing for Bridge IC info
### END INIT INFO

echo "Setup Caching for Bridge IC info.."
/usr/bin/bic-cached > /dev/null 2>&1 &

echo "done."


#!/bin/bash
. /usr/local/fbpackages/utils/ast-functions

ME_UTIL="/usr/bin/me-util"
FRUID_UTIL="/usr/local/bin/fruid-util"
FW_UTIL="/usr/bin/fw-util"
FRU_NAME=$1
INTERFACE="PECI_INTERFACE"
PCIE_INTERFACE="PECI_INTERFACE"

function is_numeric {
  if [ $(echo "$1" | grep -cE "^\-?([[:xdigit:]]+)(\.[[:xdigit:]]+)?$") -gt 0 ]; then
    return 1
  else
    return 0
  fi
}

if [ "$FRU_NAME" != "server" ]; then
  echo "FRU: $FRU_NAME is not supported"
  exit 1
fi

# File format autodump.pid (See pal_is_crashdump_ongoing()
# function definition)
PID=$$
PID_FILE="/var/run/autodump.pid"

# check if running auto dump
[ -r $PID_FILE ] && OLDPID=`cat $PID_FILE` || OLDPID=''

# Set current pid
echo $PID > $PID_FILE

# kill previous autodump if exist
if [ ! -z "$OLDPID" ] && (grep "autodump" /proc/$OLDPID/cmdline &> /dev/null) ; then
  # Check if 2nd dump is running
  if [ ! -z "$(ps | grep '{autodump.sh}' | grep "server" | grep "second\|dwr")" ]; then
    echo $OLDPID > $PID_FILE
    echo "2nd DUMP or Demoted Warm Reset DUMP is running. exit."
    exit 1
  fi

  LOG_FILE="/tmp/autodump.log"
  LOG_ARCHIVE="/mnt/data/autodump_uncompleted_server.tar.gz"
  echo -n "(uncompleted) Auto Dump End at " >> $LOG_FILE
  date >> $LOG_FILE

  tar zcf $LOG_ARCHIVE -C `dirname $LOG_FILE` `basename $LOG_FILE` && \
  rm -rf $LOG_FILE && \

  echo "kill pid $OLDPID..."
  kill -s 9 $OLDPID
  ps | grep '{dump.sh}' | grep "server" | awk '{print $1}'| xargs kill -s 9 &> /dev/null
  ps | grep 'me-util' | grep "server" | awk '{print $1}'| xargs kill -s 9 &> /dev/null
  ps | grep 'bic-util' | grep "server" | awk '{print $1}'| xargs kill -s 9 &> /dev/null
  ps | grep 'fw-util' | grep "server" | grep "version" | awk '{print $1}'| xargs kill -s 9 &> /dev/null
fi
unset OLDPID

# Set crashdump timestamp
sys_runtime=$(awk '{print $1}' /proc/uptime)
sys_runtime=$(printf "%0.f" $sys_runtime)
kv set server_crashdump $((sys_runtime+1200))

DUMP_SCRIPT="/usr/bin/crashdump/dump.sh"
CRASHDUMP_FILE="/mnt/data/crashdump_server"
CRASHDUMP_LOG_ARCHIVE="/mnt/data/crashdump_server.tar.gz"
LOG_MSG_PREFIX=""

DWR=0
SECOND_DUMP=0
DELAY_SEC=30

while test $# -gt 1
do
  case "$2" in
  --dwr)
    DWR=1
    ;;
  --now)
    DELAY_SEC=0
    ;;
  --second)
    SECOND_DUMP=1
    ;;
  *)
    echo "unknown argument $2"
    ;;
  esac
  shift
done

if [ "$DWR" == "1" ] || [ "$SECOND_DUMP" == "1" ]; then
  echo "Auto Dump after System Reset or Demoted Warm Reset"
fi

if [ "$DELAY_SEC" != "0" ]; then
  echo "Auto Dump will start after ${DELAY_SEC}s..."

  sleep ${DELAY_SEC}
fi

echo "Auto Dump for Server Started"
logger -t "ipmid" -p daemon.crit "${LOG_MSG_PREFIX}Crashdump for FRU: server started"

#HEADER LINE for the dump
$DUMP_SCRIPT "time" > $CRASHDUMP_FILE

# Get BMC version & hostname
strings /dev/mtd0 | grep 2019.04 >> $CRASHDUMP_FILE
uname -a >> $CRASHDUMP_FILE
cat /etc/issue >> $CRASHDUMP_FILE

# Get fw info
echo "Get firmware version info: " >> "$CRASHDUMP_FILE"
RES=$("$FW_UTIL" "server" "--version")
echo "$RES" >> "$CRASHDUMP_FILE"

# Get FRUID info
echo "Get FRUID Info:" >> $CRASHDUMP_FILE
RES=$($FRUID_UTIL server)
echo "$RES" >> $CRASHDUMP_FILE

# Get Device ID
echo "Get Device ID:" >> $CRASHDUMP_FILE
RES=$($ME_UTIL server 0x18 0x01)
echo "$RES" >> $CRASHDUMP_FILE
RET=$?

# if ME has response and in operational mode, PECI through ME
if [ "$RET" -eq "0" ] && [ "${RES:6:1}" == "0" ]; then
  RES=$($ME_UTIL server 0xb8 0x40 0x57 0x01 0x00 0x30 0x05 0x05 0xa1 0x00 0x00 0x00 0x00)
  RET=$?
  if [ "$RET" -eq "0" ] && [ "${RES:0:11}" == "57 01 00 40" ]; then
    INTERFACE="ME_INTERFACE"
  else
    INTERFACE="PECI_INTERFACE"
  fi
  # else use wired PECI directly
else
  # echo "Use BIC wired PECI interface due to ME abnormal"
  INTERFACE="PECI_INTERFACE"
fi
PCIE_INTERFACE=$INTERFACE

# Major Firmware Revision
REV=$(echo $RES| awk '{print $3;}')
# Check whether the first parameter is numeric or not
# If not, then it is an error message from me-util
is_numeric $(echo $RES| awk '{print $1;}')
if [ "$?" == 1 ] ;then
  Mode=$(echo $(($REV & 0x80)))
  if [ $Mode -ne 0 ] ;then
    echo "Device firmware update or Self-initialization in progress or Firmware in the recovery boot-loader mode" >> $CRASHDUMP_FILE
  fi
  # Get Self-test result
  echo "Get Self-test result:" >> $CRASHDUMP_FILE
  RES=$($ME_UTIL server 0x18 0x04)
  echo "$RES" >> $CRASHDUMP_FILE
  CC=$(echo $RES| awk '{print $1;}')
  # Check whether the first parameter is numeric or not
  # If not, then it is an error message from me-util
  is_numeric $CC
  if [ "$?" == 1 ] ;then
    if [ $CC -ne 55 ] ;then
      if [ $CC -eq 56 ] ;then
        echo "Self Test function not implemented in this controller" >> $CRASHDUMP_FILE
      elif [ $CC -eq 57 ] ;then
        echo "Corrupted or inaccessible data or devices" >> $CRASHDUMP_FILE
      elif [ $CC -eq 58 ] ;then
        echo "Fatal hardware error" >> $CRASHDUMP_FILE
      elif [ $CC -eq 80 ] ;then
        echo "PSU Monitoring service error" >> $CRASHDUMP_FILE
      elif [ $CC -eq 81 ] ;then
        echo "Firmware entered Recovery boot-loader mode" >> $CRASHDUMP_FILE
      elif [ $CC -eq 82 ] ;then
        echo "HSC Monitoring service error" >> $CRASHDUMP_FILE
      elif [ $CC -eq 83 ] ;then
        echo "Firmware entered non-UMA restricted mode of operation" >> $CRASHDUMP_FILE
      else
        echo "Unknown error" >> $CRASHDUMP_FILE
      fi
    fi
  fi

  # PCI config read is not support ME DMI interface
  RES=$($ME_UTIL server 0xb8 0x40 0x57 0x01 0x00 0x30 0x06 0x05 0x61 0x00 0x00 0x81 0x0D 0x00)
  RET=$?
  if [ "$RET" -eq "0" ] && [ "${RES:0:19}" == "Completion Code: AC" ]; then
    PCIE_INTERFACE="PECI_INTERFACE"
  fi
fi

echo "Set coreid msr interface = $INTERFACE" >> $CRASHDUMP_FILE
echo "Set pcie dwr interface = $PCIE_INTERFACE" >> $CRASHDUMP_FILE

# Sensors & sensor thresholds
echo "Sensor history at dump:" >> $CRASHDUMP_FILE 2>&1
$DUMP_SCRIPT server "sensors" >> $CRASHDUMP_FILE
echo "Sensor threshold at dump:" >> $CRASHDUMP_FILE 2>&1
$DUMP_SCRIPT server "threshold" >> $CRASHDUMP_FILE

#COREID dump
$DUMP_SCRIPT server "coreid" $INTERFACE >> $CRASHDUMP_FILE
#MSR dump
$DUMP_SCRIPT server "msr" $INTERFACE >> $CRASHDUMP_FILE
#PCIe dump
$DUMP_SCRIPT server "pcie" $PCIE_INTERFACE >> $CRASHDUMP_FILE

# only second/dwr autodump need to rename accordingly
if [ "$DWR" == "1" ] || [ "$SECOND_DUMP" == "1" ]; then
  # dwr
  $DUMP_SCRIPT server  "dwr" $PCIE_INTERFACE >> $CRASHDUMP_FILE

  # rename the archieve file based on whether dump in DWR mode or not
  if [ "$?" == "2" ]; then
    CRASHDUMP_LOG_ARCHIVE="/mnt/data/crashdump_dwr_server.tar.gz"
    LOG_MSG_PREFIX="DWR "
  else
    CRASHDUMP_LOG_ARCHIVE="/mnt/data/crashdump_second_server.tar.gz"
    LOG_MSG_PREFIX="SECOND_DUMP "
  fi
fi

echo -n "Auto Dump End at " >> $CRASHDUMP_FILE
date >> $CRASHDUMP_FILE

tar zcf $CRASHDUMP_LOG_ARCHIVE -C `dirname $CRASHDUMP_FILE` `basename $CRASHDUMP_FILE` && \
rm -rf $CRASHDUMP_FILE && \
logger -t "ipmid" -p daemon.crit "${LOG_MSG_PREFIX}Crashdump for FRU: server is generated at $CRASHDUMP_LOG_ARCHIVE"
cp -f "$CRASHDUMP_LOG_ARCHIVE" /tmp
echo "Auto Dump for Server Completed"

# Remove current pid file
rm $PID_FILE

echo "${LOG_MSG_PREFIX}Auto Dump Stored in $CRASHDUMP_LOG_ARCHIVE"
exit 0