102ac6454SAndrew Thompson /* $FreeBSD$ */ 202ac6454SAndrew Thompson /*- 302ac6454SAndrew Thompson * Copyright (c) 2009 Hans Petter Selasky. All rights reserved. 402ac6454SAndrew Thompson * 502ac6454SAndrew Thompson * Redistribution and use in source and binary forms, with or without 602ac6454SAndrew Thompson * modification, are permitted provided that the following conditions 702ac6454SAndrew Thompson * are met: 802ac6454SAndrew Thompson * 1. Redistributions of source code must retain the above copyright 902ac6454SAndrew Thompson * notice, this list of conditions and the following disclaimer. 1002ac6454SAndrew Thompson * 2. Redistributions in binary form must reproduce the above copyright 1102ac6454SAndrew Thompson * notice, this list of conditions and the following disclaimer in the 1202ac6454SAndrew Thompson * documentation and/or other materials provided with the distribution. 1302ac6454SAndrew Thompson * 1402ac6454SAndrew Thompson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1502ac6454SAndrew Thompson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1602ac6454SAndrew Thompson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1702ac6454SAndrew Thompson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1802ac6454SAndrew Thompson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1902ac6454SAndrew Thompson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2002ac6454SAndrew Thompson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2102ac6454SAndrew Thompson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2202ac6454SAndrew Thompson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2302ac6454SAndrew Thompson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2402ac6454SAndrew Thompson * SUCH DAMAGE. 2502ac6454SAndrew Thompson */ 2602ac6454SAndrew Thompson 2702ac6454SAndrew Thompson /* 28fde87526SAndrew Thompson * USB Device Port register definitions, copied from ATMEGA documentation 29fde87526SAndrew Thompson * provided by ATMEL. 3002ac6454SAndrew Thompson */ 3102ac6454SAndrew Thompson 3202ac6454SAndrew Thompson #ifndef _ATMEGADCI_H_ 3302ac6454SAndrew Thompson #define _ATMEGADCI_H_ 3402ac6454SAndrew Thompson 3502ac6454SAndrew Thompson #define ATMEGA_MAX_DEVICES (USB_MIN_DEVICES + 1) 3602ac6454SAndrew Thompson 377eaa41aeSAndrew Thompson #define ATMEGA_OTGTCON 0xF9 387eaa41aeSAndrew Thompson #define ATMEGA_OTGTCON_VALUE(x) ((x) << 0) 397eaa41aeSAndrew Thompson #define ATMEGA_OTGTCON_PAGE(x) ((x) << 5) 407eaa41aeSAndrew Thompson 4102ac6454SAndrew Thompson #define ATMEGA_UEINT 0xF4 4202ac6454SAndrew Thompson #define ATMEGA_UEINT_MASK(n) (1 << (n)) /* endpoint interrupt mask */ 4302ac6454SAndrew Thompson 4402ac6454SAndrew Thompson #define ATMEGA_UEBCHX 0xF3 /* FIFO byte count high */ 4502ac6454SAndrew Thompson #define ATMEGA_UEBCLX 0xF2 /* FIFO byte count low */ 4602ac6454SAndrew Thompson #define ATMEGA_UEDATX 0xF1 /* FIFO data */ 4702ac6454SAndrew Thompson 4802ac6454SAndrew Thompson #define ATMEGA_UEIENX 0xF0 /* interrupt enable register */ 4902ac6454SAndrew Thompson #define ATMEGA_UEIENX_TXINE (1 << 0) 5002ac6454SAndrew Thompson #define ATMEGA_UEIENX_STALLEDE (1 << 1) 5102ac6454SAndrew Thompson #define ATMEGA_UEIENX_RXOUTE (1 << 2) 5202ac6454SAndrew Thompson #define ATMEGA_UEIENX_RXSTPE (1 << 3) /* received SETUP packet */ 5302ac6454SAndrew Thompson #define ATMEGA_UEIENX_NAKOUTE (1 << 4) 5402ac6454SAndrew Thompson #define ATMEGA_UEIENX_NAKINE (1 << 6) 5502ac6454SAndrew Thompson #define ATMEGA_UEIENX_FLERRE (1 << 7) 5602ac6454SAndrew Thompson 5702ac6454SAndrew Thompson #define ATMEGA_UESTA1X 0xEF 5802ac6454SAndrew Thompson #define ATMEGA_UESTA1X_CURRBK (3 << 0) /* current bank */ 5902ac6454SAndrew Thompson #define ATMEGA_UESTA1X_CTRLDIR (1 << 2) /* control endpoint direction */ 6002ac6454SAndrew Thompson 6102ac6454SAndrew Thompson #define ATMEGA_UESTA0X 0xEE 6202ac6454SAndrew Thompson #define ATMEGA_UESTA0X_NBUSYBK (3 << 0) 6302ac6454SAndrew Thompson #define ATMEGA_UESTA0X_DTSEQ (3 << 2) 6402ac6454SAndrew Thompson #define ATMEGA_UESTA0X_UNDERFI (1 << 5) /* underflow */ 6502ac6454SAndrew Thompson #define ATMEGA_UESTA0X_OVERFI (1 << 6) /* overflow */ 6602ac6454SAndrew Thompson #define ATMEGA_UESTA0X_CFGOK (1 << 7) 6702ac6454SAndrew Thompson 6802ac6454SAndrew Thompson #define ATMEGA_UECFG1X 0xED /* endpoint config register */ 6902ac6454SAndrew Thompson #define ATMEGA_UECFG1X_ALLOC (1 << 1) 7002ac6454SAndrew Thompson #define ATMEGA_UECFG1X_EPBK0 (0 << 2) 7102ac6454SAndrew Thompson #define ATMEGA_UECFG1X_EPBK1 (1 << 2) 7202ac6454SAndrew Thompson #define ATMEGA_UECFG1X_EPBK2 (2 << 2) 7302ac6454SAndrew Thompson #define ATMEGA_UECFG1X_EPBK3 (3 << 2) 7402ac6454SAndrew Thompson #define ATMEGA_UECFG1X_EPSIZE(n) ((n) << 4) 7502ac6454SAndrew Thompson 7602ac6454SAndrew Thompson #define ATMEGA_UECFG0X 0xEC 7702ac6454SAndrew Thompson #define ATMEGA_UECFG0X_EPDIR (1 << 0) /* endpoint direction */ 7802ac6454SAndrew Thompson #define ATMEGA_UECFG0X_EPTYPE0 (0 << 6) 7902ac6454SAndrew Thompson #define ATMEGA_UECFG0X_EPTYPE1 (1 << 6) 8002ac6454SAndrew Thompson #define ATMEGA_UECFG0X_EPTYPE2 (2 << 6) 8102ac6454SAndrew Thompson #define ATMEGA_UECFG0X_EPTYPE3 (3 << 6) 8202ac6454SAndrew Thompson 8302ac6454SAndrew Thompson #define ATMEGA_UECONX 0xEB 8402ac6454SAndrew Thompson #define ATMEGA_UECONX_EPEN (1 << 0) 8502ac6454SAndrew Thompson #define ATMEGA_UECONX_RSTDT (1 << 3) 8602ac6454SAndrew Thompson #define ATMEGA_UECONX_STALLRQC (1 << 4) /* stall request clear */ 8702ac6454SAndrew Thompson #define ATMEGA_UECONX_STALLRQ (1 << 5) /* stall request set */ 8802ac6454SAndrew Thompson 8902ac6454SAndrew Thompson #define ATMEGA_UERST 0xEA /* endpoint reset register */ 9002ac6454SAndrew Thompson #define ATMEGA_UERST_MASK(n) (1 << (n)) 9102ac6454SAndrew Thompson 9202ac6454SAndrew Thompson #define ATMEGA_UENUM 0xE9 /* endpoint number */ 9302ac6454SAndrew Thompson 9402ac6454SAndrew Thompson #define ATMEGA_UEINTX 0xE8 /* interrupt register */ 9502ac6454SAndrew Thompson #define ATMEGA_UEINTX_TXINI (1 << 0) 9602ac6454SAndrew Thompson #define ATMEGA_UEINTX_STALLEDI (1 << 1) 9702ac6454SAndrew Thompson #define ATMEGA_UEINTX_RXOUTI (1 << 2) 9802ac6454SAndrew Thompson #define ATMEGA_UEINTX_RXSTPI (1 << 3) /* received setup packet */ 9902ac6454SAndrew Thompson #define ATMEGA_UEINTX_NAKOUTI (1 << 4) 10002ac6454SAndrew Thompson #define ATMEGA_UEINTX_RWAL (1 << 5) 10102ac6454SAndrew Thompson #define ATMEGA_UEINTX_NAKINI (1 << 6) 10202ac6454SAndrew Thompson #define ATMEGA_UEINTX_FIFOCON (1 << 7) 10302ac6454SAndrew Thompson 10402ac6454SAndrew Thompson #define ATMEGA_UDMFN 0xE6 10502ac6454SAndrew Thompson #define ATMEGA_UDMFN_FNCERR (1 << 4) 10602ac6454SAndrew Thompson 10702ac6454SAndrew Thompson #define ATMEGA_UDFNUMH 0xE5 /* frame number high */ 10802ac6454SAndrew Thompson #define ATMEGA_UDFNUMH_MASK 7 10902ac6454SAndrew Thompson 11002ac6454SAndrew Thompson #define ATMEGA_UDFNUML 0xE4 /* frame number low */ 11102ac6454SAndrew Thompson #define ATMEGA_UDFNUML_MASK 0xFF 11202ac6454SAndrew Thompson 11302ac6454SAndrew Thompson #define ATMEGA_FRAME_MASK 0x7FF 11402ac6454SAndrew Thompson 11502ac6454SAndrew Thompson #define ATMEGA_UDADDR 0xE3 /* USB address */ 11602ac6454SAndrew Thompson #define ATMEGA_UDADDR_MASK 0x7F 11702ac6454SAndrew Thompson #define ATMEGA_UDADDR_ADDEN (1 << 7) 11802ac6454SAndrew Thompson 11902ac6454SAndrew Thompson #define ATMEGA_UDIEN 0xE2 /* USB device interrupt enable */ 12002ac6454SAndrew Thompson #define ATMEGA_UDINT_SUSPE (1 << 0) 12102ac6454SAndrew Thompson #define ATMEGA_UDINT_MSOFE (1 << 1) 12202ac6454SAndrew Thompson #define ATMEGA_UDINT_SOFE (1 << 2) 12302ac6454SAndrew Thompson #define ATMEGA_UDINT_EORSTE (1 << 3) 12402ac6454SAndrew Thompson #define ATMEGA_UDINT_WAKEUPE (1 << 4) 12502ac6454SAndrew Thompson #define ATMEGA_UDINT_EORSME (1 << 5) 12602ac6454SAndrew Thompson #define ATMEGA_UDINT_UPRSME (1 << 6) 12702ac6454SAndrew Thompson 12802ac6454SAndrew Thompson #define ATMEGA_UDINT 0xE1 /* USB device interrupt status */ 12902ac6454SAndrew Thompson #define ATMEGA_UDINT_SUSPI (1 << 0) 13002ac6454SAndrew Thompson #define ATMEGA_UDINT_MSOFI (1 << 1) 13102ac6454SAndrew Thompson #define ATMEGA_UDINT_SOFI (1 << 2) 13202ac6454SAndrew Thompson #define ATMEGA_UDINT_EORSTI (1 << 3) 13302ac6454SAndrew Thompson #define ATMEGA_UDINT_WAKEUPI (1 << 4) 13402ac6454SAndrew Thompson #define ATMEGA_UDINT_EORSMI (1 << 5) 13502ac6454SAndrew Thompson #define ATMEGA_UDINT_UPRSMI (1 << 6) 13602ac6454SAndrew Thompson 13702ac6454SAndrew Thompson #define ATMEGA_UDCON 0xE0 /* USB device connection register */ 13802ac6454SAndrew Thompson #define ATMEGA_UDCON_DETACH (1 << 0) 13902ac6454SAndrew Thompson #define ATMEGA_UDCON_RMWKUP (1 << 1) 14002ac6454SAndrew Thompson #define ATMEGA_UDCON_LSM (1 << 2) 14102ac6454SAndrew Thompson #define ATMEGA_UDCON_RSTCPU (1 << 3) 14202ac6454SAndrew Thompson 1437eaa41aeSAndrew Thompson #define ATMEGA_OTGINT 0xDF 1447eaa41aeSAndrew Thompson 1457eaa41aeSAndrew Thompson #define ATMEGA_OTGCON 0xDD 1467eaa41aeSAndrew Thompson #define ATMEGA_OTGCON_VBUSRQC (1 << 0) 1477eaa41aeSAndrew Thompson #define ATMEGA_OTGCON_VBUSREQ (1 << 1) 1487eaa41aeSAndrew Thompson #define ATMEGA_OTGCON_VBUSHWC (1 << 2) 1497eaa41aeSAndrew Thompson #define ATMEGA_OTGCON_SRPSEL (1 << 3) 1507eaa41aeSAndrew Thompson #define ATMEGA_OTGCON_SRPREQ (1 << 4) 1517eaa41aeSAndrew Thompson #define ATMEGA_OTGCON_HNPREQ (1 << 5) 1527eaa41aeSAndrew Thompson 15302ac6454SAndrew Thompson #define ATMEGA_USBINT 0xDA 15402ac6454SAndrew Thompson #define ATMEGA_USBINT_VBUSTI (1 << 0) /* USB VBUS interrupt */ 1557eaa41aeSAndrew Thompson #define ATMEGA_USBINT_IDI (1 << 1) /* USB ID interrupt */ 15602ac6454SAndrew Thompson 15702ac6454SAndrew Thompson #define ATMEGA_USBSTA 0xD9 15802ac6454SAndrew Thompson #define ATMEGA_USBSTA_VBUS (1 << 0) 15902ac6454SAndrew Thompson #define ATMEGA_USBSTA_ID (1 << 1) 16002ac6454SAndrew Thompson 16102ac6454SAndrew Thompson #define ATMEGA_USBCON 0xD8 16202ac6454SAndrew Thompson #define ATMEGA_USBCON_VBUSTE (1 << 0) 1637eaa41aeSAndrew Thompson #define ATMEGA_USBCON_IDE (1 << 1) 16402ac6454SAndrew Thompson #define ATMEGA_USBCON_OTGPADE (1 << 4) 16502ac6454SAndrew Thompson #define ATMEGA_USBCON_FRZCLK (1 << 5) 16602ac6454SAndrew Thompson #define ATMEGA_USBCON_USBE (1 << 7) 16702ac6454SAndrew Thompson 16802ac6454SAndrew Thompson #define ATMEGA_UHWCON 0xD7 16902ac6454SAndrew Thompson #define ATMEGA_UHWCON_UVREGE (1 << 0) 170d59dbd0aSAndrew Thompson #define ATMEGA_UHWCON_UVCONE (1 << 4) 171d59dbd0aSAndrew Thompson #define ATMEGA_UHWCON_UIDE (1 << 6) 172d59dbd0aSAndrew Thompson #define ATMEGA_UHWCON_UIMOD (1 << 7) 17302ac6454SAndrew Thompson 17402ac6454SAndrew Thompson #define ATMEGA_READ_1(sc, reg) \ 17502ac6454SAndrew Thompson bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg) 17602ac6454SAndrew Thompson 17702ac6454SAndrew Thompson #define ATMEGA_WRITE_1(sc, reg, data) \ 17802ac6454SAndrew Thompson bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data) 17902ac6454SAndrew Thompson 18002ac6454SAndrew Thompson #define ATMEGA_WRITE_MULTI_1(sc, reg, ptr, len) \ 18102ac6454SAndrew Thompson bus_space_write_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len) 18202ac6454SAndrew Thompson 18302ac6454SAndrew Thompson #define ATMEGA_READ_MULTI_1(sc, reg, ptr, len) \ 18402ac6454SAndrew Thompson bus_space_read_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len) 18502ac6454SAndrew Thompson 18602ac6454SAndrew Thompson /* 18702ac6454SAndrew Thompson * Maximum number of endpoints supported: 18802ac6454SAndrew Thompson */ 18902ac6454SAndrew Thompson #define ATMEGA_EP_MAX 7 19002ac6454SAndrew Thompson 19102ac6454SAndrew Thompson struct atmegadci_td; 19202ac6454SAndrew Thompson 19302ac6454SAndrew Thompson typedef uint8_t (atmegadci_cmd_t)(struct atmegadci_td *td); 19402ac6454SAndrew Thompson typedef void (atmegadci_clocks_t)(struct usb2_bus *); 19502ac6454SAndrew Thompson 19602ac6454SAndrew Thompson struct atmegadci_td { 19702ac6454SAndrew Thompson struct atmegadci_td *obj_next; 19802ac6454SAndrew Thompson atmegadci_cmd_t *func; 19902ac6454SAndrew Thompson struct usb2_page_cache *pc; 20002ac6454SAndrew Thompson uint32_t offset; 20102ac6454SAndrew Thompson uint32_t remainder; 20202ac6454SAndrew Thompson uint16_t max_packet_size; 20302ac6454SAndrew Thompson uint8_t error:1; 20402ac6454SAndrew Thompson uint8_t alt_next:1; 20502ac6454SAndrew Thompson uint8_t short_pkt:1; 20602ac6454SAndrew Thompson uint8_t support_multi_buffer:1; 20702ac6454SAndrew Thompson uint8_t did_stall:1; 20802ac6454SAndrew Thompson uint8_t ep_no:3; 20902ac6454SAndrew Thompson }; 21002ac6454SAndrew Thompson 21102ac6454SAndrew Thompson struct atmegadci_std_temp { 21202ac6454SAndrew Thompson atmegadci_cmd_t *func; 21302ac6454SAndrew Thompson struct usb2_page_cache *pc; 21402ac6454SAndrew Thompson struct atmegadci_td *td; 21502ac6454SAndrew Thompson struct atmegadci_td *td_next; 21602ac6454SAndrew Thompson uint32_t len; 21702ac6454SAndrew Thompson uint32_t offset; 21802ac6454SAndrew Thompson uint16_t max_frame_size; 21902ac6454SAndrew Thompson uint8_t short_pkt; 22002ac6454SAndrew Thompson /* 22102ac6454SAndrew Thompson * short_pkt = 0: transfer should be short terminated 22202ac6454SAndrew Thompson * short_pkt = 1: transfer should not be short terminated 22302ac6454SAndrew Thompson */ 22402ac6454SAndrew Thompson uint8_t setup_alt_next; 22502ac6454SAndrew Thompson }; 22602ac6454SAndrew Thompson 22702ac6454SAndrew Thompson struct atmegadci_config_desc { 22802ac6454SAndrew Thompson struct usb2_config_descriptor confd; 22902ac6454SAndrew Thompson struct usb2_interface_descriptor ifcd; 23002ac6454SAndrew Thompson struct usb2_endpoint_descriptor endpd; 23102ac6454SAndrew Thompson } __packed; 23202ac6454SAndrew Thompson 23302ac6454SAndrew Thompson union atmegadci_hub_temp { 23402ac6454SAndrew Thompson uWord wValue; 23502ac6454SAndrew Thompson struct usb2_port_status ps; 23602ac6454SAndrew Thompson }; 23702ac6454SAndrew Thompson 23802ac6454SAndrew Thompson struct atmegadci_flags { 23902ac6454SAndrew Thompson uint8_t change_connect:1; 24002ac6454SAndrew Thompson uint8_t change_suspend:1; 24102ac6454SAndrew Thompson uint8_t status_suspend:1; /* set if suspended */ 24202ac6454SAndrew Thompson uint8_t status_vbus:1; /* set if present */ 24302ac6454SAndrew Thompson uint8_t status_bus_reset:1; /* set if reset complete */ 24402ac6454SAndrew Thompson uint8_t remote_wakeup:1; 24502ac6454SAndrew Thompson uint8_t self_powered:1; 24602ac6454SAndrew Thompson uint8_t clocks_off:1; 24702ac6454SAndrew Thompson uint8_t port_powered:1; 24802ac6454SAndrew Thompson uint8_t port_enabled:1; 24902ac6454SAndrew Thompson uint8_t d_pulled_up:1; 25002ac6454SAndrew Thompson }; 25102ac6454SAndrew Thompson 25202ac6454SAndrew Thompson struct atmegadci_softc { 25302ac6454SAndrew Thompson struct usb2_bus sc_bus; 25402ac6454SAndrew Thompson union atmegadci_hub_temp sc_hub_temp; 25502ac6454SAndrew Thompson 25602ac6454SAndrew Thompson /* must be set by by the bus interface layer */ 25702ac6454SAndrew Thompson atmegadci_clocks_t *sc_clocks_on; 25802ac6454SAndrew Thompson atmegadci_clocks_t *sc_clocks_off; 25902ac6454SAndrew Thompson 26002ac6454SAndrew Thompson struct usb2_device *sc_devices[ATMEGA_MAX_DEVICES]; 26102ac6454SAndrew Thompson struct resource *sc_irq_res; 26202ac6454SAndrew Thompson void *sc_intr_hdl; 26302ac6454SAndrew Thompson struct resource *sc_io_res; 26402ac6454SAndrew Thompson bus_space_tag_t sc_io_tag; 26502ac6454SAndrew Thompson bus_space_handle_t sc_io_hdl; 26639307315SAndrew Thompson 26702ac6454SAndrew Thompson uint8_t sc_rt_addr; /* root hub address */ 26802ac6454SAndrew Thompson uint8_t sc_dv_addr; /* device address */ 26902ac6454SAndrew Thompson uint8_t sc_conf; /* root hub config */ 27002ac6454SAndrew Thompson 27102ac6454SAndrew Thompson uint8_t sc_hub_idata[1]; 27202ac6454SAndrew Thompson 27302ac6454SAndrew Thompson struct atmegadci_flags sc_flags; 27402ac6454SAndrew Thompson }; 27502ac6454SAndrew Thompson 27602ac6454SAndrew Thompson /* prototypes */ 27702ac6454SAndrew Thompson 27802ac6454SAndrew Thompson usb2_error_t atmegadci_init(struct atmegadci_softc *sc); 27902ac6454SAndrew Thompson void atmegadci_uninit(struct atmegadci_softc *sc); 28002ac6454SAndrew Thompson void atmegadci_suspend(struct atmegadci_softc *sc); 28102ac6454SAndrew Thompson void atmegadci_resume(struct atmegadci_softc *sc); 28202ac6454SAndrew Thompson void atmegadci_interrupt(struct atmegadci_softc *sc); 28302ac6454SAndrew Thompson 28402ac6454SAndrew Thompson #endif /* _ATMEGADCI_H_ */ 285