blob: ee65f51c5d271c5712e56beafcec22b32aa0af01 [file] [log] [blame]
Rayagonda Kokatanur9cadf052020-04-09 09:23:15 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Broadcom.
4 */
5
6#include <common.h>
7#include <dm.h>
8#include <fdtdec.h>
9#include <usb.h>
10#include <asm/io.h>
11#include <usb/xhci.h>
12
13#define DRD2U3H_XHC_REGS_AXIWRA 0xC08
14#define DRD2U3H_XHC_REGS_AXIRDA 0xC0C
15
16#define USBAXI_CACHE 0xF
17#define USBAXI_PROT 0x8
18#define USBAXI_SA_MASK 0x1FF
19#define USBAXI_UA_MASK (0x1FF << 16)
20#define USBAXI_SA_VAL ((USBAXI_CACHE << 4) | USBAXI_PROT)
21#define USBAXI_UA_VAL (USBAXI_SA_VAL << 16)
22#define USBAXI_SA_UA_MASK (USBAXI_UA_MASK | USBAXI_SA_MASK)
23#define USBAXI_SA_UA_VAL (USBAXI_UA_VAL | USBAXI_SA_VAL)
24
25struct brcm_xhci_platdata {
26 unsigned int arcache;
27 unsigned int awcache;
28 void __iomem *hc_base;
29};
30
31static int xhci_brcm_probe(struct udevice *dev)
32{
33 struct brcm_xhci_platdata *plat = dev_get_platdata(dev);
34 struct xhci_hcor *hcor;
35 struct xhci_hccr *hcd;
36 int len, ret = 0;
37
38 if (!plat) {
39 dev_err(dev, "Can't get xHCI Plat data\n");
40 return -ENOMEM;
41 }
42
43 hcd = dev_read_addr_ptr(dev);
44 if (!hcd) {
45 dev_err(dev, "Can't get the xHCI register base address\n");
46 return -ENXIO;
47 }
48
49 plat->hc_base = hcd;
50 len = HC_LENGTH(xhci_readl(&hcd->cr_capbase));
51 hcor = (struct xhci_hcor *)(plat->hc_base + len);
52
53 /* Save the default values of AXI read and write attributes */
54 plat->awcache = readl(plat->hc_base + DRD2U3H_XHC_REGS_AXIWRA);
55 plat->arcache = readl(plat->hc_base + DRD2U3H_XHC_REGS_AXIRDA);
56
57 /* Enable AXI write attributes */
58 clrsetbits_le32(plat->hc_base + DRD2U3H_XHC_REGS_AXIWRA,
59 USBAXI_SA_UA_MASK, USBAXI_SA_UA_VAL);
60
61 /* Enable AXI read attributes */
62 clrsetbits_le32(plat->hc_base + DRD2U3H_XHC_REGS_AXIRDA,
63 USBAXI_SA_UA_MASK, USBAXI_SA_UA_VAL);
64
65 ret = xhci_register(dev, hcd, hcor);
66 if (ret)
67 dev_err(dev, "Failed to register xHCI\n");
68
69 return ret;
70}
71
72static int xhci_brcm_deregister(struct udevice *dev)
73{
74 struct brcm_xhci_platdata *plat = dev_get_platdata(dev);
75
76 /* Restore the default values for AXI read and write attributes */
77 writel(plat->awcache, plat->hc_base + DRD2U3H_XHC_REGS_AXIWRA);
78 writel(plat->arcache, plat->hc_base + DRD2U3H_XHC_REGS_AXIRDA);
79
80 return xhci_deregister(dev);
81}
82
83static const struct udevice_id xhci_brcm_ids[] = {
84 { .compatible = "brcm,generic-xhci" },
85 { }
86};
87
88U_BOOT_DRIVER(usb_xhci) = {
89 .name = "xhci_brcm",
90 .id = UCLASS_USB,
91 .probe = xhci_brcm_probe,
92 .remove = xhci_brcm_deregister,
93 .ops = &xhci_usb_ops,
94 .of_match = xhci_brcm_ids,
95 .platdata_auto_alloc_size = sizeof(struct brcm_xhci_platdata),
96 .priv_auto_alloc_size = sizeof(struct xhci_ctrl),
97 .flags = DM_FLAG_ALLOC_PRIV_DMA,
98};