193 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Samsung Exynos SoC series PCIe PHY driver4 *5 * Phy provider for PCIe controller on Exynos SoC series6 *7 * Copyright (C) 2017-2020 Samsung Electronics Co., Ltd.8 * Jaehoon Chung <jh80.chung@samsung.com>9 */10 11#include <linux/io.h>12#include <linux/mfd/syscon.h>13#include <linux/of_platform.h>14#include <linux/platform_device.h>15#include <linux/phy/phy.h>16#include <linux/regmap.h>17 18#define PCIE_PHY_OFFSET(x) ((x) * 0x4)19 20/* Sysreg FSYS register offsets and bits for Exynos5433 */21#define PCIE_EXYNOS5433_PHY_MAC_RESET 0x020822#define PCIE_MAC_RESET_MASK 0xFF23#define PCIE_MAC_RESET BIT(4)24#define PCIE_EXYNOS5433_PHY_L1SUB_CM_CON 0x101025#define PCIE_REFCLK_GATING_EN BIT(0)26#define PCIE_EXYNOS5433_PHY_COMMON_RESET 0x102027#define PCIE_PHY_RESET BIT(0)28#define PCIE_EXYNOS5433_PHY_GLOBAL_RESET 0x104029#define PCIE_GLOBAL_RESET BIT(0)30#define PCIE_REFCLK BIT(1)31#define PCIE_REFCLK_MASK 0x1632#define PCIE_APP_REQ_EXIT_L1_MODE BIT(5)33 34/* PMU PCIE PHY isolation control */35#define EXYNOS5433_PMU_PCIE_PHY_OFFSET 0x73036 37/* For Exynos pcie phy */38struct exynos_pcie_phy {39 void __iomem *base;40 struct regmap *pmureg;41 struct regmap *fsysreg;42};43 44static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset)45{46 writel(val, base + offset);47}48 49/* Exynos5433 specific functions */50static int exynos5433_pcie_phy_init(struct phy *phy)51{52 struct exynos_pcie_phy *ep = phy_get_drvdata(phy);53 54 regmap_update_bits(ep->pmureg, EXYNOS5433_PMU_PCIE_PHY_OFFSET,55 BIT(0), 1);56 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_GLOBAL_RESET,57 PCIE_APP_REQ_EXIT_L1_MODE, 0);58 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_L1SUB_CM_CON,59 PCIE_REFCLK_GATING_EN, 0);60 61 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_COMMON_RESET,62 PCIE_PHY_RESET, 1);63 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_MAC_RESET,64 PCIE_MAC_RESET, 0);65 66 /* PHY refclk 24MHz */67 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_GLOBAL_RESET,68 PCIE_REFCLK_MASK, PCIE_REFCLK);69 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_GLOBAL_RESET,70 PCIE_GLOBAL_RESET, 0);71 72 73 exynos_pcie_phy_writel(ep->base, 0x11, PCIE_PHY_OFFSET(0x3));74 75 /* band gap reference on */76 exynos_pcie_phy_writel(ep->base, 0, PCIE_PHY_OFFSET(0x20));77 exynos_pcie_phy_writel(ep->base, 0, PCIE_PHY_OFFSET(0x4b));78 79 /* jitter tuning */80 exynos_pcie_phy_writel(ep->base, 0x34, PCIE_PHY_OFFSET(0x4));81 exynos_pcie_phy_writel(ep->base, 0x02, PCIE_PHY_OFFSET(0x7));82 exynos_pcie_phy_writel(ep->base, 0x41, PCIE_PHY_OFFSET(0x21));83 exynos_pcie_phy_writel(ep->base, 0x7F, PCIE_PHY_OFFSET(0x14));84 exynos_pcie_phy_writel(ep->base, 0xC0, PCIE_PHY_OFFSET(0x15));85 exynos_pcie_phy_writel(ep->base, 0x61, PCIE_PHY_OFFSET(0x36));86 87 /* D0 uninit.. */88 exynos_pcie_phy_writel(ep->base, 0x44, PCIE_PHY_OFFSET(0x3D));89 90 /* 24MHz */91 exynos_pcie_phy_writel(ep->base, 0x94, PCIE_PHY_OFFSET(0x8));92 exynos_pcie_phy_writel(ep->base, 0xA7, PCIE_PHY_OFFSET(0x9));93 exynos_pcie_phy_writel(ep->base, 0x93, PCIE_PHY_OFFSET(0xA));94 exynos_pcie_phy_writel(ep->base, 0x6B, PCIE_PHY_OFFSET(0xC));95 exynos_pcie_phy_writel(ep->base, 0xA5, PCIE_PHY_OFFSET(0xF));96 exynos_pcie_phy_writel(ep->base, 0x34, PCIE_PHY_OFFSET(0x16));97 exynos_pcie_phy_writel(ep->base, 0xA3, PCIE_PHY_OFFSET(0x17));98 exynos_pcie_phy_writel(ep->base, 0xA7, PCIE_PHY_OFFSET(0x1A));99 exynos_pcie_phy_writel(ep->base, 0x71, PCIE_PHY_OFFSET(0x23));100 exynos_pcie_phy_writel(ep->base, 0x4C, PCIE_PHY_OFFSET(0x24));101 102 exynos_pcie_phy_writel(ep->base, 0x0E, PCIE_PHY_OFFSET(0x26));103 exynos_pcie_phy_writel(ep->base, 0x14, PCIE_PHY_OFFSET(0x7));104 exynos_pcie_phy_writel(ep->base, 0x48, PCIE_PHY_OFFSET(0x43));105 exynos_pcie_phy_writel(ep->base, 0x44, PCIE_PHY_OFFSET(0x44));106 exynos_pcie_phy_writel(ep->base, 0x03, PCIE_PHY_OFFSET(0x45));107 exynos_pcie_phy_writel(ep->base, 0xA7, PCIE_PHY_OFFSET(0x48));108 exynos_pcie_phy_writel(ep->base, 0x13, PCIE_PHY_OFFSET(0x54));109 exynos_pcie_phy_writel(ep->base, 0x04, PCIE_PHY_OFFSET(0x31));110 exynos_pcie_phy_writel(ep->base, 0, PCIE_PHY_OFFSET(0x32));111 112 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_COMMON_RESET,113 PCIE_PHY_RESET, 0);114 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_MAC_RESET,115 PCIE_MAC_RESET_MASK, PCIE_MAC_RESET);116 return 0;117}118 119static int exynos5433_pcie_phy_exit(struct phy *phy)120{121 struct exynos_pcie_phy *ep = phy_get_drvdata(phy);122 123 regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_L1SUB_CM_CON,124 PCIE_REFCLK_GATING_EN, PCIE_REFCLK_GATING_EN);125 regmap_update_bits(ep->pmureg, EXYNOS5433_PMU_PCIE_PHY_OFFSET,126 BIT(0), 0);127 return 0;128}129 130static const struct phy_ops exynos5433_phy_ops = {131 .init = exynos5433_pcie_phy_init,132 .exit = exynos5433_pcie_phy_exit,133 .owner = THIS_MODULE,134};135 136static const struct of_device_id exynos_pcie_phy_match[] = {137 {138 .compatible = "samsung,exynos5433-pcie-phy",139 },140 {},141};142 143static int exynos_pcie_phy_probe(struct platform_device *pdev)144{145 struct device *dev = &pdev->dev;146 struct exynos_pcie_phy *exynos_phy;147 struct phy *generic_phy;148 struct phy_provider *phy_provider;149 150 exynos_phy = devm_kzalloc(dev, sizeof(*exynos_phy), GFP_KERNEL);151 if (!exynos_phy)152 return -ENOMEM;153 154 exynos_phy->base = devm_platform_ioremap_resource(pdev, 0);155 if (IS_ERR(exynos_phy->base))156 return PTR_ERR(exynos_phy->base);157 158 exynos_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,159 "samsung,pmu-syscon");160 if (IS_ERR(exynos_phy->pmureg)) {161 dev_err(&pdev->dev, "PMU regmap lookup failed.\n");162 return PTR_ERR(exynos_phy->pmureg);163 }164 165 exynos_phy->fsysreg = syscon_regmap_lookup_by_phandle(dev->of_node,166 "samsung,fsys-sysreg");167 if (IS_ERR(exynos_phy->fsysreg)) {168 dev_err(&pdev->dev, "FSYS sysreg regmap lookup failed.\n");169 return PTR_ERR(exynos_phy->fsysreg);170 }171 172 generic_phy = devm_phy_create(dev, dev->of_node, &exynos5433_phy_ops);173 if (IS_ERR(generic_phy)) {174 dev_err(dev, "failed to create PHY\n");175 return PTR_ERR(generic_phy);176 }177 178 phy_set_drvdata(generic_phy, exynos_phy);179 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);180 181 return PTR_ERR_OR_ZERO(phy_provider);182}183 184static struct platform_driver exynos_pcie_phy_driver = {185 .probe = exynos_pcie_phy_probe,186 .driver = {187 .of_match_table = exynos_pcie_phy_match,188 .name = "exynos_pcie_phy",189 .suppress_bind_attrs = true,190 }191};192builtin_platform_driver(exynos_pcie_phy_driver);193