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-meson-g12a-usb3-pcie.c (11511B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Amlogic G12A USB3 + PCIE Combo PHY driver
      4 *
      5 * Copyright (C) 2017 Amlogic, Inc. All rights reserved
      6 * Copyright (C) 2019 BayLibre, SAS
      7 * Author: Neil Armstrong <narmstrong@baylibre.com>
      8 */
      9
     10#include <linux/bitfield.h>
     11#include <linux/bitops.h>
     12#include <linux/clk.h>
     13#include <linux/module.h>
     14#include <linux/of_device.h>
     15#include <linux/phy/phy.h>
     16#include <linux/regmap.h>
     17#include <linux/reset.h>
     18#include <linux/platform_device.h>
     19#include <dt-bindings/phy/phy.h>
     20
     21#define PHY_R0							0x00
     22	#define PHY_R0_PCIE_POWER_STATE				GENMASK(4, 0)
     23	#define PHY_R0_PCIE_USB3_SWITCH				GENMASK(6, 5)
     24
     25#define PHY_R1							0x04
     26	#define PHY_R1_PHY_TX1_TERM_OFFSET			GENMASK(4, 0)
     27	#define PHY_R1_PHY_TX0_TERM_OFFSET			GENMASK(9, 5)
     28	#define PHY_R1_PHY_RX1_EQ				GENMASK(12, 10)
     29	#define PHY_R1_PHY_RX0_EQ				GENMASK(15, 13)
     30	#define PHY_R1_PHY_LOS_LEVEL				GENMASK(20, 16)
     31	#define PHY_R1_PHY_LOS_BIAS				GENMASK(23, 21)
     32	#define PHY_R1_PHY_REF_CLKDIV2				BIT(24)
     33	#define PHY_R1_PHY_MPLL_MULTIPLIER			GENMASK(31, 25)
     34
     35#define PHY_R2							0x08
     36	#define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB			GENMASK(5, 0)
     37	#define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB			GENMASK(11, 6)
     38	#define PHY_R2_PCS_TX_DEEMPH_GEN1			GENMASK(17, 12)
     39	#define PHY_R2_PHY_TX_VBOOST_LVL			GENMASK(20, 18)
     40
     41#define PHY_R4							0x10
     42	#define PHY_R4_PHY_CR_WRITE				BIT(0)
     43	#define PHY_R4_PHY_CR_READ				BIT(1)
     44	#define PHY_R4_PHY_CR_DATA_IN				GENMASK(17, 2)
     45	#define PHY_R4_PHY_CR_CAP_DATA				BIT(18)
     46	#define PHY_R4_PHY_CR_CAP_ADDR				BIT(19)
     47
     48#define PHY_R5							0x14
     49	#define PHY_R5_PHY_CR_DATA_OUT				GENMASK(15, 0)
     50	#define PHY_R5_PHY_CR_ACK				BIT(16)
     51	#define PHY_R5_PHY_BS_OUT				BIT(17)
     52
     53#define PCIE_RESET_DELAY					500
     54
     55struct phy_g12a_usb3_pcie_priv {
     56	struct regmap		*regmap;
     57	struct regmap		*regmap_cr;
     58	struct clk		*clk_ref;
     59	struct reset_control	*reset;
     60	struct phy		*phy;
     61	unsigned int		mode;
     62};
     63
     64static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf = {
     65	.reg_bits = 8,
     66	.val_bits = 32,
     67	.reg_stride = 4,
     68	.max_register = PHY_R5,
     69};
     70
     71static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv,
     72					  unsigned int addr)
     73{
     74	unsigned int val, reg;
     75	int ret;
     76
     77	reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr);
     78
     79	regmap_write(priv->regmap, PHY_R4, reg);
     80	regmap_write(priv->regmap, PHY_R4, reg);
     81
     82	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR);
     83
     84	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
     85				       (val & PHY_R5_PHY_CR_ACK),
     86				       5, 1000);
     87	if (ret)
     88		return ret;
     89
     90	regmap_write(priv->regmap, PHY_R4, reg);
     91
     92	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
     93				       !(val & PHY_R5_PHY_CR_ACK),
     94				       5, 1000);
     95	if (ret)
     96		return ret;
     97
     98	return 0;
     99}
    100
    101static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr,
    102					  unsigned int *data)
    103{
    104	struct phy_g12a_usb3_pcie_priv *priv = context;
    105	unsigned int val;
    106	int ret;
    107
    108	ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
    109	if (ret)
    110		return ret;
    111
    112	regmap_write(priv->regmap, PHY_R4, 0);
    113	regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ);
    114
    115	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
    116				       (val & PHY_R5_PHY_CR_ACK),
    117				       5, 1000);
    118	if (ret)
    119		return ret;
    120
    121	*data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val);
    122
    123	regmap_write(priv->regmap, PHY_R4, 0);
    124
    125	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
    126				       !(val & PHY_R5_PHY_CR_ACK),
    127				       5, 1000);
    128	if (ret)
    129		return ret;
    130
    131	return 0;
    132}
    133
    134static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr,
    135					   unsigned int data)
    136{
    137	struct phy_g12a_usb3_pcie_priv *priv = context;
    138	unsigned int val, reg;
    139	int ret;
    140
    141	ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
    142	if (ret)
    143		return ret;
    144
    145	reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data);
    146
    147	regmap_write(priv->regmap, PHY_R4, reg);
    148	regmap_write(priv->regmap, PHY_R4, reg);
    149
    150	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA);
    151
    152	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
    153				       (val & PHY_R5_PHY_CR_ACK),
    154				       5, 1000);
    155	if (ret)
    156		return ret;
    157
    158	regmap_write(priv->regmap, PHY_R4, reg);
    159
    160	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
    161				       (val & PHY_R5_PHY_CR_ACK) == 0,
    162				       5, 1000);
    163	if (ret)
    164		return ret;
    165
    166	regmap_write(priv->regmap, PHY_R4, reg);
    167
    168	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE);
    169
    170	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
    171				       (val & PHY_R5_PHY_CR_ACK),
    172				       5, 1000);
    173	if (ret)
    174		return ret;
    175
    176	regmap_write(priv->regmap, PHY_R4, reg);
    177
    178	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
    179				       (val & PHY_R5_PHY_CR_ACK) == 0,
    180				       5, 1000);
    181	if (ret)
    182		return ret;
    183
    184	return 0;
    185}
    186
    187static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = {
    188	.reg_bits = 16,
    189	.val_bits = 16,
    190	.reg_read = phy_g12a_usb3_pcie_cr_bus_read,
    191	.reg_write = phy_g12a_usb3_pcie_cr_bus_write,
    192	.max_register = 0xffff,
    193	.disable_locking = true,
    194};
    195
    196static int phy_g12a_usb3_init(struct phy *phy)
    197{
    198	struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);
    199	int data, ret;
    200
    201	ret = reset_control_reset(priv->reset);
    202	if (ret)
    203		return ret;
    204
    205	/* Switch PHY to USB3 */
    206	/* TODO figure out how to handle when PCIe was set in the bootloader */
    207	regmap_update_bits(priv->regmap, PHY_R0,
    208			   PHY_R0_PCIE_USB3_SWITCH,
    209			   PHY_R0_PCIE_USB3_SWITCH);
    210
    211	/*
    212	 * WORKAROUND: There is SSPHY suspend bug due to
    213	 * which USB enumerates
    214	 * in HS mode instead of SS mode. Workaround it by asserting
    215	 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus
    216	 * mode
    217	 */
    218	ret = regmap_update_bits(priv->regmap_cr, 0x102d, BIT(7), BIT(7));
    219	if (ret)
    220		return ret;
    221
    222	ret = regmap_update_bits(priv->regmap_cr, 0x1010, 0xff0, 20);
    223	if (ret)
    224		return ret;
    225
    226	/*
    227	 * Fix RX Equalization setting as follows
    228	 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
    229	 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
    230	 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
    231	 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
    232	 */
    233	ret = regmap_read(priv->regmap_cr, 0x1006, &data);
    234	if (ret)
    235		return ret;
    236
    237	data &= ~BIT(6);
    238	data |= BIT(7);
    239	data &= ~(0x7 << 8);
    240	data |= (0x3 << 8);
    241	data |= (1 << 11);
    242	ret = regmap_write(priv->regmap_cr, 0x1006, data);
    243	if (ret)
    244		return ret;
    245
    246	/*
    247	 * Set EQ and TX launch amplitudes as follows
    248	 * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22
    249	 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
    250	 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
    251	 */
    252	ret = regmap_read(priv->regmap_cr, 0x1002, &data);
    253	if (ret)
    254		return ret;
    255
    256	data &= ~0x3f80;
    257	data |= (0x16 << 7);
    258	data &= ~0x7f;
    259	data |= (0x7f | BIT(14));
    260	ret = regmap_write(priv->regmap_cr, 0x1002, data);
    261	if (ret)
    262		return ret;
    263
    264	/* MPLL_LOOP_CTL.PROP_CNTRL = 8 */
    265	ret = regmap_update_bits(priv->regmap_cr, 0x30, 0xf << 4, 8 << 4);
    266	if (ret)
    267		return ret;
    268
    269	regmap_update_bits(priv->regmap, PHY_R2,
    270			PHY_R2_PHY_TX_VBOOST_LVL,
    271			FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4));
    272
    273	regmap_update_bits(priv->regmap, PHY_R1,
    274			PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL,
    275			FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) |
    276			FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9));
    277
    278	return 0;
    279}
    280
    281static int phy_g12a_usb3_pcie_power_on(struct phy *phy)
    282{
    283	struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);
    284
    285	if (priv->mode == PHY_TYPE_USB3)
    286		return 0;
    287
    288	regmap_update_bits(priv->regmap, PHY_R0,
    289			   PHY_R0_PCIE_POWER_STATE,
    290			   FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1c));
    291
    292	return 0;
    293}
    294
    295static int phy_g12a_usb3_pcie_power_off(struct phy *phy)
    296{
    297	struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);
    298
    299	if (priv->mode == PHY_TYPE_USB3)
    300		return 0;
    301
    302	regmap_update_bits(priv->regmap, PHY_R0,
    303			   PHY_R0_PCIE_POWER_STATE,
    304			   FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1d));
    305
    306	return 0;
    307}
    308
    309static int phy_g12a_usb3_pcie_reset(struct phy *phy)
    310{
    311	struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);
    312	int ret;
    313
    314	if (priv->mode == PHY_TYPE_USB3)
    315		return 0;
    316
    317	ret = reset_control_assert(priv->reset);
    318	if (ret)
    319		return ret;
    320
    321	udelay(PCIE_RESET_DELAY);
    322
    323	ret = reset_control_deassert(priv->reset);
    324	if (ret)
    325		return ret;
    326
    327	udelay(PCIE_RESET_DELAY);
    328
    329	return 0;
    330}
    331
    332static int phy_g12a_usb3_pcie_init(struct phy *phy)
    333{
    334	struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);
    335
    336	if (priv->mode == PHY_TYPE_USB3)
    337		return phy_g12a_usb3_init(phy);
    338
    339	return 0;
    340}
    341
    342static int phy_g12a_usb3_pcie_exit(struct phy *phy)
    343{
    344	struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);
    345
    346	if (priv->mode == PHY_TYPE_USB3)
    347		return reset_control_reset(priv->reset);
    348
    349	return 0;
    350}
    351
    352static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev,
    353					    struct of_phandle_args *args)
    354{
    355	struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev);
    356	unsigned int mode;
    357
    358	if (args->args_count < 1) {
    359		dev_err(dev, "invalid number of arguments\n");
    360		return ERR_PTR(-EINVAL);
    361	}
    362
    363	mode = args->args[0];
    364
    365	if (mode != PHY_TYPE_USB3 && mode != PHY_TYPE_PCIE) {
    366		dev_err(dev, "invalid phy mode select argument\n");
    367		return ERR_PTR(-EINVAL);
    368	}
    369
    370	priv->mode = mode;
    371
    372	return priv->phy;
    373}
    374
    375static const struct phy_ops phy_g12a_usb3_pcie_ops = {
    376	.init		= phy_g12a_usb3_pcie_init,
    377	.exit		= phy_g12a_usb3_pcie_exit,
    378	.power_on	= phy_g12a_usb3_pcie_power_on,
    379	.power_off	= phy_g12a_usb3_pcie_power_off,
    380	.reset		= phy_g12a_usb3_pcie_reset,
    381	.owner		= THIS_MODULE,
    382};
    383
    384static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
    385{
    386	struct device *dev = &pdev->dev;
    387	struct device_node *np = dev->of_node;
    388	struct phy_g12a_usb3_pcie_priv *priv;
    389	struct phy_provider *phy_provider;
    390	void __iomem *base;
    391	int ret;
    392
    393	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    394	if (!priv)
    395		return -ENOMEM;
    396
    397	base = devm_platform_ioremap_resource(pdev, 0);
    398	if (IS_ERR(base))
    399		return PTR_ERR(base);
    400
    401	priv->regmap = devm_regmap_init_mmio(dev, base,
    402					     &phy_g12a_usb3_pcie_regmap_conf);
    403	if (IS_ERR(priv->regmap))
    404		return PTR_ERR(priv->regmap);
    405
    406	priv->regmap_cr = devm_regmap_init(dev, NULL, priv,
    407					   &phy_g12a_usb3_pcie_cr_regmap_conf);
    408	if (IS_ERR(priv->regmap_cr))
    409		return PTR_ERR(priv->regmap_cr);
    410
    411	priv->clk_ref = devm_clk_get(dev, "ref_clk");
    412	if (IS_ERR(priv->clk_ref))
    413		return PTR_ERR(priv->clk_ref);
    414
    415	ret = clk_prepare_enable(priv->clk_ref);
    416	if (ret)
    417		return ret;
    418
    419	priv->reset = devm_reset_control_array_get_exclusive(dev);
    420	if (IS_ERR(priv->reset)) {
    421		ret = PTR_ERR(priv->reset);
    422		goto err_disable_clk_ref;
    423	}
    424
    425	priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops);
    426	if (IS_ERR(priv->phy)) {
    427		ret = PTR_ERR(priv->phy);
    428		dev_err_probe(dev, ret, "failed to create PHY\n");
    429		goto err_disable_clk_ref;
    430	}
    431
    432	phy_set_drvdata(priv->phy, priv);
    433	dev_set_drvdata(dev, priv);
    434
    435	phy_provider = devm_of_phy_provider_register(dev,
    436						     phy_g12a_usb3_pcie_xlate);
    437	if (IS_ERR(phy_provider)) {
    438		ret = PTR_ERR(phy_provider);
    439		goto err_disable_clk_ref;
    440	}
    441
    442	return 0;
    443
    444err_disable_clk_ref:
    445	clk_disable_unprepare(priv->clk_ref);
    446
    447	return ret;
    448}
    449
    450static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = {
    451	{ .compatible = "amlogic,g12a-usb3-pcie-phy", },
    452	{ },
    453};
    454MODULE_DEVICE_TABLE(of, phy_g12a_usb3_pcie_of_match);
    455
    456static struct platform_driver phy_g12a_usb3_pcie_driver = {
    457	.probe	= phy_g12a_usb3_pcie_probe,
    458	.driver	= {
    459		.name		= "phy-g12a-usb3-pcie",
    460		.of_match_table	= phy_g12a_usb3_pcie_of_match,
    461	},
    462};
    463module_platform_driver(phy_g12a_usb3_pcie_driver);
    464
    465MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
    466MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver");
    467MODULE_LICENSE("GPL v2");