]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/usb/host/xhci-uniphier.c
ARM: UniPhier: adjust device trees for business transfer
[karo-tx-uboot.git] / drivers / usb / host / xhci-uniphier.c
1 /*
2  * Copyright (C) 2015 Panasonic Corporation
3  * Copyright (C) 2015 Socionext Inc.
4  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <linux/err.h>
11 #include <usb.h>
12 #include <fdtdec.h>
13 #include "xhci.h"
14
15 static int get_uniphier_xhci_base(int index, struct xhci_hccr **base)
16 {
17         DECLARE_GLOBAL_DATA_PTR;
18         int node_list[2];
19         fdt_addr_t addr;
20         int count;
21
22         count = fdtdec_find_aliases_for_id(gd->fdt_blob, "usb",
23                                            COMPAT_SOCIONEXT_XHCI, node_list,
24                                            ARRAY_SIZE(node_list));
25
26         if (index >= count)
27                 return -ENODEV;
28
29         addr = fdtdec_get_addr(gd->fdt_blob, node_list[index], "reg");
30         if (addr == FDT_ADDR_T_NONE)
31                 return -ENODEV;
32
33         *base = (struct xhci_hccr *)addr;
34
35         return 0;
36 }
37
38 #define USB3_RST_CTRL           0x00100040
39 #define IOMMU_RST_N             (1 << 5)
40 #define LINK_RST_N              (1 << 4)
41
42 static void uniphier_xhci_reset(void __iomem *base, int on)
43 {
44         u32 tmp;
45
46         tmp = readl(base + USB3_RST_CTRL);
47
48         if (on)
49                 tmp &= ~(IOMMU_RST_N | LINK_RST_N);
50         else
51                 tmp |= IOMMU_RST_N | LINK_RST_N;
52
53         writel(tmp, base + USB3_RST_CTRL);
54 }
55
56 int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
57 {
58         int ret;
59         struct xhci_hccr *cr;
60         struct xhci_hcor *or;
61
62         ret = get_uniphier_xhci_base(index, &cr);
63         if (ret < 0)
64                 return ret;
65
66         uniphier_xhci_reset(cr, 0);
67
68         or = (void *)cr + HC_LENGTH(xhci_readl(&cr->cr_capbase));
69
70         *hccr = cr;
71         *hcor = or;
72
73         return 0;
74 }
75
76 void xhci_hcd_stop(int index)
77 {
78         int ret;
79         struct xhci_hccr *cr;
80
81         ret = get_uniphier_xhci_base(index, &cr);
82         if (ret < 0)
83                 return;
84
85         uniphier_xhci_reset(cr, 1);
86 }