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