brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · 89a5a2b Raw
129 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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	0x033022#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	0x005027#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);129