1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <intelblocks/xdci.h>
8 #include <soc/pci_devs.h>
11 #define DUAL_ROLE_CFG0 0x80d8
12 # define DRD_CONFIG_MASK (0x3 << 0)
13 # define DRD_CONFIG_DYNAMIC (0x0 << 0)
14 # define DRD_CONFIG_HOST (0x1 << 0)
15 # define DRD_CONFIG_DEVICE (0x2 << 0)
16 # define SW_VBUS_VALID_MASK (1 << 24)
17 # define SW_VBUS_DEASSERT_VALID (0 << 24)
18 # define SW_VBUS_ASSERT_VALID (1 << 24)
19 # define SW_IDPIN_EN_MASK (1 << 21)
20 # define SW_IDPIN_DIS (0 << 21)
21 # define SW_IDPIN_EN (1 << 21)
22 # define SW_IDPIN_MASK (1 << 20)
23 # define SW_IDPIN_HOST (0 << 20)
24 # define SW_IDPIN_DEVICE (1 << 20)
25 #define DUAL_ROLE_CFG1 0x80dc
26 # define DRD_MODE_MASK (1 << 29)
27 # define DRD_MODE_DEVICE (0 << 29)
28 # define DRD_MODE_HOST (1 << 29)
30 static void configure_host_mode_port0(struct device
*dev
)
34 const struct resource
*res
;
39 * Only default to host mode if the xdci device is present and
40 * enabled. If it's disabled assume the switch was already done
46 printk(BIOS_INFO
, "Putting port 0 into host mode.\n");
48 res
= find_resource(dev
, PCI_BASE_ADDRESS_0
);
50 cfg0
= (void *)(uintptr_t)(res
->base
+ DUAL_ROLE_CFG0
);
51 cfg1
= (void *)(uintptr_t)(res
->base
+ DUAL_ROLE_CFG1
);
54 reg
&= ~(DRD_CONFIG_MASK
| SW_IDPIN_EN_MASK
| SW_IDPIN_MASK
);
55 reg
&= ~(SW_VBUS_VALID_MASK
);
56 reg
|= DRD_CONFIG_DYNAMIC
| SW_IDPIN_EN
| SW_IDPIN_HOST
;
57 reg
|= SW_VBUS_DEASSERT_VALID
;
60 stopwatch_init_msecs_expire(&sw
, 10);
62 /* Wait for the host mode status bit. */
63 while ((read32(cfg1
) & DRD_MODE_MASK
) != DRD_MODE_HOST
) {
64 if (stopwatch_expired(&sw
)) {
65 printk(BIOS_INFO
, "Timed out waiting for host mode.\n");
70 printk(BIOS_INFO
, "XDCI port 0 host switch over took %lld ms\n",
71 stopwatch_duration_msecs(&sw
));
74 void soc_xdci_init(struct device
*dev
)
76 configure_host_mode_port0(dev
);