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-berlin-sata.c (7254B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Marvell Berlin SATA PHY driver
      4 *
      5 * Copyright (C) 2014 Marvell Technology Group Ltd.
      6 *
      7 * Antoine Ténart <antoine.tenart@free-electrons.com>
      8 */
      9
     10#include <linux/clk.h>
     11#include <linux/module.h>
     12#include <linux/phy/phy.h>
     13#include <linux/io.h>
     14#include <linux/platform_device.h>
     15
     16#define HOST_VSA_ADDR		0x0
     17#define HOST_VSA_DATA		0x4
     18#define PORT_SCR_CTL		0x2c
     19#define PORT_VSR_ADDR		0x78
     20#define PORT_VSR_DATA		0x7c
     21
     22#define CONTROL_REGISTER	0x0
     23#define MBUS_SIZE_CONTROL	0x4
     24
     25#define POWER_DOWN_PHY0			BIT(6)
     26#define POWER_DOWN_PHY1			BIT(14)
     27#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
     28#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
     29
     30#define BG2_PHY_BASE		0x080
     31#define BG2Q_PHY_BASE		0x200
     32
     33/* register 0x01 */
     34#define REF_FREF_SEL_25		BIT(0)
     35#define PHY_BERLIN_MODE_SATA	(0x0 << 5)
     36
     37/* register 0x02 */
     38#define USE_MAX_PLL_RATE	BIT(12)
     39
     40/* register 0x23 */
     41#define DATA_BIT_WIDTH_10	(0x0 << 10)
     42#define DATA_BIT_WIDTH_20	(0x1 << 10)
     43#define DATA_BIT_WIDTH_40	(0x2 << 10)
     44
     45/* register 0x25 */
     46#define PHY_GEN_MAX_1_5		(0x0 << 10)
     47#define PHY_GEN_MAX_3_0		(0x1 << 10)
     48#define PHY_GEN_MAX_6_0		(0x2 << 10)
     49
     50struct phy_berlin_desc {
     51	struct phy	*phy;
     52	u32		power_bit;
     53	unsigned	index;
     54};
     55
     56struct phy_berlin_priv {
     57	void __iomem		*base;
     58	spinlock_t		lock;
     59	struct clk		*clk;
     60	struct phy_berlin_desc	**phys;
     61	unsigned		nphys;
     62	u32			phy_base;
     63};
     64
     65static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
     66			       u32 phy_base, u32 reg, u32 mask, u32 val)
     67{
     68	u32 regval;
     69
     70	/* select register */
     71	writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);
     72
     73	/* set bits */
     74	regval = readl(ctrl_reg + PORT_VSR_DATA);
     75	regval &= ~mask;
     76	regval |= val;
     77	writel(regval, ctrl_reg + PORT_VSR_DATA);
     78}
     79
     80static int phy_berlin_sata_power_on(struct phy *phy)
     81{
     82	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
     83	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
     84	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
     85	u32 regval;
     86
     87	clk_prepare_enable(priv->clk);
     88
     89	spin_lock(&priv->lock);
     90
     91	/* Power on PHY */
     92	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
     93	regval = readl(priv->base + HOST_VSA_DATA);
     94	regval &= ~desc->power_bit;
     95	writel(regval, priv->base + HOST_VSA_DATA);
     96
     97	/* Configure MBus */
     98	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
     99	regval = readl(priv->base + HOST_VSA_DATA);
    100	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
    101	writel(regval, priv->base + HOST_VSA_DATA);
    102
    103	/* set PHY mode and ref freq to 25 MHz */
    104	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
    105				    0x00ff,
    106				    REF_FREF_SEL_25 | PHY_BERLIN_MODE_SATA);
    107
    108	/* set PHY up to 6 Gbps */
    109	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
    110				    0x0c00, PHY_GEN_MAX_6_0);
    111
    112	/* set 40 bits width */
    113	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
    114				    0x0c00, DATA_BIT_WIDTH_40);
    115
    116	/* use max pll rate */
    117	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
    118				    0x0000, USE_MAX_PLL_RATE);
    119
    120	/* set Gen3 controller speed */
    121	regval = readl(ctrl_reg + PORT_SCR_CTL);
    122	regval &= ~GENMASK(7, 4);
    123	regval |= 0x30;
    124	writel(regval, ctrl_reg + PORT_SCR_CTL);
    125
    126	spin_unlock(&priv->lock);
    127
    128	clk_disable_unprepare(priv->clk);
    129
    130	return 0;
    131}
    132
    133static int phy_berlin_sata_power_off(struct phy *phy)
    134{
    135	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
    136	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
    137	u32 regval;
    138
    139	clk_prepare_enable(priv->clk);
    140
    141	spin_lock(&priv->lock);
    142
    143	/* Power down PHY */
    144	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
    145	regval = readl(priv->base + HOST_VSA_DATA);
    146	regval |= desc->power_bit;
    147	writel(regval, priv->base + HOST_VSA_DATA);
    148
    149	spin_unlock(&priv->lock);
    150
    151	clk_disable_unprepare(priv->clk);
    152
    153	return 0;
    154}
    155
    156static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
    157					     struct of_phandle_args *args)
    158{
    159	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
    160	int i;
    161
    162	if (WARN_ON(args->args[0] >= priv->nphys))
    163		return ERR_PTR(-ENODEV);
    164
    165	for (i = 0; i < priv->nphys; i++) {
    166		if (priv->phys[i]->index == args->args[0])
    167			break;
    168	}
    169
    170	if (i == priv->nphys)
    171		return ERR_PTR(-ENODEV);
    172
    173	return priv->phys[i]->phy;
    174}
    175
    176static const struct phy_ops phy_berlin_sata_ops = {
    177	.power_on	= phy_berlin_sata_power_on,
    178	.power_off	= phy_berlin_sata_power_off,
    179	.owner		= THIS_MODULE,
    180};
    181
    182static u32 phy_berlin_power_down_bits[] = {
    183	POWER_DOWN_PHY0,
    184	POWER_DOWN_PHY1,
    185};
    186
    187static int phy_berlin_sata_probe(struct platform_device *pdev)
    188{
    189	struct device *dev = &pdev->dev;
    190	struct device_node *child;
    191	struct phy *phy;
    192	struct phy_provider *phy_provider;
    193	struct phy_berlin_priv *priv;
    194	struct resource *res;
    195	int ret, i = 0;
    196	u32 phy_id;
    197
    198	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    199	if (!priv)
    200		return -ENOMEM;
    201
    202	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    203	if (!res)
    204		return -EINVAL;
    205
    206	priv->base = devm_ioremap(dev, res->start, resource_size(res));
    207	if (!priv->base)
    208		return -ENOMEM;
    209
    210	priv->clk = devm_clk_get(dev, NULL);
    211	if (IS_ERR(priv->clk))
    212		return PTR_ERR(priv->clk);
    213
    214	priv->nphys = of_get_child_count(dev->of_node);
    215	if (priv->nphys == 0)
    216		return -ENODEV;
    217
    218	priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
    219				  GFP_KERNEL);
    220	if (!priv->phys)
    221		return -ENOMEM;
    222
    223	if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
    224		priv->phy_base = BG2_PHY_BASE;
    225	else
    226		priv->phy_base = BG2Q_PHY_BASE;
    227
    228	dev_set_drvdata(dev, priv);
    229	spin_lock_init(&priv->lock);
    230
    231	for_each_available_child_of_node(dev->of_node, child) {
    232		struct phy_berlin_desc *phy_desc;
    233
    234		if (of_property_read_u32(child, "reg", &phy_id)) {
    235			dev_err(dev, "missing reg property in node %pOFn\n",
    236				child);
    237			ret = -EINVAL;
    238			goto put_child;
    239		}
    240
    241		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
    242			dev_err(dev, "invalid reg in node %pOFn\n", child);
    243			ret = -EINVAL;
    244			goto put_child;
    245		}
    246
    247		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
    248		if (!phy_desc) {
    249			ret = -ENOMEM;
    250			goto put_child;
    251		}
    252
    253		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
    254		if (IS_ERR(phy)) {
    255			dev_err(dev, "failed to create PHY %d\n", phy_id);
    256			ret = PTR_ERR(phy);
    257			goto put_child;
    258		}
    259
    260		phy_desc->phy = phy;
    261		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
    262		phy_desc->index = phy_id;
    263		phy_set_drvdata(phy, phy_desc);
    264
    265		priv->phys[i++] = phy_desc;
    266
    267		/* Make sure the PHY is off */
    268		phy_berlin_sata_power_off(phy);
    269	}
    270
    271	phy_provider =
    272		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
    273	return PTR_ERR_OR_ZERO(phy_provider);
    274put_child:
    275	of_node_put(child);
    276	return ret;
    277}
    278
    279static const struct of_device_id phy_berlin_sata_of_match[] = {
    280	{ .compatible = "marvell,berlin2-sata-phy" },
    281	{ .compatible = "marvell,berlin2q-sata-phy" },
    282	{ },
    283};
    284MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
    285
    286static struct platform_driver phy_berlin_sata_driver = {
    287	.probe	= phy_berlin_sata_probe,
    288	.driver	= {
    289		.name		= "phy-berlin-sata",
    290		.of_match_table	= phy_berlin_sata_of_match,
    291	},
    292};
    293module_platform_driver(phy_berlin_sata_driver);
    294
    295MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
    296MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
    297MODULE_LICENSE("GPL v2");