bcwc_pcie: Rework PLL setup and minor fixes/changes

Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
This commit is contained in:
Patrik Jakobsson
2015-06-29 21:00:14 +02:00
parent 13eae07583
commit cc61a7ef05

109
bcwc_hw.c
View File

@@ -103,12 +103,13 @@ static int bcwc_hw_s2_pll_init(struct bcwc_private *dev_priv, u32 ddr_speed)
u32 reg; u32 reg;
int retries = 0; int retries = 0;
ref_clk_25 = BCWC_S2_REG_READ(S2_PLL_STATUS_04) & S2_PLL_REFCLK; reg = BCWC_S2_REG_READ(S2_PLL_REFCLK);
ref_clk_25 = reg & S2_PLL_REFCLK_25MHZ ? 1 : 0;
if (ref_clk_25) if (ref_clk_25)
dev_info(&dev_priv->pdev->dev, "Refclk: 25MHz\n"); dev_info(&dev_priv->pdev->dev, "Refclk: 25MHz (0x%x)\n", reg);
else else
dev_info(&dev_priv->pdev->dev, "Refclk: 24MHz\n"); dev_info(&dev_priv->pdev->dev, "Refclk: 24MHz (0x%x\n", reg);
if (ddr_speed == 400) { if (ddr_speed == 400) {
if (ref_clk_25) { if (ref_clk_25) {
@@ -145,8 +146,8 @@ static int bcwc_hw_s2_pll_init(struct bcwc_private *dev_priv, u32 ddr_speed)
dev_err(&dev_priv->pdev->dev, dev_err(&dev_priv->pdev->dev,
"Unsupported DDR speed %uMHz, using 450MHz\n", "Unsupported DDR speed %uMHz, using 450MHz\n",
ddr_speed); ddr_speed);
ddr_speed = 450;
} }
ddr_speed = 450;
if (ref_clk_25) { if (ref_clk_25) {
/* Ref clk 25 */ /* Ref clk 25 */
@@ -166,10 +167,10 @@ static int bcwc_hw_s2_pll_init(struct bcwc_private *dev_priv, u32 ddr_speed)
ddr_speed); ddr_speed);
do { do {
reg = BCWC_S2_REG_READ(S2_PLL_STATUS_0C); reg = BCWC_S2_REG_READ(S2_PLL_CMU_STATUS);
udelay(10); udelay(10);
retries++; retries++;
} while ((reg & 0x8000) == 0 && retries <= 10000); } while (((reg & 0xff00) & S2_PLL_CMU_STATUS_LOCKED) && retries <= 10000);
if (retries > 10000) { if (retries > 10000) {
dev_info(&dev_priv->pdev->dev, "Failed to lock S2 PLL: 0x%x\n", dev_info(&dev_priv->pdev->dev, "Failed to lock S2 PLL: 0x%x\n",
@@ -185,11 +186,10 @@ static int bcwc_hw_s2_pll_init(struct bcwc_private *dev_priv, u32 ddr_speed)
udelay(10000); udelay(10000);
reg = BCWC_S2_REG_READ(S2_PLL_STATUS_A8); reg = BCWC_S2_REG_READ(S2_PLL_STATUS_A8);
if (reg & 0x1) { if (reg & S2_PLL_BYPASS)
dev_info(&dev_priv->pdev->dev, "S2 PLL is in bypass mode\n"); dev_info(&dev_priv->pdev->dev, "S2 PLL is in bypass mode\n");
} else { else
dev_info(&dev_priv->pdev->dev, "S2 PLL is in non-bypass mode\n"); dev_info(&dev_priv->pdev->dev, "S2 PLL is in non-bypass mode\n");
}
return 0; return 0;
} }
@@ -295,9 +295,6 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
u32 vtt_cons, vtt_ovr; u32 vtt_cons, vtt_ovr;
int ret, i; int ret, i;
/* Set DDR speed (450 MHz for now) */
dev_priv->ddr_speed = 450;
/* Read PCI config command register */ /* Read PCI config command register */
ret = pci_read_config_dword(dev_priv->pdev, 4, &cmd); ret = pci_read_config_dword(dev_priv->pdev, 4, &cmd);
if (ret) { if (ret) {
@@ -312,26 +309,24 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
} }
reg = BCWC_S2_REG_READ(S2_PLL_CTRL_9C); reg = BCWC_S2_REG_READ(S2_PLL_CTRL_9C);
reg &= 0xfffffcff; BCWC_S2_REG_WRITE(reg & 0xfffffcff, S2_PLL_CTRL_9C);
BCWC_S2_REG_WRITE(reg, S2_PLL_CTRL_9C);
BCWC_S2_REG_WRITE(reg | 0x300, S2_PLL_CTRL_9C); BCWC_S2_REG_WRITE(reg | 0x300, S2_PLL_CTRL_9C);
/* Default to 450 MHz DDR speed for now */
bcwc_hw_s2_pll_init(dev_priv, dev_priv->ddr_speed); bcwc_hw_s2_pll_init(dev_priv, dev_priv->ddr_speed);
bcwc_hw_ddr_phy_soft_reset(dev_priv); bcwc_hw_ddr_phy_soft_reset(dev_priv);
/* Not sure what this is yet (perhaps safe/slow DDR PLL settings) */ BCWC_S2_REG_WRITE(0x2, S2_DDR40_WL_DRV_PAD_CTL);
BCWC_S2_REG_WRITE(0x2, S2_2BA4); BCWC_S2_REG_WRITE(0x2, S2_DDR40_WL_CLK_PAD_DISABLE);
BCWC_S2_REG_WRITE(0x2, S2_2BA8);
/* Disable the hardware frequency change function */ /* Disable the hardware frequency change function */
BCWC_S2_REG_WRITE(0x3f4, S2_20F8); BCWC_S2_REG_WRITE(0x3f4, S2_20F8);
/* Setup the PLL */ /* Setup the PLL */
BCWC_S2_REG_WRITE(0x40, S2_2434); BCWC_S2_REG_WRITE(0x40, S2_2434);
BCWC_S2_REG_WRITE(0x10000000, S2_2438); BCWC_S2_REG_WRITE(0x10000000, S2_2438);
BCWC_S2_REG_WRITE(0x4, S2_2424);
BCWC_S2_REG_WRITE(0x1f37291, S2_2430);
/* Wait for DDR PLL to lock */ /* Wait for DDR PLL to lock */
for (i = 0; i <= 10000; i++) { for (i = 0; i <= 10000; i++) {
@@ -364,6 +359,7 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
udelay(10000); udelay(10000);
/* WL */
BCWC_S2_REG_WRITE(0x0c10, S2_DDR40_PHY_PLL_DIV); BCWC_S2_REG_WRITE(0x0c10, S2_DDR40_PHY_PLL_DIV);
BCWC_S2_REG_WRITE(0x0010, S2_DDR40_PHY_PLL_CFG); BCWC_S2_REG_WRITE(0x0010, S2_DDR40_PHY_PLL_CFG);
@@ -384,22 +380,32 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
"DDR40 PHY PLL locked on safe settings\n"); "DDR40 PHY PLL locked on safe settings\n");
/* Default is DDR model 4 */ /* Default is DDR model 4 */
if (dev_priv->ddr_model == 2) switch (dev_priv->ddr_model) {
val = 0x42500c2; case 4:
else
val = 0x46a00c2; val = 0x46a00c2;
break;
case 2:
val = 0x42500c2;
break;
default:
val = 0;
}
BCWC_S2_REG_WRITE(0x10737545, S2_DDR_20A0); BCWC_S2_REG_WRITE(0x10737545, S2_DDR_20A0);
BCWC_S2_REG_WRITE(0x12643173, S2_DDR_20A4); BCWC_S2_REG_WRITE(0x12643173, S2_DDR_20A4);
BCWC_S2_REG_WRITE(0xff3f, S2_DDR_20A8); BCWC_S2_REG_WRITE(0xff3f, S2_DDR_20A8);
BCWC_S2_REG_WRITE(val, S2_DDR_20B0); BCWC_S2_REG_WRITE(val, S2_DDR_20B0);
BCWC_S2_REG_WRITE(0x101f, S2_DDR_2118); BCWC_S2_REG_WRITE(0x101f, S2_DDR_2118);
BCWC_S2_REG_WRITE(0x1c0, S2_DDR40_AUX_CTL); BCWC_S2_REG_WRITE(0x1c0, S2_DDR40_PHY_AUX_CTL);
if (dev_priv->ddr_model == 2) switch (dev_priv->ddr_model) {
val = 0x2155558; case 4:
else
val = 0x2159518; val = 0x2159518;
break;
case 2:
val = 0x2155558;
break;
}
BCWC_S2_REG_WRITE(val, S2_DDR40_STRAP_CTL); BCWC_S2_REG_WRITE(val, S2_DDR40_STRAP_CTL);
@@ -488,7 +494,7 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
"First DDR40 VDL calibration completed after %d us", "First DDR40 VDL calibration completed after %d us",
i); i);
if (!(reg & 0x2)) { if ((reg & 0x2) == 0) {
dev_info(&dev_priv->pdev->dev, dev_info(&dev_priv->pdev->dev,
"...but failed to lock\n"); "...but failed to lock\n");
} }
@@ -499,7 +505,8 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
} }
BCWC_S2_REG_WRITE(0, S2_DDR40_PHY_VDL_CTL); BCWC_S2_REG_WRITE(0, S2_DDR40_PHY_VDL_CTL);
BCWC_S2_REG_WRITE(0x200, S2_DDR40_PHY_VDL_CTL); BCWC_S2_REG_WRITE(0, S2_DDR40_PHY_VDL_CTL); /* Needed? */
BCWC_S2_REG_WRITE(0x200, S2_DDR40_PHY_VDL_CTL); /* calib steps */
for (i = 0; i < 1000; i++) { for (i = 0; i < 1000; i++) {
reg = BCWC_S2_REG_READ(S2_DDR40_PHY_VDL_STATUS); reg = BCWC_S2_REG_READ(S2_DDR40_PHY_VDL_STATUS);
@@ -508,26 +515,17 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
udelay(1); udelay(1);
} }
step_size = 0; dev_info(&dev_priv->pdev->dev,
"Second DDR40 VDL calibration completed after %d us\n", i);
if (reg & 0x1) { if (reg & 0x2) {
dev_info(&dev_priv->pdev->dev, step_size = (reg & S2_DDR40_PHY_VDL_STEP_MASK) >>
"Second DDR40 VDL calibration completed after %d us\n", S2_DDR40_PHY_VDL_STEP_SHIFT;
i); dev_info(&dev_priv->pdev->dev, "Using step size %u\n",
step_size);
if (!(reg & 0x2)) {
step_size = (reg >> 2) & 0x3ff;
dev_info(&dev_priv->pdev->dev, "Using step size %u\n",
step_size);
}
} else { } else {
dev_info(&dev_priv->pdev->dev,
"Second DDR40 VDL calibration failed, using default step size\n");
}
val = 1000000 / dev_priv->ddr_speed; val = 1000000 / dev_priv->ddr_speed;
if (step_size == 0) {
step_size = (val * 0x4ec4ec4f) >> 22; step_size = (val * 0x4ec4ec4f) >> 22;
dev_info(&dev_priv->pdev->dev, "Using default step size (%u)\n", dev_info(&dev_priv->pdev->dev, "Using default step size (%u)\n",
step_size); step_size);
@@ -536,7 +534,9 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
dev_priv->vdl_step_size = step_size; dev_priv->vdl_step_size = step_size;
vdl_fine = BCWC_S2_REG_READ(S2_DDR40_PHY_VDL_CHAN_STATUS); vdl_fine = BCWC_S2_REG_READ(S2_DDR40_PHY_VDL_CHAN_STATUS);
if (!(vdl_fine & 2)) {
/* lock = 1 and byte_sel = 1 */
if ((vdl_fine & 2) == 0) {
vdl_fine = (vdl_fine >> 8) & 0x3f; vdl_fine = (vdl_fine >> 8) & 0x3f;
vdl_fine |= 0x10100; vdl_fine |= 0x10100;
@@ -576,24 +576,26 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
/* Process, Voltage and Temperature compensation */ /* Process, Voltage and Temperature compensation */
BCWC_S2_REG_WRITE(0xc0fff, S2_DDR40_PHY_ZQ_PVT_COMP_CTL); BCWC_S2_REG_WRITE(0xc0fff, S2_DDR40_PHY_ZQ_PVT_COMP_CTL);
BCWC_S2_REG_WRITE(0x2, S2_DDR40_PHY_DRV_PAD_CTL); BCWC_S2_REG_WRITE(0x2, S2_DDR40_PHY_DRV_PAD_CTL);
BCWC_S2_REG_WRITE(0x2, S2_2BA4); BCWC_S2_REG_WRITE(0x2, S2_DDR40_WL_DRV_PAD_CTL);
val = 1000000 / dev_priv->ddr_speed; val = 1000000 / dev_priv->ddr_speed;
reg = 4; reg = 4;
if (val >= 400) { if (val >= 400) {
if (val > 900) if (val > 900)
reg |= 0xff; reg = 1;
reg += 5; reg += 5;
} }
/* DDR read FIFO delay? */ /* DDR read FIFO delay? */
BCWC_S2_REG_WRITE(reg, S2_DDR40_RD_DATA_DLY_FIFO); BCWC_S2_REG_WRITE(reg, S2_DDR40_WL_RD_DATA_DLY);
BCWC_S2_REG_WRITE(0x2, S2_DDR40_2B64); BCWC_S2_REG_WRITE(0x2, S2_DDR40_WL_READ_CTL); /* le_adj, te_adj */
BCWC_S2_REG_WRITE(0x3, S2_2BAC); BCWC_S2_REG_WRITE(0x3, S2_DDR40_WL_WR_PREAMBLE_MODE); /* mode, long */
reg = BCWC_S2_REG_READ(S2_2BA0); /* dq_oeb, dq_reb, dq_iddq, dq_rxenb */
BCWC_S2_REG_WRITE(reg & 0xff0fffff, S2_2BA0); reg = BCWC_S2_REG_READ(S2_DDR40_WL_IDLE_PAD_CTL);
BCWC_S2_REG_WRITE(reg & 0xff0fffff, S2_DDR40_WL_IDLE_PAD_CTL);
udelay(500); udelay(500);
BCWC_S2_REG_WRITE(0, S2_DDR_2004); BCWC_S2_REG_WRITE(0, S2_DDR_2004);
@@ -623,6 +625,7 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv)
val = 0x0fffffff; val = 0x0fffffff;
break; break;
default: default:
/* Probably just invalid model */
val = dev_priv->ddr_model; val = dev_priv->ddr_model;
} }