cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy-qcom-pcie2.c (8799B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
      4 * Copyright (c) 2019, Linaro Ltd.
      5 */
      6
      7#include <linux/clk-provider.h>
      8#include <linux/clk.h>
      9#include <linux/iopoll.h>
     10#include <linux/module.h>
     11#include <linux/phy/phy.h>
     12#include <linux/platform_device.h>
     13#include <linux/reset.h>
     14#include <linux/slab.h>
     15
     16#include <dt-bindings/phy/phy.h>
     17
     18#define PCIE20_PARF_PHY_STTS         0x3c
     19#define PCIE2_PHY_RESET_CTRL         0x44
     20#define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0
     21#define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4
     22#define PCIE20_PARF_PCS_SWING_CTRL1  0x88
     23#define PCIE20_PARF_PCS_SWING_CTRL2  0x8c
     24#define PCIE20_PARF_PCS_DEEMPH1      0x74
     25#define PCIE20_PARF_PCS_DEEMPH2      0x78
     26#define PCIE20_PARF_PCS_DEEMPH3      0x7c
     27#define PCIE20_PARF_CONFIGBITS       0x84
     28#define PCIE20_PARF_PHY_CTRL3        0x94
     29#define PCIE20_PARF_PCS_CTRL         0x80
     30
     31#define TX_AMP_VAL                   120
     32#define PHY_RX0_EQ_GEN1_VAL          0
     33#define PHY_RX0_EQ_GEN2_VAL          4
     34#define TX_DEEMPH_GEN1_VAL           24
     35#define TX_DEEMPH_GEN2_3_5DB_VAL     26
     36#define TX_DEEMPH_GEN2_6DB_VAL       36
     37#define PHY_TX0_TERM_OFFST_VAL       0
     38
     39struct qcom_phy {
     40	struct device *dev;
     41	void __iomem *base;
     42
     43	struct regulator_bulk_data vregs[2];
     44
     45	struct reset_control *phy_reset;
     46	struct reset_control *pipe_reset;
     47	struct clk *pipe_clk;
     48};
     49
     50static int qcom_pcie2_phy_init(struct phy *phy)
     51{
     52	struct qcom_phy *qphy = phy_get_drvdata(phy);
     53	int ret;
     54
     55	ret = reset_control_deassert(qphy->phy_reset);
     56	if (ret) {
     57		dev_err(qphy->dev, "cannot deassert pipe reset\n");
     58		return ret;
     59	}
     60
     61	ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
     62	if (ret)
     63		reset_control_assert(qphy->phy_reset);
     64
     65	return ret;
     66}
     67
     68static int qcom_pcie2_phy_power_on(struct phy *phy)
     69{
     70	struct qcom_phy *qphy = phy_get_drvdata(phy);
     71	int ret;
     72	u32 val;
     73
     74	/* Program REF_CLK source */
     75	val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);
     76	val &= ~BIT(1);
     77	writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);
     78
     79	usleep_range(1000, 2000);
     80
     81	/* Don't use PAD for refclock */
     82	val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);
     83	val &= ~BIT(0);
     84	writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);
     85
     86	/* Program SSP ENABLE */
     87	val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3);
     88	val |= BIT(0);
     89	writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3);
     90
     91	usleep_range(1000, 2000);
     92
     93	/* Assert Phy SW Reset */
     94	val = readl(qphy->base + PCIE2_PHY_RESET_CTRL);
     95	val |= BIT(0);
     96	writel(val, qphy->base + PCIE2_PHY_RESET_CTRL);
     97
     98	/* Program Tx Amplitude */
     99	val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL1);
    100	val &= ~0x7f;
    101	val |= TX_AMP_VAL;
    102	writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL1);
    103
    104	val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL2);
    105	val &= ~0x7f;
    106	val |= TX_AMP_VAL;
    107	writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL2);
    108
    109	/* Program De-Emphasis */
    110	val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH1);
    111	val &= ~0x3f;
    112	val |= TX_DEEMPH_GEN2_6DB_VAL;
    113	writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH1);
    114
    115	val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH2);
    116	val &= ~0x3f;
    117	val |= TX_DEEMPH_GEN2_3_5DB_VAL;
    118	writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH2);
    119
    120	val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH3);
    121	val &= ~0x3f;
    122	val |= TX_DEEMPH_GEN1_VAL;
    123	writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH3);
    124
    125	/* Program Rx_Eq */
    126	val = readl(qphy->base + PCIE20_PARF_CONFIGBITS);
    127	val &= ~0x7;
    128	val |= PHY_RX0_EQ_GEN2_VAL;
    129	writel(val, qphy->base + PCIE20_PARF_CONFIGBITS);
    130
    131	/* Program Tx0_term_offset */
    132	val = readl(qphy->base + PCIE20_PARF_PHY_CTRL3);
    133	val &= ~0x1f;
    134	val |= PHY_TX0_TERM_OFFST_VAL;
    135	writel(val, qphy->base + PCIE20_PARF_PHY_CTRL3);
    136
    137	/* disable Tx2Rx Loopback */
    138	val = readl(qphy->base + PCIE20_PARF_PCS_CTRL);
    139	val &= ~BIT(1);
    140	writel(val, qphy->base + PCIE20_PARF_PCS_CTRL);
    141
    142	/* De-assert Phy SW Reset */
    143	val = readl(qphy->base + PCIE2_PHY_RESET_CTRL);
    144	val &= ~BIT(0);
    145	writel(val, qphy->base + PCIE2_PHY_RESET_CTRL);
    146
    147	usleep_range(1000, 2000);
    148
    149	ret = reset_control_deassert(qphy->pipe_reset);
    150	if (ret) {
    151		dev_err(qphy->dev, "cannot deassert pipe reset\n");
    152		goto out;
    153	}
    154
    155	clk_set_rate(qphy->pipe_clk, 250000000);
    156
    157	ret = clk_prepare_enable(qphy->pipe_clk);
    158	if (ret) {
    159		dev_err(qphy->dev, "failed to enable pipe clock\n");
    160		goto out;
    161	}
    162
    163	ret = readl_poll_timeout(qphy->base + PCIE20_PARF_PHY_STTS, val,
    164				 !(val & BIT(0)), 1000, 10);
    165	if (ret)
    166		dev_err(qphy->dev, "phy initialization failed\n");
    167
    168out:
    169	return ret;
    170}
    171
    172static int qcom_pcie2_phy_power_off(struct phy *phy)
    173{
    174	struct qcom_phy *qphy = phy_get_drvdata(phy);
    175	u32 val;
    176
    177	val = readl(qphy->base + PCIE2_PHY_RESET_CTRL);
    178	val |= BIT(0);
    179	writel(val, qphy->base + PCIE2_PHY_RESET_CTRL);
    180
    181	clk_disable_unprepare(qphy->pipe_clk);
    182	reset_control_assert(qphy->pipe_reset);
    183
    184	return 0;
    185}
    186
    187static int qcom_pcie2_phy_exit(struct phy *phy)
    188{
    189	struct qcom_phy *qphy = phy_get_drvdata(phy);
    190
    191	regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
    192	reset_control_assert(qphy->phy_reset);
    193
    194	return 0;
    195}
    196
    197static const struct phy_ops qcom_pcie2_ops = {
    198	.init = qcom_pcie2_phy_init,
    199	.power_on = qcom_pcie2_phy_power_on,
    200	.power_off = qcom_pcie2_phy_power_off,
    201	.exit = qcom_pcie2_phy_exit,
    202	.owner = THIS_MODULE,
    203};
    204
    205/*
    206 * Register a fixed rate pipe clock.
    207 *
    208 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
    209 * controls it. The <s>_pipe_clk coming out of the GCC is requested
    210 * by the PHY driver for its operations.
    211 * We register the <s>_pipe_clksrc here. The gcc driver takes care
    212 * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
    213 * Below picture shows this relationship.
    214 *
    215 *         +---------------+
    216 *         |   PHY block   |<<---------------------------------------+
    217 *         |               |                                         |
    218 *         |   +-------+   |                   +-----+               |
    219 *   I/P---^-->|  PLL  |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
    220 *    clk  |   +-------+   |                   +-----+
    221 *         +---------------+
    222 */
    223static int phy_pipe_clksrc_register(struct qcom_phy *qphy)
    224{
    225	struct device_node *np = qphy->dev->of_node;
    226	struct clk_fixed_rate *fixed;
    227	struct clk_init_data init = { };
    228	int ret;
    229
    230	ret = of_property_read_string(np, "clock-output-names", &init.name);
    231	if (ret) {
    232		dev_err(qphy->dev, "%s: No clock-output-names\n", np->name);
    233		return ret;
    234	}
    235
    236	fixed = devm_kzalloc(qphy->dev, sizeof(*fixed), GFP_KERNEL);
    237	if (!fixed)
    238		return -ENOMEM;
    239
    240	init.ops = &clk_fixed_rate_ops;
    241
    242	/* controllers using QMP phys use 250MHz pipe clock interface */
    243	fixed->fixed_rate = 250000000;
    244	fixed->hw.init = &init;
    245
    246	return devm_clk_hw_register(qphy->dev, &fixed->hw);
    247}
    248
    249static int qcom_pcie2_phy_probe(struct platform_device *pdev)
    250{
    251	struct phy_provider *phy_provider;
    252	struct qcom_phy *qphy;
    253	struct device *dev = &pdev->dev;
    254	struct phy *phy;
    255	int ret;
    256
    257	qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
    258	if (!qphy)
    259		return -ENOMEM;
    260
    261	qphy->dev = dev;
    262	qphy->base = devm_platform_ioremap_resource(pdev, 0);
    263	if (IS_ERR(qphy->base))
    264		return PTR_ERR(qphy->base);
    265
    266	ret = phy_pipe_clksrc_register(qphy);
    267	if (ret) {
    268		dev_err(dev, "failed to register pipe_clk\n");
    269		return ret;
    270	}
    271
    272	qphy->vregs[0].supply = "vdda-vp";
    273	qphy->vregs[1].supply = "vdda-vph";
    274	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(qphy->vregs), qphy->vregs);
    275	if (ret < 0)
    276		return ret;
    277
    278	qphy->pipe_clk = devm_clk_get(dev, NULL);
    279	if (IS_ERR(qphy->pipe_clk)) {
    280		dev_err(dev, "failed to acquire pipe clock\n");
    281		return PTR_ERR(qphy->pipe_clk);
    282	}
    283
    284	qphy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
    285	if (IS_ERR(qphy->phy_reset)) {
    286		dev_err(dev, "failed to acquire phy reset\n");
    287		return PTR_ERR(qphy->phy_reset);
    288	}
    289
    290	qphy->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe");
    291	if (IS_ERR(qphy->pipe_reset)) {
    292		dev_err(dev, "failed to acquire pipe reset\n");
    293		return PTR_ERR(qphy->pipe_reset);
    294	}
    295
    296	phy = devm_phy_create(dev, dev->of_node, &qcom_pcie2_ops);
    297	if (IS_ERR(phy)) {
    298		dev_err(dev, "failed to create phy\n");
    299		return PTR_ERR(phy);
    300	}
    301
    302	phy_set_drvdata(phy, qphy);
    303
    304	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
    305	if (IS_ERR(phy_provider))
    306		dev_err(dev, "failed to register phy provider\n");
    307
    308	return PTR_ERR_OR_ZERO(phy_provider);
    309}
    310
    311static const struct of_device_id qcom_pcie2_phy_match_table[] = {
    312	{ .compatible = "qcom,pcie2-phy" },
    313	{}
    314};
    315MODULE_DEVICE_TABLE(of, qcom_pcie2_phy_match_table);
    316
    317static struct platform_driver qcom_pcie2_phy_driver = {
    318	.probe = qcom_pcie2_phy_probe,
    319	.driver = {
    320		.name = "phy-qcom-pcie2",
    321		.of_match_table = qcom_pcie2_phy_match_table,
    322	},
    323};
    324
    325module_platform_driver(qcom_pcie2_phy_driver);
    326
    327MODULE_DESCRIPTION("Qualcomm PCIe PHY driver");
    328MODULE_LICENSE("GPL v2");