cancel
Showing results for 
Search instead for 
Did you mean: 

USB3.0 in U-BOOT

Jacob1234
Associate

Hi,

I'm working on enabling USB 3.0 support for the STM32MP257 in U-Boot and need a suitable driver. I’ve attempted to modify the U-Boot kernel driver to support USB 3.0, but I’m running into issues with the PLL configuration.

The problem seems to stem from setting up the correct clocking for the USB3 PHY. Despite adjusting the PLL parameters, I’m not getting stable operation, and the PHY doesn't initialize correctly. If you have any insights on configuring the PLLs for USB3 in U-Boot on STM32MP257, or if there's an existing implementation I could reference, I’d really appreciate your guidance.

Thanks in advance!

Here is my function.

static int stm32_combophy_pll_init(struct stm32_combophy *combophy)
{
int ret = 0;
u32 refclksel = 0, pllmult = 0, propcntrl = 0, sr = 0;
unsigned long clk_rate = 0;
int retry;
const int max_retries = 5;

/* get reference clock rate */
if (combophy->pad_clk) {
clk_rate = clk_get_rate(combophy->pad_clk);
printf("PADCLK rate: %lu\n", clk_rate);
} else {
clk_rate = clk_get_rate(combophy->ker_clk);
printf("KERCLK rate: %lu\n", clk_rate);
}

/* ensure PHY in known reset state before programming */
printf("Assert reset %p\n", combophy->phy_reset);
reset_assert(combophy->phy_reset);
mdelay(1);
printf("Deassert reset %p\n", combophy->phy_reset);
reset_deassert(combophy->phy_reset);
mdelay(1);

/* basic SYSCFG setup */
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
SYSCFG_COMBOPHY_CR2_ISO_DIS, SYSCFG_COMBOPHY_CR2_ISO_DIS);

if (combophy->type != PHY_TYPE_PCIE)
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
SYSCFG_COMBOPHY_CR1_REFSSPEN, SYSCFG_COMBOPHY_CR1_REFSSPEN);

if (combophy->type == PHY_TYPE_PCIE && !combophy->pad_clk)
regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
STM32MP25_PCIEPRGCR_EN, STM32MP25_PCIEPRGCR_EN);

/* optional SSC enable (kept as before) */
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
SYSCFG_COMBOPHY_CR1_SSCEN, SYSCFG_COMBOPHY_CR1_SSCEN);

/* choose PLL parameters based on detected reference clock */
switch (clk_rate) {
case 100000000UL:
pllmult = MPLLMULT_100;
refclksel = REFCLKSEL_0;
propcntrl = 0x8u << 4;
break;
case 19200000UL:
pllmult = MPLLMULT_19_2;
refclksel = REFCLKSEL_1;
propcntrl = 0x8u << 4;
break;
case 20000000UL:
pllmult = MPLLMULT_20;
refclksel = REFCLKSEL_0;
propcntrl = 0xEu << 4;
break;
case 24000000UL:
pllmult = MPLLMULT_24;
refclksel = REFCLKSEL_1;
propcntrl = 0xEu << 4;
break;
case 25000000UL:
pllmult = MPLLMULT_25;
refclksel = REFCLKSEL_0;
propcntrl = 0xEu << 4;
break;
default:
dev_err(combophy->dev, "unsupported refclk %lu\n", clk_rate);
ret = -EINVAL;
goto out;
}

/* program CR1 fields: refclk divider/selector and mpll mult */
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
SYSCFG_COMBOPHY_CR1_REFCLKDIV2, REFCLDIV_0);
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
SYSCFG_COMBOPHY_CR1_REFCLKSEL, refclksel);
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
SYSCFG_COMBOPHY_CR1_MPLLMULT, pllmult);

/* Force common clocks as before */
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR5,
SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS, SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS);

/* ensure PHY released from reset to let PLL try to lock */
printf("Deassert control/reset %p\n", combophy->phy_reset);
reset_deassert(combophy->phy_reset);
mdelay(100);

/* Poll PIPE0_PHYSTATUS with bounded retries */
printf("PLL Polling\n");
for (retry = 0; retry < max_retries; retry++) {
ret = regmap_read(combophy->regmap, SYSCFG_COMBOPHY_SR, &sr);
if (ret) {
dev_err(combophy->dev, "regmap_read SR failed (try %d): %d\n",
retry + 1, ret);
mdelay(100);
continue;
}

if (sr & STM32MP25_PIPE0_PHYSTATUS) {
printf("PHY status ready (attempt %d), sr=0x%08x\n", retry + 1, sr);
ret = 0;
break;
}

printf("PHY not ready yet (attempt %d), sr=0x%08x\n", retry + 1, sr);

/* short reset cycle between attempts to re-trigger PLL */
reset_assert(combophy->phy_reset);
mdelay(2);
reset_deassert(combophy->phy_reset);
mdelay(200);
}

if (!(sr & STM32MP25_PIPE0_PHYSTATUS)) {
dev_err(combophy->dev, "PLL/PHY did not come up after %d attempts, last sr=0x%08x\n",
max_retries, sr);
ret = -ETIMEDOUT;
goto out;
}

/* read USB3 DR status for debug */
sr = readl(USB3DR_REGISTER + USB3DR_DEV_DSTS);
printf("USB3DR Status is 0x%08x\n", sr);

/* program analog loop control for PCIE if needed */
if (combophy->type == PHY_TYPE_PCIE) {
u32 val32 = readl_relaxed(combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
val32 &= ~COMBOPHY_PROP_CNTRL;
val32 |= propcntrl;
writel_relaxed(val32, combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
}

return 0;

out:
/* rollback the enables we set on error */
if (combophy->type == PHY_TYPE_PCIE && !combophy->pad_clk)
regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
STM32MP25_PCIEPRGCR_EN, 0);

if (combophy->type != PHY_TYPE_PCIE)
regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);

regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);

return ret;
}

 

And the terminal response

 

ums 0 mmc 1
UMS: LUN 0, dev mmc 1, hwpart 0, sector 0x0, count 0xe90000
Function xlate ran succesfully
Probe succeeded
Clocks enabled succesfully
00000000f8057da0: Setting USB3 ComboPHY: 3
Mode set succesfully
KERCLK -> 00000000f808f800
Reset Assert to do: 00000000f808f880
Reset Assert done
combophy type: 0000000000000004
00000000f8057da0: Enabling clock with SSC
Clock rate is: 20000000
Control deassert 00000000fa0a50b8
PLL Polling
PHY not ready yet (attempt 1), sr=0x00000000
PHY not ready yet (attempt 2), sr=0x00000000
PHY not ready yet (attempt 3), sr=0x00000000
phy-stm32-combophy phy@480c0000: PLL/PHY did not come up after 3 attempts, last sr=0x00000000
phy-stm32-combophy phy@480c0000: PHY: Failed to init phy@480c0000: -110.
Can't init PHY1

 

0 REPLIES 0