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