Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/phy/amlogic/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  phy-meson-axg-pcie.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Amlogic AXG PCIE PHY driver
 *
 * Copyright (C) 2020 Remi Pommarel <repk@triplefau.lt>
 */

#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/platform_device.h>
#include <linux/bitfield.h>
#include <dt-bindings/phy/phy.h>

#define MESON_PCIE_REG0 0x00
#define  MESON_PCIE_COMMON_CLK BIT(4)
#define  MESON_PCIE_PORT_SEL GENMASK(3, 2)
#define  MESON_PCIE_CLK  BIT(1)
#define  MESON_PCIE_POWERDOWN BIT(0)

#define MESON_PCIE_TWO_X1  FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3)
#define MESON_PCIE_COMMON_REF_CLK FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1)
#define MESON_PCIE_PHY_INIT  (MESON_PCIE_TWO_X1 |  \
      MESON_PCIE_COMMON_REF_CLK)
#define MESON_PCIE_RESET_DELAY  500

struct phy_axg_pcie_priv {
 struct phy *phy;
 struct phy *analog;
 struct regmap *regmap;
 struct reset_control *reset;
};

static const struct regmap_config phy_axg_pcie_regmap_conf = {
 .reg_bits = 8,
 .val_bits = 32,
 .reg_stride = 4,
 .max_register = MESON_PCIE_REG0,
};

static int phy_axg_pcie_power_on(struct phy *phy)
{
 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
 int ret;

 ret = phy_power_on(priv->analog);
 if (ret != 0)
  return ret;

 regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
      MESON_PCIE_POWERDOWN, 0);
 return 0;
}

static int phy_axg_pcie_power_off(struct phy *phy)
{
 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
 int ret;

 ret = phy_power_off(priv->analog);
 if (ret != 0)
  return ret;

 regmap_update_bits(priv->regmap, MESON_PCIE_REG0,
      MESON_PCIE_POWERDOWN, 1);
 return 0;
}

static int phy_axg_pcie_init(struct phy *phy)
{
 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
 int ret;

 ret = phy_init(priv->analog);
 if (ret != 0)
  return ret;

 regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT);
 return reset_control_reset(priv->reset);
}

static int phy_axg_pcie_exit(struct phy *phy)
{
 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
 int ret;

 ret = phy_exit(priv->analog);
 if (ret != 0)
  return ret;

 return reset_control_reset(priv->reset);
}

static int phy_axg_pcie_reset(struct phy *phy)
{
 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy);
 int ret = 0;

 ret = phy_reset(priv->analog);
 if (ret != 0)
  goto out;

 ret = reset_control_assert(priv->reset);
 if (ret != 0)
  goto out;
 udelay(MESON_PCIE_RESET_DELAY);

 ret = reset_control_deassert(priv->reset);
 if (ret != 0)
  goto out;
 udelay(MESON_PCIE_RESET_DELAY);

out:
 return ret;
}

static const struct phy_ops phy_axg_pcie_ops = {
 .init = phy_axg_pcie_init,
 .exit = phy_axg_pcie_exit,
 .power_on = phy_axg_pcie_power_on,
 .power_off = phy_axg_pcie_power_off,
 .reset = phy_axg_pcie_reset,
 .owner = THIS_MODULE,
};

static int phy_axg_pcie_probe(struct platform_device *pdev)
{
 struct phy_provider *pphy;
 struct device *dev = &pdev->dev;
 struct phy_axg_pcie_priv *priv;
 struct device_node *np = dev->of_node;
 void __iomem *base;

 priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
 if (!priv)
  return -ENOMEM;

 base = devm_platform_ioremap_resource(pdev, 0);
 if (IS_ERR(base))
  return PTR_ERR(base);

 priv->regmap = devm_regmap_init_mmio(dev, base,
          &phy_axg_pcie_regmap_conf);
 if (IS_ERR(priv->regmap))
  return PTR_ERR(priv->regmap);

 priv->reset = devm_reset_control_array_get_exclusive(dev);
 if (IS_ERR(priv->reset))
  return PTR_ERR(priv->reset);

 priv->analog = devm_phy_get(dev, "analog");
 if (IS_ERR(priv->analog))
  return PTR_ERR(priv->analog);

 priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops);
 if (IS_ERR(priv->phy))
  return dev_err_probe(dev, PTR_ERR(priv->phy),
         "failed to create PHY\n");

 phy_set_drvdata(priv->phy, priv);
 dev_set_drvdata(dev, priv);
 pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

 return PTR_ERR_OR_ZERO(pphy);
}

static const struct of_device_id phy_axg_pcie_of_match[] = {
 {
  .compatible = "amlogic,axg-pcie-phy",
 },
 { },
};
MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match);

static struct platform_driver phy_axg_pcie_driver = {
 .probe = phy_axg_pcie_probe,
 .driver = {
  .name = "phy-axg-pcie",
  .of_match_table = phy_axg_pcie_of_match,
 },
};
module_platform_driver(phy_axg_pcie_driver);

MODULE_AUTHOR("Remi Pommarel ");
MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver");
MODULE_LICENSE("GPL v2");

Messung V0.5
C=99 H=93 G=95

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.