diff options
Diffstat (limited to 'meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl')
7 files changed, 532 insertions, 0 deletions
diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/host-poweroff@.service b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/host-poweroff@.service new file mode 100644 index 000000000..50cd53283 --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/host-poweroff@.service @@ -0,0 +1,10 @@ +[Unit] +Description=Power off System in Sled%i by Step Motor +Requires=motor-init-calibration@%i.service +After=motor-init-calibration@%i.service + +[Service] +Type=oneshot +ExecStart=/usr/sbin/power-ctrl sled%i off +SyslogIdentifier=power-ctrl + diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/host-poweron@.service b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/host-poweron@.service new file mode 100644 index 000000000..6ff11202d --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/host-poweron@.service @@ -0,0 +1,10 @@ +[Unit] +Description=Power on System in Sled%i by Step Motor +Requires=motor-init-calibration@%i.service +After=motor-init-calibration@%i.service + +[Service] +Type=oneshot +ExecStart=/usr/sbin/power-ctrl sled%i on +SyslogIdentifier=power-ctrl + diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-ctrl b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-ctrl new file mode 100755 index 000000000..3f8f2ca21 --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-ctrl @@ -0,0 +1,101 @@ +#!/bin/bash -e +# +# Control step motor rotate of sled + +function set_gpio() +{ + NET_NAME=$1 + OUT_VAL=$2 + mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME") + if [ "${#GPIO_INFO[@]}" -ne 2 ]; then + echo "set_gpio: can not find gpio, $NET_NAME" + return 1 + fi + echo -n "set_gpio: set $NET_NAME = $OUT_VAL" + if ! gpioset "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}"="$OUT_VAL"; then + echo " failed" + return 1 + fi + echo " success" + return 0 +} + +#Get i2c bus number for sledN +function get_bus_num() { + SLED_NUM=$1 + local bus=0 + + if [[ "$SLED_NUM" = [0-5] ]]; then + bus="$SLED_NUM" + fi + echo "$bus" +} + +#Enable sledN Motor VRef +function open_vref() { + i2cset -f -y "${1}" 0x67 0x06 0x95 +} + +#Disable sledN Motor VRef +function close_vref() { + i2cset -f -y "${1}" 0x67 0x06 0x55 +} + +####################################### +# Setting step motor control pins to start/stop motor +# Arguments: +# 1. SLED NUMBER +# 2. Value of STBY RESET PIN +# 3. Value of ENABLE PIN +# 4. Value of DIRECTION PIN +####################################### +function set_motor() { + STBY_PIN="SLED${1}_MD_STBY_RESET" + EN_PIN="SLED${1}_MD_IOEXP_EN_FAULT" + DIR_PIN="SLED${1}_MD_DIR" + set_gpio "$STBY_PIN" "$2" + set_gpio "$EN_PIN" "$3" + set_gpio "$DIR_PIN" "$4" +} + +function show_usage(){ + echo "Usage: motor-ctrl [sled0 | sled1 | sled2 | sled3 | sled4 | sled5] [f r s]" + echo " f : Step Motor go forward" + echo " r : Step Motor go reverse" + echo " s : Step Motor stop " +} + +if [ $# -ne 2 ]; then + show_usage + exit 1; +fi + +if [[ "$1" =~ ^(slot[0-5]{1})$ ]] || [[ "$1" =~ ^(sled[0-5]{1})$ ]]; then + SLED=$1 + SLED_NUM=${SLED:4} + I2C_NUM=$(get_bus_num "$SLED_NUM") + ACTION=$2 +else + echo "invalid sled name: $1" + exit 1; +fi + +if [[ "$ACTION" == "s" ]]; then + echo "stop motor" + set_motor "$SLED_NUM" 1 0 0 + close_vref "$I2C_NUM" +elif [[ "$ACTION" == "f" ]];then + echo "start motor, direction:forward" + set_motor "$SLED_NUM" 1 1 0 + open_vref "$I2C_NUM" +elif [[ "$ACTION" == "r" ]];then + echo "start motor, direction:reverse" + set_motor "$SLED_NUM" 1 1 1 + open_vref "$I2C_NUM" +else + echo "Error: Unknown action!" + exit 1 +fi + +exit 0 + diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-init b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-init new file mode 100755 index 000000000..cecb99618 --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-init @@ -0,0 +1,185 @@ +#!/bin/bash -e + +# Initialize for step motor of sled: +# Enable pwm and setup pwm duty +# Setup gpio pins for step motor control +# Moving step motor back to initial position + +export PATH=$PATH:/usr/libexec + +PWM_BASE_ADDR="0x1e61" +DEV_FILE="/dev/mem" +CALIBRATE_TIMEOUT=120 + +#Get pwm register address for sledN +function get_pwm_offset() { + local offset=0 + case $1 in + 0) + offset="0080" + ;; + 1) + offset="0090" + ;; + 2) + offset="00a0" + ;; + 3) + offset="00b0" + ;; + 4) + offset="00c0" + ;; + 5) + offset="00d0" + ;; + esac + + echo ${PWM_BASE_ADDR}${offset} +} + +#Get pwm duty register address for sledN +function get_duty_offset() { + local offset=0 + case $1 in + 0) + offset="0084" + ;; + 1) + offset="0094" + ;; + 2) + offset="00a4" + ;; + 3) + offset="00b4" + ;; + 4) + offset="00c4" + ;; + 5) + offset="00d4" + ;; + esac + + echo ${PWM_BASE_ADDR}${offset} +} + +#Enable pwm for sledN +function open_pwm() { + local SLED_NUM="$1" + echo "Open pwm of sled$SLED_NUM" + #enable BMC PWM + if [ ! -c "$DEV_FILE" ]; then + mknod /dev/mem c 1 1 + fi + + PWM_OFFSET=$(get_pwm_offset "$SLED_NUM") + DUTY_OFFSET=$(get_duty_offset "$SLED_NUM") + echo "setting ${PWM_OFFSET} to 0x000113F3" + echo "setting ${DUTY_OFFSET} to 0xFF006400" + devmem "$PWM_OFFSET" 32 0x000113F3 + devmem "$DUTY_OFFSET" 32 0xFF006400 +} + +function set_gpio() +{ + NET_NAME=$1 + OUT_VAL=$2 + mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME") + if [ "${#GPIO_INFO[@]}" -ne 2 ]; then + echo "set_gpio: can not find gpio, $NET_NAME" + return 1 + fi + echo -n "set_gpio: set $NET_NAME = $OUT_VAL" + if ! gpioset "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}"="$OUT_VAL"; then + echo " failed" + return 1 + fi + echo " success" + return 0 +} + +function get_gpio() +{ + NET_NAME=$1 + RET_VAL=2 + + mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME") + if [ "${#GPIO_INFO[@]}" -ne 2 ]; then + echo "get_gpio: can not find gpio, $NET_NAME" >&2 + return 1 + fi + if ! RET_VAL=$(gpioget "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}") ; then + echo "get_gpio: get ${NET_NAME} failed" >&2 + return 1 + fi + echo "${RET_VAL}" + return 0 +} + +#Init gpio pins for step motor control +function init_gpios() { + echo "Init GPIOs:" + motor_ctrl_gpio_pins_names=( "SLED${1}_MD_STBY_RESET" + "SLED${1}_MD_IOEXP_EN_FAULT" + "SLED${1}_MD_DIR" + "SLED${1}_MD_DECAY" + "SLED${1}_MD_MODE1" + "SLED${1}_MD_MODE2" + "SLED${1}_MD_MODE3" ) + + for gpio_name in "${motor_ctrl_gpio_pins_names[@]}"; do + set_gpio "$gpio_name" 0 + done +} + +if [[ "$1" =~ ^(slot[0-5]{1})$ ]] || [[ "$1" =~ ^(sled[0-5]{1})$ ]]; then + SLED=$1 + SLED_NUM=${SLED:4} +else + #show_usage + echo "invalid sled name: ${1}" + exit 1; +fi + +#Check if sled is present +SLED_PRESENT=$(get_gpio "presence-sled${SLED_NUM}") +if [ "$SLED_PRESENT" != 0 ];then + echo "${SLED} is not present, skip motor initialize" + exit 1 +fi + +#Init gpios +init_gpios "$SLED_NUM" + +#enable pwm +open_pwm "$SLED_NUM" + +#SLED{N}_MS_DETECT1 (initial position) +DETECT_PIN1="SLED${SLED_NUM}_MS_DETECT1" +INIT_POS=$(get_gpio "$DETECT_PIN1") + +if [ "$INIT_POS" -eq 1 ];then + time_count=0 + echo "Making motor back to initial position..." + motor-ctrl "$SLED" r >/dev/null + while [ "$INIT_POS" -eq 1 ] ;do + INIT_POS=$(get_gpio "$DETECT_PIN1") + sleep 0.1 + time_count=$(( time_count + 1 )) + if [ $time_count -gt $CALIBRATE_TIMEOUT ];then + echo "Error: Step motor run over 1 cycle but switch never triggered" + break + fi + done + motor-ctrl "$SLED" s >/dev/null +fi + +if [ "$INIT_POS" -eq 0 ];then + echo "Motor calibrated to initial position." + exit 0 +else + echo "Find motor initial position failed" + exit 1 +fi diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-init-calibration@.service b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-init-calibration@.service new file mode 100644 index 000000000..aab61b7fe --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/motor-init-calibration@.service @@ -0,0 +1,11 @@ +[Unit] +Description=Motor Initialize for sled%i + +[Service] +ExecStart=/usr/libexec/motor-init sled%i +SyslogIdentifier=Motor Initialize sled%i +Type=oneshot +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/power-ctrl b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/power-ctrl new file mode 100755 index 000000000..111ce8bbc --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/files/power-ctrl @@ -0,0 +1,178 @@ +#!/bin/bash +# +# Power Control tool +# Enable/disable AC relay +# On/off System by step moter to press power key + +export PATH=$PATH:/usr/sbin:/usr/libexec + +DELAY_POWER_ON="0.5" +DELAY_POWER_OFF="5" +POWER_BTN_TIMEOUT_CNT=60 + +#Switch pull low while it be touched +function wait_for_switch() { + TARGET_PIN=$1 + TARGET_SWITCH=1 + TIME_CNT=0 + while [ "$TARGET_SWITCH" -eq 1 ] ;do + TARGET_SWITCH=$(get_gpio "$TARGET_PIN") + sleep 0.1 + TIME_CNT=$(( TIME_CNT +1)) + if [ $TIME_CNT -gt $POWER_BTN_TIMEOUT_CNT ];then + echo "Error: Too long to get target switch, force exit" >&2 + break + fi + done +} + +function trigger_power_button() { + local sled_num=$1 + local delay_time=$2 + + #SLED{N}_MS_DETECT1 (initial position) + GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1" + #SLED{N}_MS_DETECT0 (MAC position) + GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0" + + echo "Motor go forward to press Power key" + motor-ctrl "sled${sled_num}" f >/dev/null + wait_for_switch "${GPIO_DETECT_PIN0}" + motor-ctrl "sled${sled_num}" s >/dev/null + + if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then + echo "Power key switch triggered" + echo "Press power key for Sled${1} ${delay_time} seconds..." + sleep "$delay_time" + else + echo "Power key switch not trigger, back motor to initail position" + fi + + motor-ctrl "sled${sled_num}" r >/dev/null + wait_for_switch "${GPIO_DETECT_PIN1}" + motor-ctrl "sled${sled_num}" s >/dev/null + if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then + echo "Motor reverse to initial position successful" + else + echo "Initail position switch not trigger, force stop motor" + fi +} + +#Get i2c bus number for sledN +function get_bus_num() { + SLED_NUM=$1 + local bus=0 + + if [[ "$SLED_NUM" = [0-5] ]]; then + bus="$SLED_NUM" + fi + echo "$bus" +} + +function set_gpio() +{ + NET_NAME=$1 + OUT_VAL=$2 + mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME") + if [ "${#GPIO_INFO[@]}" -ne 2 ]; then + echo "set_gpio: can not find gpio, $NET_NAME" + return 1 + fi + echo -n "set_gpio: set $NET_NAME = $OUT_VAL" + if ! gpioset "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}"="$OUT_VAL"; then + echo " failed" + return 1 + fi + echo " success" + return 0 +} + +function get_gpio() +{ + NET_NAME=$1 + RET_VAL=2 + + mapfile -t -d " " GPIO_INFO < <(gpiofind "$NET_NAME") + if [ "${#GPIO_INFO[@]}" -ne 2 ]; then + echo "get_gpio: can not find gpio, $NET_NAME" >&2 + return 1 + fi + if ! RET_VAL=$(gpioget "${GPIO_INFO[0]}" "${GPIO_INFO[1]%$'\n'}") ; then + echo "get_gpio: get ${NET_NAME} failed" >&2 + return 1 + fi + echo "${RET_VAL}" + return 0 +} + +function get_ac_status(){ + i2c_bus=$(get_bus_num "$1") + p1_output_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x03) + p1_config_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x07) + host_pwr="$(( (p1_output_reg & 0x80)>>7 ))" + is_output="$(( (~p1_config_reg & 0x80)>>7 ))" + + if [ "$(( host_pwr & is_output ))" -eq 1 ];then + echo "AC on" + else + echo "AC off" + fi +} + +function show_usage(){ + echo "Usage: power-ctrl [sled0 | sled1 | sled2 | sled3 | sled4 | sled5] [on off ac-on ac-off status]" + echo " power-ctrl chassis-cycle" +} + +if [ $# -eq 1 ]; then + if [ "$1" = "chassis-cycle" ];then + echo "chassis cycle...." + i2cset -y -f 12 0x11 0xd9 c + exit 0 + else + echo "Invalid argument: [ $1 ]" + show_usage + exit 1; + fi +fi + +if [ $# -gt 2 ]; then + echo "Too many arguments" + show_usage + exit 1; +fi + +if [[ "$1" =~ ^(slot[0-5]{1})$ ]] || [[ "$1" =~ ^(sled[0-5]{1})$ ]]; then + SLED=$1 + ACTION=$2 + SLED_NUM=${SLED:4} +else + echo "invalid sled name: ${1}" + show_usage + exit 1; +fi + +#Check if sled is present +SLED_PRESENT=$(get_gpio "presence-sled${SLED_NUM}") +if [ "$SLED_PRESENT" != 0 ];then + echo "${SLED} is not present!" + exit 1 +fi + +if [[ "$ACTION" == "on" ]]; then + echo "Power on ${SLED}" + trigger_power_button "$SLED_NUM" "$DELAY_POWER_ON" +elif [[ "$ACTION" == "off" ]];then + echo "Power off ${SLED}" + trigger_power_button "$SLED_NUM" "$DELAY_POWER_OFF" +elif [[ "$ACTION" == "status" ]];then + get_ac_status "$SLED_NUM" + #TODO : check or record Host(DC) power status +elif [[ "$ACTION" == "ac-on" ]];then + set_gpio "power-host${SLED_NUM}" 1 +elif [[ "$ACTION" == "ac-off" ]];then + set_gpio "power-host${SLED_NUM}" 0 +else + echo "Unknown action: [ ${ACTION} ]" + show_usage +fi diff --git a/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/motor-ctrl_0.1.bb b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/motor-ctrl_0.1.bb new file mode 100644 index 000000000..2705eb850 --- /dev/null +++ b/meta-facebook/meta-bletchley/recipes-bletchley/motor-ctrl/motor-ctrl_0.1.bb @@ -0,0 +1,37 @@ +SUMMARY = "Bletchley Motor control" +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit obmc-phosphor-systemd + +RDEPENDS:${PN} += "bash" +RDEPENDS:${PN} += "libgpiod-tools" +RDEPENDS:${PN} += "i2c-tools" + +S = "${WORKDIR}" +SRC_URI += "file://motor-init \ + file://motor-ctrl \ + file://power-ctrl " + +do_install() { + install -d ${D}${sbindir} + install -m 0755 ${WORKDIR}/power-ctrl ${D}${sbindir} + + install -d ${D}${libexecdir} + install -m 0755 ${WORKDIR}/motor-init ${D}${libexecdir} + install -m 0755 ${WORKDIR}/motor-ctrl ${D}${libexecdir} +} + +MOTOR_INIT_INSTFMT= "motor-init-calibration@{0}.service" +PWR_ON_INSTFMT="host-poweron@.service:host-poweron@{0}.service" +PWR_OFF_INSTFMT="host-poweroff@.service:host-poweroff@{0}.service" + +SYSTEMD_SERVICE:${PN} ="${@compose_list(d, 'MOTOR_INIT_INSTFMT', 'OBMC_HOST_INSTANCES')}" +FILES:${PN} += "${systemd_system_unitdir}/motor-init-calibration@.service" + +SYSTEMD_SERVICE:${PN} +="host-poweron@.service" +SYSTEMD_LINK:${PN} += "${@compose_list(d, 'PWR_ON_INSTFMT', 'OBMC_HOST_INSTANCES')}" + +SYSTEMD_SERVICE:${PN} +="host-poweroff@.service" +SYSTEMD_LINK:${PN} += "${@compose_list(d, 'PWR_OFF_INSTFMT', 'OBMC_HOST_INSTANCES')}" |