This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TPS53681: Unable to write VOUT_COMMAND to NVM

Part Number: TPS53681

Tool/software:

Hello. I have written an I2C script to program an on-board TPS53861. All the values hold, except VOUT_COMMAND is reset to default 0x0033 value after I execute the STORE_DEFAULT_ALL command. I set 10mV step mode, and then assign 0.8V to Rail A by writing 0x001F to the VOUT_COMMAND (0x21) register. This works correctly until I run STORE_DEFAULT_ALL, which resets VOUT_COMMAND to default value. Is there some security mechanism I am missing? 

Please see the programming script I wrote below:

#!/bin/sh

bus=3
device=0x60

check_device() {
    if ! i2cdetect -y $bus | grep -q "${device#0x}"; then
        echo "Error: Device $device not found on I2C bus $bus"
        exit 1
    fi
    echo "TPS53861 device found on I2C bus $bus"
}

i2c_write() {
    local register=$1
    local value=$2
    local mode=$3
   
    i2cset -y $bus $device $register $value $mode
}

i2c_read() {
    local register=$1
    local mode=$2
    i2cget -y $bus $device $register $mode | tr 'A-Z' 'a-z'
}

store_custom_defaults() {
    echo "Disabling write protect..."
    i2c_write 0x10 0x00 b
   
    write_protect=$(i2c_read 0x10 b)
    if [ "$write_protect" != "0x00" ]; then
        echo "Error: Failed to disable write protect"
        exit 1
    fi

    echo "Storing current configuration to NVM..."
    i2c_write 0x11 # STORE_USER_ALL - dataless send byte transaction
   
    # wait for NVM store (500ms minimum for EEPROM write)
    sleep 0.5

    status=$(i2c_read 0x7E b) # Check STATUS_CML register
    if [ $((status & 0x08)) -ne 0 ]; then
        echo "Error: Memory write operation failed"
        exit 1
    fi

    echo "Re-enabling write protect..."
    i2c_write 0x10 0x80 b

    echo "Custom configuration stored successfully as NVM defaults"
    echo "Power cycle the device for the changes to take effect"
}

echo "Entering TPS53861 program..."
check_device

printf "Do you want to continue? (y/n): "
read response
case $response in
    [Yy]*)
        ;;
    *)
        echo "Exit."
        exit 1
        ;;
esac

echo "Configuring TPS53681 PMIC..."

i2c_write 0x00 0x00 b  # Set PAGE to 0 for Rail A

# Set dynamic phase shedding (DSP_EN)
echo "Enabling dynamic phase shedding..."
i2c_write 0xDE 0x85 w

# Set maximum output current (IOUT_MAX)
echo "Setting maximum output current for Rail A to 185A..."
i2c_write 0xDA 0xC8B9 w

# Set over-current fault threshold (IOUT_OC_FAULT_LIMIT)
echo "Setting over-current protection threshold for Rail A to 278A..."
i2c_write 0x46 0x0116 w

# Set over-current warning threshold (IOUT_OC_WARN_LIMIT)
echo "Setting over-current warning threshold for Rail A to 185A..."
i2c_write 0x4A 0x00B9 w

# Read current MFR_SPECIFIC_13 value
mfr_specific_13=$(i2c_read 0xDD w)
# Only modify bits 7:5 in the lower byte, preserve upper byte
new_value=$(( ($mfr_specific_13 & 0xFF1F) | 0x0080 ))
i2c_write 0xDD $new_value w

status_cml_pre=$(i2c_read 0x7E b)
echo "STATUS_CML before: 0x$(printf '%02x' $status_cml_pre)"

verify_value=$(i2c_read 0xDD w)
echo "MFR_SPECIFIC_13 before: 0x$(printf '%04x' $mfr_specific_13)"
echo "MFR_SPECIFIC_13 after: 0x$(printf '%04x' $verify_value)"

status_cml_post=$(i2c_read 0x7E b)
echo "STATUS_CML after: 0x$(printf '%02x' $status_cml_post)"

echo "Ensure VID_MODE DAC resolution"
vid_mode=$(i2c_read 0x20 b)
if [ "$vid_mode" != "0x21" ]; then
    echo "VID mode changed from defaults! Got $vid_mode"
else
    echo "VID mode is default, 5mV DAC resolution"
fi

# Set VOUT_COMMAND for Rail A to 0.8V -- default 0, so no need to set PAGE register
echo "Setting VOUT_COMMAND for Rail A to 0.8V..."
#i2c_write 0x21 0x6F w
i2c_write 0x21 0x001F w

# Set ON_OFF_CONFIG to be enabled by AVR_EN (ON_OFF_CONFIG)
echo "Setting ON_OFF_CONFIG fo Rail A to be enabled by AVR_EN"
i2c_write 0x02 0x17

# Enable Rail A
#echo "Enabling Rail A..."
#i2c_write 0x01 0x80 b

# Disable Rail B
echo "Disabling Rail B..."
i2c_write 0x00 0x01 b  # Set PAGE to 1
i2c_write 0x01 0x00 b  # Set OPERATION to off

echo "Verifying settings..."

page_value=$(i2c_read 0x00 b)
if [ "$page_value" != "0x01" ]; then
    echo "Error: PAGE register verification failed. Expected 0x01, got $page_value"
    exit 1
fi

rail_b_value=$(i2c_read 0x01 b)
if [ "$rail_b_value" != "0x00" ]; then
    echo "Error: Rail B verification failed. Expected 0x00, got $rail_b_value"
    exit 1
fi

# Set back to PAGE 0
i2c_write 0x00 0x00 b

#rail_a_value=$(i2c_read 0x01 b)
#if [ "$rail_a_value" != "0x80" ]; then
#    echo "Error: Rail A verification failed. Expected 0x80, got $rail_a_value"
#    exit 1
#fi

# All following values in PAGE 0 (RAIL A)
vout_value=$(i2c_read 0x21 w)
if [ "$vout_value" != "0x001f" ]; then
    echo "Error: VOUT_COMMAND verification failed. Expected 0x001f, got $vout_value"
    exit 1
fi

dsp_value=$(i2c_read 0xDE w)
if [ "$dsp_value" != "0x0085" ]; then
    echo "Error: DSP_EN verification failed. Expected 0x0085, got $dsp_value"
    exit 1
fi

vout_value=$(i2c_read 0xDA w)
if [ "$vout_value" != "0xc8b9" ]; then
    echo "Error: IOUT_MAX verification failed. Expected 0xc8b9, got $vout_value"
    exit 1
fi

fault_value=$(i2c_read 0x46 w)
if [ "$fault_value" != "0x0116" ]; then
    echo "Error: IOUT_OC_FAULT_LIMIT verification failed. Expected 0x0116, got $fault_value"
    exit 1
fi

warn_value=$(i2c_read 0x4A w)
if [ "$warn_value" != "0x00b9" ]; then
    echo "Error: IOUT_OC_WARN_LIMIT verification failed. Expected 0x00b9, got $warn_value"
    exit 1
fi

on_off_config=$(i2c_read 0x02 b)
if [ "$on_off_config" != "0x17" ]; then
    echo "Error: ON_OFF_CONFIG verification failed. Expected 0x17, got $on_off_config"
    exit 1
fi

store_custom_defaults

echo "TPS53861 programming complete"