in marvell/phy-mvebu-cp110-comphy.c [336:450]
static int mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane)
{
struct mvebu_comphy_priv *priv = lane->priv;
u32 val;
regmap_read(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), &val);
val &= ~MVEBU_COMPHY_CONF1_USB_PCIE;
val |= MVEBU_COMPHY_CONF1_PWRUP;
regmap_write(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), val);
/* Select baud rates and PLLs */
val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
val &= ~(MVEBU_COMPHY_SERDES_CFG0_PU_PLL |
MVEBU_COMPHY_SERDES_CFG0_PU_RX |
MVEBU_COMPHY_SERDES_CFG0_PU_TX |
MVEBU_COMPHY_SERDES_CFG0_HALF_BUS |
MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) |
MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf) |
MVEBU_COMPHY_SERDES_CFG0_RXAUI_MODE);
switch (lane->submode) {
case PHY_INTERFACE_MODE_10GBASER:
val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) |
MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe);
break;
case PHY_INTERFACE_MODE_RXAUI:
val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xb) |
MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xb) |
MVEBU_COMPHY_SERDES_CFG0_RXAUI_MODE;
break;
case PHY_INTERFACE_MODE_2500BASEX:
val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x8) |
MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x8) |
MVEBU_COMPHY_SERDES_CFG0_HALF_BUS;
break;
case PHY_INTERFACE_MODE_SGMII:
val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) |
MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) |
MVEBU_COMPHY_SERDES_CFG0_HALF_BUS;
break;
default:
dev_err(priv->dev,
"unsupported comphy submode (%d) on lane %d\n",
lane->submode,
lane->id);
return -ENOTSUPP;
}
writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
if (lane->submode == PHY_INTERFACE_MODE_RXAUI) {
regmap_read(priv->regmap, MVEBU_COMPHY_SD1_CTRL1, &val);
switch (lane->id) {
case 2:
case 3:
val |= MVEBU_COMPHY_SD1_CTRL1_RXAUI0_EN;
break;
case 4:
case 5:
val |= MVEBU_COMPHY_SD1_CTRL1_RXAUI1_EN;
break;
default:
dev_err(priv->dev,
"RXAUI is not supported on comphy lane %d\n",
lane->id);
return -EINVAL;
}
regmap_write(priv->regmap, MVEBU_COMPHY_SD1_CTRL1, val);
}
/* reset */
val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET |
MVEBU_COMPHY_SERDES_CFG1_CORE_RESET |
MVEBU_COMPHY_SERDES_CFG1_RF_RESET);
writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
/* de-assert reset */
val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
val |= MVEBU_COMPHY_SERDES_CFG1_RESET |
MVEBU_COMPHY_SERDES_CFG1_CORE_RESET;
writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
/* wait until clocks are ready */
mdelay(1);
/* exlicitly disable 40B, the bits isn't clear on reset */
regmap_read(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), &val);
val &= ~MVEBU_COMPHY_CONF6_40B;
regmap_write(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), val);
/* refclk selection */
val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL;
if (lane->submode == PHY_INTERFACE_MODE_10GBASER)
val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE;
writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
/* power and pll selection */
val = readl(priv->base + MVEBU_COMPHY_PWRPLL_CTRL(lane->id));
val &= ~(MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(0x1f) |
MVEBU_COMPHY_PWRPLL_PHY_MODE(0x7));
val |= MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(0x1) |
MVEBU_COMPHY_PWRPLL_PHY_MODE(0x4);
writel(val, priv->base + MVEBU_COMPHY_PWRPLL_CTRL(lane->id));
val = readl(priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
val &= ~MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(0x7);
val |= MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(0x1);
writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
return 0;
}