diff options
author | Jaehoon Chung <jh80.chung@samsung.com> | 2015-04-08 15:30:53 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2016-12-14 13:44:34 +0900 |
commit | 8a98afa4fd6163404c1b9e6820fec1ce8f61a6cf (patch) | |
tree | ead0adaa65e7e821326cf7cfa12ff5b700a270aa /drivers/pci | |
parent | f903272be5fc0f58954bef4bde4298560591d243 (diff) |
local/pci: pci-exynos5433: Add workaround code to control bcm4358 device
To control bcm4358 device driver, add the workaround code.
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/pci-exynos5433.c | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/drivers/pci/host/pci-exynos5433.c b/drivers/pci/host/pci-exynos5433.c index 31b3e1537061..243776080d6f 100644 --- a/drivers/pci/host/pci-exynos5433.c +++ b/drivers/pci/host/pci-exynos5433.c @@ -109,6 +109,9 @@ struct exynos_pcie { */ #define PCIE_PHY_OFFSET(x) ((x) * 0x4) +/* Workaround code to use broadcom device driver */ +static struct exynos_pcie *g_pcie; + void exynos_pcie_register_dump(struct pcie_port *pp) { struct exynos_pcie *g_pcie = to_exynos_pcie(pp); @@ -307,6 +310,7 @@ static int exynos_pcie_reset(struct pcie_port *pp) val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_LEVEL); if (val & 0x10) { + /* EP BAR(Base Address Register) Setting 64 bit */ writel(0x0c200004, ep->pp.va_cfg0_base + 0x10); writel(0x0c400004, ep->pp.va_cfg0_base + 0x18); return 0; @@ -342,7 +346,7 @@ static int exynos_pcie_establish_link(struct pcie_port *pp) exynos_pcie_assert_phy_reset(pp); - /* Setup root complext */ + /* Setup root complex */ dw_pcie_setup_rc(pp); /* assert LTSSM enable */ @@ -374,7 +378,9 @@ static int exynos_pcie_link_up(struct pcie_port *pp) u32 val; val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP); - if (val == PCIE_ELBI_LTSSM_ENABLE) + val &= 0x1f; + + if (val >= 0x0d && val <= 0x15) return 1; return 0; @@ -435,7 +441,7 @@ static struct pcie_host_ops exynos_pcie_host_ops = { .link_up = exynos_pcie_link_up, }; -static int exynos_pcie_probe(struct platform_device *pdev) +static int __init exynos_pcie_probe(struct platform_device *pdev) { struct exynos_pcie *exynos_pcie; struct device_node *np = pdev->dev.of_node; @@ -502,6 +508,9 @@ static int exynos_pcie_probe(struct platform_device *pdev) exynos_pcie->pmureg = NULL; } + /* Workaround code to use broadcom device driver */ + g_pcie = exynos_pcie; + pp->irq = platform_get_irq(pdev, 0); if (!pp->irq) { dev_err(&pdev->dev, "failed to get irq\n"); @@ -533,7 +542,63 @@ fail_bus_clk: fail_clk: clk_disable_unprepare(exynos_pcie->clk); return ret; +} + +/* + * Workaround : To enable the broadcom device. + */ +void exynos_pcie_poweron(void) +{ + u32 val; + + if (g_pcie) { + clk_prepare_enable(g_pcie->clk); + clk_prepare_enable(g_pcie->bus_clk); + + val = exynos_pcie_readl(g_pcie->phy_base, PCIE_PHY_OFFSET(0x55)); + val &= ~(0x1 << 3); + exynos_pcie_writel(g_pcie->phy_base, val, PCIE_PHY_OFFSET(0x55)); + + udelay(100); + + val = exynos_pcie_readl(g_pcie->phy_base, PCIE_PHY_OFFSET(0x21)); + val &= ~(0x1 << 4); + exynos_pcie_writel(g_pcie->phy_base, val, PCIE_PHY_OFFSET(0x21)); + + exynos_pcie_establish_link(&g_pcie->pp); + val = exynos_pcie_readl(g_pcie->elbi_base, PCIE_IRQ_SPECIAL); + exynos_pcie_writel(g_pcie->elbi_base, val, PCIE_IRQ_SPECIAL); + } +} + +/* + * Workaround : To enable the broadcom device. + */ +void exynos_pcie_poweroff(void) +{ + u32 val; + + if (g_pcie) { + + if (g_pcie->reset_gpio) + gpio_set_value(g_pcie->reset_gpio, 0); + + exynos_pcie_writel(g_pcie->elbi_base, PCIE_ELBI_LTSSM_DISABLE, + PCIE_APP_LTSSM_ENABLE); + + val = exynos_pcie_readl(g_pcie->phy_base, PCIE_PHY_OFFSET(0x55)); + val |= (0x1 << 3); + exynos_pcie_writel(g_pcie->phy_base, val, PCIE_PHY_OFFSET(0x55)); + + val = exynos_pcie_readl(g_pcie->phy_base, PCIE_PHY_OFFSET(0x21)); + val |= (0x1 << 4); + exynos_pcie_writel(g_pcie->phy_base, val, PCIE_PHY_OFFSET(0x21)); + + clk_disable_unprepare(g_pcie->bus_clk); + clk_disable_unprepare(g_pcie->clk); + + } } static int exynos_pcie_remove(struct platform_device *pdev) |