Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *	phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
  4 *
  5 *	Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
  6 */
  7
  8#include <linux/kernel.h>
  9#include <linux/init.h>
 10#include <linux/clk.h>
 11#include <linux/phy/phy.h>
 12#include <linux/io.h>
 13#include <linux/mod_devicetable.h>
 14#include <linux/platform_device.h>
 15
 16struct priv {
 17	struct clk	*clk;
 18	void __iomem	*base;
 19};
 20
 21#define SATA_PHY_MODE_2	0x0330
 22#define  MODE_2_FORCE_PU_TX	BIT(0)
 23#define  MODE_2_FORCE_PU_RX	BIT(1)
 24#define  MODE_2_PU_PLL		BIT(2)
 25#define  MODE_2_PU_IVREF	BIT(3)
 26#define SATA_IF_CTRL	0x0050
 27#define  CTRL_PHY_SHUTDOWN	BIT(9)
 28
 29static int phy_mvebu_sata_power_on(struct phy *phy)
 30{
 31	struct priv *priv = phy_get_drvdata(phy);
 32	u32 reg;
 33
 34	clk_prepare_enable(priv->clk);
 35
 36	/* Enable PLL and IVREF */
 37	reg = readl(priv->base + SATA_PHY_MODE_2);
 38	reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
 39		MODE_2_PU_PLL | MODE_2_PU_IVREF);
 40	writel(reg , priv->base + SATA_PHY_MODE_2);
 41
 42	/* Enable PHY */
 43	reg = readl(priv->base + SATA_IF_CTRL);
 44	reg &= ~CTRL_PHY_SHUTDOWN;
 45	writel(reg, priv->base + SATA_IF_CTRL);
 46
 47	clk_disable_unprepare(priv->clk);
 48
 49	return 0;
 50}
 51
 52static int phy_mvebu_sata_power_off(struct phy *phy)
 53{
 54	struct priv *priv = phy_get_drvdata(phy);
 55	u32 reg;
 56
 57	clk_prepare_enable(priv->clk);
 58
 59	/* Disable PLL and IVREF */
 60	reg = readl(priv->base + SATA_PHY_MODE_2);
 61	reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
 62		 MODE_2_PU_PLL | MODE_2_PU_IVREF);
 63	writel(reg, priv->base + SATA_PHY_MODE_2);
 64
 65	/* Disable PHY */
 66	reg = readl(priv->base + SATA_IF_CTRL);
 67	reg |= CTRL_PHY_SHUTDOWN;
 68	writel(reg, priv->base + SATA_IF_CTRL);
 69
 70	clk_disable_unprepare(priv->clk);
 71
 72	return 0;
 73}
 74
 75static const struct phy_ops phy_mvebu_sata_ops = {
 76	.power_on	= phy_mvebu_sata_power_on,
 77	.power_off	= phy_mvebu_sata_power_off,
 78	.owner		= THIS_MODULE,
 79};
 80
 81static int phy_mvebu_sata_probe(struct platform_device *pdev)
 82{
 83	struct phy_provider *phy_provider;
 84	struct priv *priv;
 85	struct phy *phy;
 86
 87	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 88	if (!priv)
 89		return -ENOMEM;
 90
 91	priv->base = devm_platform_ioremap_resource(pdev, 0);
 92	if (IS_ERR(priv->base))
 93		return PTR_ERR(priv->base);
 94
 95	priv->clk = devm_clk_get(&pdev->dev, "sata");
 96	if (IS_ERR(priv->clk))
 97		return PTR_ERR(priv->clk);
 98
 99	phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
100	if (IS_ERR(phy))
101		return PTR_ERR(phy);
102
103	phy_set_drvdata(phy, priv);
104
105	phy_provider = devm_of_phy_provider_register(&pdev->dev,
106						     of_phy_simple_xlate);
107	if (IS_ERR(phy_provider))
108		return PTR_ERR(phy_provider);
109
110	/* The boot loader may of left it on. Turn it off. */
111	phy_mvebu_sata_power_off(phy);
112
113	return 0;
114}
115
116static const struct of_device_id phy_mvebu_sata_of_match[] = {
117	{ .compatible = "marvell,mvebu-sata-phy" },
118	{ },
119};
120
121static struct platform_driver phy_mvebu_sata_driver = {
122	.probe	= phy_mvebu_sata_probe,
123	.driver = {
124		.name	= "phy-mvebu-sata",
125		.of_match_table	= phy_mvebu_sata_of_match,
126	}
127};
128builtin_platform_driver(phy_mvebu_sata_driver);