Merge tag 'ti-v2020.07-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti
[oweals/u-boot.git] / drivers / usb / host / xhci-brcm.c
1 // 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
25 struct brcm_xhci_platdata {
26         unsigned int arcache;
27         unsigned int awcache;
28         void __iomem *hc_base;
29 };
30
31 static 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
72 static 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
83 static const struct udevice_id xhci_brcm_ids[] = {
84         { .compatible = "brcm,generic-xhci" },
85         { }
86 };
87
88 U_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 };