Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  phy-ralink-usb.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2017 John Crispin <john@phrozen.org>
 *
 * Based on code from
 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
 */


#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>

#define RT_SYSC_REG_SYSCFG1  0x014
#define RT_SYSC_REG_CLKCFG1  0x030
#define RT_SYSC_REG_USB_PHY_CFG  0x05c

#define OFS_U2_PHY_AC0   0x800
#define OFS_U2_PHY_AC1   0x804
#define OFS_U2_PHY_AC2   0x808
#define OFS_U2_PHY_ACR0   0x810
#define OFS_U2_PHY_ACR1   0x814
#define OFS_U2_PHY_ACR2   0x818
#define OFS_U2_PHY_ACR3   0x81C
#define OFS_U2_PHY_ACR4   0x820
#define OFS_U2_PHY_AMON0  0x824
#define OFS_U2_PHY_DCR0   0x860
#define OFS_U2_PHY_DCR1   0x864
#define OFS_U2_PHY_DTM0   0x868
#define OFS_U2_PHY_DTM1   0x86C

#define RT_RSTCTRL_UDEV   BIT(25)
#define RT_RSTCTRL_UHST   BIT(22)
#define RT_SYSCFG1_USB0_HOST_MODE BIT(10)

#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25)
#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22)
#define RT_CLKCFG1_UPHY1_CLK_EN  BIT(20)
#define RT_CLKCFG1_UPHY0_CLK_EN  BIT(18)

#define USB_PHY_UTMI_8B60M  BIT(1)
#define UDEV_WAKEUP   BIT(0)

struct ralink_usb_phy {
 struct reset_control *rstdev;
 struct reset_control *rsthost;
 u32   clk;
 struct phy  *phy;
 void __iomem  *base;
 struct regmap  *sysctl;
};

static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg)
{
 writel(val, phy->base + reg);
}

static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg)
{
 return readl(phy->base + reg);
}

static void ralink_usb_phy_init(struct ralink_usb_phy *phy)
{
 u2_phy_r32(phy, OFS_U2_PHY_AC2);
 u2_phy_r32(phy, OFS_U2_PHY_ACR0);
 u2_phy_r32(phy, OFS_U2_PHY_DCR0);

 u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
 u2_phy_r32(phy, OFS_U2_PHY_DCR0);
 u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
 u2_phy_r32(phy, OFS_U2_PHY_DCR0);
 u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
 u2_phy_r32(phy, OFS_U2_PHY_DCR0);
 u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
 u2_phy_r32(phy, OFS_U2_PHY_DCR0);
 u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
 u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
 u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
 u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
}

static int ralink_usb_phy_power_on(struct phy *_phy)
{
 struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
 u32 t;

 /* enable the phy */
 regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
      phy->clk, phy->clk);

 /* setup host mode */
 regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,
      RT_SYSCFG1_USB0_HOST_MODE,
      RT_SYSCFG1_USB0_HOST_MODE);

 /* deassert the reset lines */
 reset_control_deassert(phy->rsthost);
 reset_control_deassert(phy->rstdev);

 /*
 * The SDK kernel had a delay of 100ms. however on device
 * testing showed that 10ms is enough
 */

 mdelay(10);

 if (phy->base)
  ralink_usb_phy_init(phy);

 /* print some status info */
 regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);
 dev_info(&phy->phy->dev, "remote usb device wakeup %s\n",
  (t & UDEV_WAKEUP) ? ("enabled") : ("disabled"));
 if (t & USB_PHY_UTMI_8B60M)
  dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n");
 else
  dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n");

 return 0;
}

static int ralink_usb_phy_power_off(struct phy *_phy)
{
 struct ralink_usb_phy *phy = phy_get_drvdata(_phy);

 /* disable the phy */
 regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
      phy->clk, 0);

 /* assert the reset lines */
 reset_control_assert(phy->rstdev);
 reset_control_assert(phy->rsthost);

 return 0;
}

static const struct phy_ops ralink_usb_phy_ops = {
 .power_on = ralink_usb_phy_power_on,
 .power_off = ralink_usb_phy_power_off,
 .owner  = THIS_MODULE,
};

static const struct of_device_id ralink_usb_phy_of_match[] = {
 {
  .compatible = "ralink,rt3352-usbphy",
  .data = (void *)(uintptr_t)(RT_CLKCFG1_UPHY1_CLK_EN |
         RT_CLKCFG1_UPHY0_CLK_EN)
 },
 {
  .compatible = "mediatek,mt7620-usbphy",
  .data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |
         MT7620_CLKCFG1_UPHY0_CLK_EN)
 },
 {
  .compatible = "mediatek,mt7628-usbphy",
  .data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |
         MT7620_CLKCFG1_UPHY0_CLK_EN) },
 { },
};
MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);

static int ralink_usb_phy_probe(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct phy_provider *phy_provider;
 struct ralink_usb_phy *phy;

 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
 if (!phy)
  return -ENOMEM;

 phy->clk = (uintptr_t)device_get_match_data(&pdev->dev);
 phy->base = NULL;

 phy->sysctl = syscon_regmap_lookup_by_phandle(dev->of_node, "ralink,sysctl");
 if (IS_ERR(phy->sysctl)) {
  dev_err(dev, "failed to get sysctl registers\n");
  return PTR_ERR(phy->sysctl);
 }

 /* The MT7628 and MT7688 require extra setup of PHY registers. */
 if (of_device_is_compatible(dev->of_node, "mediatek,mt7628-usbphy")) {
  phy->base = devm_platform_ioremap_resource(pdev, 0);
  if (IS_ERR(phy->base)) {
   dev_err(dev, "failed to remap register memory\n");
   return PTR_ERR(phy->base);
  }
 }

 phy->rsthost = devm_reset_control_get(&pdev->dev, "host");
 if (IS_ERR(phy->rsthost)) {
  dev_err(dev, "host reset is missing\n");
  return PTR_ERR(phy->rsthost);
 }

 phy->rstdev = devm_reset_control_get(&pdev->dev, "device");
 if (IS_ERR(phy->rstdev)) {
  dev_err(dev, "device reset is missing\n");
  return PTR_ERR(phy->rstdev);
 }

 phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops);
 if (IS_ERR(phy->phy)) {
  dev_err(dev, "failed to create PHY\n");
  return PTR_ERR(phy->phy);
 }
 phy_set_drvdata(phy->phy, phy);

 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

 return PTR_ERR_OR_ZERO(phy_provider);
}

static struct platform_driver ralink_usb_phy_driver = {
 .probe = ralink_usb_phy_probe,
 .driver = {
  .of_match_table = ralink_usb_phy_of_match,
  .name  = "ralink-usb-phy",
 }
};
module_platform_driver(ralink_usb_phy_driver);

MODULE_DESCRIPTION("Ralink USB phy driver");
MODULE_AUTHOR("John Crispin ");
MODULE_LICENSE("GPL v2");

Messung V0.5
C=96 H=93 G=94

¤ Dauer der Verarbeitung: 0.15 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge