From d46e322622949cdb8a9a994dbb6dbd04149754b1 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 20 Dec 2017 20:57:25 +0900 Subject: [PATCH] LOCAL / phy: samsung: phy-exynos-pcie: support the exynos5433 pcie for phy This is to support the exynos5433 SoCs for PCIe. (WIP) Change-Id: Ie6a018023789544a330cdaf6b13380a114af2d3f Signed-off-by: Jaehoon Chung --- drivers/phy/samsung/phy-exynos-pcie.c | 148 +++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 4 deletions(-) diff --git a/drivers/phy/samsung/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c index a89c12f..68fab05 100644 --- a/drivers/phy/samsung/phy-exynos-pcie.c +++ b/drivers/phy/samsung/phy-exynos-pcie.c @@ -62,6 +62,23 @@ #define PCIE_PHY_TRSV3_PD_TSV BIT(7) #define PCIE_PHY_TRSV3_LVCC 0x31c +#define PCIE_EXYNOS5433_PMU_PHY_OFFSET 0x730 +#define PCIE_PHY_OFFSET(x) ((x) * 0x4) + +/* Sysreg Fsys register offset and bit for Exynos5433 */ +#define PCIE_EXYNOS5433_PHY_MAC_RESET 0x208 +#define PCIE_MAC_RESET_MASK 0xFF +#define PCIE_MAC_RESET BIT(4) +#define PCIE_L1SUB_CM_CON 0x1010 +#define PCIE_REFCLK_GATING_EN BIT(0) +#define PCIE_EXYNOS5433_PHY_COMMON_RESET 0x1020 +#define PCIE_PHY_RESET BIT(0) +#define PCIE_EXYNOS5433_PHY_GLOBAL_RESET 0x1040 +#define PCIE_GLOBAL_RESET BIT(0) +#define PCIE_REFCLK BIT(1) +#define PCIE_REFCLK_MASK 0x16 +#define PCIE_APP_REQ_EXIT_L1_MODE BIT(5) + struct exynos_pcie_phy_data { const struct phy_ops *ops; }; @@ -71,6 +88,8 @@ struct exynos_pcie_phy { const struct exynos_pcie_phy_data *drv_data; void __iomem *phy_base; void __iomem *blk_base; /* For exynos5440 */ + struct regmap *pmureg; + struct regmap *fsysreg; }; static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset) @@ -221,10 +240,113 @@ static const struct exynos_pcie_phy_data exynos5440_pcie_phy_data = { .ops = &exynos5440_phy_ops, }; +/* For Exynos5433 specific functions */ +static int exynos5433_pcie_phy_init(struct phy *phy) +{ + struct exynos_pcie_phy *ep = phy_get_drvdata(phy); + if (ep->fsysreg) { + regmap_update_bits(ep->fsysreg, + PCIE_EXYNOS5433_PHY_COMMON_RESET, + PCIE_PHY_RESET, 1); + regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_MAC_RESET, + PCIE_MAC_RESET, 0); + /* PHY refclk 24MHz */ + regmap_update_bits(ep->fsysreg, + PCIE_EXYNOS5433_PHY_GLOBAL_RESET, + PCIE_REFCLK_MASK, PCIE_REFCLK); + regmap_update_bits(ep->fsysreg, + PCIE_EXYNOS5433_PHY_GLOBAL_RESET, + PCIE_GLOBAL_RESET, 0); + } + + exynos_pcie_phy_writel(ep->phy_base, 0x11, PCIE_PHY_OFFSET(0x3)); + + /* band gap reference on */ + exynos_pcie_phy_writel(ep->phy_base, 0, PCIE_PHY_OFFSET(0x20)); + exynos_pcie_phy_writel(ep->phy_base, 0, PCIE_PHY_OFFSET(0x4b)); + + /* jitter tunning */ + exynos_pcie_phy_writel(ep->phy_base, 0x34, PCIE_PHY_OFFSET(0x4)); + exynos_pcie_phy_writel(ep->phy_base, 0x02, PCIE_PHY_OFFSET(0x7)); + exynos_pcie_phy_writel(ep->phy_base, 0x41, PCIE_PHY_OFFSET(0x21)); + exynos_pcie_phy_writel(ep->phy_base, 0x7F, PCIE_PHY_OFFSET(0x14)); + exynos_pcie_phy_writel(ep->phy_base, 0xC0, PCIE_PHY_OFFSET(0x15)); + exynos_pcie_phy_writel(ep->phy_base, 0x61, PCIE_PHY_OFFSET(0x36)); + + /* D0 uninit.. */ + exynos_pcie_phy_writel(ep->phy_base, 0x44, PCIE_PHY_OFFSET(0x3D)); + + /* 24MHz */ + exynos_pcie_phy_writel(ep->phy_base, 0x94, PCIE_PHY_OFFSET(0x8)); + exynos_pcie_phy_writel(ep->phy_base, 0xA7, PCIE_PHY_OFFSET(0x9)); + exynos_pcie_phy_writel(ep->phy_base, 0x93, PCIE_PHY_OFFSET(0xA)); + exynos_pcie_phy_writel(ep->phy_base, 0x6B, PCIE_PHY_OFFSET(0xC)); + exynos_pcie_phy_writel(ep->phy_base, 0xA5, PCIE_PHY_OFFSET(0xF)); + exynos_pcie_phy_writel(ep->phy_base, 0x34, PCIE_PHY_OFFSET(0x16)); + exynos_pcie_phy_writel(ep->phy_base, 0xA3, PCIE_PHY_OFFSET(0x17)); + exynos_pcie_phy_writel(ep->phy_base, 0xA7, PCIE_PHY_OFFSET(0x1A)); + exynos_pcie_phy_writel(ep->phy_base, 0x71, PCIE_PHY_OFFSET(0x23)); + exynos_pcie_phy_writel(ep->phy_base, 0x4C, PCIE_PHY_OFFSET(0x24)); + + exynos_pcie_phy_writel(ep->phy_base, 0x0E, PCIE_PHY_OFFSET(0x26)); + exynos_pcie_phy_writel(ep->phy_base, 0x14, PCIE_PHY_OFFSET(0x7)); + exynos_pcie_phy_writel(ep->phy_base, 0x48, PCIE_PHY_OFFSET(0x43)); + exynos_pcie_phy_writel(ep->phy_base, 0x44, PCIE_PHY_OFFSET(0x44)); + exynos_pcie_phy_writel(ep->phy_base, 0x03, PCIE_PHY_OFFSET(0x45)); + exynos_pcie_phy_writel(ep->phy_base, 0xA7, PCIE_PHY_OFFSET(0x48)); + exynos_pcie_phy_writel(ep->phy_base, 0x13, PCIE_PHY_OFFSET(0x54)); + exynos_pcie_phy_writel(ep->phy_base, 0x04, PCIE_PHY_OFFSET(0x31)); + exynos_pcie_phy_writel(ep->phy_base, 0, PCIE_PHY_OFFSET(0x32)); + + if (ep->fsysreg) { + regmap_update_bits(ep->fsysreg, + PCIE_EXYNOS5433_PHY_COMMON_RESET, + PCIE_PHY_RESET, 0); + regmap_update_bits(ep->fsysreg, + PCIE_EXYNOS5433_PHY_MAC_RESET, + PCIE_MAC_RESET_MASK, PCIE_MAC_RESET); + } + + return 0; +} + +static int exynos5433_pcie_phy_power_on(struct phy *phy) +{ + struct exynos_pcie_phy *ep = phy_get_drvdata(phy); + + if (ep->pmureg) { + if (regmap_update_bits(ep->pmureg, PCIE_EXYNOS5433_PMU_PHY_OFFSET, + BIT(0), 1)) + dev_warn(&phy->dev, "Failed to update regmap bit.\n"); + } + + if (ep->fsysreg) { + regmap_update_bits(ep->fsysreg, PCIE_PHY_GLOBAL_RESET, + PCIE_APP_REQ_EXIT_L1_MODE, 0); + regmap_update_bits(ep->fsysreg, PCIE_L1SUB_CM_CON, + PCIE_REFCLK_GATING_EN, 0); + } + + return 0; +} + +static const struct phy_ops exynos5433_phy_ops = { + .init = exynos5433_pcie_phy_init, + .power_on = exynos5433_pcie_phy_power_on, + .owner = THIS_MODULE, +}; + +static const struct exynos_pcie_phy_data exynos5433_pcie_phy_data = { + .ops = &exynos5433_phy_ops, +}; + static const struct of_device_id exynos_pcie_phy_match[] = { { .compatible = "samsung,exynos5440-pcie-phy", .data = &exynos5440_pcie_phy_data, + }, { + .compatible = "samsung,exynos5433-pcie-phy", + .data = &exynos5433_pcie_phy_data, }, {}, }; @@ -251,10 +373,28 @@ static int exynos_pcie_phy_probe(struct platform_device *pdev) if (IS_ERR(exynos_phy->phy_base)) return PTR_ERR(exynos_phy->phy_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - exynos_phy->blk_base = devm_ioremap_resource(dev, res); - if (IS_ERR(exynos_phy->blk_base)) - return PTR_ERR(exynos_phy->blk_base); + /* Exynos5440 has the blk register */ + if (of_device_is_compatible(dev->of_node, + "samsung,exynos5440-pcie-phy")) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + exynos_phy->blk_base = devm_ioremap_resource(dev, res); + if (IS_ERR(exynos_phy->phy_base)) + return PTR_ERR(exynos_phy->phy_base); + } + + exynos_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node, + "samsung,pmureg-phandle"); + if (IS_ERR(exynos_phy->pmureg)) { + dev_warn(&pdev->dev, "pmureg syscon regmap lookup failed.\n"); + exynos_phy->pmureg = NULL; + } + + exynos_phy->fsysreg = syscon_regmap_lookup_by_phandle(dev->of_node, + "samsung,fsys-sysreg"); + if (IS_ERR(exynos_phy->fsysreg)) { + dev_warn(&pdev->dev, "Fsysreg syscon regmap lookup failed.\n"); + exynos_phy->fsysreg = NULL; + } exynos_phy->drv_data = drv_data; -- 2.7.4