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-rockchip-pcie.c (10907B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Rockchip PCIe PHY driver
      4 *
      5 * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
      6 * Copyright (C) 2016 ROCKCHIP, Inc.
      7 */
      8
      9#include <linux/clk.h>
     10#include <linux/delay.h>
     11#include <linux/io.h>
     12#include <linux/mfd/syscon.h>
     13#include <linux/module.h>
     14#include <linux/of.h>
     15#include <linux/of_address.h>
     16#include <linux/of_platform.h>
     17#include <linux/phy/phy.h>
     18#include <linux/platform_device.h>
     19#include <linux/regmap.h>
     20#include <linux/reset.h>
     21
     22/*
     23 * The higher 16-bit of this register is used for write protection
     24 * only if BIT(x + 16) set to 1 the BIT(x) can be written.
     25 */
     26#define HIWORD_UPDATE(val, mask, shift) \
     27		((val) << (shift) | (mask) << ((shift) + 16))
     28
     29#define PHY_MAX_LANE_NUM      4
     30#define PHY_CFG_DATA_SHIFT    7
     31#define PHY_CFG_ADDR_SHIFT    1
     32#define PHY_CFG_DATA_MASK     0xf
     33#define PHY_CFG_ADDR_MASK     0x3f
     34#define PHY_CFG_RD_MASK       0x3ff
     35#define PHY_CFG_WR_ENABLE     1
     36#define PHY_CFG_WR_DISABLE    1
     37#define PHY_CFG_WR_SHIFT      0
     38#define PHY_CFG_WR_MASK       1
     39#define PHY_CFG_PLL_LOCK      0x10
     40#define PHY_CFG_CLK_TEST      0x10
     41#define PHY_CFG_CLK_SCC       0x12
     42#define PHY_CFG_SEPE_RATE     BIT(3)
     43#define PHY_CFG_PLL_100M      BIT(3)
     44#define PHY_PLL_LOCKED        BIT(9)
     45#define PHY_PLL_OUTPUT        BIT(10)
     46#define PHY_LANE_A_STATUS     0x30
     47#define PHY_LANE_B_STATUS     0x31
     48#define PHY_LANE_C_STATUS     0x32
     49#define PHY_LANE_D_STATUS     0x33
     50#define PHY_LANE_RX_DET_SHIFT 11
     51#define PHY_LANE_RX_DET_TH    0x1
     52#define PHY_LANE_IDLE_OFF     0x1
     53#define PHY_LANE_IDLE_MASK    0x1
     54#define PHY_LANE_IDLE_A_SHIFT 3
     55#define PHY_LANE_IDLE_B_SHIFT 4
     56#define PHY_LANE_IDLE_C_SHIFT 5
     57#define PHY_LANE_IDLE_D_SHIFT 6
     58
     59struct rockchip_pcie_data {
     60	unsigned int pcie_conf;
     61	unsigned int pcie_status;
     62	unsigned int pcie_laneoff;
     63};
     64
     65struct rockchip_pcie_phy {
     66	struct rockchip_pcie_data *phy_data;
     67	struct regmap *reg_base;
     68	struct phy_pcie_instance {
     69		struct phy *phy;
     70		u32 index;
     71	} phys[PHY_MAX_LANE_NUM];
     72	struct mutex pcie_mutex;
     73	struct reset_control *phy_rst;
     74	struct clk *clk_pciephy_ref;
     75	int pwr_cnt;
     76	int init_cnt;
     77};
     78
     79static struct rockchip_pcie_phy *to_pcie_phy(struct phy_pcie_instance *inst)
     80{
     81	return container_of(inst, struct rockchip_pcie_phy,
     82					phys[inst->index]);
     83}
     84
     85static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev,
     86					      struct of_phandle_args *args)
     87{
     88	struct rockchip_pcie_phy *rk_phy = dev_get_drvdata(dev);
     89
     90	if (args->args_count == 0)
     91		return rk_phy->phys[0].phy;
     92
     93	if (WARN_ON(args->args[0] >= PHY_MAX_LANE_NUM))
     94		return ERR_PTR(-ENODEV);
     95
     96	return rk_phy->phys[args->args[0]].phy;
     97}
     98
     99
    100static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy,
    101			      u32 addr, u32 data)
    102{
    103	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
    104		     HIWORD_UPDATE(data,
    105				   PHY_CFG_DATA_MASK,
    106				   PHY_CFG_DATA_SHIFT) |
    107		     HIWORD_UPDATE(addr,
    108				   PHY_CFG_ADDR_MASK,
    109				   PHY_CFG_ADDR_SHIFT));
    110	udelay(1);
    111	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
    112		     HIWORD_UPDATE(PHY_CFG_WR_ENABLE,
    113				   PHY_CFG_WR_MASK,
    114				   PHY_CFG_WR_SHIFT));
    115	udelay(1);
    116	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
    117		     HIWORD_UPDATE(PHY_CFG_WR_DISABLE,
    118				   PHY_CFG_WR_MASK,
    119				   PHY_CFG_WR_SHIFT));
    120}
    121
    122static inline u32 phy_rd_cfg(struct rockchip_pcie_phy *rk_phy,
    123			     u32 addr)
    124{
    125	u32 val;
    126
    127	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
    128		     HIWORD_UPDATE(addr,
    129				   PHY_CFG_RD_MASK,
    130				   PHY_CFG_ADDR_SHIFT));
    131	regmap_read(rk_phy->reg_base,
    132		    rk_phy->phy_data->pcie_status,
    133		    &val);
    134	return val;
    135}
    136
    137static int rockchip_pcie_phy_power_off(struct phy *phy)
    138{
    139	struct phy_pcie_instance *inst = phy_get_drvdata(phy);
    140	struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
    141	int err = 0;
    142
    143	mutex_lock(&rk_phy->pcie_mutex);
    144
    145	regmap_write(rk_phy->reg_base,
    146		     rk_phy->phy_data->pcie_laneoff,
    147		     HIWORD_UPDATE(PHY_LANE_IDLE_OFF,
    148				   PHY_LANE_IDLE_MASK,
    149				   PHY_LANE_IDLE_A_SHIFT + inst->index));
    150
    151	if (--rk_phy->pwr_cnt)
    152		goto err_out;
    153
    154	err = reset_control_assert(rk_phy->phy_rst);
    155	if (err) {
    156		dev_err(&phy->dev, "assert phy_rst err %d\n", err);
    157		goto err_restore;
    158	}
    159
    160err_out:
    161	mutex_unlock(&rk_phy->pcie_mutex);
    162	return 0;
    163
    164err_restore:
    165	rk_phy->pwr_cnt++;
    166	regmap_write(rk_phy->reg_base,
    167		     rk_phy->phy_data->pcie_laneoff,
    168		     HIWORD_UPDATE(!PHY_LANE_IDLE_OFF,
    169				   PHY_LANE_IDLE_MASK,
    170				   PHY_LANE_IDLE_A_SHIFT + inst->index));
    171	mutex_unlock(&rk_phy->pcie_mutex);
    172	return err;
    173}
    174
    175static int rockchip_pcie_phy_power_on(struct phy *phy)
    176{
    177	struct phy_pcie_instance *inst = phy_get_drvdata(phy);
    178	struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
    179	int err = 0;
    180	u32 status;
    181	unsigned long timeout;
    182
    183	mutex_lock(&rk_phy->pcie_mutex);
    184
    185	if (rk_phy->pwr_cnt++)
    186		goto err_out;
    187
    188	err = reset_control_deassert(rk_phy->phy_rst);
    189	if (err) {
    190		dev_err(&phy->dev, "deassert phy_rst err %d\n", err);
    191		goto err_pwr_cnt;
    192	}
    193
    194	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
    195		     HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
    196				   PHY_CFG_ADDR_MASK,
    197				   PHY_CFG_ADDR_SHIFT));
    198
    199	regmap_write(rk_phy->reg_base,
    200		     rk_phy->phy_data->pcie_laneoff,
    201		     HIWORD_UPDATE(!PHY_LANE_IDLE_OFF,
    202				   PHY_LANE_IDLE_MASK,
    203				   PHY_LANE_IDLE_A_SHIFT + inst->index));
    204
    205	/*
    206	 * No documented timeout value for phy operation below,
    207	 * so we make it large enough here. And we use loop-break
    208	 * method which should not be harmful.
    209	 */
    210	timeout = jiffies + msecs_to_jiffies(1000);
    211
    212	err = -EINVAL;
    213	while (time_before(jiffies, timeout)) {
    214		regmap_read(rk_phy->reg_base,
    215			    rk_phy->phy_data->pcie_status,
    216			    &status);
    217		if (status & PHY_PLL_LOCKED) {
    218			dev_dbg(&phy->dev, "pll locked!\n");
    219			err = 0;
    220			break;
    221		}
    222		msleep(20);
    223	}
    224
    225	if (err) {
    226		dev_err(&phy->dev, "pll lock timeout!\n");
    227		goto err_pll_lock;
    228	}
    229
    230	phy_wr_cfg(rk_phy, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE);
    231	phy_wr_cfg(rk_phy, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M);
    232
    233	err = -ETIMEDOUT;
    234	while (time_before(jiffies, timeout)) {
    235		regmap_read(rk_phy->reg_base,
    236			    rk_phy->phy_data->pcie_status,
    237			    &status);
    238		if (!(status & PHY_PLL_OUTPUT)) {
    239			dev_dbg(&phy->dev, "pll output enable done!\n");
    240			err = 0;
    241			break;
    242		}
    243		msleep(20);
    244	}
    245
    246	if (err) {
    247		dev_err(&phy->dev, "pll output enable timeout!\n");
    248		goto err_pll_lock;
    249	}
    250
    251	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
    252		     HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
    253				   PHY_CFG_ADDR_MASK,
    254				   PHY_CFG_ADDR_SHIFT));
    255	err = -EINVAL;
    256	while (time_before(jiffies, timeout)) {
    257		regmap_read(rk_phy->reg_base,
    258			    rk_phy->phy_data->pcie_status,
    259			    &status);
    260		if (status & PHY_PLL_LOCKED) {
    261			dev_dbg(&phy->dev, "pll relocked!\n");
    262			err = 0;
    263			break;
    264		}
    265		msleep(20);
    266	}
    267
    268	if (err) {
    269		dev_err(&phy->dev, "pll relock timeout!\n");
    270		goto err_pll_lock;
    271	}
    272
    273err_out:
    274	mutex_unlock(&rk_phy->pcie_mutex);
    275	return 0;
    276
    277err_pll_lock:
    278	reset_control_assert(rk_phy->phy_rst);
    279err_pwr_cnt:
    280	rk_phy->pwr_cnt--;
    281	mutex_unlock(&rk_phy->pcie_mutex);
    282	return err;
    283}
    284
    285static int rockchip_pcie_phy_init(struct phy *phy)
    286{
    287	struct phy_pcie_instance *inst = phy_get_drvdata(phy);
    288	struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
    289	int err = 0;
    290
    291	mutex_lock(&rk_phy->pcie_mutex);
    292
    293	if (rk_phy->init_cnt++)
    294		goto err_out;
    295
    296	err = clk_prepare_enable(rk_phy->clk_pciephy_ref);
    297	if (err) {
    298		dev_err(&phy->dev, "Fail to enable pcie ref clock.\n");
    299		goto err_refclk;
    300	}
    301
    302	err = reset_control_assert(rk_phy->phy_rst);
    303	if (err) {
    304		dev_err(&phy->dev, "assert phy_rst err %d\n", err);
    305		goto err_reset;
    306	}
    307
    308err_out:
    309	mutex_unlock(&rk_phy->pcie_mutex);
    310	return 0;
    311
    312err_reset:
    313
    314	clk_disable_unprepare(rk_phy->clk_pciephy_ref);
    315err_refclk:
    316	rk_phy->init_cnt--;
    317	mutex_unlock(&rk_phy->pcie_mutex);
    318	return err;
    319}
    320
    321static int rockchip_pcie_phy_exit(struct phy *phy)
    322{
    323	struct phy_pcie_instance *inst = phy_get_drvdata(phy);
    324	struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
    325
    326	mutex_lock(&rk_phy->pcie_mutex);
    327
    328	if (--rk_phy->init_cnt)
    329		goto err_init_cnt;
    330
    331	clk_disable_unprepare(rk_phy->clk_pciephy_ref);
    332
    333err_init_cnt:
    334	mutex_unlock(&rk_phy->pcie_mutex);
    335	return 0;
    336}
    337
    338static const struct phy_ops ops = {
    339	.init		= rockchip_pcie_phy_init,
    340	.exit		= rockchip_pcie_phy_exit,
    341	.power_on	= rockchip_pcie_phy_power_on,
    342	.power_off	= rockchip_pcie_phy_power_off,
    343	.owner		= THIS_MODULE,
    344};
    345
    346static const struct rockchip_pcie_data rk3399_pcie_data = {
    347	.pcie_conf = 0xe220,
    348	.pcie_status = 0xe2a4,
    349	.pcie_laneoff = 0xe214,
    350};
    351
    352static const struct of_device_id rockchip_pcie_phy_dt_ids[] = {
    353	{
    354		.compatible = "rockchip,rk3399-pcie-phy",
    355		.data = &rk3399_pcie_data,
    356	},
    357	{}
    358};
    359
    360MODULE_DEVICE_TABLE(of, rockchip_pcie_phy_dt_ids);
    361
    362static int rockchip_pcie_phy_probe(struct platform_device *pdev)
    363{
    364	struct device *dev = &pdev->dev;
    365	struct rockchip_pcie_phy *rk_phy;
    366	struct phy_provider *phy_provider;
    367	struct regmap *grf;
    368	const struct of_device_id *of_id;
    369	int i;
    370	u32 phy_num;
    371
    372	grf = syscon_node_to_regmap(dev->parent->of_node);
    373	if (IS_ERR(grf)) {
    374		dev_err(dev, "Cannot find GRF syscon\n");
    375		return PTR_ERR(grf);
    376	}
    377
    378	rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
    379	if (!rk_phy)
    380		return -ENOMEM;
    381
    382	of_id = of_match_device(rockchip_pcie_phy_dt_ids, &pdev->dev);
    383	if (!of_id)
    384		return -EINVAL;
    385
    386	rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data;
    387	rk_phy->reg_base = grf;
    388
    389	mutex_init(&rk_phy->pcie_mutex);
    390
    391	rk_phy->phy_rst = devm_reset_control_get(dev, "phy");
    392	if (IS_ERR(rk_phy->phy_rst)) {
    393		if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER)
    394			dev_err(dev,
    395				"missing phy property for reset controller\n");
    396		return PTR_ERR(rk_phy->phy_rst);
    397	}
    398
    399	rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk");
    400	if (IS_ERR(rk_phy->clk_pciephy_ref)) {
    401		dev_err(dev, "refclk not found.\n");
    402		return PTR_ERR(rk_phy->clk_pciephy_ref);
    403	}
    404
    405	/* parse #phy-cells to see if it's legacy PHY model */
    406	if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num))
    407		return -ENOENT;
    408
    409	phy_num = (phy_num == 0) ? 1 : PHY_MAX_LANE_NUM;
    410	dev_dbg(dev, "phy number is %d\n", phy_num);
    411
    412	for (i = 0; i < phy_num; i++) {
    413		rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops);
    414		if (IS_ERR(rk_phy->phys[i].phy)) {
    415			dev_err(dev, "failed to create PHY%d\n", i);
    416			return PTR_ERR(rk_phy->phys[i].phy);
    417		}
    418		rk_phy->phys[i].index = i;
    419		phy_set_drvdata(rk_phy->phys[i].phy, &rk_phy->phys[i]);
    420	}
    421
    422	platform_set_drvdata(pdev, rk_phy);
    423	phy_provider = devm_of_phy_provider_register(dev,
    424					rockchip_pcie_phy_of_xlate);
    425
    426	return PTR_ERR_OR_ZERO(phy_provider);
    427}
    428
    429static struct platform_driver rockchip_pcie_driver = {
    430	.probe		= rockchip_pcie_phy_probe,
    431	.driver		= {
    432		.name	= "rockchip-pcie-phy",
    433		.of_match_table = rockchip_pcie_phy_dt_ids,
    434	},
    435};
    436
    437module_platform_driver(rockchip_pcie_driver);
    438
    439MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
    440MODULE_DESCRIPTION("Rockchip PCIe PHY driver");
    441MODULE_LICENSE("GPL v2");