Commit 4b12783c8e011859e70ba5811654a21ee1a22237

Authored by Jean-Jacques Hiblot
Committed by Marek Vasut
1 parent d53653f3f9

PHY: Add phy driver for the keystone USB PHY

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>

Showing 3 changed files with 120 additions and 0 deletions Side-by-side Diff

... ... @@ -164,5 +164,15 @@
164 164  
165 165 This PHY is found on OMAP devices supporting USB2.
166 166  
  167 +
  168 +config KEYSTONE_USB_PHY
  169 + bool "Support TI Keystone USB PHY"
  170 + depends on PHY
  171 + depends on ARCH_KEYSTONE
  172 + help
  173 + Support for the USB PHY found on some Keystone (k2) processors
  174 +
  175 + This PHY is found on some Keystone (K2) devices supporting USB.
  176 +
167 177 endmenu
drivers/phy/Makefile
... ... @@ -18,4 +18,5 @@
18 18 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
19 19 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
20 20 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
  21 +obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
drivers/phy/keystone-usb-phy.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
  4 + * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <dm.h>
  9 +#include <dm/device.h>
  10 +#include <generic-phy.h>
  11 +#include <asm/io.h>
  12 +
  13 +/* USB PHY control register offsets */
  14 +#define USB_PHY_CTL_UTMI 0x0000
  15 +#define USB_PHY_CTL_PIPE 0x0004
  16 +#define USB_PHY_CTL_PARAM_1 0x0008
  17 +#define USB_PHY_CTL_PARAM_2 0x000c
  18 +#define USB_PHY_CTL_CLOCK 0x0010
  19 +#define USB_PHY_CTL_PLL 0x0014
  20 +
  21 +#define PHY_OTG_VBUSVLDECTSEL BIT(16)
  22 +#define PHY_REF_SSP_EN BIT(29)
  23 +
  24 +struct keystone_usb_phy {
  25 + void __iomem *reg;
  26 +};
  27 +
  28 +static int keystone_usb_init(struct phy *phy)
  29 +{
  30 + u32 val;
  31 + struct udevice *dev = phy->dev;
  32 + struct keystone_usb_phy *keystone = dev_get_priv(dev);
  33 +
  34 + /*
  35 + * VBUSVLDEXTSEL has a default value of 1 in BootCfg but shouldn't.
  36 + * It should always be cleared because our USB PHY has an onchip VBUS
  37 + * analog comparator.
  38 + */
  39 + val = readl(keystone->reg + USB_PHY_CTL_CLOCK);
  40 + /* quit selecting the vbusvldextsel by default! */
  41 + val &= ~PHY_OTG_VBUSVLDECTSEL;
  42 + writel(val, keystone->reg + USB_PHY_CTL_CLOCK);
  43 +
  44 + return 0;
  45 +}
  46 +
  47 +static int keystone_usb_power_on(struct phy *phy)
  48 +{
  49 + u32 val;
  50 + struct udevice *dev = phy->dev;
  51 + struct keystone_usb_phy *keystone = dev_get_priv(dev);
  52 +
  53 + val = readl(keystone->reg + USB_PHY_CTL_CLOCK);
  54 + val |= PHY_REF_SSP_EN;
  55 + writel(val, keystone->reg + USB_PHY_CTL_CLOCK);
  56 +
  57 + return 0;
  58 +}
  59 +
  60 +static int keystone_usb_power_off(struct phy *phy)
  61 +{
  62 + u32 val;
  63 + struct udevice *dev = phy->dev;
  64 + struct keystone_usb_phy *keystone = dev_get_priv(dev);
  65 +
  66 + val = readl(keystone->reg + USB_PHY_CTL_CLOCK);
  67 + val &= ~PHY_REF_SSP_EN;
  68 + writel(val, keystone->reg + USB_PHY_CTL_CLOCK);
  69 +
  70 + return 0;
  71 +}
  72 +
  73 +static int keystone_usb_exit(struct phy *phy)
  74 +{
  75 + return 0;
  76 +}
  77 +
  78 +static int keystone_usb_phy_probe(struct udevice *dev)
  79 +{
  80 + struct keystone_usb_phy *keystone = dev_get_priv(dev);
  81 +
  82 + keystone->reg = dev_remap_addr_index(dev, 0);
  83 + if (!keystone->reg) {
  84 + pr_err("unable to remap usb phy\n");
  85 + return -EINVAL;
  86 + }
  87 + return 0;
  88 +}
  89 +
  90 +static const struct udevice_id keystone_usb_phy_ids[] = {
  91 + { .compatible = "ti,keystone-usbphy" },
  92 + { }
  93 +};
  94 +
  95 +static struct phy_ops keystone_usb_phy_ops = {
  96 + .init = keystone_usb_init,
  97 + .power_on = keystone_usb_power_on,
  98 + .power_off = keystone_usb_power_off,
  99 + .exit = keystone_usb_exit,
  100 +};
  101 +
  102 +U_BOOT_DRIVER(keystone_usb_phy) = {
  103 + .name = "keystone_usb_phy",
  104 + .id = UCLASS_PHY,
  105 + .of_match = keystone_usb_phy_ids,
  106 + .ops = &keystone_usb_phy_ops,
  107 + .probe = keystone_usb_phy_probe,
  108 + .priv_auto_alloc_size = sizeof(struct keystone_usb_phy),
  109 +};