mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
2874c5fd28
Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 3029 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
129 lines
3 KiB
C
129 lines
3 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
|
|
*
|
|
* Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/phy/phy.h>
|
|
#include <linux/io.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
struct priv {
|
|
struct clk *clk;
|
|
void __iomem *base;
|
|
};
|
|
|
|
#define SATA_PHY_MODE_2 0x0330
|
|
#define MODE_2_FORCE_PU_TX BIT(0)
|
|
#define MODE_2_FORCE_PU_RX BIT(1)
|
|
#define MODE_2_PU_PLL BIT(2)
|
|
#define MODE_2_PU_IVREF BIT(3)
|
|
#define SATA_IF_CTRL 0x0050
|
|
#define CTRL_PHY_SHUTDOWN BIT(9)
|
|
|
|
static int phy_mvebu_sata_power_on(struct phy *phy)
|
|
{
|
|
struct priv *priv = phy_get_drvdata(phy);
|
|
u32 reg;
|
|
|
|
clk_prepare_enable(priv->clk);
|
|
|
|
/* Enable PLL and IVREF */
|
|
reg = readl(priv->base + SATA_PHY_MODE_2);
|
|
reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
|
|
MODE_2_PU_PLL | MODE_2_PU_IVREF);
|
|
writel(reg , priv->base + SATA_PHY_MODE_2);
|
|
|
|
/* Enable PHY */
|
|
reg = readl(priv->base + SATA_IF_CTRL);
|
|
reg &= ~CTRL_PHY_SHUTDOWN;
|
|
writel(reg, priv->base + SATA_IF_CTRL);
|
|
|
|
clk_disable_unprepare(priv->clk);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int phy_mvebu_sata_power_off(struct phy *phy)
|
|
{
|
|
struct priv *priv = phy_get_drvdata(phy);
|
|
u32 reg;
|
|
|
|
clk_prepare_enable(priv->clk);
|
|
|
|
/* Disable PLL and IVREF */
|
|
reg = readl(priv->base + SATA_PHY_MODE_2);
|
|
reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
|
|
MODE_2_PU_PLL | MODE_2_PU_IVREF);
|
|
writel(reg, priv->base + SATA_PHY_MODE_2);
|
|
|
|
/* Disable PHY */
|
|
reg = readl(priv->base + SATA_IF_CTRL);
|
|
reg |= CTRL_PHY_SHUTDOWN;
|
|
writel(reg, priv->base + SATA_IF_CTRL);
|
|
|
|
clk_disable_unprepare(priv->clk);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct phy_ops phy_mvebu_sata_ops = {
|
|
.power_on = phy_mvebu_sata_power_on,
|
|
.power_off = phy_mvebu_sata_power_off,
|
|
.owner = THIS_MODULE,
|
|
};
|
|
|
|
static int phy_mvebu_sata_probe(struct platform_device *pdev)
|
|
{
|
|
struct phy_provider *phy_provider;
|
|
struct resource *res;
|
|
struct priv *priv;
|
|
struct phy *phy;
|
|
|
|
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
|
if (!priv)
|
|
return -ENOMEM;
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
priv->base = devm_ioremap_resource(&pdev->dev, res);
|
|
if (IS_ERR(priv->base))
|
|
return PTR_ERR(priv->base);
|
|
|
|
priv->clk = devm_clk_get(&pdev->dev, "sata");
|
|
if (IS_ERR(priv->clk))
|
|
return PTR_ERR(priv->clk);
|
|
|
|
phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
|
|
if (IS_ERR(phy))
|
|
return PTR_ERR(phy);
|
|
|
|
phy_set_drvdata(phy, priv);
|
|
|
|
phy_provider = devm_of_phy_provider_register(&pdev->dev,
|
|
of_phy_simple_xlate);
|
|
if (IS_ERR(phy_provider))
|
|
return PTR_ERR(phy_provider);
|
|
|
|
/* The boot loader may of left it on. Turn it off. */
|
|
phy_mvebu_sata_power_off(phy);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct of_device_id phy_mvebu_sata_of_match[] = {
|
|
{ .compatible = "marvell,mvebu-sata-phy" },
|
|
{ },
|
|
};
|
|
|
|
static struct platform_driver phy_mvebu_sata_driver = {
|
|
.probe = phy_mvebu_sata_probe,
|
|
.driver = {
|
|
.name = "phy-mvebu-sata",
|
|
.of_match_table = phy_mvebu_sata_of_match,
|
|
}
|
|
};
|
|
builtin_platform_driver(phy_mvebu_sata_driver);
|