/* SATA and USB3 PHY offset compared to SATA PHY */ #define COMPHY_LANE2_REGS_BASE 0x200
/* * When accessing common PHY lane registers directly, we need to shift by 1, * since the registers are 16-bit.
*/ #define COMPHY_LANE_REG_DIRECT(reg) (((reg) & 0x7FF) << 1)
/* * This register is not from PHY lane register space. It only exists in the * indirect register space, before the actual PHY lane 2 registers. So the * offset is absolute, not relative to COMPHY_LANE2_REGS_BASE. * It is used only for SATA PHY initialization.
*/ #define COMPHY_RESERVED_REG 0x0E #define PHYCTRL_FRM_PIN_BIT BIT(13)
switch (lane->mode) { case PHY_MODE_SATA: /* SATA must be in Lane2 */ if (lane->id == 2)
clr = COMPHY_SELECTOR_USB3_PHY_SEL_BIT; else goto error; break;
case PHY_MODE_ETHERNET: if (lane->id == 0)
clr = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; elseif (lane->id == 1)
clr = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; else goto error; break;
case PHY_MODE_USB_HOST_SS: if (lane->id == 2)
set = COMPHY_SELECTOR_USB3_PHY_SEL_BIT; elseif (lane->id == 0)
set = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; else goto error; break;
case PHY_MODE_PCIE: /* PCIE must be in Lane1 */ if (lane->id == 1)
set = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; else goto error; break;
default: goto error;
}
spin_lock_irqsave(&lane->priv->lock, flags);
old = readl(lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG); new = (old & ~clr) | set;
writel(new, lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG);
/* Configure phy selector for SATA */
ret = mvebu_a3700_comphy_set_phy_selector(lane); if (ret) return ret;
/* Clear phy isolation mode to make it work in normal mode */
comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL,
0x0, PHY_ISOLATE_MODE);
/* 0. Check the Polarity invert bits */
data = 0x0; if (lane->invert_tx)
data |= TXD_INVERT_BIT; if (lane->invert_rx)
data |= RXD_INVERT_BIT;
mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
/* 3. Use maximum PLL rate (no power save) */
comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL,
USE_MAX_PLL_RATE_BIT, USE_MAX_PLL_RATE_BIT);
/* 4. Reset reserved bit */
comphy_set_indirect(lane->priv, COMPHY_RESERVED_REG,
0x0, PHYCTRL_FRM_PIN_BIT);
/* 5. Set vendor-specific configuration (It is done in sata driver) */ /* XXX: in U-Boot below sequence was executed in this place, in Linux * not. Now it is done only in U-Boot before this comphy * initialization - tests shows that it works ok, but in case of any * future problem it is left for reference. * reg_set(MVEBU_REGS_BASE + 0xe00a0, 0, 0xffffffff); * reg_set(MVEBU_REGS_BASE + 0xe00a4, BIT(6), BIT(6));
*/
/* Wait for > 55 us to allow PLL be enabled */
udelay(PLL_SET_DELAY_US);
/* Polling status */
ret = comphy_lane_reg_poll(lane, COMPHY_DIG_LOOPBACK_EN,
PLL_READY_TX_BIT, COMPHY_PLL_SLEEP,
COMPHY_PLL_TIMEOUT); if (ret)
dev_err(lane->dev, "Failed to lock SATA PLL\n");
fix_idx = 0; for (addr = 0; addr < ARRAY_SIZE(gbe_phy_init); addr++) { /* * All PHY register values are defined in full for 3.125Gbps * SERDES speed. The values required for 1.25 Gbps are almost * the same and only few registers should be "fixed" in * comparison to 3.125 Gbps values. These register values are * stored in "gbe_phy_init_fix" array.
*/ if (!is_1gbps &&
fix_idx < ARRAY_SIZE(gbe_phy_init_fix) &&
gbe_phy_init_fix[fix_idx].addr == addr) { /* Use new value */
val = gbe_phy_init_fix[fix_idx].value;
fix_idx++;
} else {
val = gbe_phy_init[addr];
}
/* Set selector */
ret = mvebu_a3700_comphy_set_phy_selector(lane); if (ret) return ret;
/* * 1. Reset PHY by setting PHY input port PIN_RESET=1. * 2. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep * PHY TXP/TXN output to idle state during PHY initialization * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0.
*/
data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT;
mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT |
PIN_PU_TX_BIT | PHY_RX_INIT_BIT;
comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
/* 4. Release reset to the PHY by setting PIN_RESET=0. */
data = 0x0;
mask = PIN_RESET_COMPHY_BIT;
comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
/* * 5. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide COMPHY * bit rate
*/ switch (lane->submode) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_1000BASEX: /* SGMII 1G, SerDes speed 1.25G */
speed_sel = SERDES_SPEED_1_25_G; break; case PHY_INTERFACE_MODE_2500BASEX: /* 2500Base-X, SerDes speed 3.125G */
speed_sel = SERDES_SPEED_3_125_G; break; default: /* Other rates are not supported */
dev_err(lane->dev, "unsupported phy speed %d on comphy lane%d\n",
lane->submode, lane->id); return -EINVAL;
}
data = GEN_RX_SEL_VALUE(speed_sel) | GEN_TX_SEL_VALUE(speed_sel);
mask = GEN_RX_SEL_MASK | GEN_TX_SEL_MASK;
comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
/* * 6. Wait 10mS for bandgap and reference clocks to stabilize; then * start SW programming.
*/
mdelay(10);
/* 7. Program COMPHY register PHY_MODE */
data = COMPHY_MODE_SERDES;
mask = COMPHY_MODE_MASK;
comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask);
/* * 8. Set COMPHY register REFCLK_SEL to select the correct REFCLK * source
*/
data = 0x0;
mask = PHY_REF_CLK_SEL;
comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask);
/* * 9. Set correct reference clock frequency in COMPHY register * REF_FREF_SEL.
*/ if (lane->priv->xtal_is_40m)
data = REF_FREF_SEL_SERDES_50MHZ; else
data = REF_FREF_SEL_SERDES_25MHZ;
/* * 10. Program COMPHY register PHY_GEN_MAX[1:0] * This step is mentioned in the flow received from verification team. * However the PHY_GEN_MAX value is only meaningful for other interfaces * (not SERDES). For instance, it selects SATA speed 1.5/3/6 Gbps or * PCIe speed 2.5/5 Gbps
*/
/* * 11. Program COMPHY register SEL_BITS to set correct parallel data * bus width
*/
data = DATA_WIDTH_10BIT;
mask = SEL_DATA_WIDTH_MASK;
comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, data, mask);
/* * 12. As long as DFE function needs to be enabled in any mode, * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F * for real chip during COMPHY power on. * The value of the DFE_UPDATE_EN already is 0x3F, because it is the * default value after reset of the PHY.
*/
/* * 13. Program COMPHY GEN registers. * These registers should be programmed based on the lab testing result * to achieve optimal performance. Please contact the CEA group to get * the related GEN table during real chip bring-up. We only required to * run though the entire registers programming flow defined by * "comphy_gbe_phy_init" when the REF clock is 40 MHz. For REF clock * 25 MHz the default values stored in PHY registers are OK.
*/
dev_dbg(lane->dev, "Running C-DPI phy init %s mode\n",
lane->submode == PHY_INTERFACE_MODE_2500BASEX ? "2G5" : "1G"); if (lane->priv->xtal_is_40m)
comphy_gbe_phy_init(lane,
lane->submode != PHY_INTERFACE_MODE_2500BASEX);
/* * 14. Check the PHY Polarity invert bit
*/
data = 0x0; if (lane->invert_tx)
data |= TXD_INVERT_BIT; if (lane->invert_rx)
data |= RXD_INVERT_BIT;
mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
/* * 15. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to * start PHY power up sequence. All the PHY register programming should * be done before PIN_PU_PLL=1. There should be no register programming * for normal PHY operation from this point.
*/
data = PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT;
mask = data;
comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
/* * 16. Wait for PHY power up sequence to finish by checking output ports * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1.
*/
ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1,
PHY_PLL_READY_TX_BIT |
PHY_PLL_READY_RX_BIT,
COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); if (ret) {
dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n",
lane->id); return ret;
}
/* * 17. Set COMPHY input port PIN_TX_IDLE=0
*/
comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, 0x0, PIN_TX_IDLE_BIT);
/* * 18. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. To * start RX initialization. PIN_RX_INIT_DONE will be cleared to 0 by the * PHY After RX initialization is done, PIN_RX_INIT_DONE will be set to * 1 by COMPHY Set PIN_RX_INIT=0 after PIN_RX_INIT_DONE= 1. Please * refer to RX initialization part for details.
*/
comphy_periph_reg_set(lane, COMPHY_PHY_CFG1,
PHY_RX_INIT_BIT, PHY_RX_INIT_BIT);
ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1,
PHY_PLL_READY_TX_BIT |
PHY_PLL_READY_RX_BIT,
COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); if (ret) {
dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n",
lane->id); return ret;
}
ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1,
PHY_RX_INIT_DONE_BIT,
COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); if (ret)
dev_err(lane->dev, "Failed to init RX of SERDES PHY %d\n",
lane->id);
/* * 2. Set BIT0: enable transmitter in high impedance mode * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency * Set BIT6: Tx detect Rx at HiZ mode * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db * together with bit 0 of COMPHY_PIPE_LANE_CFG0 register
*/
data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN;
mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK |
TX_ELEC_IDLE_MODE_EN;
comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1, data, mask);
/* * 4. Set Override Margining Controls From the MAC: * Use margining signals from lane configuration
*/
comphy_lane_reg_set(lane, COMPHY_PIPE_TEST_MODE_CTRL,
MODE_MARGIN_OVERRIDE, 0xFFFF);
/* * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles * set Mode Clock Source = PCLK is generated from REFCLK
*/
data = 0x0;
mask = MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE_MASK |
BUNDLE_SAMPLE_CTRL | PLL_READY_DLY_MASK;
comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO, data, mask);
/* * 6. Set G2 Spread Spectrum Clock Amplitude at 4K
*/
comphy_lane_reg_set(lane, COMPHY_GEN2_SET2,
GS2_TX_SSC_AMP_4128, GS2_TX_SSC_AMP_MASK);
/* * 7. Unset G3 Spread Spectrum Clock Amplitude * set G3 TX and RX Register Master Current Select
*/
data = GS2_VREG_RXTX_MAS_ISET_60U;
mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK |
GS2_RSVD_6_0_MASK;
comphy_lane_reg_set(lane, COMPHY_GEN3_SET2, data, mask);
/* * 8. Check crystal jumper setting and program the Power and PLL Control * accordingly Change RX wait
*/ if (lane->priv->xtal_is_40m) {
ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ;
cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT;
} else {
ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ;
cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT;
}
/* * 10. Enable the output of 500M clock
*/
comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, CLK500M_EN, CLK500M_EN);
/* * 11. Set 20-bit data width
*/
comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN,
DATA_WIDTH_20BIT, 0xFFFF);
/* * 12. Override Speed_PLL value and use MAC PLL
*/
data = SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT;
mask = 0xFFFF;
comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, data, mask);
/* * 13. Check the Polarity invert bit
*/
data = 0x0; if (lane->invert_tx)
data |= TXD_INVERT_BIT; if (lane->invert_rx)
data |= RXD_INVERT_BIT;
mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
/* * 14. Set max speed generation to USB3.0 5Gbps
*/
comphy_lane_reg_set(lane, COMPHY_SYNC_MASK_GEN,
PHY_GEN_MAX_USB3_5G, PHY_GEN_MAX_MASK);
/* * 15. Set capacitor value for FFE gain peaking to 0xF
*/
comphy_lane_reg_set(lane, COMPHY_GEN2_SET3,
GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK);
/* Wait for > 55 us to allow PCLK be enabled */
udelay(PLL_SET_DELAY_US);
ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN,
COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); if (ret)
dev_err(lane->dev, "Failed to lock USB3 PLL\n");
/* 9. Override Speed_PLL value and use MAC PLL */
comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL,
SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT,
0xFFFF);
/* 10. Check the Polarity invert bit */
data = 0x0; if (lane->invert_tx)
data |= TXD_INVERT_BIT; if (lane->invert_rx)
data |= RXD_INVERT_BIT;
mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
/* Wait for > 55 us to allow PCLK be enabled */
udelay(PLL_SET_DELAY_US);
ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN,
COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); if (ret)
dev_err(lane->dev, "Failed to lock PCIE PLL\n");
staticvoid mvebu_a3700_comphy_usb3_power_off(struct mvebu_a3700_comphy_lane *lane)
{ /* * The USB3 MAC sets the USB3 PHY to low state, so we do not * need to power off USB3 PHY again.
*/
}
staticbool mvebu_a3700_comphy_check_mode(int lane, enum phy_mode mode, int submode)
{ int i, n = ARRAY_SIZE(mvebu_a3700_comphy_modes);
/* Unused PHY mux value is 0x0 */ if (mode == PHY_MODE_INVALID) returnfalse;
for (i = 0; i < n; i++) { if (mvebu_a3700_comphy_modes[i].lane == lane &&
mvebu_a3700_comphy_modes[i].mode == mode &&
mvebu_a3700_comphy_modes[i].submode == submode) break;
}
switch (lane->mode) { case PHY_MODE_USB_HOST_SS:
dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id); return mvebu_a3700_comphy_usb3_power_on(lane); case PHY_MODE_SATA:
dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id); return mvebu_a3700_comphy_sata_power_on(lane); case PHY_MODE_ETHERNET:
dev_dbg(lane->dev, "set lane %d to Ethernet mode\n", lane->id); return mvebu_a3700_comphy_ethernet_power_on(lane); case PHY_MODE_PCIE:
dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); return mvebu_a3700_comphy_pcie_power_on(lane); default:
dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode); return -EOPNOTSUPP;
}
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
spin_lock_init(&priv->lock);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "comphy");
priv->comphy_regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->comphy_regs)) return PTR_ERR(priv->comphy_regs);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lane1_pcie_gbe");
priv->lane1_phy_regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->lane1_phy_regs)) return PTR_ERR(priv->lane1_phy_regs);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lane0_usb3_gbe");
priv->lane0_phy_regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->lane0_phy_regs)) return PTR_ERR(priv->lane0_phy_regs);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lane2_sata_usb3");
priv->lane2_phy_indirect = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->lane2_phy_indirect)) return PTR_ERR(priv->lane2_phy_indirect);
/* * Driver needs to know if reference xtal clock is 40MHz or 25MHz. * Old DT bindings do not have xtal clk present. So do not fail here * and expects that default 25MHz reference clock is used.
*/
clk = clk_get(&pdev->dev, "xtal"); if (IS_ERR(clk)) { if (PTR_ERR(clk) == -EPROBE_DEFER) return -EPROBE_DEFER;
dev_warn(&pdev->dev, "missing 'xtal' clk (%ld)\n",
PTR_ERR(clk));
} else {
ret = clk_prepare_enable(clk); if (ret) {
dev_warn(&pdev->dev, "enabling xtal clk failed (%d)\n",
ret);
} else { if (clk_get_rate(clk) == 40000000)
priv->xtal_is_40m = true;
clk_disable_unprepare(clk);
}
clk_put(clk);
}
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.