1f9f848faSopenharmony_ci/*- 2f9f848faSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 3f9f848faSopenharmony_ci * 4f9f848faSopenharmony_ci * Copyright (c) 2001 The NetBSD Foundation, Inc. 5f9f848faSopenharmony_ci * All rights reserved. 6f9f848faSopenharmony_ci * 7f9f848faSopenharmony_ci * This code is derived from software contributed to The NetBSD Foundation 8f9f848faSopenharmony_ci * by Lennart Augustsson (lennart@augustsson.net). 9f9f848faSopenharmony_ci * 10f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without 11f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions 12f9f848faSopenharmony_ci * are met: 13f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 14f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer. 15f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 16f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 17f9f848faSopenharmony_ci * documentation and/or other materials provided with the distribution. 18f9f848faSopenharmony_ci * 19f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20f9f848faSopenharmony_ci * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21f9f848faSopenharmony_ci * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22f9f848faSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23f9f848faSopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24f9f848faSopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25f9f848faSopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26f9f848faSopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27f9f848faSopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28f9f848faSopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29f9f848faSopenharmony_ci * POSSIBILITY OF SUCH DAMAGE. 30f9f848faSopenharmony_ci */ 31f9f848faSopenharmony_ci 32f9f848faSopenharmony_ci#ifndef _EHCI_H_ 33f9f848faSopenharmony_ci#define _EHCI_H_ 34f9f848faSopenharmony_ci 35f9f848faSopenharmony_ci#include <sys/endian.h> 36f9f848faSopenharmony_ci 37f9f848faSopenharmony_ci#define EHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128) 38f9f848faSopenharmony_ci 39f9f848faSopenharmony_ci/* 40f9f848faSopenharmony_ci * Alignment NOTE: structures must be aligned so that the hardware can index 41f9f848faSopenharmony_ci * without performing addition. 42f9f848faSopenharmony_ci */ 43f9f848faSopenharmony_ci#define EHCI_FRAMELIST_ALIGN 0x1000 /* bytes */ 44f9f848faSopenharmony_ci#define EHCI_FRAMELIST_COUNT 1024 /* units */ 45f9f848faSopenharmony_ci#define EHCI_VIRTUAL_FRAMELIST_COUNT 128 /* units */ 46f9f848faSopenharmony_ci 47f9f848faSopenharmony_ci#if ((8 * EHCI_VIRTUAL_FRAMELIST_COUNT) < USB_MAX_HS_ISOC_FRAMES_PER_XFER) 48f9f848faSopenharmony_ci#error "maximum number of high-speed isochronous frames is higher than supported!" 49f9f848faSopenharmony_ci#endif 50f9f848faSopenharmony_ci 51f9f848faSopenharmony_ci#if (EHCI_VIRTUAL_FRAMELIST_COUNT < USB_MAX_FS_ISOC_FRAMES_PER_XFER) 52f9f848faSopenharmony_ci#error "maximum number of full-speed isochronous frames is higher than supported!" 53f9f848faSopenharmony_ci#endif 54f9f848faSopenharmony_ci 55f9f848faSopenharmony_ci/* Link types */ 56f9f848faSopenharmony_ci#define EHCI_LINK_TERMINATE 0x00000001 57f9f848faSopenharmony_ci#define EHCI_LINK_TYPE(x) ((x) & 0x00000006) 58f9f848faSopenharmony_ci#define EHCI_LINK_ITD 0x0 59f9f848faSopenharmony_ci#define EHCI_LINK_QH 0x2 60f9f848faSopenharmony_ci#define EHCI_LINK_SITD 0x4 61f9f848faSopenharmony_ci#define EHCI_LINK_FSTN 0x6 62f9f848faSopenharmony_ci#define EHCI_LINK_ADDR(x) ((x) &~ 0x1f) 63f9f848faSopenharmony_ci 64f9f848faSopenharmony_ci/* Structures alignment (bytes) */ 65f9f848faSopenharmony_ci#define EHCI_ITD_ALIGN 128 66f9f848faSopenharmony_ci#define EHCI_SITD_ALIGN 64 67f9f848faSopenharmony_ci#define EHCI_QTD_ALIGN 64 68f9f848faSopenharmony_ci#define EHCI_QH_ALIGN 128 69f9f848faSopenharmony_ci#define EHCI_FSTN_ALIGN 32 70f9f848faSopenharmony_ci/* Data buffers are divided into one or more pages */ 71f9f848faSopenharmony_ci#define EHCI_PAGE_SIZE 0x1000 72f9f848faSopenharmony_ci#if ((USB_PAGE_SIZE < EHCI_PAGE_SIZE) || (EHCI_PAGE_SIZE == 0) || \ 73f9f848faSopenharmony_ci (USB_PAGE_SIZE < EHCI_ITD_ALIGN) || (EHCI_ITD_ALIGN == 0) || \ 74f9f848faSopenharmony_ci (USB_PAGE_SIZE < EHCI_SITD_ALIGN) || (EHCI_SITD_ALIGN == 0) || \ 75f9f848faSopenharmony_ci (USB_PAGE_SIZE < EHCI_QTD_ALIGN) || (EHCI_QTD_ALIGN == 0) || \ 76f9f848faSopenharmony_ci (USB_PAGE_SIZE < EHCI_QH_ALIGN) || (EHCI_QH_ALIGN == 0) || \ 77f9f848faSopenharmony_ci (USB_PAGE_SIZE < EHCI_FSTN_ALIGN) || (EHCI_FSTN_ALIGN == 0)) 78f9f848faSopenharmony_ci#error "Invalid USB page size!" 79f9f848faSopenharmony_ci#endif 80f9f848faSopenharmony_ci 81f9f848faSopenharmony_ci/* 82f9f848faSopenharmony_ci * Isochronous Transfer Descriptor. This descriptor is used for high speed 83f9f848faSopenharmony_ci * transfers only. 84f9f848faSopenharmony_ci */ 85f9f848faSopenharmony_cistruct ehci_itd { 86f9f848faSopenharmony_ci volatile uint32_t itd_next; 87f9f848faSopenharmony_ci volatile uint32_t itd_status[8]; 88f9f848faSopenharmony_ci#define EHCI_ITD_SET_LEN(x) ((x) << 16) 89f9f848faSopenharmony_ci#define EHCI_ITD_GET_LEN(x) (((x) >> 16) & 0xFFF) 90f9f848faSopenharmony_ci#define EHCI_ITD_IOC (1 << 15) 91f9f848faSopenharmony_ci#define EHCI_ITD_SET_PG(x) ((x) << 12) 92f9f848faSopenharmony_ci#define EHCI_ITD_GET_PG(x) (((x) >> 12) & 0x7) 93f9f848faSopenharmony_ci#define EHCI_ITD_SET_OFFS(x) (x) 94f9f848faSopenharmony_ci#define EHCI_ITD_GET_OFFS(x) (((x) >> 0) & 0xFFF) 95f9f848faSopenharmony_ci#define EHCI_ITD_ACTIVE (1U << 31) 96f9f848faSopenharmony_ci#define EHCI_ITD_DATABUFERR (1 << 30) 97f9f848faSopenharmony_ci#define EHCI_ITD_BABBLE (1 << 29) 98f9f848faSopenharmony_ci#define EHCI_ITD_XACTERR (1 << 28) 99f9f848faSopenharmony_ci 100f9f848faSopenharmony_ci#define EHCI_ITD_BP_MAX 7 101f9f848faSopenharmony_ci volatile uint32_t itd_bp[EHCI_ITD_BP_MAX]; 102f9f848faSopenharmony_ci /* itd_bp[0] */ 103f9f848faSopenharmony_ci#define EHCI_ITD_SET_ADDR(x) (x) 104f9f848faSopenharmony_ci#define EHCI_ITD_GET_ADDR(x) (((x) >> 0) & 0x7F) 105f9f848faSopenharmony_ci#define EHCI_ITD_SET_ENDPT(x) ((x) << 8) 106f9f848faSopenharmony_ci#define EHCI_ITD_GET_ENDPT(x) (((x) >> 8) & 0xF) 107f9f848faSopenharmony_ci /* itd_bp[1] */ 108f9f848faSopenharmony_ci#define EHCI_ITD_SET_DIR_IN (1 << 11) 109f9f848faSopenharmony_ci#define EHCI_ITD_SET_DIR_OUT (0 << 11) 110f9f848faSopenharmony_ci#define EHCI_ITD_SET_MPL(x) (x) 111f9f848faSopenharmony_ci#define EHCI_ITD_GET_MPL(x) (((x) >> 0) & 0x7FF) 112f9f848faSopenharmony_ci volatile uint32_t itd_bp_hi[EHCI_ITD_BP_MAX]; 113f9f848faSopenharmony_ci/* 114f9f848faSopenharmony_ci * Extra information needed: 115f9f848faSopenharmony_ci */ 116f9f848faSopenharmony_ci uint32_t itd_self; 117f9f848faSopenharmony_ci struct ehci_itd *next; 118f9f848faSopenharmony_ci struct ehci_itd *prev; 119f9f848faSopenharmony_ci struct ehci_itd *obj_next; 120f9f848faSopenharmony_ci struct usb_page_cache *page_cache; 121f9f848faSopenharmony_ci} __aligned(EHCI_ITD_ALIGN); 122f9f848faSopenharmony_ci 123f9f848faSopenharmony_citypedef struct ehci_itd ehci_itd_t; 124f9f848faSopenharmony_ci 125f9f848faSopenharmony_ci/* 126f9f848faSopenharmony_ci * Split Transaction Isochronous Transfer Descriptor. This descriptor is used 127f9f848faSopenharmony_ci * for full speed transfers only. 128f9f848faSopenharmony_ci */ 129f9f848faSopenharmony_cistruct ehci_sitd { 130f9f848faSopenharmony_ci volatile uint32_t sitd_next; 131f9f848faSopenharmony_ci volatile uint32_t sitd_portaddr; 132f9f848faSopenharmony_ci#define EHCI_SITD_SET_DIR_OUT (0 << 31) 133f9f848faSopenharmony_ci#define EHCI_SITD_SET_DIR_IN (1U << 31) 134f9f848faSopenharmony_ci#define EHCI_SITD_SET_ADDR(x) (x) 135f9f848faSopenharmony_ci#define EHCI_SITD_GET_ADDR(x) ((x) & 0x7F) 136f9f848faSopenharmony_ci#define EHCI_SITD_SET_ENDPT(x) ((x) << 8) 137f9f848faSopenharmony_ci#define EHCI_SITD_GET_ENDPT(x) (((x) >> 8) & 0xF) 138f9f848faSopenharmony_ci#define EHCI_SITD_GET_DIR(x) ((x) >> 31) 139f9f848faSopenharmony_ci#define EHCI_SITD_SET_PORT(x) ((x) << 24) 140f9f848faSopenharmony_ci#define EHCI_SITD_GET_PORT(x) (((x) >> 24) & 0x7F) 141f9f848faSopenharmony_ci#define EHCI_SITD_SET_HUBA(x) ((x) << 16) 142f9f848faSopenharmony_ci#define EHCI_SITD_GET_HUBA(x) (((x) >> 16) & 0x7F) 143f9f848faSopenharmony_ci volatile uint32_t sitd_mask; 144f9f848faSopenharmony_ci#define EHCI_SITD_SET_SMASK(x) (x) 145f9f848faSopenharmony_ci#define EHCI_SITD_SET_CMASK(x) ((x) << 8) 146f9f848faSopenharmony_ci volatile uint32_t sitd_status; 147f9f848faSopenharmony_ci#define EHCI_SITD_COMPLETE_SPLIT (1<<1) 148f9f848faSopenharmony_ci#define EHCI_SITD_START_SPLIT (0<<1) 149f9f848faSopenharmony_ci#define EHCI_SITD_MISSED_MICRO_FRAME (1<<2) 150f9f848faSopenharmony_ci#define EHCI_SITD_XACTERR (1<<3) 151f9f848faSopenharmony_ci#define EHCI_SITD_BABBLE (1<<4) 152f9f848faSopenharmony_ci#define EHCI_SITD_DATABUFERR (1<<5) 153f9f848faSopenharmony_ci#define EHCI_SITD_ERROR (1<<6) 154f9f848faSopenharmony_ci#define EHCI_SITD_ACTIVE (1<<7) 155f9f848faSopenharmony_ci#define EHCI_SITD_IOC (1U<<31) 156f9f848faSopenharmony_ci#define EHCI_SITD_SET_LEN(len) ((len)<<16) 157f9f848faSopenharmony_ci#define EHCI_SITD_GET_LEN(x) (((x)>>16) & 0x3FF) 158f9f848faSopenharmony_ci volatile uint32_t sitd_bp[2]; 159f9f848faSopenharmony_ci volatile uint32_t sitd_back; 160f9f848faSopenharmony_ci volatile uint32_t sitd_bp_hi[2]; 161f9f848faSopenharmony_ci/* 162f9f848faSopenharmony_ci * Extra information needed: 163f9f848faSopenharmony_ci */ 164f9f848faSopenharmony_ci uint32_t sitd_self; 165f9f848faSopenharmony_ci struct ehci_sitd *next; 166f9f848faSopenharmony_ci struct ehci_sitd *prev; 167f9f848faSopenharmony_ci struct ehci_sitd *obj_next; 168f9f848faSopenharmony_ci struct usb_page_cache *page_cache; 169f9f848faSopenharmony_ci} __aligned(EHCI_SITD_ALIGN); 170f9f848faSopenharmony_ci 171f9f848faSopenharmony_citypedef struct ehci_sitd ehci_sitd_t; 172f9f848faSopenharmony_ci 173f9f848faSopenharmony_ci/* Queue Element Transfer Descriptor */ 174f9f848faSopenharmony_cistruct ehci_qtd { 175f9f848faSopenharmony_ci volatile uint32_t qtd_next; 176f9f848faSopenharmony_ci volatile uint32_t qtd_altnext; 177f9f848faSopenharmony_ci volatile uint32_t qtd_status; 178f9f848faSopenharmony_ci#define EHCI_QTD_GET_STATUS(x) (((x) >> 0) & 0xff) 179f9f848faSopenharmony_ci#define EHCI_QTD_SET_STATUS(x) ((x) << 0) 180f9f848faSopenharmony_ci#define EHCI_QTD_ACTIVE 0x80 181f9f848faSopenharmony_ci#define EHCI_QTD_HALTED 0x40 182f9f848faSopenharmony_ci#define EHCI_QTD_BUFERR 0x20 183f9f848faSopenharmony_ci#define EHCI_QTD_BABBLE 0x10 184f9f848faSopenharmony_ci#define EHCI_QTD_XACTERR 0x08 185f9f848faSopenharmony_ci#define EHCI_QTD_MISSEDMICRO 0x04 186f9f848faSopenharmony_ci#define EHCI_QTD_SPLITXSTATE 0x02 187f9f848faSopenharmony_ci#define EHCI_QTD_PINGSTATE 0x01 188f9f848faSopenharmony_ci#define EHCI_QTD_STATERRS 0x74 189f9f848faSopenharmony_ci#define EHCI_QTD_GET_PID(x) (((x) >> 8) & 0x3) 190f9f848faSopenharmony_ci#define EHCI_QTD_SET_PID(x) ((x) << 8) 191f9f848faSopenharmony_ci#define EHCI_QTD_PID_OUT 0x0 192f9f848faSopenharmony_ci#define EHCI_QTD_PID_IN 0x1 193f9f848faSopenharmony_ci#define EHCI_QTD_PID_SETUP 0x2 194f9f848faSopenharmony_ci#define EHCI_QTD_GET_CERR(x) (((x) >> 10) & 0x3) 195f9f848faSopenharmony_ci#define EHCI_QTD_SET_CERR(x) ((x) << 10) 196f9f848faSopenharmony_ci#define EHCI_QTD_GET_C_PAGE(x) (((x) >> 12) & 0x7) 197f9f848faSopenharmony_ci#define EHCI_QTD_SET_C_PAGE(x) ((x) << 12) 198f9f848faSopenharmony_ci#define EHCI_QTD_GET_IOC(x) (((x) >> 15) & 0x1) 199f9f848faSopenharmony_ci#define EHCI_QTD_IOC 0x00008000 200f9f848faSopenharmony_ci#define EHCI_QTD_GET_BYTES(x) (((x) >> 16) & 0x7fff) 201f9f848faSopenharmony_ci#define EHCI_QTD_SET_BYTES(x) ((x) << 16) 202f9f848faSopenharmony_ci#define EHCI_QTD_GET_TOGGLE(x) (((x) >> 31) & 0x1) 203f9f848faSopenharmony_ci#define EHCI_QTD_SET_TOGGLE(x) ((x) << 31) 204f9f848faSopenharmony_ci#define EHCI_QTD_TOGGLE_MASK 0x80000000 205f9f848faSopenharmony_ci#define EHCI_QTD_NBUFFERS 5 206f9f848faSopenharmony_ci#define EHCI_QTD_PAYLOAD_MAX ((EHCI_QTD_NBUFFERS-1)*EHCI_PAGE_SIZE) 207f9f848faSopenharmony_ci volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS]; 208f9f848faSopenharmony_ci volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS]; 209f9f848faSopenharmony_ci/* 210f9f848faSopenharmony_ci * Extra information needed: 211f9f848faSopenharmony_ci */ 212f9f848faSopenharmony_ci struct ehci_qtd *alt_next; 213f9f848faSopenharmony_ci struct ehci_qtd *obj_next; 214f9f848faSopenharmony_ci struct usb_page_cache *page_cache; 215f9f848faSopenharmony_ci uint32_t qtd_self; 216f9f848faSopenharmony_ci uint16_t len; 217f9f848faSopenharmony_ci} __aligned(EHCI_QTD_ALIGN); 218f9f848faSopenharmony_ci 219f9f848faSopenharmony_citypedef struct ehci_qtd ehci_qtd_t; 220f9f848faSopenharmony_ci 221f9f848faSopenharmony_ci/* Queue Head Sub Structure */ 222f9f848faSopenharmony_cistruct ehci_qh_sub { 223f9f848faSopenharmony_ci volatile uint32_t qtd_next; 224f9f848faSopenharmony_ci volatile uint32_t qtd_altnext; 225f9f848faSopenharmony_ci volatile uint32_t qtd_status; 226f9f848faSopenharmony_ci volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS]; 227f9f848faSopenharmony_ci volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS]; 228f9f848faSopenharmony_ci} __aligned(4); 229f9f848faSopenharmony_ci 230f9f848faSopenharmony_ci/* Queue Head */ 231f9f848faSopenharmony_cistruct ehci_qh { 232f9f848faSopenharmony_ci volatile uint32_t qh_link; 233f9f848faSopenharmony_ci volatile uint32_t qh_endp; 234f9f848faSopenharmony_ci#define EHCI_QH_GET_ADDR(x) (((x) >> 0) & 0x7f) /* endpoint addr */ 235f9f848faSopenharmony_ci#define EHCI_QH_SET_ADDR(x) (x) 236f9f848faSopenharmony_ci#define EHCI_QH_ADDRMASK 0x0000007f 237f9f848faSopenharmony_ci#define EHCI_QH_GET_INACT(x) (((x) >> 7) & 0x01) /* inactivate on next */ 238f9f848faSopenharmony_ci#define EHCI_QH_INACT 0x00000080 239f9f848faSopenharmony_ci#define EHCI_QH_GET_ENDPT(x) (((x) >> 8) & 0x0f) /* endpoint no */ 240f9f848faSopenharmony_ci#define EHCI_QH_SET_ENDPT(x) ((x) << 8) 241f9f848faSopenharmony_ci#define EHCI_QH_GET_EPS(x) (((x) >> 12) & 0x03) /* endpoint speed */ 242f9f848faSopenharmony_ci#define EHCI_QH_SET_EPS(x) ((x) << 12) 243f9f848faSopenharmony_ci#define EHCI_QH_SPEED_FULL 0x0 244f9f848faSopenharmony_ci#define EHCI_QH_SPEED_LOW 0x1 245f9f848faSopenharmony_ci#define EHCI_QH_SPEED_HIGH 0x2 246f9f848faSopenharmony_ci#define EHCI_QH_GET_DTC(x) (((x) >> 14) & 0x01) /* data toggle control */ 247f9f848faSopenharmony_ci#define EHCI_QH_DTC 0x00004000 248f9f848faSopenharmony_ci#define EHCI_QH_GET_HRECL(x) (((x) >> 15) & 0x01) /* head of reclamation */ 249f9f848faSopenharmony_ci#define EHCI_QH_HRECL 0x00008000 250f9f848faSopenharmony_ci#define EHCI_QH_GET_MPL(x) (((x) >> 16) & 0x7ff) /* max packet len */ 251f9f848faSopenharmony_ci#define EHCI_QH_SET_MPL(x) ((x) << 16) 252f9f848faSopenharmony_ci#define EHCI_QH_MPLMASK 0x07ff0000 253f9f848faSopenharmony_ci#define EHCI_QH_GET_CTL(x) (((x) >> 27) & 0x01) /* control endpoint */ 254f9f848faSopenharmony_ci#define EHCI_QH_CTL 0x08000000 255f9f848faSopenharmony_ci#define EHCI_QH_GET_NRL(x) (((x) >> 28) & 0x0f) /* NAK reload */ 256f9f848faSopenharmony_ci#define EHCI_QH_SET_NRL(x) ((x) << 28) 257f9f848faSopenharmony_ci volatile uint32_t qh_endphub; 258f9f848faSopenharmony_ci#define EHCI_QH_GET_SMASK(x) (((x) >> 0) & 0xff) /* intr sched mask */ 259f9f848faSopenharmony_ci#define EHCI_QH_SET_SMASK(x) ((x) << 0) 260f9f848faSopenharmony_ci#define EHCI_QH_GET_CMASK(x) (((x) >> 8) & 0xff) /* split completion mask */ 261f9f848faSopenharmony_ci#define EHCI_QH_SET_CMASK(x) ((x) << 8) 262f9f848faSopenharmony_ci#define EHCI_QH_GET_HUBA(x) (((x) >> 16) & 0x7f) /* hub address */ 263f9f848faSopenharmony_ci#define EHCI_QH_SET_HUBA(x) ((x) << 16) 264f9f848faSopenharmony_ci#define EHCI_QH_GET_PORT(x) (((x) >> 23) & 0x7f) /* hub port */ 265f9f848faSopenharmony_ci#define EHCI_QH_SET_PORT(x) ((x) << 23) 266f9f848faSopenharmony_ci#define EHCI_QH_GET_MULT(x) (((x) >> 30) & 0x03) /* pipe multiplier */ 267f9f848faSopenharmony_ci#define EHCI_QH_SET_MULT(x) ((x) << 30) 268f9f848faSopenharmony_ci volatile uint32_t qh_curqtd; 269f9f848faSopenharmony_ci struct ehci_qh_sub qh_qtd; 270f9f848faSopenharmony_ci/* 271f9f848faSopenharmony_ci * Extra information needed: 272f9f848faSopenharmony_ci */ 273f9f848faSopenharmony_ci struct ehci_qh *next; 274f9f848faSopenharmony_ci struct ehci_qh *prev; 275f9f848faSopenharmony_ci struct ehci_qh *obj_next; 276f9f848faSopenharmony_ci struct usb_page_cache *page_cache; 277f9f848faSopenharmony_ci uint32_t qh_self; 278f9f848faSopenharmony_ci} __aligned(EHCI_QH_ALIGN); 279f9f848faSopenharmony_ci 280f9f848faSopenharmony_citypedef struct ehci_qh ehci_qh_t; 281f9f848faSopenharmony_ci 282f9f848faSopenharmony_ci/* Periodic Frame Span Traversal Node */ 283f9f848faSopenharmony_cistruct ehci_fstn { 284f9f848faSopenharmony_ci volatile uint32_t fstn_link; 285f9f848faSopenharmony_ci volatile uint32_t fstn_back; 286f9f848faSopenharmony_ci} __aligned(EHCI_FSTN_ALIGN); 287f9f848faSopenharmony_ci 288f9f848faSopenharmony_citypedef struct ehci_fstn ehci_fstn_t; 289f9f848faSopenharmony_ci 290f9f848faSopenharmony_cistruct ehci_hw_softc { 291f9f848faSopenharmony_ci struct usb_page_cache pframes_pc; 292f9f848faSopenharmony_ci struct usb_page_cache terminate_pc; 293f9f848faSopenharmony_ci struct usb_page_cache async_start_pc; 294f9f848faSopenharmony_ci struct usb_page_cache intr_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; 295f9f848faSopenharmony_ci struct usb_page_cache isoc_hs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; 296f9f848faSopenharmony_ci struct usb_page_cache isoc_fs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; 297f9f848faSopenharmony_ci 298f9f848faSopenharmony_ci struct usb_page pframes_pg; 299f9f848faSopenharmony_ci struct usb_page terminate_pg; 300f9f848faSopenharmony_ci struct usb_page async_start_pg; 301f9f848faSopenharmony_ci struct usb_page intr_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; 302f9f848faSopenharmony_ci struct usb_page isoc_hs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; 303f9f848faSopenharmony_ci struct usb_page isoc_fs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; 304f9f848faSopenharmony_ci}; 305f9f848faSopenharmony_ci 306f9f848faSopenharmony_cistruct ehci_config_desc { 307f9f848faSopenharmony_ci struct usb_config_descriptor confd; 308f9f848faSopenharmony_ci struct usb_interface_descriptor ifcd; 309f9f848faSopenharmony_ci struct usb_endpoint_descriptor endpd; 310f9f848faSopenharmony_ci} __packed; 311f9f848faSopenharmony_ci 312f9f848faSopenharmony_ciunion ehci_hub_desc { 313f9f848faSopenharmony_ci struct usb_status stat; 314f9f848faSopenharmony_ci struct usb_port_status ps; 315f9f848faSopenharmony_ci struct usb_hub_descriptor hubd; 316f9f848faSopenharmony_ci uint8_t temp[128]; 317f9f848faSopenharmony_ci}; 318f9f848faSopenharmony_ci 319f9f848faSopenharmony_citypedef struct ehci_softc { 320f9f848faSopenharmony_ci struct ehci_hw_softc sc_hw; 321f9f848faSopenharmony_ci struct usb_bus sc_bus; /* base device */ 322f9f848faSopenharmony_ci struct usb_callout sc_tmo_pcd; 323f9f848faSopenharmony_ci struct usb_callout sc_tmo_poll; 324f9f848faSopenharmony_ci union ehci_hub_desc sc_hub_desc; 325f9f848faSopenharmony_ci 326f9f848faSopenharmony_ci struct usb_device *sc_devices[EHCI_MAX_DEVICES]; 327f9f848faSopenharmony_ci struct resource *sc_io_res; 328f9f848faSopenharmony_ci struct resource *sc_irq_res; 329f9f848faSopenharmony_ci struct ehci_qh *sc_async_p_last; 330f9f848faSopenharmony_ci struct ehci_qh *sc_intr_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]; 331f9f848faSopenharmony_ci struct ehci_sitd *sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]; 332f9f848faSopenharmony_ci struct ehci_itd *sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]; 333f9f848faSopenharmony_ci void *sc_intr_hdl; 334f9f848faSopenharmony_ci bus_size_t sc_io_size; 335f9f848faSopenharmony_ci bus_space_tag_t sc_io_tag; 336f9f848faSopenharmony_ci bus_space_handle_t sc_io_hdl; 337f9f848faSopenharmony_ci 338f9f848faSopenharmony_ci uint32_t sc_terminate_self; /* TD short packet termination pointer */ 339f9f848faSopenharmony_ci uint32_t sc_eintrs; 340f9f848faSopenharmony_ci 341f9f848faSopenharmony_ci uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT]; 342f9f848faSopenharmony_ci uint16_t sc_id_vendor; /* vendor ID for root hub */ 343f9f848faSopenharmony_ci uint16_t sc_flags; /* chip specific flags */ 344f9f848faSopenharmony_ci#define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */ 345f9f848faSopenharmony_ci#define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */ 346f9f848faSopenharmony_ci#define EHCI_SCFLG_TT 0x0020 /* transaction translator present */ 347f9f848faSopenharmony_ci#define EHCI_SCFLG_LOSTINTRBUG 0x0040 /* workaround for VIA / ATI chipsets */ 348f9f848faSopenharmony_ci#define EHCI_SCFLG_IAADBUG 0x0080 /* workaround for nVidia chipsets */ 349f9f848faSopenharmony_ci#define EHCI_SCFLG_DONTRESET 0x0100 /* don't reset ctrl. in ehci_init() */ 350f9f848faSopenharmony_ci#define EHCI_SCFLG_DONEINIT 0x1000 /* ehci_init() has been called. */ 351f9f848faSopenharmony_ci 352f9f848faSopenharmony_ci uint8_t sc_offs; /* offset to operational registers */ 353f9f848faSopenharmony_ci uint8_t sc_doorbell_disable; /* set on doorbell failure */ 354f9f848faSopenharmony_ci uint8_t sc_noport; 355f9f848faSopenharmony_ci uint8_t sc_addr; /* device address */ 356f9f848faSopenharmony_ci uint8_t sc_conf; /* device configuration */ 357f9f848faSopenharmony_ci uint8_t sc_isreset; 358f9f848faSopenharmony_ci uint8_t sc_hub_idata[8]; 359f9f848faSopenharmony_ci 360f9f848faSopenharmony_ci char sc_vendor[16]; /* vendor string for root hub */ 361f9f848faSopenharmony_ci 362f9f848faSopenharmony_ci void (*sc_vendor_post_reset)(struct ehci_softc *sc); 363f9f848faSopenharmony_ci uint16_t (*sc_vendor_get_port_speed)(struct ehci_softc *sc, 364f9f848faSopenharmony_ci uint16_t index); 365f9f848faSopenharmony_ci 366f9f848faSopenharmony_ci} ehci_softc_t; 367f9f848faSopenharmony_ci 368f9f848faSopenharmony_ci#define EREAD1(sc, a) bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a)) 369f9f848faSopenharmony_ci#define EREAD2(sc, a) bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (a)) 370f9f848faSopenharmony_ci#define EREAD4(sc, a) bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (a)) 371f9f848faSopenharmony_ci#define EWRITE1(sc, a, x) \ 372f9f848faSopenharmony_ci bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x)) 373f9f848faSopenharmony_ci#define EWRITE2(sc, a, x) \ 374f9f848faSopenharmony_ci bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x)) 375f9f848faSopenharmony_ci#define EWRITE4(sc, a, x) \ 376f9f848faSopenharmony_ci bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x)) 377f9f848faSopenharmony_ci#define EOREAD1(sc, a) \ 378f9f848faSopenharmony_ci bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a)) 379f9f848faSopenharmony_ci#define EOREAD2(sc, a) \ 380f9f848faSopenharmony_ci bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a)) 381f9f848faSopenharmony_ci#define EOREAD4(sc, a) \ 382f9f848faSopenharmony_ci bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a)) 383f9f848faSopenharmony_ci#define EOWRITE1(sc, a, x) \ 384f9f848faSopenharmony_ci bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x)) 385f9f848faSopenharmony_ci#define EOWRITE2(sc, a, x) \ 386f9f848faSopenharmony_ci bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x)) 387f9f848faSopenharmony_ci#define EOWRITE4(sc, a, x) \ 388f9f848faSopenharmony_ci bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x)) 389f9f848faSopenharmony_ci 390f9f848faSopenharmony_ci#ifdef USB_EHCI_BIG_ENDIAN_DESC 391f9f848faSopenharmony_ci/* 392f9f848faSopenharmony_ci * Handle byte order conversion between host and ``host controller''. 393f9f848faSopenharmony_ci * Typically the latter is little-endian but some controllers require 394f9f848faSopenharmony_ci * big-endian in which case we may need to manually swap. 395f9f848faSopenharmony_ci */ 396f9f848faSopenharmony_cistatic __inline uint32_t 397f9f848faSopenharmony_cihtohc32(const struct ehci_softc *sc, const uint32_t v) 398f9f848faSopenharmony_ci{ 399f9f848faSopenharmony_ci return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? htobe32(v) : htole32(v); 400f9f848faSopenharmony_ci} 401f9f848faSopenharmony_ci 402f9f848faSopenharmony_cistatic __inline uint16_t 403f9f848faSopenharmony_cihtohc16(const struct ehci_softc *sc, const uint16_t v) 404f9f848faSopenharmony_ci{ 405f9f848faSopenharmony_ci return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? htobe16(v) : htole16(v); 406f9f848faSopenharmony_ci} 407f9f848faSopenharmony_ci 408f9f848faSopenharmony_cistatic __inline uint32_t 409f9f848faSopenharmony_cihc32toh(const struct ehci_softc *sc, const uint32_t v) 410f9f848faSopenharmony_ci{ 411f9f848faSopenharmony_ci return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? be32toh(v) : le32toh(v); 412f9f848faSopenharmony_ci} 413f9f848faSopenharmony_ci 414f9f848faSopenharmony_cistatic __inline uint16_t 415f9f848faSopenharmony_cihc16toh(const struct ehci_softc *sc, const uint16_t v) 416f9f848faSopenharmony_ci{ 417f9f848faSopenharmony_ci return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? be16toh(v) : le16toh(v); 418f9f848faSopenharmony_ci} 419f9f848faSopenharmony_ci#else 420f9f848faSopenharmony_ci/* 421f9f848faSopenharmony_ci * Normal little-endian only conversion routines. 422f9f848faSopenharmony_ci */ 423f9f848faSopenharmony_cistatic __inline uint32_t 424f9f848faSopenharmony_cihtohc32(const struct ehci_softc *sc, const uint32_t v) 425f9f848faSopenharmony_ci{ 426f9f848faSopenharmony_ci return htole32(v); 427f9f848faSopenharmony_ci} 428f9f848faSopenharmony_ci 429f9f848faSopenharmony_cistatic __inline uint16_t 430f9f848faSopenharmony_cihtohc16(const struct ehci_softc *sc, const uint16_t v) 431f9f848faSopenharmony_ci{ 432f9f848faSopenharmony_ci return htole16(v); 433f9f848faSopenharmony_ci} 434f9f848faSopenharmony_ci 435f9f848faSopenharmony_cistatic __inline uint32_t 436f9f848faSopenharmony_cihc32toh(const struct ehci_softc *sc, const uint32_t v) 437f9f848faSopenharmony_ci{ 438f9f848faSopenharmony_ci return le32toh(v); 439f9f848faSopenharmony_ci} 440f9f848faSopenharmony_ci 441f9f848faSopenharmony_cistatic __inline uint16_t 442f9f848faSopenharmony_cihc16toh(const struct ehci_softc *sc, const uint16_t v) 443f9f848faSopenharmony_ci{ 444f9f848faSopenharmony_ci return le16toh(v); 445f9f848faSopenharmony_ci} 446f9f848faSopenharmony_ci#endif 447f9f848faSopenharmony_ci 448f9f848faSopenharmony_ciusb_bus_mem_cb_t ehci_iterate_hw_softc; 449f9f848faSopenharmony_ci 450f9f848faSopenharmony_ciusb_error_t ehci_reset(ehci_softc_t *sc); 451f9f848faSopenharmony_ciusb_error_t ehci_init(ehci_softc_t *sc); 452f9f848faSopenharmony_civoid ehci_detach(struct ehci_softc *sc); 453f9f848faSopenharmony_civoid ehci_interrupt(unsigned int irq, ehci_softc_t *sc); 454f9f848faSopenharmony_ciuint16_t ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index); 455f9f848faSopenharmony_ciuint16_t ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index); 456f9f848faSopenharmony_ci 457f9f848faSopenharmony_ci#endif /* _EHCI_H_ */ 458