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/conf/machine/mtmitchell.conf b/meta-ampere/meta-mitchell/conf/machine/mtmitchell.conf
index 85e6f4f..c821cb1 100644
--- a/meta-ampere/meta-mitchell/conf/machine/mtmitchell.conf
+++ b/meta-ampere/meta-mitchell/conf/machine/mtmitchell.conf
@@ -28,6 +28,8 @@
                                    phosphor-misc-usb-ctrl \
                                    ampere-platform-init \
                                    ampere-ipmi-oem \
+                                   ampere-hostctrl \
+                                   ampere-driver-binder \
                                    phosphor-ipmi-blobs \
                                    phosphor-ipmi-blobs-binarystore \
                                    util-linux \
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;
diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service
new file mode 100644
index 0000000..6588191
--- /dev/null
+++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/ampere-host-shutdown-ack@.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Ampere Computing LLC host shutdown ACK
+Conflicts=obmc-chassis-poweron@0.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/env ampere_power_util.sh mb shutdown_ack
+SyslogIdentifier=ampere_host_shutdown_ack
diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json
new file mode 100644
index 0000000..20573cc
--- /dev/null
+++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-monitor.json
@@ -0,0 +1,16 @@
+[
+    {
+        "Name": "REBOOT_ACK",
+        "LineName": "host0-reboot-ack-n",
+        "EventMon": "FALLING",
+        "Target": "obmc-host-force-warm-reboot@0.target",
+        "Continue": true
+    },
+    {
+        "Name": "SHUTDOWN_ACK",
+        "LineName": "host0-shd-ack-n",
+        "EventMon": "FALLING",
+        "Target": "ampere-host-shutdown-ack@0.service",
+        "Continue": true
+    }
+]
diff --git a/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend
new file mode 100644
index 0000000..9750f28
--- /dev/null
+++ b/meta-ampere/meta-mitchell/recipes-phosphor/gpio/phosphor-gpio-monitor_%.bbappend
@@ -0,0 +1,22 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+RDEPENDS:${PN}-monitor += "bash"
+
+SRC_URI += " \
+            file://phosphor-multi-gpio-monitor.json \
+           "
+
+SYSTEMD_SERVICE:${PN}-monitor += " \
+                                  ampere-host-shutdown-ack@.service \
+                                 "
+
+FILES:${PN}-monitor += " \
+                        /usr/share/${PN}/phosphor-multi-gpio-monitor.json \
+                       "
+
+SYSTEMD_LINK:${PN}-monitor:append = " ../phosphor-multi-gpio-monitor.service:multi-user.target.requires/phosphor-multi-gpio-monitor.service"
+
+do_install:append() {
+    install -d ${D}${bindir}
+    install -m 0644 ${WORKDIR}/phosphor-multi-gpio-monitor.json ${D}${datadir}/${PN}/
+}