switch (ret) { case SMCCC_RET_SUCCESS: return 0; case SMCCC_RET_NOT_SUPPORTED: return -EOPNOTSUPP; default: return -EINVAL;
}
}
staticint mvebu_comphy_get_mode(bool fw_mode, int lane, int port, enum phy_mode mode, int submode)
{ int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes); /* Ignore PCIe submode: it represents the width */ bool ignore_submode = (mode == PHY_MODE_PCIE); conststruct mvebu_comphy_conf *conf;
/* Unused PHY mux value is 0x0 */ if (mode == PHY_MODE_INVALID) return 0;
for (i = 0; i < n; i++) {
conf = &mvebu_comphy_cp110_modes[i]; if (conf->lane == lane &&
conf->port == port &&
conf->mode == mode &&
(conf->submode == submode || ignore_submode)) break;
}
if (i == n) return -EINVAL;
if (fw_mode) return conf->fw_mode; else return conf->mux;
}
staticinlineint mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode, int submode)
{ return mvebu_comphy_get_mode(false, lane, port, mode, submode);
}
staticinlineint mvebu_comphy_get_fw_mode(int lane, int port, enum phy_mode mode, int submode)
{ return mvebu_comphy_get_mode(true, lane, port, mode, submode);
}
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;
}
/* 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);
/* explicitly 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));
err = mvebu_comphy_ethernet_init_reset(lane); if (err) return err;
val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL;
writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
val = readl(priv->base + MVEBU_COMPHY_DTL_CTRL(lane->id));
val &= ~MVEBU_COMPHY_DTL_CTRL_DTL_FLOOP_EN;
writel(val, priv->base + MVEBU_COMPHY_DTL_CTRL(lane->id));
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);
val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
val &= ~MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf);
val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
err = mvebu_comphy_ethernet_init_reset(lane); if (err) return err;
val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL |
MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
val = readl(priv->base + MVEBU_COMPHY_DTL_CTRL(lane->id));
val |= MVEBU_COMPHY_DTL_CTRL_DTL_FLOOP_EN;
writel(val, priv->base + MVEBU_COMPHY_DTL_CTRL(lane->id));
val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
val |= MVEBU_COMPHY_SERDES_CFG2_DFE_EN;
writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
val = readl(priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
val |= MVEBU_COMPHY_DFE_RES_FORCE_GEN_TBL;
writel(val, priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
val &= ~MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf);
val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xd);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
val &= ~(MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x7) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x7));
val |= MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x1) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x1) |
MVEBU_COMPHY_GEN1_S1_RX_DFE_EN;
writel(val, priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
val = readl(priv->base + MVEBU_COMPHY_COEF(lane->id));
val &= ~(MVEBU_COMPHY_COEF_DFE_EN | MVEBU_COMPHY_COEF_DFE_CTRL);
writel(val, priv->base + MVEBU_COMPHY_COEF(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
val &= ~MVEBU_COMPHY_GEN1_S4_DFE_RES(0x3);
val |= MVEBU_COMPHY_GEN1_S4_DFE_RES(0x1);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
err = mvebu_comphy_ethernet_init_reset(lane); if (err) return err;
val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL |
MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
val = readl(priv->base + MVEBU_COMPHY_DTL_CTRL(lane->id));
val |= MVEBU_COMPHY_DTL_CTRL_DTL_FLOOP_EN;
writel(val, priv->base + MVEBU_COMPHY_DTL_CTRL(lane->id));
/* Speed divider */
val = readl(priv->base + MVEBU_COMPHY_SPEED_DIV(lane->id));
val |= MVEBU_COMPHY_SPEED_DIV_TX_FORCE;
writel(val, priv->base + MVEBU_COMPHY_SPEED_DIV(lane->id));
val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
val |= MVEBU_COMPHY_SERDES_CFG2_DFE_EN;
writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
/* DFE resolution */
val = readl(priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
val |= MVEBU_COMPHY_DFE_RES_FORCE_GEN_TBL;
writel(val, priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
val &= ~(MVEBU_COMPHY_GEN1_S0_TX_AMP(0x1f) |
MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf));
val |= MVEBU_COMPHY_GEN1_S0_TX_AMP(0x1c) |
MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xe);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S2(lane->id));
val &= ~MVEBU_COMPHY_GEN1_S2_TX_EMPH(0xf);
val |= MVEBU_COMPHY_GEN1_S2_TX_EMPH_EN;
writel(val, priv->base + MVEBU_COMPHY_GEN1_S2(lane->id));
val = readl(priv->base + MVEBU_COMPHY_TX_SLEW_RATE(lane->id));
val |= MVEBU_COMPHY_TX_SLEW_RATE_EMPH(0x3) |
MVEBU_COMPHY_TX_SLEW_RATE_SLC(0x3f);
writel(val, priv->base + MVEBU_COMPHY_TX_SLEW_RATE(lane->id));
/* Impedance calibration */
val = readl(priv->base + MVEBU_COMPHY_IMP_CAL(lane->id));
val &= ~MVEBU_COMPHY_IMP_CAL_TX_EXT(0x1f);
val |= MVEBU_COMPHY_IMP_CAL_TX_EXT(0xe) |
MVEBU_COMPHY_IMP_CAL_TX_EXT_EN;
writel(val, priv->base + MVEBU_COMPHY_IMP_CAL(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S5(lane->id));
val &= ~MVEBU_COMPHY_GEN1_S5_ICP(0xf);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S5(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
val &= ~(MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x7) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x7) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_FI(0x3) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(0x3));
val |= MVEBU_COMPHY_GEN1_S1_RX_DFE_EN |
MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x2) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x2) |
MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(0x1) |
MVEBU_COMPHY_GEN1_S1_RX_DIV(0x3);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
val = readl(priv->base + MVEBU_COMPHY_COEF(lane->id));
val &= ~(MVEBU_COMPHY_COEF_DFE_EN | MVEBU_COMPHY_COEF_DFE_CTRL);
writel(val, priv->base + MVEBU_COMPHY_COEF(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
val &= ~MVEBU_COMPHY_GEN1_S4_DFE_RES(0x3);
val |= MVEBU_COMPHY_GEN1_S4_DFE_RES(0x1);
writel(val, priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
val = readl(priv->base + MVEBU_COMPHY_GEN1_S3(lane->id));
val |= MVEBU_COMPHY_GEN1_S3_FBCK_SEL;
writel(val, priv->base + MVEBU_COMPHY_GEN1_S3(lane->id));
/* rx training timer */
val = readl(priv->base + MVEBU_COMPHY_TRAINING5(lane->id));
val &= ~MVEBU_COMPHY_TRAINING5_RX_TIMER(0x3ff);
val |= MVEBU_COMPHY_TRAINING5_RX_TIMER(0x13);
writel(val, priv->base + MVEBU_COMPHY_TRAINING5(lane->id));
/* tx train peak to peak hold */
val = readl(priv->base + MVEBU_COMPHY_TRAINING0(lane->id));
val |= MVEBU_COMPHY_TRAINING0_P2P_HOLD;
writel(val, priv->base + MVEBU_COMPHY_TRAINING0(lane->id));
val = readl(priv->base + MVEBU_COMPHY_TX_PRESET(lane->id));
val &= ~MVEBU_COMPHY_TX_PRESET_INDEX(0xf);
val |= MVEBU_COMPHY_TX_PRESET_INDEX(0x2); /* preset coeff */
writel(val, priv->base + MVEBU_COMPHY_TX_PRESET(lane->id));
val = readl(priv->base + MVEBU_COMPHY_FRAME_DETECT3(lane->id));
val &= ~MVEBU_COMPHY_FRAME_DETECT3_LOST_TIMEOUT_EN;
writel(val, priv->base + MVEBU_COMPHY_FRAME_DETECT3(lane->id));
val = readl(priv->base + MVEBU_COMPHY_TX_TRAIN_PRESET(lane->id));
val |= MVEBU_COMPHY_TX_TRAIN_PRESET_16B_AUTO_EN |
MVEBU_COMPHY_TX_TRAIN_PRESET_PRBS11;
writel(val, priv->base + MVEBU_COMPHY_TX_TRAIN_PRESET(lane->id));
val = readl(priv->base + MVEBU_COMPHY_FRAME_DETECT0(lane->id));
val &= ~MVEBU_COMPHY_FRAME_DETECT0_PATN(0x1ff);
val |= MVEBU_COMPHY_FRAME_DETECT0_PATN(0x88);
writel(val, priv->base + MVEBU_COMPHY_FRAME_DETECT0(lane->id));
val = readl(priv->base + MVEBU_COMPHY_DME(lane->id));
val |= MVEBU_COMPHY_DME_ETH_MODE;
writel(val, priv->base + MVEBU_COMPHY_DME(lane->id));
val = readl(priv->base + MVEBU_COMPHY_VDD_CAL0(lane->id));
val |= MVEBU_COMPHY_VDD_CAL0_CONT_MODE;
writel(val, priv->base + MVEBU_COMPHY_VDD_CAL0(lane->id));
val = readl(priv->base + MVEBU_SP_CALIB(lane->id));
val &= ~MVEBU_SP_CALIB_SAMPLER(0x3);
val |= MVEBU_SP_CALIB_SAMPLER(0x3) |
MVEBU_SP_CALIB_SAMPLER_EN;
writel(val, priv->base + MVEBU_SP_CALIB(lane->id));
val &= ~MVEBU_SP_CALIB_SAMPLER_EN;
writel(val, priv->base + MVEBU_SP_CALIB(lane->id));
/* External rx regulator */
val = readl(priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
val &= ~MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1f);
val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a);
writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val);
val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id);
regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
switch (lane->submode) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_2500BASEX:
ret = mvebu_comphy_set_mode_sgmii(phy); break; case PHY_INTERFACE_MODE_RXAUI:
ret = mvebu_comphy_set_mode_rxaui(phy); break; case PHY_INTERFACE_MODE_10GBASER:
ret = mvebu_comphy_set_mode_10gbaser(phy); break; default: return -ENOTSUPP;
}
/* digital reset */
val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
val |= MVEBU_COMPHY_SERDES_CFG1_RF_RESET;
writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
priv->dev = &pdev->dev;
priv->regmap =
syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "marvell,system-controller"); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap);
priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(priv->base)) return PTR_ERR(priv->base);
/* * Ignore error if clocks have not been initialized properly for DT * compatibility reasons.
*/
ret = mvebu_comphy_init_clks(priv); if (ret) { if (ret == -EPROBE_DEFER) return ret;
dev_warn(&pdev->dev, "cannot initialize clocks\n");
}
/* * Hack to retrieve a physical offset relative to this CP that will be * given to the firmware
*/
priv->cp_phys = res->start;
/* * All modes are supported in this driver so we could call * mvebu_comphy_power_off(phy) here to avoid relying on the * bootloader/firmware configuration, but for compatibility * reasons we cannot de-configure the COMPHY without being sure * that the firmware is up-to-date and fully-featured.
*/
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.