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 /* 2802ac6454SAndrew Thompson * USB Device Port register definitions, copied from ATMEGA 2902ac6454SAndrew Thompson * documentation 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 3702ac6454SAndrew Thompson #ifndef ATMEGA_HAVE_BUS_SPACE 3802ac6454SAndrew Thompson #define ATMEGA_HAVE_BUS_SPACE 1 3902ac6454SAndrew Thompson #endif 4002ac6454SAndrew 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 14302ac6454SAndrew Thompson #define ATMEGA_USBINT 0xDA 14402ac6454SAndrew Thompson #define ATMEGA_USBINT_VBUSTI (1 << 0) /* USB VBUS interrupt */ 14502ac6454SAndrew Thompson 14602ac6454SAndrew Thompson #define ATMEGA_USBSTA 0xD9 14702ac6454SAndrew Thompson #define ATMEGA_USBSTA_VBUS (1 << 0) 14802ac6454SAndrew Thompson #define ATMEGA_USBSTA_ID (1 << 1) 14902ac6454SAndrew Thompson 15002ac6454SAndrew Thompson #define ATMEGA_USBCON 0xD8 15102ac6454SAndrew Thompson #define ATMEGA_USBCON_VBUSTE (1 << 0) 15202ac6454SAndrew Thompson #define ATMEGA_USBCON_OTGPADE (1 << 4) 15302ac6454SAndrew Thompson #define ATMEGA_USBCON_FRZCLK (1 << 5) 15402ac6454SAndrew Thompson #define ATMEGA_USBCON_USBE (1 << 7) 15502ac6454SAndrew Thompson 15602ac6454SAndrew Thompson #define ATMEGA_UHWCON 0xD7 15702ac6454SAndrew Thompson #define ATMEGA_UHWCON_UVREGE (1 << 0) 158d59dbd0aSAndrew Thompson #define ATMEGA_UHWCON_UVCONE (1 << 4) 159d59dbd0aSAndrew Thompson #define ATMEGA_UHWCON_UIDE (1 << 6) 160d59dbd0aSAndrew Thompson #define ATMEGA_UHWCON_UIMOD (1 << 7) 16102ac6454SAndrew Thompson 16202ac6454SAndrew Thompson #define ATMEGA_READ_1(sc, reg) \ 16302ac6454SAndrew Thompson bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg) 16402ac6454SAndrew Thompson 16502ac6454SAndrew Thompson #define ATMEGA_WRITE_1(sc, reg, data) \ 16602ac6454SAndrew Thompson bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data) 16702ac6454SAndrew Thompson 16802ac6454SAndrew Thompson #define ATMEGA_WRITE_MULTI_1(sc, reg, ptr, len) \ 16902ac6454SAndrew Thompson bus_space_write_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len) 17002ac6454SAndrew Thompson 17102ac6454SAndrew Thompson #define ATMEGA_READ_MULTI_1(sc, reg, ptr, len) \ 17202ac6454SAndrew Thompson bus_space_read_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len) 17302ac6454SAndrew Thompson 17402ac6454SAndrew Thompson /* 17502ac6454SAndrew Thompson * Maximum number of endpoints supported: 17602ac6454SAndrew Thompson */ 17702ac6454SAndrew Thompson #define ATMEGA_EP_MAX 7 17802ac6454SAndrew Thompson 17902ac6454SAndrew Thompson struct atmegadci_td; 18002ac6454SAndrew Thompson 18102ac6454SAndrew Thompson typedef uint8_t (atmegadci_cmd_t)(struct atmegadci_td *td); 18202ac6454SAndrew Thompson typedef void (atmegadci_clocks_t)(struct usb2_bus *); 18302ac6454SAndrew Thompson 18402ac6454SAndrew Thompson struct atmegadci_td { 18502ac6454SAndrew Thompson struct atmegadci_td *obj_next; 18602ac6454SAndrew Thompson atmegadci_cmd_t *func; 18702ac6454SAndrew Thompson struct usb2_page_cache *pc; 18802ac6454SAndrew Thompson uint32_t offset; 18902ac6454SAndrew Thompson uint32_t remainder; 19002ac6454SAndrew Thompson uint16_t max_packet_size; 19102ac6454SAndrew Thompson uint8_t error:1; 19202ac6454SAndrew Thompson uint8_t alt_next:1; 19302ac6454SAndrew Thompson uint8_t short_pkt:1; 19402ac6454SAndrew Thompson uint8_t support_multi_buffer:1; 19502ac6454SAndrew Thompson uint8_t did_stall:1; 19602ac6454SAndrew Thompson uint8_t ep_no:3; 19702ac6454SAndrew Thompson }; 19802ac6454SAndrew Thompson 19902ac6454SAndrew Thompson struct atmegadci_std_temp { 20002ac6454SAndrew Thompson atmegadci_cmd_t *func; 20102ac6454SAndrew Thompson struct usb2_page_cache *pc; 20202ac6454SAndrew Thompson struct atmegadci_td *td; 20302ac6454SAndrew Thompson struct atmegadci_td *td_next; 20402ac6454SAndrew Thompson uint32_t len; 20502ac6454SAndrew Thompson uint32_t offset; 20602ac6454SAndrew Thompson uint16_t max_frame_size; 20702ac6454SAndrew Thompson uint8_t short_pkt; 20802ac6454SAndrew Thompson /* 20902ac6454SAndrew Thompson * short_pkt = 0: transfer should be short terminated 21002ac6454SAndrew Thompson * short_pkt = 1: transfer should not be short terminated 21102ac6454SAndrew Thompson */ 21202ac6454SAndrew Thompson uint8_t setup_alt_next; 21302ac6454SAndrew Thompson }; 21402ac6454SAndrew Thompson 21502ac6454SAndrew Thompson struct atmegadci_config_desc { 21602ac6454SAndrew Thompson struct usb2_config_descriptor confd; 21702ac6454SAndrew Thompson struct usb2_interface_descriptor ifcd; 21802ac6454SAndrew Thompson struct usb2_endpoint_descriptor endpd; 21902ac6454SAndrew Thompson } __packed; 22002ac6454SAndrew Thompson 22102ac6454SAndrew Thompson union atmegadci_hub_temp { 22202ac6454SAndrew Thompson uWord wValue; 22302ac6454SAndrew Thompson struct usb2_port_status ps; 22402ac6454SAndrew Thompson }; 22502ac6454SAndrew Thompson 22602ac6454SAndrew Thompson struct atmegadci_flags { 22702ac6454SAndrew Thompson uint8_t change_connect:1; 22802ac6454SAndrew Thompson uint8_t change_suspend:1; 22902ac6454SAndrew Thompson uint8_t status_suspend:1; /* set if suspended */ 23002ac6454SAndrew Thompson uint8_t status_vbus:1; /* set if present */ 23102ac6454SAndrew Thompson uint8_t status_bus_reset:1; /* set if reset complete */ 23202ac6454SAndrew Thompson uint8_t remote_wakeup:1; 23302ac6454SAndrew Thompson uint8_t self_powered:1; 23402ac6454SAndrew Thompson uint8_t clocks_off:1; 23502ac6454SAndrew Thompson uint8_t port_powered:1; 23602ac6454SAndrew Thompson uint8_t port_enabled:1; 23702ac6454SAndrew Thompson uint8_t d_pulled_up:1; 23802ac6454SAndrew Thompson }; 23902ac6454SAndrew Thompson 24002ac6454SAndrew Thompson struct atmegadci_softc { 24102ac6454SAndrew Thompson struct usb2_bus sc_bus; 24202ac6454SAndrew Thompson union atmegadci_hub_temp sc_hub_temp; 24302ac6454SAndrew Thompson LIST_HEAD(, usb2_xfer) sc_interrupt_list_head; 24402ac6454SAndrew Thompson struct usb2_sw_transfer sc_root_ctrl; 24502ac6454SAndrew Thompson struct usb2_sw_transfer sc_root_intr; 24602ac6454SAndrew Thompson 24702ac6454SAndrew Thompson /* must be set by by the bus interface layer */ 24802ac6454SAndrew Thompson atmegadci_clocks_t *sc_clocks_on; 24902ac6454SAndrew Thompson atmegadci_clocks_t *sc_clocks_off; 25002ac6454SAndrew Thompson 25102ac6454SAndrew Thompson struct usb2_device *sc_devices[ATMEGA_MAX_DEVICES]; 25202ac6454SAndrew Thompson struct resource *sc_irq_res; 25302ac6454SAndrew Thompson void *sc_intr_hdl; 25402ac6454SAndrew Thompson #if (ATMEGA_HAVE_BUS_SPACE != 0) 25502ac6454SAndrew Thompson struct resource *sc_io_res; 25602ac6454SAndrew Thompson bus_space_tag_t sc_io_tag; 25702ac6454SAndrew Thompson bus_space_handle_t sc_io_hdl; 25802ac6454SAndrew Thompson #endif 25902ac6454SAndrew Thompson uint8_t sc_rt_addr; /* root hub address */ 26002ac6454SAndrew Thompson uint8_t sc_dv_addr; /* device address */ 26102ac6454SAndrew Thompson uint8_t sc_conf; /* root hub config */ 26202ac6454SAndrew Thompson 26302ac6454SAndrew Thompson uint8_t sc_hub_idata[1]; 26402ac6454SAndrew Thompson 26502ac6454SAndrew Thompson struct atmegadci_flags sc_flags; 26602ac6454SAndrew Thompson }; 26702ac6454SAndrew Thompson 26802ac6454SAndrew Thompson /* prototypes */ 26902ac6454SAndrew Thompson 27002ac6454SAndrew Thompson usb2_error_t atmegadci_init(struct atmegadci_softc *sc); 27102ac6454SAndrew Thompson void atmegadci_uninit(struct atmegadci_softc *sc); 27202ac6454SAndrew Thompson void atmegadci_suspend(struct atmegadci_softc *sc); 27302ac6454SAndrew Thompson void atmegadci_resume(struct atmegadci_softc *sc); 27402ac6454SAndrew Thompson void atmegadci_interrupt(struct atmegadci_softc *sc); 27502ac6454SAndrew Thompson 27602ac6454SAndrew Thompson #endif /* _ATMEGADCI_H_ */ 277