uboot/drivers/usb/dwc3/dwc3-uniphier.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * UniPhier Specific Glue Layer for DWC3
   4 *
   5 * Copyright (C) 2016-2017 Socionext Inc.
   6 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
   7 */
   8
   9#include <dm.h>
  10#include <dm/device_compat.h>
  11#include <linux/bitops.h>
  12#include <linux/errno.h>
  13#include <linux/io.h>
  14#include <linux/sizes.h>
  15
  16#define UNIPHIER_PRO4_DWC3_RESET        0x40
  17#define   UNIPHIER_PRO4_DWC3_RESET_XIOMMU       BIT(5)
  18#define   UNIPHIER_PRO4_DWC3_RESET_XLINK        BIT(4)
  19#define   UNIPHIER_PRO4_DWC3_RESET_PHY_SS       BIT(2)
  20
  21#define UNIPHIER_PRO5_DWC3_RESET        0x00
  22#define   UNIPHIER_PRO5_DWC3_RESET_PHY_S1       BIT(17)
  23#define   UNIPHIER_PRO5_DWC3_RESET_PHY_S0       BIT(16)
  24#define   UNIPHIER_PRO5_DWC3_RESET_XLINK        BIT(15)
  25#define   UNIPHIER_PRO5_DWC3_RESET_XIOMMU       BIT(14)
  26
  27#define UNIPHIER_PXS2_DWC3_RESET        0x00
  28#define   UNIPHIER_PXS2_DWC3_RESET_XLINK        BIT(15)
  29
  30static int uniphier_pro4_dwc3_init(void __iomem *regs)
  31{
  32        u32 tmp;
  33
  34        tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET);
  35        tmp &= ~UNIPHIER_PRO4_DWC3_RESET_PHY_SS;
  36        tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK;
  37        writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET);
  38
  39        return 0;
  40}
  41
  42static int uniphier_pro5_dwc3_init(void __iomem *regs)
  43{
  44        u32 tmp;
  45
  46        tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET);
  47        tmp &= ~(UNIPHIER_PRO5_DWC3_RESET_PHY_S1 |
  48                 UNIPHIER_PRO5_DWC3_RESET_PHY_S0);
  49        tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU;
  50        writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET);
  51
  52        return 0;
  53}
  54
  55static int uniphier_pxs2_dwc3_init(void __iomem *regs)
  56{
  57        u32 tmp;
  58
  59        tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET);
  60        tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK;
  61        writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET);
  62
  63        return 0;
  64}
  65
  66static int uniphier_dwc3_probe(struct udevice *dev)
  67{
  68        fdt_addr_t base;
  69        void __iomem *regs;
  70        int (*init)(void __iomem *regs);
  71        int ret;
  72
  73        base = dev_read_addr(dev);
  74        if (base == FDT_ADDR_T_NONE)
  75                return -EINVAL;
  76
  77        regs = ioremap(base, SZ_32K);
  78        if (!regs)
  79                return -ENOMEM;
  80
  81        init = (typeof(init))dev_get_driver_data(dev);
  82        ret = init(regs);
  83        if (ret)
  84                dev_err(dev, "failed to init glue layer\n");
  85
  86        iounmap(regs);
  87
  88        return ret;
  89}
  90
  91static const struct udevice_id uniphier_dwc3_match[] = {
  92        {
  93                .compatible = "socionext,uniphier-pro4-dwc3",
  94                .data = (ulong)uniphier_pro4_dwc3_init,
  95        },
  96        {
  97                .compatible = "socionext,uniphier-pro5-dwc3",
  98                .data = (ulong)uniphier_pro5_dwc3_init,
  99        },
 100        {
 101                .compatible = "socionext,uniphier-pxs2-dwc3",
 102                .data = (ulong)uniphier_pxs2_dwc3_init,
 103        },
 104        {
 105                .compatible = "socionext,uniphier-ld20-dwc3",
 106                .data = (ulong)uniphier_pxs2_dwc3_init,
 107        },
 108        {
 109                .compatible = "socionext,uniphier-pxs3-dwc3",
 110                .data = (ulong)uniphier_pxs2_dwc3_init,
 111        },
 112        { /* sentinel */ }
 113};
 114
 115U_BOOT_DRIVER(usb_xhci) = {
 116        .name = "uniphier-dwc3",
 117        .id = UCLASS_SIMPLE_BUS,
 118        .of_match = uniphier_dwc3_match,
 119        .probe = uniphier_dwc3_probe,
 120};
 121