DS320PR810: Code for configuring the redriver using and MCU

Part Number: DS320PR810

Tool/software:

I am trying to configure the DS320PR810 redriver through SMBus using an MCU programmed to write to the memory addresses of the redriver's registers.

I have 2 redrivers, one for each direction that are configured to have addresses using the EQ/ADDR pins with (L0, L0) for one and (L1, L1) for the other.

So there are actually 2 sets of addresses in each of them. The memory address mode that they operate with is 8bit from what I read.

I just defined some constants in the C code for the addresses and various configuration values and then I use them in the MCU C functions for communicating with the redriver.

In my case, there is more loss in a direction, from GPU to CPU and for the other way around, CPU to GPU there is less loss and I just want it to act as a basic signal conditioning without anything fancy.

Bellow is the code for configuring the redrivers, and I am curious if I need to configure anything else besides what is written bellow and if the code seems alright. Also, I could not find enough information about the EQ profiles and which ones should I use. I guess this is based on the medium used for transmission of the pcie signal, in my case being cable + PCB

I am assuming that each channel has a unique address and from that address I have the same offsets that I need to write to across all channels. For example, if I want to write to channel 0 the eq settings, I would need to write to the channel_0_Address + eq_offset_address.

Also, I saw that some registers have reserved bits so I am not doing anything with them but I am writing 0 to them, maybe I should first read the values from registers with reserved bits and only change the ones that I need, writing back to the register the previous read value with only the changed bits that I am interested in.

#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stm32f0xx_hal_i2c.h>

extern I2C_HandleTypeDef hi2c2;

#define CPU_GPU_0_3_ADDR_I2C 0x18
#define CPU_GPU_4_7_ADDR_I2C 0x19
#define GPU_CPU_0_3_ADDR_I2C 0x22
#define GPU_CPU_4_7_ADDR_I2C 0x23

#define CHANNEL_0_REGISTER 0x00
#define CHANNEL_1_REGISTER 0x20
#define CHANNEL_2_REGISTER 0x40
#define CHANNEL_3_REGISTER 0x60
#define CHANNEL_4_REGISTER 0x00
#define CHANNEL_5_REGISTER 0x20
#define CHANNEL_6_REGISTER 0x40
#define CHANNEL_7_REGISTER 0x60

#define EQ_CONTROL_REGISTER_OFFSET 0x01
#define EQ_CONTROL_EQ_STAGE1_BYPASS 0x80
#define EQ_CONTROL_EQ_STAGE1_3 0x40
#define EQ_CONTROL_EQ_STAGE1_2 0x20
#define EQ_CONTROL_EQ_STAGE1_1 0x10
#define EQ_CONTROL_EQ_STAGE1_0 0x08
#define EQ_CONTROL_EQ_STAGE2_2 0x04
#define EQ_CONTROL_EQ_STAGE2_1 0x02
#define EQ_CONTROL_EQ_STAGE2_0 0x01

#define EQ_GAIN_FLAT_GAIN_REGISTER_OFFSET 0x03
#define EQ_PROFILE_3 0x40
#define EQ_PROFILE_2 0x20
#define EQ_PROFILE_1 0x10
#define EQ_PROFILE_0 0x08
#define FLAT_GAIN_2 0x04
#define FLAT_GAIN_1 0x02
#define FLAT_GAIN_0 0x01


#define RX_DETECT_CONTROL_REGISTER_OFFSET 0x04
#define MR_RX_DET_MAN 0x04 //force always detect
#define EN_RX_DET_COUNT 0x02 //enable additional rx detect polling
#define SEL_RX_DET_COUNT 0x01 //enable additional rx detect 0 = 2 valid detections, 1 = 3 additional valid detections


#define BIAS_REGISTER_OFFSET 0x06
#define BIAS_CURRENT_2 0x20
#define BIAS_CURRENT_1 0x10
#define BIAS_CURRENT_0 0x08

static void initialize_channel_eq(uint16_t redriver_address, uint16_t channel_register_address, uint8_t eq_index) {
    HAL_I2C_Mem_Write_IT(&hi2c2, redriver_address, channel_register_address + EQ_CONTROL_REGISTER_OFFSET, I2C_MEMADD_SIZE_8BIT, &eq_index, 1);
}

static void initialize_channel_rx_detect(uint16_t redriver_address, uint16_t channel_register_address, uint8_t rx_detect) {
    HAL_I2C_Mem_Write_IT(&hi2c2, redriver_address, channel_register_address + RX_DETECT_CONTROL_REGISTER_OFFSET, I2C_MEMADD_SIZE_8BIT, &rx_detect, 1);
}

static void initialize_channel_bias(uint16_t redriver_address, uint16_t channel_register_address, uint8_t bias) {
    HAL_I2C_Mem_Write_IT(&hi2c2, redriver_address, channel_register_address + BIAS_REGISTER_OFFSET, I2C_MEMADD_SIZE_8BIT, &bias, 1);
}

