Commit 92454e47bcec875490f3238d674fdc3e6c012b70

Authored by Ramon Fried
Committed by Tom Rini
1 parent 2df573e6a5

phy: db410c: Add MSM USB PHY driver

Add a PHY driver for the Qualcomm dragonboard 410c which
allows switching on/off and resetting the phy connected
to the EHCI controllers and USBHS controller.

Signed-off-by: Ramon Fried <ramon.fried@gmail.com>

Showing 4 changed files with 119 additions and 0 deletions Side-by-side Diff

... ... @@ -210,6 +210,7 @@
210 210 F: arch/arm/mach-snapdragon/
211 211 F: drivers/gpio/msm_gpio.c
212 212 F: drivers/mmc/msm_sdhci.c
  213 +F: drivers/phy/msm8916-usbh-phy.c
213 214 F: drivers/serial/serial_msm.c
214 215 F: drivers/smem/msm_smem.c
215 216 F: drivers/usb/host/ehci-msm.c
... ... @@ -139,5 +139,13 @@
139 139 This is the generic phy driver for the Amlogic Meson GXL
140 140 USB2 and USB3 PHYS.
141 141  
  142 +config MSM8916_USB_PHY
  143 + bool "Qualcomm MSM8916 USB PHY support"
  144 + depends on PHY
  145 + help
  146 + Support the USB PHY in msm8916
  147 +
  148 + This PHY is found on qualcomm dragonboard410c development board.
  149 +
142 150 endmenu
drivers/phy/Makefile
... ... @@ -15,4 +15,5 @@
15 15 obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
16 16 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
17 17 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
  18 +obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
drivers/phy/msm8916-usbh-phy.c
  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 +
  22 +struct 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 +
  28 +static 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 +
  39 +static 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 +
  49 +static 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 +
  72 +static 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 +
  91 +static 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 +
  97 +static const struct udevice_id msm_phy_ids[] = {
  98 + { .compatible = "qcom,apq8016-usbphy" },
  99 + { }
  100 +};
  101 +
  102 +U_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 +};