summaryrefslogtreecommitdiff
path: root/sys/dev/usb/uhcireg.h
blob: 59b0953dfe3897a895034c4995de122d3ccdd161 (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*	$NetBSD: uhcireg.h,v 1.22 2016/04/23 10:15:32 skrll Exp $	*/
/*	$FreeBSD: src/sys/dev/usb/uhcireg.h,v 1.12 1999/11/17 22:33:42 n_hibma Exp $ */

/*
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Lennart Augustsson (lennart@augustsson.net) at
 * Carlstedt Research & Technology.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _DEV_USB_UHCIREG_H_
#define _DEV_USB_UHCIREG_H_

/*** PCI config registers ***/

#define PCI_USBREV		0x60	/* USB protocol revision */
#define  PCI_USBREV_MASK	0xff
#define  PCI_USBREV_PRE_1_0	0x00
#define  PCI_USBREV_1_0		0x10
#define  PCI_USBREV_1_1		0x11

#define PCI_LEGSUP		0xc0	/* Legacy Support register */
#define  PCI_LEGSUP_A20PTS	__BIT(15)	/* End of A20GATE passthru status */
#define  PCI_LEGSUP_USBPIRQDEN	__BIT(13)	/* USB PIRQ D Enable */
#define  PCI_LEGSUP_USBIRQS	__BIT(12)	/* USB IRQ status */
#define  PCI_LEGSUP_TBY64W	__BIT(11)	/* Trap by 64h write status */
#define  PCI_LEGSUP_TBY64R	__BIT(10)	/* Trap by 64h read status */
#define  PCI_LEGSUP_TBY60W	__BIT(9)	/* Trap by 60h write status */
#define  PCI_LEGSUP_TBY60R	__BIT(8)	/* Trap by 60h read status */
#define  PCI_LEGSUP_SMIEPTE	__BIT(7)	/* SMI at end of passthru enable */
#define  PCI_LEGSUP_PSS		__BIT(6)	/* Passthru status */
#define  PCI_LEGSUP_A20PTEN	__BIT(5)	/* A20GATE passthru enable */
#define  PCI_LEGSUP_USBSMIEN	__BIT(4)	/* Enable SMI# generation */

#define PCI_CBIO		0x20	/* configuration base IO */

#define PCI_INTERFACE_UHCI	0x00

/*** UHCI registers ***/

#define UHCI_CMD		0x00
#define  UHCI_CMD_RS		__BIT(0)
#define  UHCI_CMD_HCRESET	__BIT(1)
#define  UHCI_CMD_GRESET	__BIT(2)
#define  UHCI_CMD_EGSM		__BIT(3)
#define  UHCI_CMD_FGR		__BIT(4)
#define  UHCI_CMD_SWDBG		__BIT(5)
#define  UHCI_CMD_CF		__BIT(6)
#define  UHCI_CMD_MAXP		__BIT(7)

#define UHCI_STS		0x02
#define  UHCI_STS_USBINT	__BIT(0)
#define  UHCI_STS_USBEI		__BIT(1)
#define  UHCI_STS_RD		__BIT(2)
#define  UHCI_STS_HSE		__BIT(3)
#define  UHCI_STS_HCPE		__BIT(4)
#define  UHCI_STS_HCH		__BIT(5)
#define  UHCI_STS_ALLINTRS	__BITS(5,0)

#define UHCI_INTR		0x04
#define  UHCI_INTR_TOCRCIE	__BIT(0)
#define  UHCI_INTR_RIE		__BIT(1)
#define  UHCI_INTR_IOCE		__BIT(2)
#define  UHCI_INTR_SPIE		__BIT(3)

#define UHCI_FRNUM		0x06
#define  UHCI_FRNUM_MASK	__BITS(9,0)


#define UHCI_FLBASEADDR		0x08

#define UHCI_SOF		0x0c
#define  UHCI_SOF_MASK		__BITS(6,0)

#define UHCI_PORTSC1		0x010
#define UHCI_PORTSC2		0x012
#define UHCI_PORTSC_CCS		__BIT(0)
#define UHCI_PORTSC_CSC		__BIT(1)
#define UHCI_PORTSC_PE		__BIT(2)
#define UHCI_PORTSC_POEDC	__BIT(3)
#define UHCI_PORTSC_LS_MASK	__BITS(5,4)
#define UHCI_PORTSC_GET_LS(p)	__SHIFTOUT((p), UHCI_PORTSC_LS_MASK)
#define UHCI_PORTSC_RD		__BIT(6)
#define UHCI_PORTSC_LSDA	__BIT(8)
#define UHCI_PORTSC_PR		__BIT(9)
#define UHCI_PORTSC_OCI		__BIT(10)
#define UHCI_PORTSC_OCIC	__BIT(11)
#define UHCI_PORTSC_SUSP	__BIT(12)

#define URWMASK(x) \
  ((x) & (UHCI_PORTSC_SUSP | UHCI_PORTSC_PR | UHCI_PORTSC_RD | UHCI_PORTSC_PE))

#define UHCI_FRAMELIST_COUNT	1024
#define UHCI_FRAMELIST_ALIGN	4096

#define UHCI_TD_ALIGN		16
#define UHCI_QH_ALIGN		16

typedef uint32_t uhci_physaddr_t;
#define UHCI_PTR_T		__BIT(0)
#define UHCI_PTR_TD		0x00000000
#define UHCI_PTR_QH		__BIT(1)
#define UHCI_PTR_VF		__BIT(2)

/*
 * Wait this long after a QH has been removed.  This gives that HC a
 * chance to stop looking at it before it's recycled.
 */
#define UHCI_QH_REMOVE_DELAY	5

/*
 * The Queue Heads and Transfer Descriptors are accessed
 * by both the CPU and the USB controller which run
 * concurrently.  This means that they have to be accessed
 * with great care.  As long as the data structures are
 * not linked into the controller's frame list they cannot
 * be accessed by it and anything goes.  As soon as a
 * TD is accessible by the controller it "owns" the td_status
 * field; it will not be written by the CPU.  Similarly
 * the controller "owns" the qh_elink field.
 */

typedef struct {
	volatile uhci_physaddr_t td_link;
	volatile uint32_t td_status;
#define UHCI_TD_ACTLEN_MASK	__BITS(10,0)
#define UHCI_TD_GET_ACTLEN(s)	\
    ((__SHIFTOUT((s), UHCI_TD_ACTLEN_MASK) + 1) & __SHIFTOUT_MASK(UHCI_TD_ACTLEN_MASK))
#define UHCI_TD_ZERO_ACTLEN(t)	((t) | 0x3ff)
#define UHCI_TD_BITSTUFF	__BIT(17)
#define UHCI_TD_CRCTO		__BIT(18)
#define UHCI_TD_NAK		__BIT(19)
#define UHCI_TD_BABBLE		__BIT(20)
#define UHCI_TD_DBUFFER		__BIT(21)
#define UHCI_TD_STALLED		__BIT(22)
#define UHCI_TD_ACTIVE		__BIT(23)
#define UHCI_TD_STATUS_MASK	__BITS(16,23)
#define UHCI_TD_IOC		__BIT(24)
#define UHCI_TD_IOS		__BIT(25)
#define UHCI_TD_LS		__BIT(26)
#define UHCI_TD_ERRCNT_MASK	__BITS(28,27)
#define UHCI_TD_GET_ERRCNT(s)	__SHIFTOUT((s), UHCI_TD_ERRCNT_MASK)
#define UHCI_TD_SET_ERRCNT(n)	__SHIFTIN((n), UHCI_TD_ERRCNT_MASK)
#define UHCI_TD_SPD		__BIT(29)
	volatile uint32_t td_token;
#define UHCI_TD_PID_IN		0x69
#define UHCI_TD_PID_OUT		0xe1
#define UHCI_TD_PID_SETUP	0x2d
#define UHCI_TD_PID_MASK	__BITS(7,0)
#define UHCI_TD_SET_PID(p)	__SHIFTIN((p), UHCI_TD_PID_MASK)
#define UHCI_TD_GET_PID(s)	__SHIFTOUT((s), UHCI_TD_PID_MASK)
#define UHCI_TD_DEVADDR_MASK	__BITS(14,8)
#define UHCI_TD_SET_DEVADDR(a)	__SHIFTIN((a), UHCI_TD_DEVADDR_MASK)
#define UHCI_TD_GET_DEVADDR(s)	__SHIFTOUT((s), UHCI_TD_DEVADDR_MASK)
#define UHCI_TD_ENDPT_MASK	__BITS(18,15)
#define UHCI_TD_SET_ENDPT(e)	__SHIFTIN((e), UHCI_TD_ENDPT_MASK)
#define UHCI_TD_GET_ENDPT(s)	__SHIFTOUT((s), UHCI_TD_ENDPT_MASK)
#define UHCI_TD_DT_MASK		__BIT(19)
#define UHCI_TD_SET_DT(t)	__SHIFTIN((t), UHCI_TD_DT_MASK)
#define UHCI_TD_GET_DT(s)	__SHIFTOUT((s), UHCI_TD_DT_MASK)
#define UHCI_TD_MAXLEN_MASK	__BITS(31,21)
#define UHCI_TD_SET_MAXLEN(l)	\
    __SHIFTIN((((l)-1) & __SHIFTOUT_MASK(UHCI_TD_MAXLEN_MASK)), UHCI_TD_MAXLEN_MASK)
#define UHCI_TD_GET_MAXLEN(s)	\
    (__SHIFTOUT((s), UHCI_TD_MAXLEN_MASK) + 1)
	volatile uint32_t td_buffer;
} uhci_td_t;

#define UHCI_TD_ERROR \
    (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED)

#define UHCI_TD_SETUP(len, endp, dev) \
    (UHCI_TD_SET_MAXLEN(len) | UHCI_TD_SET_ENDPT(endp) | \
    UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_SETUP)
#define UHCI_TD_OUT(len, endp, dev, dt) \
    (UHCI_TD_SET_MAXLEN(len) | UHCI_TD_SET_ENDPT(endp) | \
    UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt))
#define UHCI_TD_IN(len, endp, dev, dt) \
    (UHCI_TD_SET_MAXLEN(len) | UHCI_TD_SET_ENDPT(endp) | \
    UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_IN | UHCI_TD_SET_DT(dt))

typedef struct {
	volatile uhci_physaddr_t qh_hlink;
	volatile uhci_physaddr_t qh_elink;
} uhci_qh_t;

#endif /* _DEV_USB_UHCIREG_H_ */