blob: 11f1c02000af6dc06f08d7792f145e6a1c649577 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Simon Glass40ffb682015-01-27 22:13:31 -07002/*
3 * Copyright (c) 2015, Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 * All rights reserved.
Simon Glass40ffb682015-01-27 22:13:31 -07006 */
7
8#include <common.h>
Stefan Roeseb0ff2c12016-07-18 12:51:39 +02009#include <dm.h>
Samuel Holland386d1282021-07-05 13:29:02 +010010#include <dm/device_compat.h>
Simon Glass97589732020-05-10 11:40:02 -060011#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass40ffb682015-01-27 22:13:31 -070013#include <pci.h>
Samuel Holland386d1282021-07-05 13:29:02 +010014#include <reset.h>
Simon Glass40ffb682015-01-27 22:13:31 -070015#include <usb.h>
Jean-Jacques Hiblotad4142b2019-09-11 11:33:46 +020016#include <usb/xhci.h>
Simon Glass40ffb682015-01-27 22:13:31 -070017
Samuel Holland386d1282021-07-05 13:29:02 +010018struct xhci_pci_plat {
19 struct reset_ctl reset;
20};
21
Pali Rohárde1627b2021-01-18 12:30:04 +010022static int xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr,
23 struct xhci_hcor **ret_hcor)
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020024{
25 struct xhci_hccr *hccr;
26 struct xhci_hcor *hcor;
27 u32 cmd;
28
29 hccr = (struct xhci_hccr *)dm_pci_map_bar(dev,
Andrew Scull6520c822022-04-21 16:11:13 +000030 PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE,
31 PCI_REGION_MEM);
Pali Rohárde1627b2021-01-18 12:30:04 +010032 if (!hccr) {
33 printf("xhci-pci init cannot map PCI mem bar\n");
34 return -EIO;
35 }
36
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020037 hcor = (struct xhci_hcor *)((uintptr_t) hccr +
38 HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
39
Bin Meng7380f7a2018-06-03 19:04:14 -070040 debug("XHCI-PCI init hccr %p and hcor %p hc_length %d\n",
41 hccr, hcor, (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020042
43 *ret_hccr = hccr;
44 *ret_hcor = hcor;
45
46 /* enable busmaster */
47 dm_pci_read_config32(dev, PCI_COMMAND, &cmd);
48 cmd |= PCI_COMMAND_MASTER;
49 dm_pci_write_config32(dev, PCI_COMMAND, cmd);
Pali Rohárde1627b2021-01-18 12:30:04 +010050 return 0;
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020051}
52
53static int xhci_pci_probe(struct udevice *dev)
54{
Samuel Holland386d1282021-07-05 13:29:02 +010055 struct xhci_pci_plat *plat = dev_get_plat(dev);
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020056 struct xhci_hccr *hccr;
57 struct xhci_hcor *hcor;
Pali Rohárde1627b2021-01-18 12:30:04 +010058 int ret;
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020059
Samuel Holland386d1282021-07-05 13:29:02 +010060 ret = reset_get_by_index(dev, 0, &plat->reset);
61 if (ret && ret != -ENOENT && ret != -ENOTSUPP) {
62 dev_err(dev, "failed to get reset\n");
63 return ret;
64 }
65
66 if (reset_valid(&plat->reset)) {
67 ret = reset_assert(&plat->reset);
68 if (ret)
69 goto err_reset;
70
71 ret = reset_deassert(&plat->reset);
72 if (ret)
73 goto err_reset;
74 }
75
Pali Rohárde1627b2021-01-18 12:30:04 +010076 ret = xhci_pci_init(dev, &hccr, &hcor);
77 if (ret)
Samuel Holland386d1282021-07-05 13:29:02 +010078 goto err_reset;
79
80 ret = xhci_register(dev, hccr, hcor);
81 if (ret)
82 goto err_reset;
83
84 return 0;
85
86err_reset:
87 if (reset_valid(&plat->reset))
88 reset_free(&plat->reset);
89
90 return ret;
91}
92
93static int xhci_pci_remove(struct udevice *dev)
94{
95 struct xhci_pci_plat *plat = dev_get_plat(dev);
Stefan Roeseb0ff2c12016-07-18 12:51:39 +020096
Samuel Holland386d1282021-07-05 13:29:02 +010097 xhci_deregister(dev);
98 if (reset_valid(&plat->reset))
99 reset_free(&plat->reset);
100
101 return 0;
Stefan Roeseb0ff2c12016-07-18 12:51:39 +0200102}
103
Stefan Roeseb0ff2c12016-07-18 12:51:39 +0200104static const struct udevice_id xhci_pci_ids[] = {
105 { .compatible = "xhci-pci" },
106 { }
107};
108
109U_BOOT_DRIVER(xhci_pci) = {
110 .name = "xhci_pci",
111 .id = UCLASS_USB,
112 .probe = xhci_pci_probe,
Samuel Holland386d1282021-07-05 13:29:02 +0100113 .remove = xhci_pci_remove,
Stefan Roeseb0ff2c12016-07-18 12:51:39 +0200114 .of_match = xhci_pci_ids,
115 .ops = &xhci_usb_ops,
Samuel Holland386d1282021-07-05 13:29:02 +0100116 .plat_auto = sizeof(struct xhci_pci_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700117 .priv_auto = sizeof(struct xhci_ctrl),
Nicolas Saenz Julienne96316252021-01-14 16:49:00 +0100118 .flags = DM_FLAG_OS_PREPARE | DM_FLAG_ALLOC_PRIV_DMA,
Stefan Roeseb0ff2c12016-07-18 12:51:39 +0200119};
120
121static struct pci_device_id xhci_pci_supported[] = {
122 { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0) },
123 {},
124};
125
126U_BOOT_PCI_DEVICE(xhci_pci, xhci_pci_supported);