phy: db410c: Add MSM USB PHY driver
authorRamon Fried <ramon.fried@gmail.com>
Fri, 21 Sep 2018 10:35:47 +0000 (13:35 +0300)
committerTom Rini <trini@konsulko.com>
Sun, 30 Sep 2018 17:00:36 +0000 (13:00 -0400)
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>
MAINTAINERS
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/msm8916-usbh-phy.c [new file with mode: 0644]

index 4551843..6147a4f 100644 (file)
@@ -210,6 +210,7 @@ S:  Maintained
 F:     arch/arm/mach-snapdragon/
 F:     drivers/gpio/msm_gpio.c
 F:     drivers/mmc/msm_sdhci.c
 F:     arch/arm/mach-snapdragon/
 F:     drivers/gpio/msm_gpio.c
 F:     drivers/mmc/msm_sdhci.c
+F:     drivers/phy/msm8916-usbh-phy.c
 F:     drivers/serial/serial_msm.c
 F:     drivers/smem/msm_smem.c
 F:     drivers/usb/host/ehci-msm.c
 F:     drivers/serial/serial_msm.c
 F:     drivers/smem/msm_smem.c
 F:     drivers/usb/host/ehci-msm.c
index e0822bb..bcc8e22 100644 (file)
@@ -139,4 +139,12 @@ config MESON_GXL_USB_PHY
          This is the generic phy driver for the Amlogic Meson GXL
          USB2 and USB3 PHYS.
 
          This is the generic phy driver for the Amlogic Meson GXL
          USB2 and USB3 PHYS.
 
+config MSM8916_USB_PHY
+       bool "Qualcomm MSM8916 USB PHY support"
+       depends on PHY
+       help
+          Support the USB PHY in msm8916
+
+         This PHY is found on qualcomm dragonboard410c development board.
+
 endmenu
 endmenu
index 178fb45..1e1e4ca 100644 (file)
@@ -15,3 +15,4 @@ obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o
 obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
 obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
+obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
diff --git a/drivers/phy/msm8916-usbh-phy.c b/drivers/phy/msm8916-usbh-phy.c
new file mode 100644 (file)
index 0000000..2c90738
--- /dev/null
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Ramon Fried <ramon.fried@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <usb/ehci-ci.h>
+#include <usb/ulpi.h>
+#include <asm/io.h>
+
+/* PHY viewport regs */
+#define ULPI_MISC_A_READ               0x96
+#define ULPI_MISC_A_SET                        0x97
+#define ULPI_MISC_A_CLEAR              0x98
+#define ULPI_MISC_A_VBUSVLDEXT         BIT(0)
+#define ULPI_MISC_A_VBUSVLDEXTSEL      BIT(1)
+#define GEN2_SESS_VLD_CTRL_EN          BIT(7)
+#define SESS_VLD_CTRL                  BIT(25)
+
+struct msm_phy_priv {
+       void __iomem *regs;
+       struct usb_ehci *ehci; /* Start of IP core*/
+       struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
+};
+
+static int msm_phy_power_on(struct phy *phy)
+{
+       struct msm_phy_priv *priv = dev_get_priv(phy->dev);
+
+       /* Select and enable external configuration with USB PHY */
+       ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_SET,
+                  ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+
+       return 0;
+}
+
+static int msm_phy_power_off(struct phy *phy)
+{
+       struct msm_phy_priv *priv = dev_get_priv(phy->dev);
+
+       /* Disable VBUS mimicing in the controller. */
+       ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
+                  ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+       return 0;
+}
+
+static int msm_phy_reset(struct phy *phy)
+{
+       struct msm_phy_priv *p = dev_get_priv(phy->dev);
+
+       /* select ULPI phy */
+       writel(PORT_PTS_ULPI, &p->ehci->portsc);
+
+       /* Enable sess_vld */
+       setbits_le32(&p->ehci->genconfig2, GEN2_SESS_VLD_CTRL_EN);
+
+       /* Enable external vbus configuration in the LINK */
+       setbits_le32(&p->ehci->usbcmd, SESS_VLD_CTRL);
+
+       /* USB_OTG_HS_AHB_BURST */
+       writel(0x0, &p->ehci->sbuscfg);
+
+       /* USB_OTG_HS_AHB_MODE: HPROT_MODE */
+       /* Bus access related config. */
+       writel(0x08, &p->ehci->sbusmode);
+
+       return 0;
+}
+
+static int msm_phy_probe(struct udevice *dev)
+{
+       struct msm_phy_priv *priv = dev_get_priv(dev);
+
+       priv->regs = dev_remap_addr(dev);
+       if (!priv->regs)
+               return -EINVAL;
+
+       priv->ehci = (struct usb_ehci *)priv->regs;
+       priv->ulpi_vp.port_num = 0;
+
+       /* Warning: this will not work if viewport address is > 64 bit due to
+        * ULPI design.
+        */
+       priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint;
+
+       return 0;
+}
+
+static struct phy_ops msm_phy_ops = {
+       .power_on = msm_phy_power_on,
+       .power_off = msm_phy_power_off,
+       .reset = msm_phy_reset,
+};
+
+static const struct udevice_id msm_phy_ids[] = {
+       { .compatible = "qcom,apq8016-usbphy" },
+       { }
+};
+
+U_BOOT_DRIVER(msm8916_usbphy) = {
+       .name           = "msm8916_usbphy",
+       .id             = UCLASS_PHY,
+       .of_match       = msm_phy_ids,
+       .ops            = &msm_phy_ops,
+       .probe          = msm_phy_probe,
+       .priv_auto_alloc_size = sizeof(struct msm_phy_priv),
+};