1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
5 * Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/clk.h>
11 #include <linux/phy/phy.h>
13 #include <linux/platform_device.h>
20 #define SATA_PHY_MODE_2 0x0330
21 #define MODE_2_FORCE_PU_TX BIT(0)
22 #define MODE_2_FORCE_PU_RX BIT(1)
23 #define MODE_2_PU_PLL BIT(2)
24 #define MODE_2_PU_IVREF BIT(3)
25 #define SATA_IF_CTRL 0x0050
26 #define CTRL_PHY_SHUTDOWN BIT(9)
28 static int phy_mvebu_sata_power_on(struct phy
*phy
)
30 struct priv
*priv
= phy_get_drvdata(phy
);
33 clk_prepare_enable(priv
->clk
);
35 /* Enable PLL and IVREF */
36 reg
= readl(priv
->base
+ SATA_PHY_MODE_2
);
37 reg
|= (MODE_2_FORCE_PU_TX
| MODE_2_FORCE_PU_RX
|
38 MODE_2_PU_PLL
| MODE_2_PU_IVREF
);
39 writel(reg
, priv
->base
+ SATA_PHY_MODE_2
);
42 reg
= readl(priv
->base
+ SATA_IF_CTRL
);
43 reg
&= ~CTRL_PHY_SHUTDOWN
;
44 writel(reg
, priv
->base
+ SATA_IF_CTRL
);
46 clk_disable_unprepare(priv
->clk
);
51 static int phy_mvebu_sata_power_off(struct phy
*phy
)
53 struct priv
*priv
= phy_get_drvdata(phy
);
56 clk_prepare_enable(priv
->clk
);
58 /* Disable PLL and IVREF */
59 reg
= readl(priv
->base
+ SATA_PHY_MODE_2
);
60 reg
&= ~(MODE_2_FORCE_PU_TX
| MODE_2_FORCE_PU_RX
|
61 MODE_2_PU_PLL
| MODE_2_PU_IVREF
);
62 writel(reg
, priv
->base
+ SATA_PHY_MODE_2
);
65 reg
= readl(priv
->base
+ SATA_IF_CTRL
);
66 reg
|= CTRL_PHY_SHUTDOWN
;
67 writel(reg
, priv
->base
+ SATA_IF_CTRL
);
69 clk_disable_unprepare(priv
->clk
);
74 static const struct phy_ops phy_mvebu_sata_ops
= {
75 .power_on
= phy_mvebu_sata_power_on
,
76 .power_off
= phy_mvebu_sata_power_off
,
80 static int phy_mvebu_sata_probe(struct platform_device
*pdev
)
82 struct phy_provider
*phy_provider
;
86 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
90 priv
->base
= devm_platform_ioremap_resource(pdev
, 0);
91 if (IS_ERR(priv
->base
))
92 return PTR_ERR(priv
->base
);
94 priv
->clk
= devm_clk_get(&pdev
->dev
, "sata");
95 if (IS_ERR(priv
->clk
))
96 return PTR_ERR(priv
->clk
);
98 phy
= devm_phy_create(&pdev
->dev
, NULL
, &phy_mvebu_sata_ops
);
102 phy_set_drvdata(phy
, priv
);
104 phy_provider
= devm_of_phy_provider_register(&pdev
->dev
,
105 of_phy_simple_xlate
);
106 if (IS_ERR(phy_provider
))
107 return PTR_ERR(phy_provider
);
109 /* The boot loader may of left it on. Turn it off. */
110 phy_mvebu_sata_power_off(phy
);
115 static const struct of_device_id phy_mvebu_sata_of_match
[] = {
116 { .compatible
= "marvell,mvebu-sata-phy" },
120 static struct platform_driver phy_mvebu_sata_driver
= {
121 .probe
= phy_mvebu_sata_probe
,
123 .name
= "phy-mvebu-sata",
124 .of_match_table
= phy_mvebu_sata_of_match
,
127 builtin_platform_driver(phy_mvebu_sata_driver
);