1184610Salfred/* $FreeBSD$ */ 2184610Salfred/*- 3189002Sed * Copyright (c) 2007 Hans Petter Selasky <hselasky@FreeBSD.org> 4184610Salfred * All rights reserved. 5184610Salfred * 6184610Salfred * Redistribution and use in source and binary forms, with or without 7184610Salfred * modification, are permitted provided that the following conditions 8184610Salfred * are met: 9184610Salfred * 1. Redistributions of source code must retain the above copyright 10184610Salfred * notice, this list of conditions and the following disclaimer. 11184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 12184610Salfred * notice, this list of conditions and the following disclaimer in the 13184610Salfred * documentation and/or other materials provided with the distribution. 14184610Salfred * 15184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25184610Salfred * SUCH DAMAGE. 26184610Salfred */ 27184610Salfred 28184610Salfred#ifndef _USS820_DCI_H_ 29184610Salfred#define _USS820_DCI_H_ 30184610Salfred 31187170Sthompsa#define USS820_MAX_DEVICES (USB_MIN_DEVICES + 1) 32187170Sthompsa 33184610Salfred#define USS820_EP_MAX 8 /* maximum number of endpoints */ 34184610Salfred 35184610Salfred#define USS820_TXDAT 0x00 /* Transmit FIFO data */ 36184610Salfred 37184610Salfred#define USS820_TXCNTL 0x01 /* Transmit FIFO byte count low */ 38184610Salfred#define USS820_TXCNTL_MASK 0xFF 39184610Salfred 40184610Salfred#define USS820_TXCNTH 0x02 /* Transmit FIFO byte count high */ 41184610Salfred#define USS820_TXCNTH_MASK 0x03 42184610Salfred#define USS820_TXCNTH_UNUSED 0xFC 43184610Salfred 44184610Salfred#define USS820_TXCON 0x03 /* USB transmit FIFO control */ 45184610Salfred#define USS820_TXCON_REVRP 0x01 46184610Salfred#define USS820_TXCON_ADVRM 0x02 47184610Salfred#define USS820_TXCON_ATM 0x04 /* Automatic Transmit Management */ 48184610Salfred#define USS820_TXCON_TXISO 0x08 /* Transmit Isochronous Data */ 49184610Salfred#define USS820_TXCON_UNUSED 0x10 50184610Salfred#define USS820_TXCON_FFSZ_16_64 0x00 51184610Salfred#define USS820_TXCON_FFSZ_64_256 0x20 52184610Salfred#define USS820_TXCON_FFSZ_8_512 0x40 53184610Salfred#define USS820_TXCON_FFSZ_32_1024 0x60 54184610Salfred#define USS820_TXCON_FFSZ_MASK 0x60 55184610Salfred#define USS820_TXCON_TXCLR 0x80 /* Transmit FIFO clear */ 56184610Salfred 57184610Salfred#define USS820_TXFLG 0x04 /* Transmit FIFO flag (Read Only) */ 58184610Salfred#define USS820_TXFLG_TXOVF 0x01 /* TX overrun */ 59184610Salfred#define USS820_TXFLG_TXURF 0x02 /* TX underrun */ 60184610Salfred#define USS820_TXFLG_TXFULL 0x04 /* TX full */ 61184610Salfred#define USS820_TXFLG_TXEMP 0x08 /* TX empty */ 62184610Salfred#define USS820_TXFLG_UNUSED 0x30 63184610Salfred#define USS820_TXFLG_TXFIF0 0x40 64184610Salfred#define USS820_TXFLG_TXFIF1 0x80 65184610Salfred 66184610Salfred#define USS820_RXDAT 0x05 /* Receive FIFO data */ 67184610Salfred 68184610Salfred#define USS820_RXCNTL 0x06 /* Receive FIFO byte count low */ 69184610Salfred#define USS820_RXCNTL_MASK 0xFF 70184610Salfred 71184610Salfred#define USS820_RXCNTH 0x07 /* Receive FIFO byte count high */ 72184610Salfred#define USS820_RXCNTH_MASK 0x03 73184610Salfred#define USS820_RXCNTH_UNUSED 0xFC 74184610Salfred 75184610Salfred#define USS820_RXCON 0x08 /* Receive FIFO control */ 76184610Salfred#define USS820_RXCON_REVWP 0x01 77184610Salfred#define USS820_RXCON_ADVWM 0x02 78184610Salfred#define USS820_RXCON_ARM 0x04 /* Auto Receive Management */ 79184610Salfred#define USS820_RXCON_RXISO 0x08 /* Receive Isochronous Data */ 80184610Salfred#define USS820_RXCON_RXFFRC 0x10 /* FIFO Read Complete */ 81184610Salfred#define USS820_RXCON_FFSZ_16_64 0x00 82184610Salfred#define USS820_RXCON_FFSZ_64_256 0x20 83184610Salfred#define USS820_RXCON_FFSZ_8_512 0x40 84184610Salfred#define USS820_RXCON_FFSZ_32_1024 0x60 85184610Salfred#define USS820_RXCON_RXCLR 0x80 /* Receive FIFO clear */ 86184610Salfred 87184610Salfred#define USS820_RXFLG 0x09 /* Receive FIFO flag (Read Only) */ 88184610Salfred#define USS820_RXFLG_RXOVF 0x01 /* RX overflow */ 89184610Salfred#define USS820_RXFLG_RXURF 0x02 /* RX underflow */ 90184610Salfred#define USS820_RXFLG_RXFULL 0x04 /* RX full */ 91184610Salfred#define USS820_RXFLG_RXEMP 0x08 /* RX empty */ 92184610Salfred#define USS820_RXFLG_RXFLUSH 0x10 /* RX flush */ 93184610Salfred#define USS820_RXFLG_UNUSED 0x20 94184610Salfred#define USS820_RXFLG_RXFIF0 0x40 95184610Salfred#define USS820_RXFLG_RXFIF1 0x80 96184610Salfred 97184610Salfred#define USS820_EPINDEX 0x0a /* Endpoint index selection */ 98184610Salfred#define USS820_EPINDEX_MASK 0x07 99184610Salfred#define USS820_EPINDEX_UNUSED 0xF8 100184610Salfred 101184610Salfred#define USS820_EPCON 0x0b /* Endpoint control */ 102184610Salfred#define USS820_EPCON_TXEPEN 0x01 /* Transmit Endpoint Enable */ 103184610Salfred#define USS820_EPCON_TXOE 0x02 /* Transmit Output Enable */ 104184610Salfred#define USS820_EPCON_RXEPEN 0x04 /* Receive Endpoint Enable */ 105184610Salfred#define USS820_EPCON_RXIE 0x08 /* Receive Input Enable */ 106184610Salfred#define USS820_EPCON_RXSPM 0x10 /* Receive Single-Packet Mode */ 107184610Salfred#define USS820_EPCON_CTLEP 0x20 /* Control Endpoint */ 108184610Salfred#define USS820_EPCON_TXSTL 0x40 /* Stall Transmit Endpoint */ 109184610Salfred#define USS820_EPCON_RXSTL 0x80 /* Stall Receive Endpoint */ 110184610Salfred 111184610Salfred#define USS820_TXSTAT 0x0c /* Transmit status */ 112184610Salfred#define USS820_TXSTAT_TXACK 0x01 /* Transmit Acknowledge */ 113184610Salfred#define USS820_TXSTAT_TXERR 0x02 /* Transmit Error */ 114184610Salfred#define USS820_TXSTAT_TXVOID 0x04 /* Transmit Void */ 115184610Salfred#define USS820_TXSTAT_TXSOVW 0x08 /* Transmit Data Sequence Overwrite 116184610Salfred * Bit */ 117184610Salfred#define USS820_TXSTAT_TXFLUSH 0x10 /* Transmit FIFO Packet Flushed */ 118184610Salfred#define USS820_TXSTAT_TXNAKE 0x20 /* Transmit NAK Mode Enable */ 119184610Salfred#define USS820_TXSTAT_TXDSAM 0x40 /* Transmit Data-Set-Available Mode */ 120184610Salfred#define USS820_TXSTAT_TXSEQ 0x80 /* Transmitter Current Sequence Bit */ 121184610Salfred 122184610Salfred#define USS820_RXSTAT 0x0d /* Receive status */ 123184610Salfred#define USS820_RXSTAT_RXACK 0x01 /* Receive Acknowledge */ 124184610Salfred#define USS820_RXSTAT_RXERR 0x02 /* Receive Error */ 125184610Salfred#define USS820_RXSTAT_RXVOID 0x04 /* Receive Void */ 126184610Salfred#define USS820_RXSTAT_RXSOVW 0x08 /* Receive Data Sequence Overwrite Bit */ 127184610Salfred#define USS820_RXSTAT_EDOVW 0x10 /* End Overwrite Flag */ 128184610Salfred#define USS820_RXSTAT_STOVW 0x20 /* Start Overwrite Flag */ 129184610Salfred#define USS820_RXSTAT_RXSETUP 0x40 /* Received SETUP token */ 130184610Salfred#define USS820_RXSTAT_RXSEQ 0x80 /* Receiver Endpoint Sequence Bit */ 131184610Salfred 132184610Salfred#define USS820_SOFL 0x0e /* Start Of Frame counter low */ 133184610Salfred#define USS820_SOFL_MASK 0xFF 134184610Salfred 135184610Salfred#define USS820_SOFH 0x0f /* Start Of Frame counter high */ 136184610Salfred#define USS820_SOFH_MASK 0x07 137184610Salfred#define USS820_SOFH_SOFDIS 0x08 /* SOF Pin Output Disable */ 138184610Salfred#define USS820_SOFH_FTLOCK 0x10 /* Frame Timer Lock */ 139184610Salfred#define USS820_SOFH_SOFIE 0x20 /* SOF Interrupt Enable */ 140184610Salfred#define USS820_SOFH_ASOF 0x40 /* Any Start of Frame */ 141184610Salfred#define USS820_SOFH_SOFACK 0x80 /* SOF Token Received Without Error */ 142184610Salfred 143184610Salfred#define USS820_FADDR 0x10 /* Function Address */ 144184610Salfred#define USS820_FADDR_MASK 0x7F 145184610Salfred#define USS820_FADDR_UNUSED 0x80 146184610Salfred 147184610Salfred#define USS820_SCR 0x11 /* System Control */ 148184610Salfred#define USS820_SCR_UNUSED 0x01 149184610Salfred#define USS820_SCR_T_IRQ 0x02 /* Global Interrupt Enable */ 150184610Salfred#define USS820_SCR_IRQLVL 0x04 /* Interrupt Mode */ 151184610Salfred#define USS820_SCR_SRESET 0x08 /* Software reset */ 152184610Salfred#define USS820_SCR_IE_RESET 0x10 /* Enable Reset Interrupt */ 153184610Salfred#define USS820_SCR_IE_SUSP 0x20 /* Enable Suspend Interrupt */ 154184610Salfred#define USS820_SCR_RWUPE 0x40 /* Enable Remote Wake-Up Feature */ 155184610Salfred#define USS820_SCR_IRQPOL 0x80 /* IRQ polarity */ 156184610Salfred 157184610Salfred#define USS820_SSR 0x12 /* System Status */ 158184610Salfred#define USS820_SSR_RESET 0x01 /* Reset Condition Detected on USB 159184610Salfred * cable */ 160184610Salfred#define USS820_SSR_SUSPEND 0x02 /* Suspend Detected */ 161184610Salfred#define USS820_SSR_RESUME 0x04 /* Resume Detected */ 162184610Salfred#define USS820_SSR_SUSPDIS 0x08 /* Suspend Disable */ 163184610Salfred#define USS820_SSR_SUSPPO 0x10 /* Suspend Power Off */ 164184610Salfred#define USS820_SSR_UNUSED 0xE0 165184610Salfred 166184610Salfred#define USS820_UNK0 0x13 /* Unknown */ 167184610Salfred#define USS820_UNK0_UNUSED 0xFF 168184610Salfred 169184610Salfred#define USS820_SBI 0x14 /* Serial bus interrupt low */ 170184610Salfred#define USS820_SBI_FTXD0 0x01 /* Function Transmit Done, EP 0 */ 171184610Salfred#define USS820_SBI_FRXD0 0x02 /* Function Receive Done, EP 0 */ 172184610Salfred#define USS820_SBI_FTXD1 0x04 173184610Salfred#define USS820_SBI_FRXD1 0x08 174184610Salfred#define USS820_SBI_FTXD2 0x10 175184610Salfred#define USS820_SBI_FRXD2 0x20 176184610Salfred#define USS820_SBI_FTXD3 0x40 177184610Salfred#define USS820_SBI_FRXD3 0x80 178184610Salfred 179184610Salfred#define USS820_SBI1 0x15 /* Serial bus interrupt high */ 180184610Salfred#define USS820_SBI1_FTXD4 0x01 181184610Salfred#define USS820_SBI1_FRXD4 0x02 182184610Salfred#define USS820_SBI1_FTXD5 0x04 183184610Salfred#define USS820_SBI1_FRXD5 0x08 184184610Salfred#define USS820_SBI1_FTXD6 0x10 185184610Salfred#define USS820_SBI1_FRXD6 0x20 186184610Salfred#define USS820_SBI1_FTXD7 0x40 187184610Salfred#define USS820_SBI1_FRXD7 0x80 188184610Salfred 189184610Salfred#define USS820_SBIE 0x16 /* Serial bus interrupt enable low */ 190184610Salfred#define USS820_SBIE_FTXIE0 0x01 191184610Salfred#define USS820_SBIE_FRXIE0 0x02 192184610Salfred#define USS820_SBIE_FTXIE1 0x04 193184610Salfred#define USS820_SBIE_FRXIE1 0x08 194184610Salfred#define USS820_SBIE_FTXIE2 0x10 195184610Salfred#define USS820_SBIE_FRXIE2 0x20 196184610Salfred#define USS820_SBIE_FTXIE3 0x40 197184610Salfred#define USS820_SBIE_FRXIE3 0x80 198184610Salfred 199184610Salfred#define USS820_SBIE1 0x17 /* Serial bus interrupt enable high */ 200184610Salfred#define USS820_SBIE1_FTXIE4 0x01 201184610Salfred#define USS820_SBIE1_FRXIE4 0x02 202184610Salfred#define USS820_SBIE1_FTXIE5 0x04 203184610Salfred#define USS820_SBIE1_FRXIE5 0x08 204184610Salfred#define USS820_SBIE1_FTXIE6 0x10 205184610Salfred#define USS820_SBIE1_FRXIE6 0x20 206184610Salfred#define USS820_SBIE1_FTXIE7 0x40 207184610Salfred#define USS820_SBIE1_FRXIE7 0x80 208184610Salfred 209184610Salfred#define USS820_REV 0x18 /* Hardware revision */ 210184610Salfred#define USS820_REV_MIN 0x0F 211184610Salfred#define USS820_REV_MAJ 0xF0 212184610Salfred 213184610Salfred#define USS820_LOCK 0x19 /* Suspend power-off locking */ 214184610Salfred#define USS820_LOCK_UNLOCKED 0x01 215184610Salfred#define USS820_LOCK_UNUSED 0xFE 216184610Salfred 217184610Salfred#define USS820_PEND 0x1a /* Pend hardware status update */ 218184610Salfred#define USS820_PEND_PEND 0x01 219184610Salfred#define USS820_PEND_UNUSED 0xFE 220184610Salfred 221184610Salfred#define USS820_SCRATCH 0x1b /* Scratch firmware information */ 222184610Salfred#define USS820_SCRATCH_MASK 0x7F 223184610Salfred#define USS820_SCRATCH_IE_RESUME 0x80 /* Enable Resume Interrupt */ 224184610Salfred 225184610Salfred#define USS820_MCSR 0x1c /* Miscellaneous control and status */ 226184610Salfred#define USS820_MCSR_DPEN 0x01 /* DPLS Pull-Up Enable */ 227184610Salfred#define USS820_MCSR_SUSPLOE 0x02 /* Suspend Lock Out Enable */ 228184610Salfred#define USS820_MCSR_BDFEAT 0x04 /* Board Feature Enable */ 229184610Salfred#define USS820_MCSR_FEAT 0x08 /* Feature Enable */ 230184610Salfred#define USS820_MCSR_PKGID 0x10 /* Package Identification */ 231184610Salfred#define USS820_MCSR_SUSPS 0x20 /* Suspend Status */ 232184610Salfred#define USS820_MCSR_INIT 0x40 /* Device Initialized */ 233184610Salfred#define USS820_MCSR_RWUPR 0x80 /* Remote Wakeup-Up Remember */ 234184610Salfred 235184610Salfred#define USS820_DSAV 0x1d /* Data set available low (Read Only) */ 236184610Salfred#define USS820_DSAV_TXAV0 0x01 237184610Salfred#define USS820_DSAV_RXAV0 0x02 238184610Salfred#define USS820_DSAV_TXAV1 0x04 239184610Salfred#define USS820_DSAV_RXAV1 0x08 240184610Salfred#define USS820_DSAV_TXAV2 0x10 241184610Salfred#define USS820_DSAV_RXAV2 0x20 242184610Salfred#define USS820_DSAV_TXAV3 0x40 243184610Salfred#define USS820_DSAV_RXAV3 0x80 244184610Salfred 245184610Salfred#define USS820_DSAV1 0x1e /* Data set available high */ 246184610Salfred#define USS820_DSAV1_TXAV4 0x01 247184610Salfred#define USS820_DSAV1_RXAV4 0x02 248184610Salfred#define USS820_DSAV1_TXAV5 0x04 249184610Salfred#define USS820_DSAV1_RXAV5 0x08 250184610Salfred#define USS820_DSAV1_TXAV6 0x10 251184610Salfred#define USS820_DSAV1_RXAV6 0x20 252184610Salfred#define USS820_DSAV1_TXAV7 0x40 253184610Salfred#define USS820_DSAV1_RXAV7 0x80 254184610Salfred 255184610Salfred#define USS820_UNK1 0x1f /* Unknown */ 256184610Salfred#define USS820_UNK1_UNKNOWN 0xFF 257184610Salfred 258184610Salfred#define USS820_READ_1(sc, reg) \ 259192448Sthompsa bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg) 260184610Salfred 261184610Salfred#define USS820_WRITE_1(sc, reg, data) \ 262192448Sthompsa bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data) 263184610Salfred 264184610Salfredstruct uss820dci_td; 265184610Salfred 266184610Salfredtypedef uint8_t (uss820dci_cmd_t)(struct uss820dci_td *td); 267184610Salfred 268184610Salfredstruct uss820dci_td { 269184610Salfred bus_space_tag_t io_tag; 270184610Salfred bus_space_handle_t io_hdl; 271184610Salfred struct uss820dci_td *obj_next; 272184610Salfred uss820dci_cmd_t *func; 273192984Sthompsa struct usb_page_cache *pc; 274184610Salfred uint32_t offset; 275184610Salfred uint32_t remainder; 276184610Salfred uint16_t max_packet_size; 277184610Salfred uint8_t ep_index; 278184610Salfred uint8_t error:1; 279184610Salfred uint8_t alt_next:1; 280184610Salfred uint8_t short_pkt:1; 281184610Salfred uint8_t support_multi_buffer:1; 282184610Salfred uint8_t did_stall:1; 283192552Sthompsa uint8_t did_enable:1; 284184610Salfred}; 285184610Salfred 286184610Salfredstruct uss820_std_temp { 287184610Salfred uss820dci_cmd_t *func; 288192984Sthompsa struct usb_page_cache *pc; 289184610Salfred struct uss820dci_td *td; 290184610Salfred struct uss820dci_td *td_next; 291184610Salfred uint32_t len; 292184610Salfred uint32_t offset; 293184610Salfred uint16_t max_frame_size; 294184610Salfred uint8_t short_pkt; 295184610Salfred /* 296184610Salfred * short_pkt = 0: transfer should be short terminated 297184610Salfred * short_pkt = 1: transfer should not be short terminated 298184610Salfred */ 299184610Salfred uint8_t setup_alt_next; 300192552Sthompsa uint8_t did_stall; 301184610Salfred}; 302184610Salfred 303184610Salfredstruct uss820dci_config_desc { 304192984Sthompsa struct usb_config_descriptor confd; 305192984Sthompsa struct usb_interface_descriptor ifcd; 306192984Sthompsa struct usb_endpoint_descriptor endpd; 307184610Salfred} __packed; 308184610Salfred 309184610Salfredunion uss820_hub_temp { 310184610Salfred uWord wValue; 311192984Sthompsa struct usb_port_status ps; 312184610Salfred}; 313184610Salfred 314184610Salfredstruct uss820_flags { 315184610Salfred uint8_t change_connect:1; 316184610Salfred uint8_t change_suspend:1; 317184610Salfred uint8_t status_suspend:1; /* set if suspended */ 318184610Salfred uint8_t status_vbus:1; /* set if present */ 319184610Salfred uint8_t status_bus_reset:1; /* set if reset complete */ 320184610Salfred uint8_t clocks_off:1; 321184610Salfred uint8_t port_powered:1; 322184610Salfred uint8_t port_enabled:1; 323184610Salfred uint8_t d_pulled_up:1; 324184610Salfred uint8_t mcsr_feat:1; 325184610Salfred}; 326184610Salfred 327184610Salfredstruct uss820dci_softc { 328192984Sthompsa struct usb_bus sc_bus; 329184610Salfred union uss820_hub_temp sc_hub_temp; 330184610Salfred 331192984Sthompsa struct usb_device *sc_devices[USS820_MAX_DEVICES]; 332184610Salfred struct resource *sc_io_res; 333184610Salfred struct resource *sc_irq_res; 334184610Salfred void *sc_intr_hdl; 335184610Salfred bus_size_t sc_io_size; 336184610Salfred bus_space_tag_t sc_io_tag; 337184610Salfred bus_space_handle_t sc_io_hdl; 338184610Salfred 339184610Salfred uint8_t sc_rt_addr; /* root HUB address */ 340184610Salfred uint8_t sc_dv_addr; /* device address */ 341184610Salfred uint8_t sc_conf; /* root HUB config */ 342184610Salfred 343184610Salfred uint8_t sc_hub_idata[1]; 344184610Salfred 345184610Salfred struct uss820_flags sc_flags; 346184610Salfred}; 347184610Salfred 348184610Salfred/* prototypes */ 349184610Salfred 350193045Sthompsausb_error_t uss820dci_init(struct uss820dci_softc *sc); 351184610Salfredvoid uss820dci_uninit(struct uss820dci_softc *sc); 352184610Salfredvoid uss820dci_interrupt(struct uss820dci_softc *sc); 353184610Salfred 354184610Salfred#endif /* _USS820_DCI_H_ */ 355