blob: fea885da7f3aedda39679d00b4076db559c488d2 [file] [log] [blame]
#!/bin/bash
#
# mdio-util - MDIO Utility for AST2600
#
# This shell script provides the ability to access MDIO bus over devmem
#
# TODO: A read/write action contains multiple MDIO operations, it needs a
# lock to protect entire action.
RETRY_CNT=30
RETRY_DEALY_SEC="0.1"
MDIO_BASE_REG=$((16#1e650000))
C22_READ_CMD=$((16#98000000))
C22_WRITE_CMD=$((16#94000000))
C45_ADDR_CMD=$((16#80000000))
C45_WRITE_CMD=$((16#84000000))
C45_PREAD_CMD=$((16#88000000))
C45_READ_CMD=$((16#8C000000))
PHY_ADDR_STEP=$((16#200000))
DEV_ADDR_STEP=$((16#10000))
REG_ADDR_STEP=$((16#10000))
aspeed_mdio_c22_read() {
BUS=$1
PHY_ADDR=$2
REG_ADDR=$3
MDIO_CTRL_REG=$((MDIO_BASE_REG+BUS*8))
MDIO_DATA_REG=$((MDIO_CTRL_REG+4))
CMD=$((C22_READ_CMD+PHY_ADDR*PHY_ADDR_STEP+REG_ADDR*REG_ADDR_STEP))
# write control register
devmem $MDIO_CTRL_REG 32 $CMD
for i in $(seq 1 1 $RETRY_CNT)
do
CHECK_STR=$(devmem $MDIO_CTRL_REG)
CHECK_VAL=$((16#${CHECK_STR#"0x"}))
if [ $((CHECK_VAL&16#80000000)) -eq 0 ]; then
break
elif [ "$i" -eq "${RETRY_CNT}" ]; then
echo "[c22] read operation timeout"
return 1
fi
sleep "$RETRY_DEALY_SEC"
done
# read data register
for i in $(seq 1 1 $RETRY_CNT)
do
DATA_STR=$(devmem $MDIO_DATA_REG)
DATA_VAL=$((16#${DATA_STR#"0x"}))
if [ $((DATA_VAL&16#00010000)) -ne 0 ]; then
DATA_VAL=$((DATA_VAL&16#0000FFFF))
echo "0x$(printf %04x $DATA_VAL)"
break
elif [ "$i" -eq "$RETRY_CNT" ]; then
echo "[c22] read data timeout"
return 1
fi
sleep "$RETRY_DEALY_SEC"
done
return 0
}
aspeed_mdio_c22_write() {
BUS=$1
PHY_ADDR=$2
REG_ADDR=$3
WR_DATA=$4
MDIO_CTRL_REG=$((MDIO_BASE_REG+BUS*8))
MDIO_DATA_REG=$((MDIO_CTRL_REG+4))
CMD=$((C22_WRITE_CMD+PHY_ADDR*PHY_ADDR_STEP+REG_ADDR*REG_ADDR_STEP+WR_DATA))
# write control register
devmem $MDIO_CTRL_REG 32 $CMD
for i in $(seq 1 1 $RETRY_CNT)
do
CHECK_STR=$(devmem $MDIO_CTRL_REG)
CHECK_VAL=$((16#${CHECK_STR#"0x"}))
if [ $((CHECK_VAL&16#80000000)) -eq 0 ]; then
break
elif [ "$i" -eq "$RETRY_CNT" ]; then
echo "[c22] write operation timeout"
return 1
fi
sleep "$RETRY_DEALY_SEC"
done
return 0
}
aspeed_mdio_c45_ctrl() {
BUS=$1
C45_OP=$2
PHY_ADDR=$3
DEV_ADDR=$4
CMD_DATA=$5
MDIO_CTRL_REG=$((MDIO_BASE_REG+BUS*8))
case "$C45_OP" in
0)
CMD=$C45_ADDR_CMD
;;
1)
CMD=$C45_WRITE_CMD
;;
2)
CMD=$C45_PREAD_CMD
;;
3)
CMD=$C45_READ_CMD
;;
*)
echo "[c45] unknow operator $C45_OP"
return 1
;;
esac
CMD=$((CMD+PHY_ADDR*PHY_ADDR_STEP+DEV_ADDR*DEV_ADDR_STEP+CMD_DATA))
# write control register
devmem $MDIO_CTRL_REG 32 $CMD
for i in $(seq 1 1 $RETRY_CNT)
do
CHECK_STR=$(devmem $MDIO_CTRL_REG)
CHECK_VAL=$((16#${CHECK_STR#"0x"}))
if [ $((CHECK_VAL&16#80000000)) -eq 0 ]; then
break
elif [ "$i" -eq "$RETRY_CNT" ]; then
echo "[c45] operation timeout, op: $C45_OP"
return 1
fi
sleep "$RETRY_DEALY_SEC"
done
return 0
}
aspeed_mdio_c45_data() {
BUS=$1
PHY_ADDR=$2
DEV_ADDR=$3
MDIO_CTRL_REG=$((MDIO_BASE_REG+BUS*8))
MDIO_DATA_REG=$((MDIO_CTRL_REG+4))
# read data register
for i in $(seq 1 1 $RETRY_CNT)
do
DATA_STR=$(devmem $MDIO_DATA_REG)
DATA_VAL=$((16#${DATA_STR#"0x"}))
if [ $((DATA_VAL&16#00010000)) -ne 0 ]; then
DATA_VAL=$((DATA_VAL&16#0000FFFF))
echo "0x$(printf %04x $DATA_VAL)"
break
elif [ "$i" -eq "$RETRY_CNT" ]; then
echo "[c45] read data timeout"
return 1
fi
sleep "$RETRY_DEALY_SEC"
done
return 0
}
print_usage() {
echo "Usage:"
echo " [clause 22]"
echo " $0 c22 r <BUS> <PHY_ADDR> <REG_ADDR>"
echo " $0 c22 w <BUS> <PHY_ADDR> <REG_ADDR> <DATA>"
echo " [clause 45]"
echo " $0 c45 r <BUS> <PHY_ADDR> <DEV_ADDR> <REG_ADDR>"
echo " $0 c45 w <BUS> <PHY_ADDR> <DEV_ADDR> <REG_ADDR> <DATA>"
}
CLAUSE_VER=${1}
CMD_TYPE=${2}
BUS=$3
PHY_ADDR=$4
if [ ! -c /dev/mem ]; then
mknod /dev/mem c 1 1
fi
if [ "$CLAUSE_VER" == "c22" ] && [ "$CMD_TYPE" == "r" ] && [ "$#" -eq 5 ]; then
REG_ADDR=${5}
aspeed_mdio_c22_read "$BUS" "$PHY_ADDR" "$REG_ADDR" || exit 1
elif [ "$CLAUSE_VER" == "c22" ] && [ "$CMD_TYPE" == "w" ] && [ "$#" -eq 6 ]; then
REG_ADDR=${5}
DATA=${6}
aspeed_mdio_c22_write "$BUS" "$PHY_ADDR" "$REG_ADDR" "$DATA" || exit 1
elif [ "$CLAUSE_VER" == "c45" ] && [ "$CMD_TYPE" == "r" ] && [ "$#" -eq 6 ]; then
DEV_ADDR=${5}
REG_ADDR=${6}
aspeed_mdio_c45_ctrl "$BUS" 0 "$PHY_ADDR" "$DEV_ADDR" "$REG_ADDR" || exit 1
aspeed_mdio_c45_ctrl "$BUS" 3 "$PHY_ADDR" "$DEV_ADDR" "$REG_ADDR" || exit 1
aspeed_mdio_c45_data "$BUS" "$PHY_ADDR" "$DEV_ADDR" || exit 1
elif [ "$CLAUSE_VER" == "c45" ] && [ "$CMD_TYPE" == "w" ] && [ "$#" -eq 7 ]; then
DEV_ADDR=${5}
REG_ADDR=${6}
DATA=${7}
aspeed_mdio_c45_ctrl "$BUS" 0 "$PHY_ADDR" "$DEV_ADDR" "$REG_ADDR" || exit 1
aspeed_mdio_c45_ctrl "$BUS" 1 "$PHY_ADDR" "$DEV_ADDR" "$DATA" || exit 1
else
print_usage
fi