From 66d13133a000dfd06aed7b7032aa7aecf01a61fa Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Fri, 27 Jun 2014 23:36:30 +0200 Subject: [PATCH] bcwc_pcie: DDR PPL programming stuff Signed-off-by: Patrik Jakobsson --- bcwc_drv.c | 2 + bcwc_drv.h | 2 + bcwc_hw.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++- bcwc_hw.h | 1 + bcwc_reg.h | 14 ++++++- 5 files changed, 125 insertions(+), 4 deletions(-) diff --git a/bcwc_drv.c b/bcwc_drv.c index 738cc76..e03621a 100644 --- a/bcwc_drv.c +++ b/bcwc_drv.c @@ -162,6 +162,8 @@ static int bcwc_pci_probe(struct pci_dev *pdev, pci_set_master(pdev); pci_set_drvdata(pdev, dev_priv); + dev_priv->ddr_model = 4; + bcwc_hw_init(dev_priv); return 0; diff --git a/bcwc_drv.h b/bcwc_drv.h index 22af202..a8cb68e 100644 --- a/bcwc_drv.h +++ b/bcwc_drv.h @@ -38,6 +38,8 @@ struct bcwc_private { /* Hardware info */ u32 core_clk; + u32 ddr_model; + u32 ddr_speed; /* DDR_PHY saved registers. Offsets need to be initialized somewhere */ u32 ddr_phy_num_regs; diff --git a/bcwc_hw.c b/bcwc_hw.c index 0b7a7e1..759fd2b 100644 --- a/bcwc_hw.c +++ b/bcwc_hw.c @@ -253,9 +253,13 @@ static int bcwc_hw_ddr_phy_soft_reset(struct bcwc_private *dev_priv) static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv) { u32 cmd; + u32 val; u32 reg; int ret, i; + /* Set DDR speed (450 MHz for now) */ + dev_priv->ddr_speed = 450; + /* Read PCI config command register */ ret = pci_read_config_dword(dev_priv->pdev, 4, &cmd); if (ret) { @@ -333,10 +337,10 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv) udelay(10000); - BCWC_S2_REG_WRITE(0x0c10, S2_281C); + BCWC_S2_REG_WRITE(0x0c10, S2_DDR_281C); bcwc_hw_pci_post(dev_priv); - BCWC_S2_REG_WRITE(0x0010, S2_2814); + BCWC_S2_REG_WRITE(0x0010, S2_DDR_2814); bcwc_hw_pci_post(dev_priv); for (i = 0; i <= 10000; i++) { @@ -354,6 +358,108 @@ static int bcwc_hw_s2_init_ddr_controller_soc(struct bcwc_private *dev_priv) dev_info(&dev_priv->pdev->dev, "DDR PHY PLL locked on safe settings\n"); + /* Default is DDR model 4 */ + if (dev_priv->ddr_model == 2) + val = 0x42500c2; + else + val = 0x46a00c2; + + BCWC_S2_REG_WRITE(0x10737545, S2_DDR_20A0); + bcwc_hw_pci_post(dev_priv); + + BCWC_S2_REG_WRITE(0x12643173, S2_DDR_20A4); + bcwc_hw_pci_post(dev_priv); + + BCWC_S2_REG_WRITE(0xff3f, S2_DDR_20A8); + bcwc_hw_pci_post(dev_priv); + + BCWC_S2_REG_WRITE(val, S2_DDR_20B0); + bcwc_hw_pci_post(dev_priv); + + BCWC_S2_REG_WRITE(0x101f, S2_DDR_2118); + bcwc_hw_pci_post(dev_priv); + + BCWC_S2_REG_WRITE(0x1c0, S2_DDR_2820); + bcwc_hw_pci_post(dev_priv); + + if (dev_priv->ddr_model == 2) + val = 0x2155558; + else + val = 0x2159518; + + BCWC_S2_REG_WRITE(val, S2_DDR_28B0); + bcwc_hw_pci_post(dev_priv); + + if (dev_priv->ddr_speed == 450) + val = 0x108307; + else + val = 0x108286; + + BCWC_S2_REG_WRITE(val, S2_DDR_28B4); + bcwc_hw_pci_post(dev_priv); + + BCWC_S2_REG_WRITE(0x2159559, S2_DDR_28B0); + bcwc_hw_pci_post(dev_priv); + + /* Polling for STRAP valid */ + for (i = 0; i < 10000; i++) { + reg = BCWC_S2_REG_READ(S2_DDR_STATUS_28B8); + if (reg & 0x1) + break; + udelay(10); + } + + if (i >= 10000) { + dev_err(&dev_priv->pdev->dev, + "Timeout waiting for STRAP valid\n"); + return -ENODEV; + } else { + dev_info(&dev_priv->pdev->dev, "STRAP valid\n"); + } + + /* Manual DDR40 PHY init */ + if (dev_priv->ddr_speed != 450) { + dev_warn(&dev_priv->pdev->dev, + "DDR frequency is %u (should be 450 MHz)", + dev_priv->ddr_speed); + } + + dev_info(&dev_priv->pdev->dev, + "Configuring DDR PLLs for %u MHz\n", dev_priv->ddr_speed); + + if ((dev_priv->ddr_speed * 2) < 500) + val = 0x2040; + else + val = 0x810; + + /* Start programming the DDR PLL */ + reg = BCWC_S2_REG_READ(S2_DDR_281C); + reg &= 0xffffc700; + val |= reg; + + BCWC_S2_REG_WRITE(val, S2_DDR_281C); + bcwc_hw_pci_post(dev_priv); + + reg = BCWC_S2_REG_READ(S2_DDR_2814); + reg &= 0xfffffffd; + BCWC_S2_REG_WRITE(reg, S2_DDR_2814); + bcwc_hw_pci_post(dev_priv); + + /* Start polling for the lock */ + for (i = 0; i < 100; i++) { + reg = BCWC_S2_REG_READ(S2_DDR_PLL_STATUS_2810); + if (reg & S2_DDR_PLL_STATUS_2810_LOCKED) + break; + udelay(1); + } + + if (i >= 100) { + dev_err(&dev_priv->pdev->dev, "Failed to lock the DDR PLL\n"); + return -ENODEV; + } + + dev_info(&dev_priv->pdev->dev, "DDR PLL is locked\n"); + /* FIXME: Unfinished */ return 0; diff --git a/bcwc_hw.h b/bcwc_hw.h index f0b66f7..2152bf3 100644 --- a/bcwc_hw.h +++ b/bcwc_hw.h @@ -16,6 +16,7 @@ #define BCWC_S2_REG_READ(offset) _BCWC_S2_REG_READ(dev_priv, (offset)) #define BCWC_S2_REG_WRITE(val, offset) _BCWC_S2_REG_WRITE(dev_priv, (val), (offset)) + #define BCWC_ISP_REG_READ(offset) _BCWC_ISP_REG_READ(dev_priv, (offset)) #define BCWC_ISP_REG_WRITE(val, offset) _BCWC_ISP_REG_WRITE(dev_priv, (val), (offset)) diff --git a/bcwc_reg.h b/bcwc_reg.h index c4bf375..7b4b4f4 100644 --- a/bcwc_reg.h +++ b/bcwc_reg.h @@ -48,7 +48,13 @@ #define S2_PLL_CTRL_510 0x0510 /* Probably DDR PHY PLL registers */ +#define S2_DDR_20A0 0x20a0 +#define S2_DDR_20A4 0x20a4 +#define S2_DDR_20A8 0x20a8 +#define S2_DDR_20B0 0x20b0 + #define S2_20F8 0x20f8 +#define S2_DDR_2118 0x2118 #define S2_2430 0x2430 #define S2_2434 0x2434 #define S2_2438 0x2438 @@ -64,8 +70,12 @@ #define S2_DDR_PLL_STATUS_2810 0x2810 #define S2_DDR_PLL_STATUS_2810_LOCKED 0x1 -#define S2_2814 0x2814 -#define S2_281C 0x281c +#define S2_DDR_2814 0x2814 +#define S2_DDR_281C 0x281c +#define S2_DDR_2820 0x2820 +#define S2_DDR_28B0 0x28b0 +#define S2_DDR_28B4 0x28b4 +#define S2_DDR_STATUS_28B8 0x28b8 #define S2_2BA4 0x2ba4 #define S2_2BA8 0x2ba8