meta-zaius: Add VCS control script and services

Add script for reading/writing VCS rail states on Zaius.
Add systemd services with VCS on after workaround and VCS off at host
power down.
Add recipe to install script and services.

This implementation of the VCS workaround is specific to Zaius as it
requires UCD power sequencer logic to default to VCS rails off.

Signed-off-by: Xo Wang <xow@google.com>
Change-Id: I3acf89f69c4d3df0036cd6fcc8639af0b3f3c68a
diff --git a/meta-zaius/recipes-phosphor/chassis/vcs-control.bb b/meta-zaius/recipes-phosphor/chassis/vcs-control.bb
new file mode 100644
index 0000000..aa14203
--- /dev/null
+++ b/meta-zaius/recipes-phosphor/chassis/vcs-control.bb
@@ -0,0 +1,31 @@
+SUMMARY = "Zaius VCS rail control"
+DESCRIPTION = "VCS voltage rail control implementation for Zaius"
+PR = "r0"
+
+inherit obmc-phosphor-systemd
+inherit obmc-phosphor-license
+
+PROVIDES += 'virtual/p9-vcs-workaround'
+RPROVIDES_${PN} += 'virtual-p9-vcs-workaround'
+
+TMPL_OFF = "vcs-off@.service"
+TMPL_ON = "vcs-on@.service"
+INSTFMT_OFF = "vcs-off@{0}.service"
+INSTFMT_ON = "vcs-on@{0}.service"
+TGTFMT_OFF = "obmc-chassis-stop@{0}.target"
+TGTFMT_ON = "obmc-chassis-start@{0}.target"
+FMT_OFF = "../${TMPL_OFF}:${TGTFMT_OFF}.wants/${INSTFMT_OFF}"
+FMT_ON = "../${TMPL_ON}:${TGTFMT_ON}.wants/${INSTFMT_ON}"
+
+SYSTEMD_SERVICE_${PN} += "${TMPL_OFF}"
+SYSTEMD_LINK_${PN} += "${@compose_list(d, 'FMT_OFF', 'OBMC_CHASSIS_INSTANCES')}"
+SYSTEMD_SERVICE_${PN} += "${TMPL_ON}"
+SYSTEMD_LINK_${PN} += "${@compose_list(d, 'FMT_ON', 'OBMC_CHASSIS_INSTANCES')}"
+
+SRC_URI += "file://zaius_vcs.sh"
+RDEPENDS_${PN} += "i2c-tools"
+
+do_install() {
+        install -d ${D}${bindir}
+        install -m 0755 ${WORKDIR}/zaius_vcs.sh ${D}${bindir}/zaius_vcs.sh
+}
diff --git a/meta-zaius/recipes-phosphor/chassis/vcs-control/vcs-off@.service b/meta-zaius/recipes-phosphor/chassis/vcs-control/vcs-off@.service
new file mode 100644
index 0000000..3acbcf8
--- /dev/null
+++ b/meta-zaius/recipes-phosphor/chassis/vcs-control/vcs-off@.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Turn VCS rails off
+Wants=obmc-power-stop-pre@%i.target
+Before=obmc-power-stop-pre@%i.target
+Conflicts=obmc-chassis-start@%i.target
+
+[Service]
+ExecStart={bindir}/zaius_vcs.sh off
+Type=oneshot
+RemainAfterExit=yes
+
+[Install]
+WantedBy=obmc-chassis-stop@%i.target
diff --git a/meta-zaius/recipes-phosphor/chassis/vcs-control/vcs-on@.service b/meta-zaius/recipes-phosphor/chassis/vcs-control/vcs-on@.service
new file mode 100644
index 0000000..5b93fea
--- /dev/null
+++ b/meta-zaius/recipes-phosphor/chassis/vcs-control/vcs-on@.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Turn VCS rails on
+Wants=vcs_workaround@%i.service
+After=vcs_workaround@%i.service
+Wants=obmc-host-start-pre@%i.target
+Before=obmc-host-start-pre@%i.target
+Conflicts=obmc-chassis-stop@%i.target
+
+[Service]
+ExecStart={bindir}/zaius_vcs.sh on
+Type=oneshot
+RemainAfterExit=yes
+
+[Install]
+WantedBy=obmc-chassis-start@%i.target
diff --git a/meta-zaius/recipes-phosphor/chassis/vcs-control/zaius_vcs.sh b/meta-zaius/recipes-phosphor/chassis/vcs-control/zaius_vcs.sh
new file mode 100755
index 0000000..fc81f27
--- /dev/null
+++ b/meta-zaius/recipes-phosphor/chassis/vcs-control/zaius_vcs.sh
@@ -0,0 +1,86 @@
+#!/bin/sh -e
+# Read and control VCS rails by sending the UCD power sequencer I2C commands.
+# This script assumes that the UCD is controlling VCS rails as GPIOs 5 and 6.
+# Also assumes that those GPIOs are already enabled.
+
+ucd_bus="0"
+ucd_addr="0x64"
+ucd_path="/sys/bus/i2c/drivers/ucd9000"
+ucd_driver="${ucd_bus}-00${ucd_addr#0x}"
+
+# Usage: ucd_get address
+# Result stored in $ucd_reg
+ucd_get()
+{
+    ucd_reg=`i2cget -y $ucd_bus $ucd_addr $1 b`
+}
+
+# Usage: ucd_get address value
+ucd_set()
+{
+    i2cset -y $ucd_bus $ucd_addr $1 $2 b
+}
+
+unbind_ucd()
+{
+    if [ -e $ucd_path/$ucd_driver ]
+    then
+        echo -e "\tUnbinding UCD driver $ucd_driver"
+        echo $ucd_driver > $ucd_path/unbind
+    else
+        echo -e "\tWarning: $ucd_path/$ucd_driver doesn't exist"
+    fi
+}
+
+rebind_ucd()
+{
+    if [ -e $ucd_path ]
+    then
+        echo -e "\tBinding UCD driver $ucd_driver"
+        echo $ucd_driver > $ucd_path/bind
+    fi
+}
+
+vcs_set_gpios()
+{
+    unbind_ucd
+    echo -e "\tSetting UCD GPIO 5 to $1"
+    ucd_set 0xFA 5
+    ucd_set 0xFB $1
+    ucd_set 0xFB $1
+    echo -e "\tSetting UCD GPIO 6 to $1"
+    ucd_set 0xFA 6
+    ucd_set 0xFB $1
+    ucd_set 0xFB $1
+    rebind_ucd
+}
+
+vcs_get()
+{
+    echo Reading VCS settings
+    unbind_ucd
+    ucd_set 0xFA 5
+    ucd_get 0xFB
+    local val=`echo $ucd_reg | grep -i -c 0x0f`
+    echo -e "\tUCD GPIO 5 state=$val"
+    ucd_set 0xFA 6
+    ucd_get 0xFB
+    local val=`echo $ucd_reg | grep -i -c 0x0f`
+    echo -e "\tUCD GPIO 6 state=$val"
+    rebind_ucd
+}
+
+
+if [ "$1" == "on" ]
+then
+    echo Turning on VCS
+    vcs_set_gpios 0x7
+
+elif [ "$1" == "off" ]
+then
+    echo Turning off VCS
+    vcs_set_gpios 0x3
+else
+    vcs_get
+    echo "$0 <on|off>" to set state
+fi