aboutsummaryrefslogtreecommitdiff
path: root/src/include/device/xhci.h
blob: c984450b912c610549bc13628fc736597afc8aa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __DEVICE_XHCI_H__
#define __DEVICE_XHCI_H__

#include <types.h>
#include <device/device.h>

#define XHCI_HCCPARAMS1_XECP 0x12

#define XHCI_ECP_CAP_ID_LEGACY 1
#define XHCI_ECP_CAP_ID_SUPP 2

/* Status flags */
/* Wake on disconnect enable */
#define XHCI_STATUS_WDE			BIT(26)
/* Wake on connect enable */
#define XHCI_STATUS_WCE			BIT(25)
/* Port link status change */
#define XHCI_STATUS_PLC			BIT(22)
/* Connect status change */
#define XHCI_STATUS_CSC			BIT(17)
/* Port link status */
#define XHCI_STATUS_PLS_SHIFT		5
#define XHCI_STATUS_PLS_MASK		(0xf << XHCI_STATUS_PLS_SHIFT)
#define XHCI_STATUS_PLS_RESUME		(15 << XHCI_STATUS_PLS_SHIFT)

static inline bool xhci_portsc_csc(uint32_t port_status)
{
	return port_status & XHCI_STATUS_CSC;
}

static inline bool xhci_portsc_wake_capable(uint32_t port_status)
{
	return (port_status & XHCI_STATUS_WCE) |
		  (port_status & XHCI_STATUS_WDE);
}

static inline bool xhci_portsc_plc(uint32_t port_status)
{
	return port_status & XHCI_STATUS_PLC;
}

static inline bool xhci_portsc_resume(uint32_t port_status)
{
	return (port_status & XHCI_STATUS_PLS_MASK) == XHCI_STATUS_PLS_RESUME;
}


struct xhci_supported_protocol {
	union {
		uint32_t reg0;
		struct {
			uint32_t cap_id : 8;
			uint32_t next_ptr : 8;
			uint32_t minor_rev : 8;
			uint32_t major_rev : 8;
		};
	};
	union {
		uint32_t reg1;
		char name[4];
	};
	union {
		uint32_t reg2;
		struct {
			uint32_t port_offset : 8;
			uint32_t port_count : 8;
			uint32_t reserved : 12;
			uint32_t protocol_speed_id_count : 4;
		};
	};
};

struct xhci_ext_cap {
	uint32_t cap_id;
	/* cap_id is used to select the correct struct in the union. */
	union {
		struct xhci_supported_protocol supported_protocol;
	};
};

/*
 * struct xhci_usb_info - Data containing number of USB ports & offset.
 * @usb2_port_status_reg: Offset to USB2 port status register.
 * @num_usb2_ports: Number of USB2 ports.
 * @usb3_port_status_reg: Offset to USB3 port status register.
 * @num_usb3_ports: Number of USB3 ports.
 */
struct xhci_usb_info {
	uint32_t usb2_port_status_reg;
	uint32_t num_usb2_ports;
	uint32_t usb3_port_status_reg;
	uint32_t num_usb3_ports;
};

struct xhci_capability_regs {
	uint8_t caplength;
	uint8_t reserved0;
	uint16_t hciversion;
	uint32_t hcsparams1;
	uint32_t hcsparams2;
	uint32_t hcsparams3;
	uint32_t hccparams1;
	uint32_t dboff;
	uint32_t rtsoff;
	uint32_t hccparams2;
} __packed;

/**
 * Iterates over the xHCI Extended Capabilities List.
 */
enum cb_err xhci_resource_for_each_ext_cap(const struct resource *res, void *context,
				  void (*callback)(void *context,
						   const struct xhci_ext_cap *cap));
enum cb_err xhci_for_each_ext_cap(const struct device *device, void *context,
				  void (*callback)(void *context,
						   const struct xhci_ext_cap *cap));

/**
 * Helper method that iterates over only the USB supported capabilities structures in the
 * xHCI Extended Capabilities List.
 */
enum cb_err xhci_for_each_supported_usb_cap(
	const struct device *device, void *context,
	void (*callback)(void *context, const struct xhci_supported_protocol *data));
enum cb_err xhci_resource_for_each_supported_usb_cap(
	const struct resource *res, void *context,
	void (*callback)(void *context, const struct xhci_supported_protocol *data));

void xhci_print_supported_protocol(const struct xhci_supported_protocol *supported_protocol);

#endif /* __DEVICE_XHCI_H__ */