aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJingoo Han <jg1.han@samsung.com>2013-09-06 04:21:45 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-09-25 18:36:03 -0400
commitf62b878b4dfc71de24ea4bc085d042862cba88e4 (patch)
tree48a874724465014062596b19f175f32f1cfc9999
parentf342d940ee0e3a2b5197fd4fbade1cb6bbc960b7 (diff)
PCI: exynos: Turn off power of phy block when link failed
When link failed, there is no need to turn on phy block. Also, turning on phy block is added, in order to turn on phy block regardless of the default value of phy registers. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/host/pci-exynos.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f062acaf052a..ee692c2c3d73 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -78,18 +78,28 @@ struct exynos_pcie {
78#define PCIE_PHY_PLL_BIAS 0x00c 78#define PCIE_PHY_PLL_BIAS 0x00c
79#define PCIE_PHY_DCC_FEEDBACK 0x014 79#define PCIE_PHY_DCC_FEEDBACK 0x014
80#define PCIE_PHY_PLL_DIV_1 0x05c 80#define PCIE_PHY_PLL_DIV_1 0x05c
81#define PCIE_PHY_COMMON_POWER 0x064
82#define PCIE_PHY_COMMON_PD_CMN (0x1 << 3)
81#define PCIE_PHY_TRSV0_EMP_LVL 0x084 83#define PCIE_PHY_TRSV0_EMP_LVL 0x084
82#define PCIE_PHY_TRSV0_DRV_LVL 0x088 84#define PCIE_PHY_TRSV0_DRV_LVL 0x088
83#define PCIE_PHY_TRSV0_RXCDR 0x0ac 85#define PCIE_PHY_TRSV0_RXCDR 0x0ac
86#define PCIE_PHY_TRSV0_POWER 0x0c4
87#define PCIE_PHY_TRSV0_PD_TSV (0x1 << 7)
84#define PCIE_PHY_TRSV0_LVCC 0x0dc 88#define PCIE_PHY_TRSV0_LVCC 0x0dc
85#define PCIE_PHY_TRSV1_EMP_LVL 0x144 89#define PCIE_PHY_TRSV1_EMP_LVL 0x144
86#define PCIE_PHY_TRSV1_RXCDR 0x16c 90#define PCIE_PHY_TRSV1_RXCDR 0x16c
91#define PCIE_PHY_TRSV1_POWER 0x184
92#define PCIE_PHY_TRSV1_PD_TSV (0x1 << 7)
87#define PCIE_PHY_TRSV1_LVCC 0x19c 93#define PCIE_PHY_TRSV1_LVCC 0x19c
88#define PCIE_PHY_TRSV2_EMP_LVL 0x204 94#define PCIE_PHY_TRSV2_EMP_LVL 0x204
89#define PCIE_PHY_TRSV2_RXCDR 0x22c 95#define PCIE_PHY_TRSV2_RXCDR 0x22c
96#define PCIE_PHY_TRSV2_POWER 0x244
97#define PCIE_PHY_TRSV2_PD_TSV (0x1 << 7)
90#define PCIE_PHY_TRSV2_LVCC 0x25c 98#define PCIE_PHY_TRSV2_LVCC 0x25c
91#define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 99#define PCIE_PHY_TRSV3_EMP_LVL 0x2c4
92#define PCIE_PHY_TRSV3_RXCDR 0x2ec 100#define PCIE_PHY_TRSV3_RXCDR 0x2ec
101#define PCIE_PHY_TRSV3_POWER 0x304
102#define PCIE_PHY_TRSV3_PD_TSV (0x1 << 7)
93#define PCIE_PHY_TRSV3_LVCC 0x31c 103#define PCIE_PHY_TRSV3_LVCC 0x31c
94 104
95static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg) 105static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
@@ -203,6 +213,58 @@ static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)
203 exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET); 213 exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
204} 214}
205 215
216static void exynos_pcie_power_on_phy(struct pcie_port *pp)
217{
218 u32 val;
219 struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
220
221 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
222 val &= ~PCIE_PHY_COMMON_PD_CMN;
223 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
224
225 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
226 val &= ~PCIE_PHY_TRSV0_PD_TSV;
227 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
228
229 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
230 val &= ~PCIE_PHY_TRSV1_PD_TSV;
231 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
232
233 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
234 val &= ~PCIE_PHY_TRSV2_PD_TSV;
235 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
236
237 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
238 val &= ~PCIE_PHY_TRSV3_PD_TSV;
239 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
240}
241
242static void exynos_pcie_power_off_phy(struct pcie_port *pp)
243{
244 u32 val;
245 struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
246
247 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
248 val |= PCIE_PHY_COMMON_PD_CMN;
249 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
250
251 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
252 val |= PCIE_PHY_TRSV0_PD_TSV;
253 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
254
255 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
256 val |= PCIE_PHY_TRSV1_PD_TSV;
257 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
258
259 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
260 val |= PCIE_PHY_TRSV2_PD_TSV;
261 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
262
263 val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
264 val |= PCIE_PHY_TRSV3_PD_TSV;
265 exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
266}
267
206static void exynos_pcie_init_phy(struct pcie_port *pp) 268static void exynos_pcie_init_phy(struct pcie_port *pp)
207{ 269{
208 struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); 270 struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
@@ -271,6 +333,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
271 /* de-assert phy reset */ 333 /* de-assert phy reset */
272 exynos_pcie_deassert_phy_reset(pp); 334 exynos_pcie_deassert_phy_reset(pp);
273 335
336 /* power on phy */
337 exynos_pcie_power_on_phy(pp);
338
274 /* initialize phy */ 339 /* initialize phy */
275 exynos_pcie_init_phy(pp); 340 exynos_pcie_init_phy(pp);
276 341
@@ -303,6 +368,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
303 PCIE_PHY_PLL_LOCKED); 368 PCIE_PHY_PLL_LOCKED);
304 dev_info(pp->dev, "PLL Locked: 0x%x\n", val); 369 dev_info(pp->dev, "PLL Locked: 0x%x\n", val);
305 } 370 }
371 /* power off phy */
372 exynos_pcie_power_off_phy(pp);
373
306 dev_err(pp->dev, "PCIe Link Fail\n"); 374 dev_err(pp->dev, "PCIe Link Fail\n");
307 return -EINVAL; 375 return -EINVAL;
308 } 376 }