blob: 1b3f3d22de115768b57a93f30bbd3b76efc6f5d7 [file] [log] [blame]
Masahiro Yamada273f84d2015-02-27 02:27:00 +09001/*
Masahiro Yamada663a23f2015-05-29 17:30:00 +09002 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
Masahiro Yamada273f84d2015-02-27 02:27:00 +09003 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <common.h>
8#include <linux/err.h>
Masahiro Yamada663a23f2015-05-29 17:30:00 +09009#include <linux/io.h>
Masahiro Yamada273f84d2015-02-27 02:27:00 +090010#include <usb.h>
11#include <fdtdec.h>
12#include "xhci.h"
13
14static int get_uniphier_xhci_base(int index, struct xhci_hccr **base)
15{
16 DECLARE_GLOBAL_DATA_PTR;
17 int node_list[2];
18 fdt_addr_t addr;
19 int count;
20
21 count = fdtdec_find_aliases_for_id(gd->fdt_blob, "usb",
Masahiro Yamadad5f83a42015-03-11 15:54:46 +090022 COMPAT_SOCIONEXT_XHCI, node_list,
Masahiro Yamada273f84d2015-02-27 02:27:00 +090023 ARRAY_SIZE(node_list));
24
25 if (index >= count)
26 return -ENODEV;
27
28 addr = fdtdec_get_addr(gd->fdt_blob, node_list[index], "reg");
29 if (addr == FDT_ADDR_T_NONE)
30 return -ENODEV;
31
32 *base = (struct xhci_hccr *)addr;
33
34 return 0;
35}
36
37#define USB3_RST_CTRL 0x00100040
38#define IOMMU_RST_N (1 << 5)
39#define LINK_RST_N (1 << 4)
40
41static void uniphier_xhci_reset(void __iomem *base, int on)
42{
43 u32 tmp;
44
45 tmp = readl(base + USB3_RST_CTRL);
46
47 if (on)
48 tmp &= ~(IOMMU_RST_N | LINK_RST_N);
49 else
50 tmp |= IOMMU_RST_N | LINK_RST_N;
51
52 writel(tmp, base + USB3_RST_CTRL);
53}
54
55int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
56{
57 int ret;
58 struct xhci_hccr *cr;
59 struct xhci_hcor *or;
60
61 ret = get_uniphier_xhci_base(index, &cr);
62 if (ret < 0)
63 return ret;
64
65 uniphier_xhci_reset(cr, 0);
66
67 or = (void *)cr + HC_LENGTH(xhci_readl(&cr->cr_capbase));
68
69 *hccr = cr;
70 *hcor = or;
71
72 return 0;
73}
74
75void xhci_hcd_stop(int index)
76{
77 int ret;
78 struct xhci_hccr *cr;
79
80 ret = get_uniphier_xhci_base(index, &cr);
81 if (ret < 0)
82 return;
83
84 uniphier_xhci_reset(cr, 1);
85}