static void initialize_channel_eq_profile(uint16_t redriver_address, uint16_t channel_register_address, uint8_t eq_profile) {
    HAL_I2C_Mem_Write_IT(&hi2c2, redriver_address, channel_register_address + EQ_GAIN_FLAT_GAIN_REGISTER_OFFSET, I2C_MEMADD_SIZE_8BIT, &eq_profile, 1);
}


static void initialize_gpu_cpu_redriver()
{
    initialize_channel_eq(GPU_CPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_2);
    initialize_channel_eq(GPU_CPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_2);
    initialize_channel_eq(GPU_CPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_2);
    initialize_channel_eq(GPU_CPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_2);
    initialize_channel_eq(GPU_CPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_1);
    initialize_channel_eq(GPU_CPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_1);
    initialize_channel_eq(GPU_CPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_1);
    initialize_channel_eq(GPU_CPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, EQ_CONTROL_EQ_STAGE2_2 | EQ_CONTROL_EQ_STAGE1_1);

    initialize_channel_rx_detect(GPU_CPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);
    initialize_channel_rx_detect(GPU_CPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, EN_RX_DET_COUNT | SEL_RX_DET_COUNT);

    initialize_channel_bias(GPU_CPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, BIAS_CURRENT_0);
    initialize_channel_bias(GPU_CPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, BIAS_CURRENT_0);

    initialize_channel_eq_profile(GPU_CPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
    initialize_channel_eq_profile(GPU_CPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, EQ_PROFILE_3 | FLAT_GAIN_0 | FLAT_GAIN_2);
}

static void initialize_cpu_gpu_redriver()
{
    initialize_channel_eq(CPU_GPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);
    initialize_channel_eq(CPU_GPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, EQ_CONTROL_EQ_STAGE2_0 | EQ_CONTROL_EQ_STAGE1_BYPASS);

    initialize_channel_rx_detect(CPU_GPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, MR_RX_DET_MAN);
    initialize_channel_rx_detect(CPU_GPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, MR_RX_DET_MAN);

    initialize_channel_bias(CPU_GPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, BIAS_CURRENT_1);
    initialize_channel_bias(CPU_GPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, BIAS_CURRENT_1);

    initialize_channel_eq_profile(CPU_GPU_0_3_ADDR_I2C, CHANNEL_0_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_0_3_ADDR_I2C, CHANNEL_1_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_0_3_ADDR_I2C, CHANNEL_2_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_0_3_ADDR_I2C, CHANNEL_3_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_4_7_ADDR_I2C, CHANNEL_4_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_4_7_ADDR_I2C, CHANNEL_5_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_4_7_ADDR_I2C, CHANNEL_6_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
    initialize_channel_eq_profile(CPU_GPU_4_7_ADDR_I2C, CHANNEL_7_REGISTER, EQ_PROFILE_0 | FLAT_GAIN_0 | FLAT_GAIN_1);
}


void initialize_redrivers() {
    HAL_I2C_IsDeviceReady(&hi2c2, CPU_GPU_0_3_ADDR_I2C, 1024, 1);
    HAL_I2C_IsDeviceReady(&hi2c2, CPU_GPU_4_7_ADDR_I2C, 1024, 1);
    HAL_I2C_IsDeviceReady(&hi2c2, GPU_CPU_0_3_ADDR_I2C, 1024, 1);
    HAL_I2C_IsDeviceReady(&hi2c2, GPU_CPU_0_3_ADDR_I2C, 1024, 1);

    initialize_gpu_cpu_redriver();
    initialize_cpu_gpu_redriver();
}
  • Hi Alecsandru,

    Have you reviewed our DS320PR8xx configuration guide? (https://www.ti.com/lit/ug/snlu302/snlu302.pdf) We recommend adjusting the redriver equalization settings to the premade EQ Index combinations in Table 3-1 and Table 4-1. Each index is a combination of a certain field/register settings, and we generally don't recommend adjusting the individual field/register settings outside of the EQ Index system because it can be confusing.

    It's best to avoid modifying reserved fields (perhaps by using write masks), but for reserved fields that are listed as read-only (and experimental behavior confirms that they are indeed read-only) there is no harm in including them in the write operation.

    Best,

    Evan Su

  • I read it and I think I misunderstood it, I saw that in the EQ register that you had to set some specific values for various stage 1 and stage 2 eq levels, and I thought I would just need to set one bit for stage 1 and one bit for stage 2 but it seems like I need to set multiple bits for stage 1 and stage 2. For example for CTLE index 15 I would need to set multiple bits for stage 1, 11 in decimal,  and stage 2, 3 in decimal, unlike I am doing now, so I would need to write the value 11 in the bits for stage 1 and the value 3 in the bits for stage 2