uboot/drivers/phy/msm8916-usbh-phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018 Ramon Fried <ramon.fried@gmail.com>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <generic-phy.h>
   9#include <usb/ehci-ci.h>
  10#include <usb/ulpi.h>
  11#include <asm/io.h>
  12
  13/* PHY viewport regs */
  14#define ULPI_MISC_A_READ                0x96
  15#define ULPI_MISC_A_SET                 0x97
  16#define ULPI_MISC_A_CLEAR               0x98
  17#define ULPI_MISC_A_VBUSVLDEXT          BIT(0)
  18#define ULPI_MISC_A_VBUSVLDEXTSEL       BIT(1)
  19#define GEN2_SESS_VLD_CTRL_EN           BIT(7)
  20#define SESS_VLD_CTRL                   BIT(25)
  21
  22struct msm_phy_priv {
  23        void __iomem *regs;
  24        struct usb_ehci *ehci; /* Start of IP core*/
  25        struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
  26};
  27
  28static int msm_phy_power_on(struct phy *phy)
  29{
  30        struct msm_phy_priv *priv = dev_get_priv(phy->dev);
  31
  32        /* Select and enable external configuration with USB PHY */
  33        ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_SET,
  34                   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
  35
  36        return 0;
  37}
  38
  39static int msm_phy_power_off(struct phy *phy)
  40{
  41        struct msm_phy_priv *priv = dev_get_priv(phy->dev);
  42
  43        /* Disable VBUS mimicing in the controller. */
  44        ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
  45                   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
  46        return 0;
  47}
  48
  49static int msm_phy_reset(struct phy *phy)
  50{
  51        struct msm_phy_priv *p = dev_get_priv(phy->dev);
  52
  53        /* select ULPI phy */
  54        writel(PORT_PTS_ULPI, &p->ehci->portsc);
  55
  56        /* Enable sess_vld */
  57        setbits_le32(&p->ehci->genconfig2, GEN2_SESS_VLD_CTRL_EN);
  58
  59        /* Enable external vbus configuration in the LINK */
  60        setbits_le32(&p->ehci->usbcmd, SESS_VLD_CTRL);
  61
  62        /* USB_OTG_HS_AHB_BURST */
  63        writel(0x0, &p->ehci->sbuscfg);
  64
  65        /* USB_OTG_HS_AHB_MODE: HPROT_MODE */
  66        /* Bus access related config. */
  67        writel(0x08, &p->ehci->sbusmode);
  68
  69        return 0;
  70}
  71
  72static int msm_phy_probe(struct udevice *dev)
  73{
  74        struct msm_phy_priv *priv = dev_get_priv(dev);
  75
  76        priv->regs = dev_remap_addr(dev);
  77        if (!priv->regs)
  78                return -EINVAL;
  79
  80        priv->ehci = (struct usb_ehci *)priv->regs;
  81        priv->ulpi_vp.port_num = 0;
  82
  83        /* Warning: this will not work if viewport address is > 64 bit due to
  84         * ULPI design.
  85         */
  86        priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint;
  87
  88        return 0;
  89}
  90
  91static struct phy_ops msm_phy_ops = {
  92        .power_on = msm_phy_power_on,
  93        .power_off = msm_phy_power_off,
  94        .reset = msm_phy_reset,
  95};
  96
  97static const struct udevice_id msm_phy_ids[] = {
  98        { .compatible = "qcom,apq8016-usbphy" },
  99        { }
 100};
 101
 102U_BOOT_DRIVER(msm8916_usbphy) = {
 103        .name           = "msm8916_usbphy",
 104        .id             = UCLASS_PHY,
 105        .of_match       = msm_phy_ids,
 106        .ops            = &msm_phy_ops,
 107        .probe          = msm_phy_probe,
 108        .priv_auto_alloc_size = sizeof(struct msm_phy_priv),
 109};
 110