meta-ampere: mtmitchell: add Host power control support

Support Host power control for Mt.Mitchell platform

Tested:
1. Verify if Host power ON/OFF/cycle/reset work via IPMI, Redfish and
WebUI.

Signed-off-by: Chanh Nguyen <chanh@os.amperecomputing.com>
Change-Id: Ia397866ac3aef128958d84696209ecab80d16266
diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils.bbappend b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils.bbappend
new file mode 100644
index 0000000..f325395
--- /dev/null
+++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils.bbappend
@@ -0,0 +1,14 @@
+FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
+
+INSANE_SKIP:${PN} = "already-stripped"
+
+SRC_URI:append = " \
+           file://ampere_power_util.sh \
+           file://ampere_power_on_driver_binder.sh \
+          "
+
+do_install:append() {
+    install -d ${D}/usr/sbin
+    install -m 0755 ${WORKDIR}/ampere_power_util.sh ${D}/${sbindir}/
+    install -m 0755 ${WORKDIR}/ampere_power_on_driver_binder.sh ${D}/${sbindir}/
+}
diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_on_driver_binder.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_on_driver_binder.sh
new file mode 100644
index 0000000..a1f30c2
--- /dev/null
+++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_on_driver_binder.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# Each driver include driver name and driver path
+declare -a DRIVER_NAMEs=(
+			 "107-0070"
+			 "100-0071"
+			 "101-0071"
+			 "102-0071"
+			 "103-0071"
+			 "104-0071"
+			 "100-0050"
+			 "101-0050"
+			 "102-0050"
+			 "100-004c"
+			 "101-004c"
+			 "102-004c"
+			)
+# Driver path should include / at the end
+declare -a DRIVER_PATHs=(
+			 "/sys/bus/i2c/drivers/pca954x/"
+			 "/sys/bus/i2c/drivers/pca954x/"
+			 "/sys/bus/i2c/drivers/pca954x/"
+			 "/sys/bus/i2c/drivers/pca954x/"
+			 "/sys/bus/i2c/drivers/pca954x/"
+			 "/sys/bus/i2c/drivers/pca954x/"
+			 "/sys/bus/i2c/drivers/at24/"
+			 "/sys/bus/i2c/drivers/at24/"
+			 "/sys/bus/i2c/drivers/at24/"
+			 "/sys/bus/i2c/drivers/lm75/"
+			 "/sys/bus/i2c/drivers/lm75/"
+			 "/sys/bus/i2c/drivers/lm75/"
+			)
+
+# get length of an array
+arraylength=${#DRIVER_NAMEs[@]}
+
+# use for loop to read all values and indexes
+for (( i=0; i<"${arraylength}"; i++ ));
+do
+	bindFile="${DRIVER_PATHs[$i]}bind"
+	driverDir="${DRIVER_PATHs[$i]}${DRIVER_NAMEs[$i]}"
+	echo "binding ${DRIVER_NAMEs[$i]} path ${DRIVER_PATHs[$i]} on Chassi Power On"
+	if [ -d "$driverDir" ]; then
+		echo "Driver ${DRIVER_NAMEs[$i]} is already bound."
+	else
+		echo "${DRIVER_NAMEs[$i]}" > "$bindFile"
+	fi
+done
+
+exit 0
diff --git a/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_util.sh b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_util.sh
new file mode 100644
index 0000000..6f799f0
--- /dev/null
+++ b/meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-utils/ampere_power_util.sh
@@ -0,0 +1,113 @@
+#!/bin/bash
+
+# shellcheck disable=SC2046
+# shellcheck source=/dev/null
+
+source /usr/sbin/gpio-lib.sh
+
+# Usage of this utility
+function usage() {
+	echo "usage: power-util mb [status|shutdown_ack|force_reset|soft_off]";
+}
+
+power_status() {
+	st=$(busctl get-property xyz.openbmc_project.State.Chassis /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis CurrentPowerState | cut -d"." -f6)
+	if [ "$st" == "On\"" ]; then
+		echo "on"
+	else
+		echo "off"
+	fi
+}
+
+shutdown_ack() {
+	if [ -f "/run/openbmc/host@0-softpoweroff" ]; then
+		echo "Receive shutdown ACK triggered after softportoff the host."
+		touch /run/openbmc/host@0-softpoweroff-shutdown-ack
+	else
+		echo "Receive shutdown ACK triggered"
+		sleep 3
+		systemctl start obmc-chassis-poweroff@0.target
+	fi
+}
+
+soft_off() {
+	# Trigger shutdown_req
+	touch /run/openbmc/host@0-softpoweroff
+	gpio_name_set host0-shd-req-n 0
+	sleep 0.05
+	gpio_name_set host0-shd-req-n 1
+
+	# Wait for shutdown_ack from the host in 30 seconds
+	cnt=30
+	while [ $cnt -gt 0 ];
+	do
+		# Wait for SHUTDOWN_ACK and create the host@0-softpoweroff-shutdown-ack
+		if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then
+			break
+		fi
+		sleep 1
+		cnt=$((cnt - 1))
+	done
+
+	# Softpoweroff is successed
+	sleep 2
+	rm -rf /run/openbmc/host@0-softpoweroff
+	if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then
+		rm -rf /run/openbmc/host@0-softpoweroff-shutdown-ack
+	fi
+	echo 0
+}
+
+force_reset() {
+	if [ -f "/run/openbmc/host@0-softpoweroff" ]; then
+		# In graceful host reset, after trigger os shutdown,
+		# the phosphor-state-manager will call force-warm-reset
+		# in this case the force_reset should wait for shutdown_ack from host
+		cnt=30
+		while [ $cnt -gt 0 ];
+		do
+			if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then
+				break
+			fi
+			echo "Waiting for shutdown-ack count down $cnt"
+			sleep 1
+			cnt=$((cnt - 1))
+		done
+		# The host OS is failed to shutdown
+		if [ $cnt == 0 ]; then
+			echo "Shutdown-ack time out after 30s."
+			exit 0
+		fi
+	fi
+	rm -f /run/openbmc/host@0-on
+	echo "Triggering sysreset pin"
+	gpio_name_set host0-sysreset-n 0
+	sleep 1
+	gpio_name_set host0-sysreset-n 1
+}
+
+
+if [ ! -d "/run/openbmc/" ]; then
+	mkdir -p "/run/openbmc/"
+fi
+
+if [ "$2" == "shutdown_ack" ]; then
+	shutdown_ack
+elif [ "$2" == "status" ]; then
+	power_status
+elif [ "$2" == "force_reset" ]; then
+	force_reset
+elif [ "$2" == "soft_off" ]; then
+	ret=$(soft_off)
+	if [ "$ret" == 0 ]; then
+		echo "The host is already softoff"
+	else
+		echo "Failed to softoff the host"
+	fi
+	exit "$ret";
+else
+	echo "Invalid parameter2=$2"
+	usage;
+fi
+
+exit 0;