0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/clk.h>
0011 #include <linux/phy/phy.h>
0012 #include <linux/io.h>
0013 #include <linux/platform_device.h>
0014
0015 struct priv {
0016 struct clk *clk;
0017 void __iomem *base;
0018 };
0019
0020 #define SATA_PHY_MODE_2 0x0330
0021 #define MODE_2_FORCE_PU_TX BIT(0)
0022 #define MODE_2_FORCE_PU_RX BIT(1)
0023 #define MODE_2_PU_PLL BIT(2)
0024 #define MODE_2_PU_IVREF BIT(3)
0025 #define SATA_IF_CTRL 0x0050
0026 #define CTRL_PHY_SHUTDOWN BIT(9)
0027
0028 static int phy_mvebu_sata_power_on(struct phy *phy)
0029 {
0030 struct priv *priv = phy_get_drvdata(phy);
0031 u32 reg;
0032
0033 clk_prepare_enable(priv->clk);
0034
0035
0036 reg = readl(priv->base + SATA_PHY_MODE_2);
0037 reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
0038 MODE_2_PU_PLL | MODE_2_PU_IVREF);
0039 writel(reg , priv->base + SATA_PHY_MODE_2);
0040
0041
0042 reg = readl(priv->base + SATA_IF_CTRL);
0043 reg &= ~CTRL_PHY_SHUTDOWN;
0044 writel(reg, priv->base + SATA_IF_CTRL);
0045
0046 clk_disable_unprepare(priv->clk);
0047
0048 return 0;
0049 }
0050
0051 static int phy_mvebu_sata_power_off(struct phy *phy)
0052 {
0053 struct priv *priv = phy_get_drvdata(phy);
0054 u32 reg;
0055
0056 clk_prepare_enable(priv->clk);
0057
0058
0059 reg = readl(priv->base + SATA_PHY_MODE_2);
0060 reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
0061 MODE_2_PU_PLL | MODE_2_PU_IVREF);
0062 writel(reg, priv->base + SATA_PHY_MODE_2);
0063
0064
0065 reg = readl(priv->base + SATA_IF_CTRL);
0066 reg |= CTRL_PHY_SHUTDOWN;
0067 writel(reg, priv->base + SATA_IF_CTRL);
0068
0069 clk_disable_unprepare(priv->clk);
0070
0071 return 0;
0072 }
0073
0074 static const struct phy_ops phy_mvebu_sata_ops = {
0075 .power_on = phy_mvebu_sata_power_on,
0076 .power_off = phy_mvebu_sata_power_off,
0077 .owner = THIS_MODULE,
0078 };
0079
0080 static int phy_mvebu_sata_probe(struct platform_device *pdev)
0081 {
0082 struct phy_provider *phy_provider;
0083 struct priv *priv;
0084 struct phy *phy;
0085
0086 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0087 if (!priv)
0088 return -ENOMEM;
0089
0090 priv->base = devm_platform_ioremap_resource(pdev, 0);
0091 if (IS_ERR(priv->base))
0092 return PTR_ERR(priv->base);
0093
0094 priv->clk = devm_clk_get(&pdev->dev, "sata");
0095 if (IS_ERR(priv->clk))
0096 return PTR_ERR(priv->clk);
0097
0098 phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
0099 if (IS_ERR(phy))
0100 return PTR_ERR(phy);
0101
0102 phy_set_drvdata(phy, priv);
0103
0104 phy_provider = devm_of_phy_provider_register(&pdev->dev,
0105 of_phy_simple_xlate);
0106 if (IS_ERR(phy_provider))
0107 return PTR_ERR(phy_provider);
0108
0109
0110 phy_mvebu_sata_power_off(phy);
0111
0112 return 0;
0113 }
0114
0115 static const struct of_device_id phy_mvebu_sata_of_match[] = {
0116 { .compatible = "marvell,mvebu-sata-phy" },
0117 { },
0118 };
0119
0120 static struct platform_driver phy_mvebu_sata_driver = {
0121 .probe = phy_mvebu_sata_probe,
0122 .driver = {
0123 .name = "phy-mvebu-sata",
0124 .of_match_table = phy_mvebu_sata_of_match,
0125 }
0126 };
0127 builtin_platform_driver(phy_mvebu_sata_driver);