xref: /freebsd/sys/dev/usb/controller/ehci.h (revision e0a69b51ac09dc0376611274903ba683e2d1ace7)
102ac6454SAndrew Thompson /* $FreeBSD$ */
202ac6454SAndrew Thompson /*-
302ac6454SAndrew Thompson  * Copyright (c) 2001 The NetBSD Foundation, Inc.
402ac6454SAndrew Thompson  * All rights reserved.
502ac6454SAndrew Thompson  *
602ac6454SAndrew Thompson  * This code is derived from software contributed to The NetBSD Foundation
702ac6454SAndrew Thompson  * by Lennart Augustsson (lennart@augustsson.net).
802ac6454SAndrew Thompson  *
902ac6454SAndrew Thompson  * Redistribution and use in source and binary forms, with or without
1002ac6454SAndrew Thompson  * modification, are permitted provided that the following conditions
1102ac6454SAndrew Thompson  * are met:
1202ac6454SAndrew Thompson  * 1. Redistributions of source code must retain the above copyright
1302ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer.
1402ac6454SAndrew Thompson  * 2. Redistributions in binary form must reproduce the above copyright
1502ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer in the
1602ac6454SAndrew Thompson  *    documentation and/or other materials provided with the distribution.
1702ac6454SAndrew Thompson  * 3. All advertising materials mentioning features or use of this software
1802ac6454SAndrew Thompson  *    must display the following acknowledgement:
1902ac6454SAndrew Thompson  *        This product includes software developed by the NetBSD
2002ac6454SAndrew Thompson  *        Foundation, Inc. and its contributors.
2102ac6454SAndrew Thompson  * 4. Neither the name of The NetBSD Foundation nor the names of its
2202ac6454SAndrew Thompson  *    contributors may be used to endorse or promote products derived
2302ac6454SAndrew Thompson  *    from this software without specific prior written permission.
2402ac6454SAndrew Thompson  *
2502ac6454SAndrew Thompson  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2602ac6454SAndrew Thompson  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2702ac6454SAndrew Thompson  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2802ac6454SAndrew Thompson  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2902ac6454SAndrew Thompson  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3002ac6454SAndrew Thompson  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3102ac6454SAndrew Thompson  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3202ac6454SAndrew Thompson  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3302ac6454SAndrew Thompson  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3402ac6454SAndrew Thompson  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3502ac6454SAndrew Thompson  * POSSIBILITY OF SUCH DAMAGE.
3602ac6454SAndrew Thompson  */
3702ac6454SAndrew Thompson 
3802ac6454SAndrew Thompson #ifndef _EHCI_H_
3902ac6454SAndrew Thompson #define	_EHCI_H_
4002ac6454SAndrew Thompson 
41ab42e8b2SAndrew Thompson #define	EHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128)
4202ac6454SAndrew Thompson 
4302ac6454SAndrew Thompson /* PCI config registers  */
4402ac6454SAndrew Thompson #define	PCI_CBMEM		0x10	/* configuration base MEM */
4502ac6454SAndrew Thompson #define	PCI_INTERFACE_EHCI	0x20
4602ac6454SAndrew Thompson #define	PCI_USBREV		0x60	/* RO USB protocol revision */
4702ac6454SAndrew Thompson #define	PCI_USB_REV_MASK	0xff
4802ac6454SAndrew Thompson #define	PCI_USB_REV_PRE_1_0	0x00
4902ac6454SAndrew Thompson #define	PCI_USB_REV_1_0		0x10
5002ac6454SAndrew Thompson #define	PCI_USB_REV_1_1		0x11
5102ac6454SAndrew Thompson #define	PCI_USB_REV_2_0		0x20
5202ac6454SAndrew Thompson #define	PCI_EHCI_FLADJ		0x61	/* RW Frame len adj, SOF=59488+6*fladj */
5302ac6454SAndrew Thompson #define	PCI_EHCI_PORTWAKECAP	0x62	/* RW Port wake caps (opt)  */
5402ac6454SAndrew Thompson 
5502ac6454SAndrew Thompson /* EHCI Extended Capabilities */
5602ac6454SAndrew Thompson #define	EHCI_EC_LEGSUP		0x01
5702ac6454SAndrew Thompson #define	EHCI_EECP_NEXT(x)	(((x) >> 8) & 0xff)
5802ac6454SAndrew Thompson #define	EHCI_EECP_ID(x)		((x) & 0xff)
5902ac6454SAndrew Thompson 
6002ac6454SAndrew Thompson /* Legacy support extended capability */
6102ac6454SAndrew Thompson #define	EHCI_LEGSUP_BIOS_SEM		0x02
6202ac6454SAndrew Thompson #define	EHCI_LEGSUP_OS_SEM		0x03
6302ac6454SAndrew Thompson #define	EHCI_LEGSUP_USBLEGCTLSTS	0x04
6402ac6454SAndrew Thompson 
6502ac6454SAndrew Thompson /* EHCI capability registers */
6602ac6454SAndrew Thompson #define	EHCI_CAPLENGTH		0x00	/* RO Capability register length field */
6702ac6454SAndrew Thompson /* reserved			0x01 */
6802ac6454SAndrew Thompson #define	EHCI_HCIVERSION		0x02	/* RO Interface version number */
6902ac6454SAndrew Thompson #define	EHCI_HCSPARAMS		0x04	/* RO Structural parameters */
7002ac6454SAndrew Thompson #define	EHCI_HCS_DEBUGPORT(x)	(((x) >> 20) & 0xf)
7102ac6454SAndrew Thompson #define	EHCI_HCS_P_INDICATOR(x) ((x) & 0x10000)
7202ac6454SAndrew Thompson #define	EHCI_HCS_N_CC(x)	(((x) >> 12) & 0xf)	/* # of companion ctlrs */
7302ac6454SAndrew Thompson #define	EHCI_HCS_N_PCC(x)	(((x) >> 8) & 0xf)	/* # of ports per comp. */
7402ac6454SAndrew Thompson #define	EHCI_HCS_PPC(x)		((x) & 0x10)	/* port power control */
7502ac6454SAndrew Thompson #define	EHCI_HCS_N_PORTS(x)	((x) & 0xf)	/* # of ports */
7602ac6454SAndrew Thompson #define	EHCI_HCCPARAMS		0x08	/* RO Capability parameters */
7702ac6454SAndrew Thompson #define	EHCI_HCC_EECP(x)	(((x) >> 8) & 0xff)	/* extended ports caps */
7802ac6454SAndrew Thompson #define	EHCI_HCC_IST(x)		(((x) >> 4) & 0xf)	/* isoc sched threshold */
7902ac6454SAndrew Thompson #define	EHCI_HCC_ASPC(x)	((x) & 0x4)	/* async sched park cap */
8002ac6454SAndrew Thompson #define	EHCI_HCC_PFLF(x)	((x) & 0x2)	/* prog frame list flag */
8102ac6454SAndrew Thompson #define	EHCI_HCC_64BIT(x)	((x) & 0x1)	/* 64 bit address cap */
8202ac6454SAndrew Thompson #define	EHCI_HCSP_PORTROUTE	0x0c	/* RO Companion port route description */
8302ac6454SAndrew Thompson 
8402ac6454SAndrew Thompson /* EHCI operational registers.  Offset given by EHCI_CAPLENGTH register */
8502ac6454SAndrew Thompson #define	EHCI_USBCMD		0x00	/* RO, RW, WO Command register */
8602ac6454SAndrew Thompson #define	EHCI_CMD_ITC_M		0x00ff0000	/* RW interrupt threshold ctrl */
8702ac6454SAndrew Thompson #define	EHCI_CMD_ITC_1		0x00010000
8802ac6454SAndrew Thompson #define	EHCI_CMD_ITC_2		0x00020000
8902ac6454SAndrew Thompson #define	EHCI_CMD_ITC_4		0x00040000
9002ac6454SAndrew Thompson #define	EHCI_CMD_ITC_8		0x00080000
9102ac6454SAndrew Thompson #define	EHCI_CMD_ITC_16		0x00100000
9202ac6454SAndrew Thompson #define	EHCI_CMD_ITC_32		0x00200000
9302ac6454SAndrew Thompson #define	EHCI_CMD_ITC_64		0x00400000
9402ac6454SAndrew Thompson #define	EHCI_CMD_ASPME		0x00000800	/* RW/RO async park enable */
9502ac6454SAndrew Thompson #define	EHCI_CMD_ASPMC		0x00000300	/* RW/RO async park count */
9602ac6454SAndrew Thompson #define	EHCI_CMD_LHCR		0x00000080	/* RW light host ctrl reset */
9702ac6454SAndrew Thompson #define	EHCI_CMD_IAAD		0x00000040	/* RW intr on async adv door
9802ac6454SAndrew Thompson 						 * bell */
9902ac6454SAndrew Thompson #define	EHCI_CMD_ASE		0x00000020	/* RW async sched enable */
10002ac6454SAndrew Thompson #define	EHCI_CMD_PSE		0x00000010	/* RW periodic sched enable */
10102ac6454SAndrew Thompson #define	EHCI_CMD_FLS_M		0x0000000c	/* RW/RO frame list size */
10202ac6454SAndrew Thompson #define	EHCI_CMD_FLS(x)		(((x) >> 2) & 3)	/* RW/RO frame list size */
10302ac6454SAndrew Thompson #define	EHCI_CMD_HCRESET	0x00000002	/* RW reset */
10402ac6454SAndrew Thompson #define	EHCI_CMD_RS		0x00000001	/* RW run/stop */
10502ac6454SAndrew Thompson #define	EHCI_USBSTS		0x04	/* RO, RW, RWC Status register */
10602ac6454SAndrew Thompson #define	EHCI_STS_ASS		0x00008000	/* RO async sched status */
10702ac6454SAndrew Thompson #define	EHCI_STS_PSS		0x00004000	/* RO periodic sched status */
10802ac6454SAndrew Thompson #define	EHCI_STS_REC		0x00002000	/* RO reclamation */
10902ac6454SAndrew Thompson #define	EHCI_STS_HCH		0x00001000	/* RO host controller halted */
11002ac6454SAndrew Thompson #define	EHCI_STS_IAA		0x00000020	/* RWC interrupt on async adv */
11102ac6454SAndrew Thompson #define	EHCI_STS_HSE		0x00000010	/* RWC host system error */
11202ac6454SAndrew Thompson #define	EHCI_STS_FLR		0x00000008	/* RWC frame list rollover */
11302ac6454SAndrew Thompson #define	EHCI_STS_PCD		0x00000004	/* RWC port change detect */
11402ac6454SAndrew Thompson #define	EHCI_STS_ERRINT		0x00000002	/* RWC error interrupt */
11502ac6454SAndrew Thompson #define	EHCI_STS_INT		0x00000001	/* RWC interrupt */
11602ac6454SAndrew Thompson #define	EHCI_STS_INTRS(x)	((x) & 0x3f)
11702ac6454SAndrew Thompson 
11802ac6454SAndrew Thompson /*
11902ac6454SAndrew Thompson  * NOTE: the doorbell interrupt is enabled, but the doorbell is never
12002ac6454SAndrew Thompson  * used! SiS chipsets require this.
12102ac6454SAndrew Thompson  */
12202ac6454SAndrew Thompson #define	EHCI_NORMAL_INTRS	(EHCI_STS_IAA | EHCI_STS_HSE |	\
12302ac6454SAndrew Thompson 				EHCI_STS_PCD | EHCI_STS_ERRINT | EHCI_STS_INT)
12402ac6454SAndrew Thompson 
12502ac6454SAndrew Thompson #define	EHCI_USBINTR		0x08	/* RW Interrupt register */
12602ac6454SAndrew Thompson #define	EHCI_INTR_IAAE		0x00000020	/* interrupt on async advance
12702ac6454SAndrew Thompson 						 * ena */
12802ac6454SAndrew Thompson #define	EHCI_INTR_HSEE		0x00000010	/* host system error ena */
12902ac6454SAndrew Thompson #define	EHCI_INTR_FLRE		0x00000008	/* frame list rollover ena */
13002ac6454SAndrew Thompson #define	EHCI_INTR_PCIE		0x00000004	/* port change ena */
13102ac6454SAndrew Thompson #define	EHCI_INTR_UEIE		0x00000002	/* USB error intr ena */
13202ac6454SAndrew Thompson #define	EHCI_INTR_UIE		0x00000001	/* USB intr ena */
13302ac6454SAndrew Thompson 
13402ac6454SAndrew Thompson #define	EHCI_FRINDEX		0x0c	/* RW Frame Index register */
13502ac6454SAndrew Thompson 
13602ac6454SAndrew Thompson #define	EHCI_CTRLDSSEGMENT	0x10	/* RW Control Data Structure Segment */
13702ac6454SAndrew Thompson 
13802ac6454SAndrew Thompson #define	EHCI_PERIODICLISTBASE	0x14	/* RW Periodic List Base */
13902ac6454SAndrew Thompson #define	EHCI_ASYNCLISTADDR	0x18	/* RW Async List Base */
14002ac6454SAndrew Thompson 
14102ac6454SAndrew Thompson #define	EHCI_CONFIGFLAG		0x40	/* RW Configure Flag register */
14202ac6454SAndrew Thompson #define	EHCI_CONF_CF		0x00000001	/* RW configure flag */
14302ac6454SAndrew Thompson 
14402ac6454SAndrew Thompson #define	EHCI_PORTSC(n)		(0x40+(4*(n)))	/* RO, RW, RWC Port Status reg */
14502ac6454SAndrew Thompson #define	EHCI_PS_WKOC_E		0x00400000	/* RW wake on over current ena */
14602ac6454SAndrew Thompson #define	EHCI_PS_WKDSCNNT_E	0x00200000	/* RW wake on disconnect ena */
14702ac6454SAndrew Thompson #define	EHCI_PS_WKCNNT_E	0x00100000	/* RW wake on connect ena */
14802ac6454SAndrew Thompson #define	EHCI_PS_PTC		0x000f0000	/* RW port test control */
14902ac6454SAndrew Thompson #define	EHCI_PS_PIC		0x0000c000	/* RW port indicator control */
15002ac6454SAndrew Thompson #define	EHCI_PS_PO		0x00002000	/* RW port owner */
15102ac6454SAndrew Thompson #define	EHCI_PS_PP		0x00001000	/* RW,RO port power */
15202ac6454SAndrew Thompson #define	EHCI_PS_LS		0x00000c00	/* RO line status */
15302ac6454SAndrew Thompson #define	EHCI_PS_IS_LOWSPEED(x)	(((x) & EHCI_PS_LS) == 0x00000400)
15402ac6454SAndrew Thompson #define	EHCI_PS_PR		0x00000100	/* RW port reset */
15502ac6454SAndrew Thompson #define	EHCI_PS_SUSP		0x00000080	/* RW suspend */
15602ac6454SAndrew Thompson #define	EHCI_PS_FPR		0x00000040	/* RW force port resume */
15702ac6454SAndrew Thompson #define	EHCI_PS_OCC		0x00000020	/* RWC over current change */
15802ac6454SAndrew Thompson #define	EHCI_PS_OCA		0x00000010	/* RO over current active */
15902ac6454SAndrew Thompson #define	EHCI_PS_PEC		0x00000008	/* RWC port enable change */
16002ac6454SAndrew Thompson #define	EHCI_PS_PE		0x00000004	/* RW port enable */
16102ac6454SAndrew Thompson #define	EHCI_PS_CSC		0x00000002	/* RWC connect status change */
16202ac6454SAndrew Thompson #define	EHCI_PS_CS		0x00000001	/* RO connect status */
16302ac6454SAndrew Thompson #define	EHCI_PS_CLEAR		(EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
16402ac6454SAndrew Thompson 
16502ac6454SAndrew Thompson #define	EHCI_USBMODE		0x68	/* RW USB Device mode register */
16602ac6454SAndrew Thompson #define	EHCI_UM_CM		0x00000003	/* R/WO Controller Mode */
16702ac6454SAndrew Thompson #define	EHCI_UM_CM_IDLE		0x0	/* Idle */
16802ac6454SAndrew Thompson #define	EHCI_UM_CM_HOST		0x3	/* Host Controller */
16902ac6454SAndrew Thompson #define	EHCI_UM_ES		0x00000004	/* R/WO Endian Select */
17002ac6454SAndrew Thompson #define	EHCI_UM_ES_LE		0x0	/* Little-endian byte alignment */
17102ac6454SAndrew Thompson #define	EHCI_UM_ES_BE		0x4	/* Big-endian byte alignment */
17202ac6454SAndrew Thompson #define	EHCI_UM_SDIS		0x00000010	/* R/WO Stream Disable Mode */
17302ac6454SAndrew Thompson 
17402ac6454SAndrew Thompson #define	EHCI_PORT_RESET_COMPLETE	2	/* ms */
17502ac6454SAndrew Thompson 
17602ac6454SAndrew Thompson /*
17702ac6454SAndrew Thompson  * Alignment NOTE: structures must be aligned so that the hardware can index
17802ac6454SAndrew Thompson  * without performing addition.
17902ac6454SAndrew Thompson  */
18002ac6454SAndrew Thompson #define	EHCI_FRAMELIST_ALIGN          0x1000	/* bytes */
18102ac6454SAndrew Thompson #define	EHCI_FRAMELIST_COUNT            1024	/* units */
18202ac6454SAndrew Thompson #define	EHCI_VIRTUAL_FRAMELIST_COUNT     128	/* units */
18302ac6454SAndrew Thompson 
18402ac6454SAndrew Thompson #if ((8*EHCI_VIRTUAL_FRAMELIST_COUNT) < USB_MAX_HS_ISOC_FRAMES_PER_XFER)
18502ac6454SAndrew Thompson #error "maximum number of high-speed isochronous frames is higher than supported!"
18602ac6454SAndrew Thompson #endif
18702ac6454SAndrew Thompson 
18802ac6454SAndrew Thompson #if (EHCI_VIRTUAL_FRAMELIST_COUNT < USB_MAX_FS_ISOC_FRAMES_PER_XFER)
18902ac6454SAndrew Thompson #error "maximum number of full-speed isochronous frames is higher than supported!"
19002ac6454SAndrew Thompson #endif
19102ac6454SAndrew Thompson 
19202ac6454SAndrew Thompson /* Link types */
19302ac6454SAndrew Thompson #define	EHCI_LINK_TERMINATE	0x00000001
19402ac6454SAndrew Thompson #define	EHCI_LINK_TYPE(x)	((x) & 0x00000006)
19502ac6454SAndrew Thompson #define	EHCI_LINK_ITD		0x0
19602ac6454SAndrew Thompson #define	EHCI_LINK_QH		0x2
19702ac6454SAndrew Thompson #define	EHCI_LINK_SITD		0x4
19802ac6454SAndrew Thompson #define	EHCI_LINK_FSTN		0x6
19902ac6454SAndrew Thompson #define	EHCI_LINK_ADDR(x)	((x) &~ 0x1f)
20002ac6454SAndrew Thompson 
20102ac6454SAndrew Thompson /* Structures alignment (bytes) */
20202ac6454SAndrew Thompson #define	EHCI_ITD_ALIGN	128
20302ac6454SAndrew Thompson #define	EHCI_SITD_ALIGN	64
20402ac6454SAndrew Thompson #define	EHCI_QTD_ALIGN	64
20502ac6454SAndrew Thompson #define	EHCI_QH_ALIGN	128
20602ac6454SAndrew Thompson #define	EHCI_FSTN_ALIGN	32
20702ac6454SAndrew Thompson /* Data buffers are divided into one or more pages */
20802ac6454SAndrew Thompson #define	EHCI_PAGE_SIZE	0x1000
20902ac6454SAndrew Thompson #if	((USB_PAGE_SIZE < EHCI_PAGE_SIZE) || (EHCI_PAGE_SIZE == 0) ||	\
21002ac6454SAndrew Thompson 	(USB_PAGE_SIZE < EHCI_ITD_ALIGN) || (EHCI_ITD_ALIGN == 0) ||	\
21102ac6454SAndrew Thompson 	(USB_PAGE_SIZE < EHCI_SITD_ALIGN) || (EHCI_SITD_ALIGN == 0) ||	\
21202ac6454SAndrew Thompson 	(USB_PAGE_SIZE < EHCI_QTD_ALIGN) || (EHCI_QTD_ALIGN == 0) ||	\
21302ac6454SAndrew Thompson 	(USB_PAGE_SIZE < EHCI_QH_ALIGN) || (EHCI_QH_ALIGN == 0) ||	\
21402ac6454SAndrew Thompson 	(USB_PAGE_SIZE < EHCI_FSTN_ALIGN) || (EHCI_FSTN_ALIGN == 0))
21502ac6454SAndrew Thompson #error	"Invalid USB page size!"
21602ac6454SAndrew Thompson #endif
21702ac6454SAndrew Thompson 
21802ac6454SAndrew Thompson 
21902ac6454SAndrew Thompson /*
22002ac6454SAndrew Thompson  * Isochronous Transfer Descriptor.  This descriptor is used for high speed
22102ac6454SAndrew Thompson  * transfers only.
22202ac6454SAndrew Thompson  */
22302ac6454SAndrew Thompson struct ehci_itd {
22402ac6454SAndrew Thompson 	volatile uint32_t itd_next;
22502ac6454SAndrew Thompson 	volatile uint32_t itd_status[8];
22602ac6454SAndrew Thompson #define	EHCI_ITD_SET_LEN(x)	((x) << 16)
22702ac6454SAndrew Thompson #define	EHCI_ITD_GET_LEN(x)	(((x) >> 16) & 0xFFF)
22802ac6454SAndrew Thompson #define	EHCI_ITD_IOC		(1 << 15)
22902ac6454SAndrew Thompson #define	EHCI_ITD_SET_PG(x)	((x) << 12)
23002ac6454SAndrew Thompson #define	EHCI_ITD_GET_PG(x)	(((x) >> 12) & 0x7)
23102ac6454SAndrew Thompson #define	EHCI_ITD_SET_OFFS(x)	(x)
23202ac6454SAndrew Thompson #define	EHCI_ITD_GET_OFFS(x)	(((x) >> 0) & 0xFFF)
23302ac6454SAndrew Thompson #define	EHCI_ITD_ACTIVE		(1 << 31)
23402ac6454SAndrew Thompson #define	EHCI_ITD_DATABUFERR	(1 << 30)
23502ac6454SAndrew Thompson #define	EHCI_ITD_BABBLE		(1 << 29)
23602ac6454SAndrew Thompson #define	EHCI_ITD_XACTERR	(1 << 28)
23702ac6454SAndrew Thompson 	volatile uint32_t itd_bp[7];
23802ac6454SAndrew Thompson 	/* itd_bp[0] */
23902ac6454SAndrew Thompson #define	EHCI_ITD_SET_ADDR(x)	(x)
24002ac6454SAndrew Thompson #define	EHCI_ITD_GET_ADDR(x)	(((x) >> 0) & 0x7F)
24102ac6454SAndrew Thompson #define	EHCI_ITD_SET_ENDPT(x)	((x) << 8)
24202ac6454SAndrew Thompson #define	EHCI_ITD_GET_ENDPT(x)	(((x) >> 8) & 0xF)
24302ac6454SAndrew Thompson 	/* itd_bp[1] */
24402ac6454SAndrew Thompson #define	EHCI_ITD_SET_DIR_IN	(1 << 11)
24502ac6454SAndrew Thompson #define	EHCI_ITD_SET_DIR_OUT	(0 << 11)
24602ac6454SAndrew Thompson #define	EHCI_ITD_SET_MPL(x)	(x)
24702ac6454SAndrew Thompson #define	EHCI_ITD_GET_MPL(x)	(((x) >> 0) & 0x7FF)
24802ac6454SAndrew Thompson 	volatile uint32_t itd_bp_hi[7];
24902ac6454SAndrew Thompson /*
25002ac6454SAndrew Thompson  * Extra information needed:
25102ac6454SAndrew Thompson  */
25202ac6454SAndrew Thompson 	uint32_t itd_self;
25302ac6454SAndrew Thompson 	struct ehci_itd *next;
25402ac6454SAndrew Thompson 	struct ehci_itd *prev;
25502ac6454SAndrew Thompson 	struct ehci_itd *obj_next;
256760bc48eSAndrew Thompson 	struct usb_page_cache *page_cache;
25702ac6454SAndrew Thompson } __aligned(EHCI_ITD_ALIGN);
25802ac6454SAndrew Thompson 
25902ac6454SAndrew Thompson typedef struct ehci_itd ehci_itd_t;
26002ac6454SAndrew Thompson 
26102ac6454SAndrew Thompson /*
26202ac6454SAndrew Thompson  * Split Transaction Isochronous Transfer Descriptor.  This descriptor is used
26302ac6454SAndrew Thompson  * for full speed transfers only.
26402ac6454SAndrew Thompson  */
26502ac6454SAndrew Thompson struct ehci_sitd {
26602ac6454SAndrew Thompson 	volatile uint32_t sitd_next;
26702ac6454SAndrew Thompson 	volatile uint32_t sitd_portaddr;
26802ac6454SAndrew Thompson #define	EHCI_SITD_SET_DIR_OUT	(0 << 31)
26902ac6454SAndrew Thompson #define	EHCI_SITD_SET_DIR_IN	(1 << 31)
27002ac6454SAndrew Thompson #define	EHCI_SITD_SET_ADDR(x)	(x)
27102ac6454SAndrew Thompson #define	EHCI_SITD_GET_ADDR(x)	((x) & 0x7F)
27202ac6454SAndrew Thompson #define	EHCI_SITD_SET_ENDPT(x)	((x) << 8)
27302ac6454SAndrew Thompson #define	EHCI_SITD_GET_ENDPT(x)	(((x) >> 8) & 0xF)
27402ac6454SAndrew Thompson #define	EHCI_SITD_GET_DIR(x)	((x) >> 31)
27502ac6454SAndrew Thompson #define	EHCI_SITD_SET_PORT(x)	((x) << 24)
27602ac6454SAndrew Thompson #define	EHCI_SITD_GET_PORT(x)	(((x) >> 24) & 0x7F)
27702ac6454SAndrew Thompson #define	EHCI_SITD_SET_HUBA(x)	((x) << 16)
27802ac6454SAndrew Thompson #define	EHCI_SITD_GET_HUBA(x)	(((x) >> 16) & 0x7F)
27902ac6454SAndrew Thompson 	volatile uint32_t sitd_mask;
28002ac6454SAndrew Thompson #define	EHCI_SITD_SET_SMASK(x)	(x)
28102ac6454SAndrew Thompson #define	EHCI_SITD_SET_CMASK(x)	((x) << 8)
28202ac6454SAndrew Thompson 	volatile uint32_t sitd_status;
28302ac6454SAndrew Thompson #define	EHCI_SITD_COMPLETE_SPLIT	(1<<1)
28402ac6454SAndrew Thompson #define	EHCI_SITD_START_SPLIT		(0<<1)
28502ac6454SAndrew Thompson #define	EHCI_SITD_MISSED_MICRO_FRAME	(1<<2)
28602ac6454SAndrew Thompson #define	EHCI_SITD_XACTERR		(1<<3)
28702ac6454SAndrew Thompson #define	EHCI_SITD_BABBLE		(1<<4)
28802ac6454SAndrew Thompson #define	EHCI_SITD_DATABUFERR		(1<<5)
28902ac6454SAndrew Thompson #define	EHCI_SITD_ERROR			(1<<6)
29002ac6454SAndrew Thompson #define	EHCI_SITD_ACTIVE		(1<<7)
29102ac6454SAndrew Thompson #define	EHCI_SITD_IOC			(1<<31)
29202ac6454SAndrew Thompson #define	EHCI_SITD_SET_LEN(len)		((len)<<16)
29302ac6454SAndrew Thompson #define	EHCI_SITD_GET_LEN(x)		(((x)>>16) & 0x3FF)
29402ac6454SAndrew Thompson 	volatile uint32_t sitd_bp[2];
29502ac6454SAndrew Thompson 	volatile uint32_t sitd_back;
29602ac6454SAndrew Thompson 	volatile uint32_t sitd_bp_hi[2];
29702ac6454SAndrew Thompson /*
29802ac6454SAndrew Thompson  * Extra information needed:
29902ac6454SAndrew Thompson  */
30002ac6454SAndrew Thompson 	uint32_t sitd_self;
30102ac6454SAndrew Thompson 	struct ehci_sitd *next;
30202ac6454SAndrew Thompson 	struct ehci_sitd *prev;
30302ac6454SAndrew Thompson 	struct ehci_sitd *obj_next;
304760bc48eSAndrew Thompson 	struct usb_page_cache *page_cache;
30502ac6454SAndrew Thompson } __aligned(EHCI_SITD_ALIGN);
30602ac6454SAndrew Thompson 
30702ac6454SAndrew Thompson typedef struct ehci_sitd ehci_sitd_t;
30802ac6454SAndrew Thompson 
30902ac6454SAndrew Thompson /* Queue Element Transfer Descriptor */
31002ac6454SAndrew Thompson struct ehci_qtd {
31102ac6454SAndrew Thompson 	volatile uint32_t qtd_next;
31202ac6454SAndrew Thompson 	volatile uint32_t qtd_altnext;
31302ac6454SAndrew Thompson 	volatile uint32_t qtd_status;
31402ac6454SAndrew Thompson #define	EHCI_QTD_GET_STATUS(x)	(((x) >>  0) & 0xff)
31502ac6454SAndrew Thompson #define	EHCI_QTD_SET_STATUS(x)  ((x) << 0)
31602ac6454SAndrew Thompson #define	EHCI_QTD_ACTIVE		0x80
31702ac6454SAndrew Thompson #define	EHCI_QTD_HALTED		0x40
31802ac6454SAndrew Thompson #define	EHCI_QTD_BUFERR		0x20
31902ac6454SAndrew Thompson #define	EHCI_QTD_BABBLE		0x10
32002ac6454SAndrew Thompson #define	EHCI_QTD_XACTERR	0x08
32102ac6454SAndrew Thompson #define	EHCI_QTD_MISSEDMICRO	0x04
32202ac6454SAndrew Thompson #define	EHCI_QTD_SPLITXSTATE	0x02
32302ac6454SAndrew Thompson #define	EHCI_QTD_PINGSTATE	0x01
32402ac6454SAndrew Thompson #define	EHCI_QTD_STATERRS	0x74
32502ac6454SAndrew Thompson #define	EHCI_QTD_GET_PID(x)	(((x) >>  8) & 0x3)
32602ac6454SAndrew Thompson #define	EHCI_QTD_SET_PID(x)	((x) <<  8)
32702ac6454SAndrew Thompson #define	EHCI_QTD_PID_OUT	0x0
32802ac6454SAndrew Thompson #define	EHCI_QTD_PID_IN		0x1
32902ac6454SAndrew Thompson #define	EHCI_QTD_PID_SETUP	0x2
33002ac6454SAndrew Thompson #define	EHCI_QTD_GET_CERR(x)	(((x) >> 10) &  0x3)
33102ac6454SAndrew Thompson #define	EHCI_QTD_SET_CERR(x)	((x) << 10)
33202ac6454SAndrew Thompson #define	EHCI_QTD_GET_C_PAGE(x)	(((x) >> 12) &  0x7)
33302ac6454SAndrew Thompson #define	EHCI_QTD_SET_C_PAGE(x)	((x) << 12)
33402ac6454SAndrew Thompson #define	EHCI_QTD_GET_IOC(x)	(((x) >> 15) &  0x1)
33502ac6454SAndrew Thompson #define	EHCI_QTD_IOC		0x00008000
33602ac6454SAndrew Thompson #define	EHCI_QTD_GET_BYTES(x)	(((x) >> 16) &  0x7fff)
33702ac6454SAndrew Thompson #define	EHCI_QTD_SET_BYTES(x)	((x) << 16)
33802ac6454SAndrew Thompson #define	EHCI_QTD_GET_TOGGLE(x)	(((x) >> 31) &  0x1)
33902ac6454SAndrew Thompson #define	EHCI_QTD_SET_TOGGLE(x)	((x) << 31)
34002ac6454SAndrew Thompson #define	EHCI_QTD_TOGGLE_MASK	0x80000000
34102ac6454SAndrew Thompson #define	EHCI_QTD_NBUFFERS	5
34202ac6454SAndrew Thompson #define	EHCI_QTD_PAYLOAD_MAX ((EHCI_QTD_NBUFFERS-1)*EHCI_PAGE_SIZE)
34302ac6454SAndrew Thompson 	volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS];
34402ac6454SAndrew Thompson 	volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
34502ac6454SAndrew Thompson /*
34602ac6454SAndrew Thompson  * Extra information needed:
34702ac6454SAndrew Thompson  */
34802ac6454SAndrew Thompson 	struct ehci_qtd *alt_next;
34902ac6454SAndrew Thompson 	struct ehci_qtd *obj_next;
350760bc48eSAndrew Thompson 	struct usb_page_cache *page_cache;
35102ac6454SAndrew Thompson 	uint32_t qtd_self;
35202ac6454SAndrew Thompson 	uint16_t len;
35302ac6454SAndrew Thompson } __aligned(EHCI_QTD_ALIGN);
35402ac6454SAndrew Thompson 
35502ac6454SAndrew Thompson typedef struct ehci_qtd ehci_qtd_t;
35602ac6454SAndrew Thompson 
35702ac6454SAndrew Thompson /* Queue Head Sub Structure */
35802ac6454SAndrew Thompson struct ehci_qh_sub {
35902ac6454SAndrew Thompson 	volatile uint32_t qtd_next;
36002ac6454SAndrew Thompson 	volatile uint32_t qtd_altnext;
36102ac6454SAndrew Thompson 	volatile uint32_t qtd_status;
36202ac6454SAndrew Thompson 	volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS];
36302ac6454SAndrew Thompson 	volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
36402ac6454SAndrew Thompson } __aligned(4);
36502ac6454SAndrew Thompson 
36602ac6454SAndrew Thompson /* Queue Head */
36702ac6454SAndrew Thompson struct ehci_qh {
36802ac6454SAndrew Thompson 	volatile uint32_t qh_link;
36902ac6454SAndrew Thompson 	volatile uint32_t qh_endp;
37002ac6454SAndrew Thompson #define	EHCI_QH_GET_ADDR(x)	(((x) >>  0) & 0x7f)	/* endpoint addr */
37102ac6454SAndrew Thompson #define	EHCI_QH_SET_ADDR(x)	(x)
37202ac6454SAndrew Thompson #define	EHCI_QH_ADDRMASK	0x0000007f
37302ac6454SAndrew Thompson #define	EHCI_QH_GET_INACT(x)	(((x) >>  7) & 0x01)	/* inactivate on next */
37402ac6454SAndrew Thompson #define	EHCI_QH_INACT		0x00000080
37502ac6454SAndrew Thompson #define	EHCI_QH_GET_ENDPT(x)	(((x) >>  8) & 0x0f)	/* endpoint no */
37602ac6454SAndrew Thompson #define	EHCI_QH_SET_ENDPT(x)	((x) <<  8)
37702ac6454SAndrew Thompson #define	EHCI_QH_GET_EPS(x)	(((x) >> 12) & 0x03)	/* endpoint speed */
37802ac6454SAndrew Thompson #define	EHCI_QH_SET_EPS(x)	((x) << 12)
37902ac6454SAndrew Thompson #define	EHCI_QH_SPEED_FULL	0x0
38002ac6454SAndrew Thompson #define	EHCI_QH_SPEED_LOW	0x1
38102ac6454SAndrew Thompson #define	EHCI_QH_SPEED_HIGH	0x2
38202ac6454SAndrew Thompson #define	EHCI_QH_GET_DTC(x)	(((x) >> 14) & 0x01)	/* data toggle control */
38302ac6454SAndrew Thompson #define	EHCI_QH_DTC		0x00004000
38402ac6454SAndrew Thompson #define	EHCI_QH_GET_HRECL(x)	(((x) >> 15) & 0x01)	/* head of reclamation */
38502ac6454SAndrew Thompson #define	EHCI_QH_HRECL		0x00008000
38602ac6454SAndrew Thompson #define	EHCI_QH_GET_MPL(x)	(((x) >> 16) & 0x7ff)	/* max packet len */
38702ac6454SAndrew Thompson #define	EHCI_QH_SET_MPL(x)	((x) << 16)
38802ac6454SAndrew Thompson #define	EHCI_QH_MPLMASK		0x07ff0000
38902ac6454SAndrew Thompson #define	EHCI_QH_GET_CTL(x)	(((x) >> 27) & 0x01)	/* control endpoint */
39002ac6454SAndrew Thompson #define	EHCI_QH_CTL		0x08000000
39102ac6454SAndrew Thompson #define	EHCI_QH_GET_NRL(x)	(((x) >> 28) & 0x0f)	/* NAK reload */
39202ac6454SAndrew Thompson #define	EHCI_QH_SET_NRL(x)	((x) << 28)
39302ac6454SAndrew Thompson 	volatile uint32_t qh_endphub;
39402ac6454SAndrew Thompson #define	EHCI_QH_GET_SMASK(x)	(((x) >>  0) & 0xff)	/* intr sched mask */
39502ac6454SAndrew Thompson #define	EHCI_QH_SET_SMASK(x)	((x) <<  0)
39602ac6454SAndrew Thompson #define	EHCI_QH_GET_CMASK(x)	(((x) >>  8) & 0xff)	/* split completion mask */
39702ac6454SAndrew Thompson #define	EHCI_QH_SET_CMASK(x)	((x) <<  8)
39802ac6454SAndrew Thompson #define	EHCI_QH_GET_HUBA(x)	(((x) >> 16) & 0x7f)	/* hub address */
39902ac6454SAndrew Thompson #define	EHCI_QH_SET_HUBA(x)	((x) << 16)
40002ac6454SAndrew Thompson #define	EHCI_QH_GET_PORT(x)	(((x) >> 23) & 0x7f)	/* hub port */
40102ac6454SAndrew Thompson #define	EHCI_QH_SET_PORT(x)	((x) << 23)
40202ac6454SAndrew Thompson #define	EHCI_QH_GET_MULT(x)	(((x) >> 30) & 0x03)	/* pipe multiplier */
40302ac6454SAndrew Thompson #define	EHCI_QH_SET_MULT(x)	((x) << 30)
40402ac6454SAndrew Thompson 	volatile uint32_t qh_curqtd;
40502ac6454SAndrew Thompson 	struct ehci_qh_sub qh_qtd;
40602ac6454SAndrew Thompson /*
40702ac6454SAndrew Thompson  * Extra information needed:
40802ac6454SAndrew Thompson  */
40902ac6454SAndrew Thompson 	struct ehci_qh *next;
41002ac6454SAndrew Thompson 	struct ehci_qh *prev;
41102ac6454SAndrew Thompson 	struct ehci_qh *obj_next;
412760bc48eSAndrew Thompson 	struct usb_page_cache *page_cache;
41302ac6454SAndrew Thompson 	uint32_t qh_self;
41402ac6454SAndrew Thompson } __aligned(EHCI_QH_ALIGN);
41502ac6454SAndrew Thompson 
41602ac6454SAndrew Thompson typedef struct ehci_qh ehci_qh_t;
41702ac6454SAndrew Thompson 
41802ac6454SAndrew Thompson /* Periodic Frame Span Traversal Node */
41902ac6454SAndrew Thompson struct ehci_fstn {
42002ac6454SAndrew Thompson 	volatile uint32_t fstn_link;
42102ac6454SAndrew Thompson 	volatile uint32_t fstn_back;
42202ac6454SAndrew Thompson } __aligned(EHCI_FSTN_ALIGN);
42302ac6454SAndrew Thompson 
42402ac6454SAndrew Thompson typedef struct ehci_fstn ehci_fstn_t;
42502ac6454SAndrew Thompson 
42602ac6454SAndrew Thompson struct ehci_hw_softc {
427760bc48eSAndrew Thompson 	struct usb_page_cache pframes_pc;
428760bc48eSAndrew Thompson 	struct usb_page_cache async_start_pc;
429760bc48eSAndrew Thompson 	struct usb_page_cache intr_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
430760bc48eSAndrew Thompson 	struct usb_page_cache isoc_hs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
431760bc48eSAndrew Thompson 	struct usb_page_cache isoc_fs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
43202ac6454SAndrew Thompson 
433760bc48eSAndrew Thompson 	struct usb_page pframes_pg;
434760bc48eSAndrew Thompson 	struct usb_page async_start_pg;
435760bc48eSAndrew Thompson 	struct usb_page intr_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
436760bc48eSAndrew Thompson 	struct usb_page isoc_hs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
437760bc48eSAndrew Thompson 	struct usb_page isoc_fs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
43802ac6454SAndrew Thompson };
43902ac6454SAndrew Thompson 
44002ac6454SAndrew Thompson struct ehci_config_desc {
441760bc48eSAndrew Thompson 	struct usb_config_descriptor confd;
442760bc48eSAndrew Thompson 	struct usb_interface_descriptor ifcd;
443760bc48eSAndrew Thompson 	struct usb_endpoint_descriptor endpd;
44402ac6454SAndrew Thompson } __packed;
44502ac6454SAndrew Thompson 
44602ac6454SAndrew Thompson union ehci_hub_desc {
447760bc48eSAndrew Thompson 	struct usb_status stat;
448760bc48eSAndrew Thompson 	struct usb_port_status ps;
449760bc48eSAndrew Thompson 	struct usb_hub_descriptor hubd;
45002ac6454SAndrew Thompson 	uint8_t	temp[128];
45102ac6454SAndrew Thompson };
45202ac6454SAndrew Thompson 
45302ac6454SAndrew Thompson typedef struct ehci_softc {
45402ac6454SAndrew Thompson 	struct ehci_hw_softc sc_hw;
455760bc48eSAndrew Thompson 	struct usb_bus sc_bus;		/* base device */
456760bc48eSAndrew Thompson 	struct usb_callout sc_tmo_pcd;
45702ac6454SAndrew Thompson 	union ehci_hub_desc sc_hub_desc;
45802ac6454SAndrew Thompson 
459760bc48eSAndrew Thompson 	struct usb_device *sc_devices[EHCI_MAX_DEVICES];
46002ac6454SAndrew Thompson 	struct resource *sc_io_res;
46102ac6454SAndrew Thompson 	struct resource *sc_irq_res;
46202ac6454SAndrew Thompson 	struct ehci_qh *sc_async_p_last;
46302ac6454SAndrew Thompson 	struct ehci_qh *sc_intr_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT];
46402ac6454SAndrew Thompson 	struct ehci_sitd *sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT];
46502ac6454SAndrew Thompson 	struct ehci_itd *sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT];
46602ac6454SAndrew Thompson 	void   *sc_intr_hdl;
46702ac6454SAndrew Thompson 	bus_size_t sc_io_size;
46802ac6454SAndrew Thompson 	bus_space_tag_t sc_io_tag;
46902ac6454SAndrew Thompson 	bus_space_handle_t sc_io_hdl;
47002ac6454SAndrew Thompson 
47102ac6454SAndrew Thompson 	uint32_t sc_eintrs;
47202ac6454SAndrew Thompson 	uint32_t sc_cmd;		/* shadow of cmd register during
47302ac6454SAndrew Thompson 					 * suspend */
47402ac6454SAndrew Thompson 
47502ac6454SAndrew Thompson 	uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT];
47602ac6454SAndrew Thompson 	uint16_t sc_id_vendor;		/* vendor ID for root hub */
47702ac6454SAndrew Thompson 	uint16_t sc_flags;		/* chip specific flags */
47802ac6454SAndrew Thompson #define	EHCI_SCFLG_SETMODE	0x0001	/* set bridge mode again after init */
47902ac6454SAndrew Thompson #define	EHCI_SCFLG_FORCESPEED	0x0002	/* force speed */
48002ac6454SAndrew Thompson #define	EHCI_SCFLG_NORESTERM	0x0004	/* don't terminate reset sequence */
48102ac6454SAndrew Thompson #define	EHCI_SCFLG_BIGEDESC	0x0008	/* big-endian byte order descriptors */
48202ac6454SAndrew Thompson #define	EHCI_SCFLG_BIGEMMIO	0x0010	/* big-endian byte order MMIO */
48302ac6454SAndrew Thompson #define	EHCI_SCFLG_TT		0x0020	/* transaction translator present */
48402ac6454SAndrew Thompson 
48502ac6454SAndrew Thompson 	uint8_t	sc_offs;		/* offset to operational registers */
48602ac6454SAndrew Thompson 	uint8_t	sc_doorbell_disable;	/* set on doorbell failure */
48702ac6454SAndrew Thompson 	uint8_t	sc_noport;
48802ac6454SAndrew Thompson 	uint8_t	sc_addr;		/* device address */
48902ac6454SAndrew Thompson 	uint8_t	sc_conf;		/* device configuration */
49002ac6454SAndrew Thompson 	uint8_t	sc_isreset;
49102ac6454SAndrew Thompson 	uint8_t	sc_hub_idata[8];
49202ac6454SAndrew Thompson 
49302ac6454SAndrew Thompson 	char	sc_vendor[16];		/* vendor string for root hub */
49402ac6454SAndrew Thompson 
49502ac6454SAndrew Thompson } ehci_softc_t;
49602ac6454SAndrew Thompson 
49702ac6454SAndrew Thompson #define	EREAD1(sc, a)	bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
49802ac6454SAndrew Thompson #define	EREAD2(sc, a)	bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
49902ac6454SAndrew Thompson #define	EREAD4(sc, a)	bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
50002ac6454SAndrew Thompson #define	EWRITE1(sc, a, x)						\
50102ac6454SAndrew Thompson 	    bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x))
50202ac6454SAndrew Thompson #define	EWRITE2(sc, a, x)						\
50302ac6454SAndrew Thompson 	    bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x))
50402ac6454SAndrew Thompson #define	EWRITE4(sc, a, x)						\
50502ac6454SAndrew Thompson 	    bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x))
50602ac6454SAndrew Thompson #define	EOREAD1(sc, a)							\
50702ac6454SAndrew Thompson 	    bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a))
50802ac6454SAndrew Thompson #define	EOREAD2(sc, a)							\
50902ac6454SAndrew Thompson 	    bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a))
51002ac6454SAndrew Thompson #define	EOREAD4(sc, a)							\
51102ac6454SAndrew Thompson 	    bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a))
51202ac6454SAndrew Thompson #define	EOWRITE1(sc, a, x)						\
51302ac6454SAndrew Thompson 	    bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x))
51402ac6454SAndrew Thompson #define	EOWRITE2(sc, a, x)						\
51502ac6454SAndrew Thompson 	    bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x))
51602ac6454SAndrew Thompson #define	EOWRITE4(sc, a, x)						\
51702ac6454SAndrew Thompson 	    bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x))
51802ac6454SAndrew Thompson 
519e55e1ebcSAndrew Thompson #ifdef USB_EHCI_BIG_ENDIAN_DESC
520e55e1ebcSAndrew Thompson /*
521e55e1ebcSAndrew Thompson  * Handle byte order conversion between host and ``host controller''.
522e55e1ebcSAndrew Thompson  * Typically the latter is little-endian but some controllers require
523e55e1ebcSAndrew Thompson  * big-endian in which case we may need to manually swap.
524e55e1ebcSAndrew Thompson  */
525e55e1ebcSAndrew Thompson static __inline uint32_t
526e55e1ebcSAndrew Thompson htohc32(const struct ehci_softc *sc, const uint32_t v)
527e55e1ebcSAndrew Thompson {
528e55e1ebcSAndrew Thompson 	return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? htobe32(v) : htole32(v);
529e55e1ebcSAndrew Thompson }
530e55e1ebcSAndrew Thompson 
531e55e1ebcSAndrew Thompson static __inline uint16_t
532e55e1ebcSAndrew Thompson htohc16(const struct ehci_softc *sc, const uint16_t v)
533e55e1ebcSAndrew Thompson {
534e55e1ebcSAndrew Thompson 	return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? htobe16(v) : htole16(v);
535e55e1ebcSAndrew Thompson }
536e55e1ebcSAndrew Thompson 
537e55e1ebcSAndrew Thompson static __inline uint32_t
538e55e1ebcSAndrew Thompson hc32toh(const struct ehci_softc *sc, const uint32_t v)
539e55e1ebcSAndrew Thompson {
540e55e1ebcSAndrew Thompson 	return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? be32toh(v) : le32toh(v);
541e55e1ebcSAndrew Thompson }
542e55e1ebcSAndrew Thompson 
543e55e1ebcSAndrew Thompson static __inline uint16_t
544e55e1ebcSAndrew Thompson hc16toh(const struct ehci_softc *sc, const uint16_t v)
545e55e1ebcSAndrew Thompson {
546e55e1ebcSAndrew Thompson 	return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? be16toh(v) : le16toh(v);
547e55e1ebcSAndrew Thompson }
548e55e1ebcSAndrew Thompson #else
549e55e1ebcSAndrew Thompson /*
550e55e1ebcSAndrew Thompson  * Normal little-endian only conversion routines.
551e55e1ebcSAndrew Thompson  */
552e55e1ebcSAndrew Thompson static __inline uint32_t
553e55e1ebcSAndrew Thompson htohc32(const struct ehci_softc *sc, const uint32_t v)
554e55e1ebcSAndrew Thompson {
555e55e1ebcSAndrew Thompson 	return htole32(v);
556e55e1ebcSAndrew Thompson }
557e55e1ebcSAndrew Thompson 
558e55e1ebcSAndrew Thompson static __inline uint16_t
559e55e1ebcSAndrew Thompson htohc16(const struct ehci_softc *sc, const uint16_t v)
560e55e1ebcSAndrew Thompson {
561e55e1ebcSAndrew Thompson 	return htole16(v);
562e55e1ebcSAndrew Thompson }
563e55e1ebcSAndrew Thompson 
564e55e1ebcSAndrew Thompson static __inline uint32_t
565e55e1ebcSAndrew Thompson hc32toh(const struct ehci_softc *sc, const uint32_t v)
566e55e1ebcSAndrew Thompson {
567e55e1ebcSAndrew Thompson 	return le32toh(v);
568e55e1ebcSAndrew Thompson }
569e55e1ebcSAndrew Thompson 
570e55e1ebcSAndrew Thompson static __inline uint16_t
571e55e1ebcSAndrew Thompson hc16toh(const struct ehci_softc *sc, const uint16_t v)
572e55e1ebcSAndrew Thompson {
573e55e1ebcSAndrew Thompson 	return le16toh(v);
574e55e1ebcSAndrew Thompson }
575e55e1ebcSAndrew Thompson #endif
576e55e1ebcSAndrew Thompson 
577e0a69b51SAndrew Thompson usb_bus_mem_cb_t ehci_iterate_hw_softc;
57802ac6454SAndrew Thompson 
579e0a69b51SAndrew Thompson usb_error_t ehci_reset(ehci_softc_t *sc);
580e0a69b51SAndrew Thompson usb_error_t ehci_init(ehci_softc_t *sc);
58102ac6454SAndrew Thompson void	ehci_detach(struct ehci_softc *sc);
58202ac6454SAndrew Thompson void	ehci_suspend(struct ehci_softc *sc);
58302ac6454SAndrew Thompson void	ehci_resume(struct ehci_softc *sc);
58402ac6454SAndrew Thompson void	ehci_shutdown(ehci_softc_t *sc);
58502ac6454SAndrew Thompson void	ehci_interrupt(ehci_softc_t *sc);
58602ac6454SAndrew Thompson 
58702ac6454SAndrew Thompson #endif					/* _EHCI_H_ */
588