at91dci.c revision 185948
1184610Salfred#include <sys/cdefs.h> 2184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb2/controller/at91dci.c 185948 2008-12-11 23:13:02Z thompsa $"); 3184610Salfred 4184610Salfred/*- 5184610Salfred * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved. 6184610Salfred * 7184610Salfred * Redistribution and use in source and binary forms, with or without 8184610Salfred * modification, are permitted provided that the following conditions 9184610Salfred * are met: 10184610Salfred * 1. Redistributions of source code must retain the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer. 12184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 13184610Salfred * notice, this list of conditions and the following disclaimer in the 14184610Salfred * documentation and/or other materials provided with the distribution. 15184610Salfred * 16184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26184610Salfred * SUCH DAMAGE. 27184610Salfred */ 28184610Salfred 29184610Salfred/* 30184610Salfred * This file contains the driver for the AT91 series USB Device 31184610Salfred * Controller 32184610Salfred */ 33184610Salfred 34184610Salfred/* 35184610Salfred * Thanks to "David Brownell" for helping out regarding the hardware 36184610Salfred * endpoint profiles. 37184610Salfred */ 38184610Salfred 39184610Salfred/* 40184610Salfred * NOTE: The "fifo_bank" is not reset in hardware when the endpoint is 41184610Salfred * reset ! 42184610Salfred * 43184610Salfred * NOTE: When the chip detects BUS-reset it will also reset the 44184610Salfred * endpoints, Function-address and more. 45184610Salfred */ 46184610Salfred 47184610Salfred#include <dev/usb2/include/usb2_standard.h> 48184610Salfred#include <dev/usb2/include/usb2_mfunc.h> 49184610Salfred#include <dev/usb2/include/usb2_error.h> 50184610Salfred#include <dev/usb2/include/usb2_defs.h> 51184610Salfred 52184610Salfred#define USB_DEBUG_VAR at91dcidebug 53184610Salfred#define usb2_config_td_cc at91dci_config_copy 54184610Salfred#define usb2_config_td_softc at91dci_softc 55184610Salfred 56184610Salfred#include <dev/usb2/core/usb2_core.h> 57184610Salfred#include <dev/usb2/core/usb2_debug.h> 58184610Salfred#include <dev/usb2/core/usb2_busdma.h> 59184610Salfred#include <dev/usb2/core/usb2_process.h> 60184610Salfred#include <dev/usb2/core/usb2_config_td.h> 61184610Salfred#include <dev/usb2/core/usb2_sw_transfer.h> 62184610Salfred#include <dev/usb2/core/usb2_transfer.h> 63184610Salfred#include <dev/usb2/core/usb2_device.h> 64184610Salfred#include <dev/usb2/core/usb2_hub.h> 65184610Salfred#include <dev/usb2/core/usb2_util.h> 66184610Salfred 67184610Salfred#include <dev/usb2/controller/usb2_controller.h> 68184610Salfred#include <dev/usb2/controller/usb2_bus.h> 69184610Salfred#include <dev/usb2/controller/at91dci.h> 70184610Salfred 71184610Salfred#define AT9100_DCI_BUS2SC(bus) \ 72184610Salfred ((struct at91dci_softc *)(((uint8_t *)(bus)) - \ 73184610Salfred USB_P2U(&(((struct at91dci_softc *)0)->sc_bus)))) 74184610Salfred 75184610Salfred#define AT9100_DCI_PC2SC(pc) \ 76184610Salfred AT9100_DCI_BUS2SC((pc)->tag_parent->info->bus) 77184610Salfred 78184610Salfred#if USB_DEBUG 79184610Salfredstatic int at91dcidebug = 0; 80184610Salfred 81184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, at91dci, CTLFLAG_RW, 0, "USB at91dci"); 82184610SalfredSYSCTL_INT(_hw_usb2_at91dci, OID_AUTO, debug, CTLFLAG_RW, 83184610Salfred &at91dcidebug, 0, "at91dci debug level"); 84184610Salfred#endif 85184610Salfred 86184610Salfred#define AT9100_DCI_INTR_ENDPT 1 87184610Salfred 88184610Salfred/* prototypes */ 89184610Salfred 90184610Salfredstruct usb2_bus_methods at91dci_bus_methods; 91184610Salfredstruct usb2_pipe_methods at91dci_device_bulk_methods; 92184610Salfredstruct usb2_pipe_methods at91dci_device_ctrl_methods; 93184610Salfredstruct usb2_pipe_methods at91dci_device_intr_methods; 94184610Salfredstruct usb2_pipe_methods at91dci_device_isoc_fs_methods; 95184610Salfredstruct usb2_pipe_methods at91dci_root_ctrl_methods; 96184610Salfredstruct usb2_pipe_methods at91dci_root_intr_methods; 97184610Salfred 98184610Salfredstatic at91dci_cmd_t at91dci_setup_rx; 99184610Salfredstatic at91dci_cmd_t at91dci_data_rx; 100184610Salfredstatic at91dci_cmd_t at91dci_data_tx; 101184610Salfredstatic at91dci_cmd_t at91dci_data_tx_sync; 102185948Sthompsastatic void at91dci_device_done(struct usb2_xfer *, usb2_error_t); 103185948Sthompsastatic void at91dci_do_poll(struct usb2_bus *); 104185948Sthompsastatic void at91dci_root_ctrl_poll(struct at91dci_softc *); 105185948Sthompsastatic void at91dci_standard_done(struct usb2_xfer *); 106184610Salfred 107184610Salfredstatic usb2_sw_transfer_func_t at91dci_root_intr_done; 108184610Salfredstatic usb2_sw_transfer_func_t at91dci_root_ctrl_done; 109184610Salfredstatic usb2_config_td_command_t at91dci_root_ctrl_task; 110184610Salfred 111184610Salfred/* 112184610Salfred * NOTE: Some of the bits in the CSR register have inverse meaning so 113184610Salfred * we need a helper macro when acknowledging events: 114184610Salfred */ 115184610Salfred#define AT91_CSR_ACK(csr, what) do { \ 116184610Salfred (csr) &= ~((AT91_UDP_CSR_FORCESTALL| \ 117184610Salfred AT91_UDP_CSR_TXPKTRDY| \ 118184610Salfred AT91_UDP_CSR_RXBYTECNT) ^ (what));\ 119184610Salfred (csr) |= ((AT91_UDP_CSR_RX_DATA_BK0| \ 120184610Salfred AT91_UDP_CSR_RX_DATA_BK1| \ 121184610Salfred AT91_UDP_CSR_TXCOMP| \ 122184610Salfred AT91_UDP_CSR_RXSETUP| \ 123184610Salfred AT91_UDP_CSR_STALLSENT) ^ (what)); \ 124184610Salfred} while (0) 125184610Salfred 126184610Salfred/* 127184610Salfred * Here is a list of what the chip supports. 128184610Salfred * Probably it supports more than listed here! 129184610Salfred */ 130184610Salfredstatic const struct usb2_hw_ep_profile 131184610Salfred at91dci_ep_profile[AT91_UDP_EP_MAX] = { 132184610Salfred 133184610Salfred [0] = { 134184610Salfred .max_in_frame_size = 8, 135184610Salfred .max_out_frame_size = 8, 136184610Salfred .is_simplex = 1, 137184610Salfred .support_control = 1, 138184610Salfred }, 139184610Salfred [1] = { 140184610Salfred .max_in_frame_size = 64, 141184610Salfred .max_out_frame_size = 64, 142184610Salfred .is_simplex = 1, 143184610Salfred .support_multi_buffer = 1, 144184610Salfred .support_bulk = 1, 145184610Salfred .support_interrupt = 1, 146184610Salfred .support_isochronous = 1, 147184610Salfred .support_in = 1, 148184610Salfred .support_out = 1, 149184610Salfred }, 150184610Salfred [2] = { 151184610Salfred .max_in_frame_size = 64, 152184610Salfred .max_out_frame_size = 64, 153184610Salfred .is_simplex = 1, 154184610Salfred .support_multi_buffer = 1, 155184610Salfred .support_bulk = 1, 156184610Salfred .support_interrupt = 1, 157184610Salfred .support_isochronous = 1, 158184610Salfred .support_in = 1, 159184610Salfred .support_out = 1, 160184610Salfred }, 161184610Salfred [3] = { 162184610Salfred /* can also do BULK */ 163184610Salfred .max_in_frame_size = 8, 164184610Salfred .max_out_frame_size = 8, 165184610Salfred .is_simplex = 1, 166184610Salfred .support_interrupt = 1, 167184610Salfred .support_in = 1, 168184610Salfred .support_out = 1, 169184610Salfred }, 170184610Salfred [4] = { 171184610Salfred .max_in_frame_size = 256, 172184610Salfred .max_out_frame_size = 256, 173184610Salfred .is_simplex = 1, 174184610Salfred .support_multi_buffer = 1, 175184610Salfred .support_bulk = 1, 176184610Salfred .support_interrupt = 1, 177184610Salfred .support_isochronous = 1, 178184610Salfred .support_in = 1, 179184610Salfred .support_out = 1, 180184610Salfred }, 181184610Salfred [5] = { 182184610Salfred .max_in_frame_size = 256, 183184610Salfred .max_out_frame_size = 256, 184184610Salfred .is_simplex = 1, 185184610Salfred .support_multi_buffer = 1, 186184610Salfred .support_bulk = 1, 187184610Salfred .support_interrupt = 1, 188184610Salfred .support_isochronous = 1, 189184610Salfred .support_in = 1, 190184610Salfred .support_out = 1, 191184610Salfred }, 192184610Salfred}; 193184610Salfred 194184610Salfredstatic void 195184610Salfredat91dci_get_hw_ep_profile(struct usb2_device *udev, 196184610Salfred const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr) 197184610Salfred{ 198184610Salfred if (ep_addr < AT91_UDP_EP_MAX) { 199184610Salfred *ppf = (at91dci_ep_profile + ep_addr); 200184610Salfred } else { 201184610Salfred *ppf = NULL; 202184610Salfred } 203184610Salfred return; 204184610Salfred} 205184610Salfred 206184610Salfredstatic void 207184610Salfredat91dci_clocks_on(struct at91dci_softc *sc) 208184610Salfred{ 209184610Salfred if (sc->sc_flags.clocks_off && 210184610Salfred sc->sc_flags.port_powered) { 211184610Salfred 212184610Salfred DPRINTFN(5, "\n"); 213184610Salfred 214184610Salfred if (sc->sc_clocks_on) { 215184610Salfred (sc->sc_clocks_on) (sc->sc_clocks_arg); 216184610Salfred } 217184610Salfred sc->sc_flags.clocks_off = 0; 218184610Salfred 219184610Salfred /* enable Transceiver */ 220184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_TXVC, 0); 221184610Salfred } 222184610Salfred return; 223184610Salfred} 224184610Salfred 225184610Salfredstatic void 226184610Salfredat91dci_clocks_off(struct at91dci_softc *sc) 227184610Salfred{ 228184610Salfred if (!sc->sc_flags.clocks_off) { 229184610Salfred 230184610Salfred DPRINTFN(5, "\n"); 231184610Salfred 232184610Salfred /* disable Transceiver */ 233184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_TXVC, AT91_UDP_TXVC_DIS); 234184610Salfred 235184610Salfred if (sc->sc_clocks_off) { 236184610Salfred (sc->sc_clocks_off) (sc->sc_clocks_arg); 237184610Salfred } 238184610Salfred sc->sc_flags.clocks_off = 1; 239184610Salfred } 240184610Salfred return; 241184610Salfred} 242184610Salfred 243184610Salfredstatic void 244184610Salfredat91dci_pull_up(struct at91dci_softc *sc) 245184610Salfred{ 246184610Salfred /* pullup D+, if possible */ 247184610Salfred 248184610Salfred if (!sc->sc_flags.d_pulled_up && 249184610Salfred sc->sc_flags.port_powered) { 250184610Salfred sc->sc_flags.d_pulled_up = 1; 251184610Salfred (sc->sc_pull_up) (sc->sc_pull_arg); 252184610Salfred } 253184610Salfred return; 254184610Salfred} 255184610Salfred 256184610Salfredstatic void 257184610Salfredat91dci_pull_down(struct at91dci_softc *sc) 258184610Salfred{ 259184610Salfred /* pulldown D+, if possible */ 260184610Salfred 261184610Salfred if (sc->sc_flags.d_pulled_up) { 262184610Salfred sc->sc_flags.d_pulled_up = 0; 263184610Salfred (sc->sc_pull_down) (sc->sc_pull_arg); 264184610Salfred } 265184610Salfred return; 266184610Salfred} 267184610Salfred 268184610Salfredstatic void 269184610Salfredat91dci_wakeup_peer(struct at91dci_softc *sc) 270184610Salfred{ 271184610Salfred uint32_t temp; 272184610Salfred 273184610Salfred if (!(sc->sc_flags.status_suspend)) { 274184610Salfred return; 275184610Salfred } 276184610Salfred temp = AT91_UDP_READ_4(sc, AT91_UDP_GSTATE); 277184610Salfred 278184610Salfred if (!(temp & AT91_UDP_GSTATE_ESR)) { 279184610Salfred return; 280184610Salfred } 281184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp); 282184610Salfred 283184610Salfred return; 284184610Salfred} 285184610Salfred 286184610Salfredstatic void 287184610Salfredat91dci_rem_wakeup_set(struct usb2_device *udev, uint8_t is_on) 288184610Salfred{ 289184610Salfred struct at91dci_softc *sc; 290184610Salfred uint32_t temp; 291184610Salfred 292184610Salfred DPRINTFN(5, "is_on=%u\n", is_on); 293184610Salfred 294184824Sthompsa USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 295184610Salfred 296184610Salfred sc = AT9100_DCI_BUS2SC(udev->bus); 297184610Salfred 298184610Salfred temp = AT91_UDP_READ_4(sc, AT91_UDP_GSTATE); 299184610Salfred 300184610Salfred if (is_on) { 301184610Salfred temp |= AT91_UDP_GSTATE_ESR; 302184610Salfred } else { 303184610Salfred temp &= ~AT91_UDP_GSTATE_ESR; 304184610Salfred } 305184610Salfred 306184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp); 307184610Salfred 308184610Salfred return; 309184610Salfred} 310184610Salfred 311184610Salfredstatic void 312184610Salfredat91dci_set_address(struct at91dci_softc *sc, uint8_t addr) 313184610Salfred{ 314184610Salfred DPRINTFN(5, "addr=%d\n", addr); 315184610Salfred 316184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_FADDR, addr | 317184610Salfred AT91_UDP_FADDR_EN); 318184610Salfred 319184610Salfred return; 320184610Salfred} 321184610Salfred 322184610Salfredstatic uint8_t 323184610Salfredat91dci_setup_rx(struct at91dci_td *td) 324184610Salfred{ 325184610Salfred struct at91dci_softc *sc; 326184610Salfred struct usb2_device_request req; 327184610Salfred uint32_t csr; 328184610Salfred uint32_t temp; 329184610Salfred uint16_t count; 330184610Salfred 331184610Salfred /* read out FIFO status */ 332184610Salfred csr = bus_space_read_4(td->io_tag, td->io_hdl, 333184610Salfred td->status_reg); 334184610Salfred 335184610Salfred DPRINTFN(5, "csr=0x%08x rem=%u\n", csr, td->remainder); 336184610Salfred 337184610Salfred temp = csr; 338184610Salfred temp &= (AT91_UDP_CSR_RX_DATA_BK0 | 339184610Salfred AT91_UDP_CSR_RX_DATA_BK1 | 340184610Salfred AT91_UDP_CSR_STALLSENT | 341184610Salfred AT91_UDP_CSR_RXSETUP | 342184610Salfred AT91_UDP_CSR_TXCOMP); 343184610Salfred 344184610Salfred if (!(csr & AT91_UDP_CSR_RXSETUP)) { 345184610Salfred /* abort any ongoing transfer */ 346184610Salfred if (!td->did_stall) { 347184610Salfred DPRINTFN(5, "stalling\n"); 348184610Salfred temp |= AT91_UDP_CSR_FORCESTALL; 349184610Salfred td->did_stall = 1; 350184610Salfred } 351184610Salfred goto not_complete; 352184610Salfred } 353184610Salfred /* get the packet byte count */ 354184610Salfred count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16; 355184610Salfred 356184610Salfred /* verify data length */ 357184610Salfred if (count != td->remainder) { 358184610Salfred DPRINTFN(0, "Invalid SETUP packet " 359184610Salfred "length, %d bytes\n", count); 360184610Salfred goto not_complete; 361184610Salfred } 362184610Salfred if (count != sizeof(req)) { 363184610Salfred DPRINTFN(0, "Unsupported SETUP packet " 364184610Salfred "length, %d bytes\n", count); 365184610Salfred goto not_complete; 366184610Salfred } 367184610Salfred /* receive data */ 368184610Salfred bus_space_read_multi_1(td->io_tag, td->io_hdl, 369184610Salfred td->fifo_reg, (void *)&req, sizeof(req)); 370184610Salfred 371184610Salfred /* copy data into real buffer */ 372184610Salfred usb2_copy_in(td->pc, 0, &req, sizeof(req)); 373184610Salfred 374184610Salfred td->offset = sizeof(req); 375184610Salfred td->remainder = 0; 376184610Salfred 377184610Salfred /* get pointer to softc */ 378184610Salfred sc = AT9100_DCI_PC2SC(td->pc); 379184610Salfred 380184610Salfred /* sneak peek the set address */ 381184610Salfred if ((req.bmRequestType == UT_WRITE_DEVICE) && 382184610Salfred (req.bRequest == UR_SET_ADDRESS)) { 383184610Salfred sc->sc_dv_addr = req.wValue[0] & 0x7F; 384184610Salfred } else { 385184610Salfred sc->sc_dv_addr = 0xFF; 386184610Salfred } 387184610Salfred 388184610Salfred /* sneak peek the endpoint direction */ 389184610Salfred if (req.bmRequestType & UE_DIR_IN) { 390184610Salfred csr |= AT91_UDP_CSR_DIR; 391184610Salfred } else { 392184610Salfred csr &= ~AT91_UDP_CSR_DIR; 393184610Salfred } 394184610Salfred 395184610Salfred /* write the direction of the control transfer */ 396184610Salfred AT91_CSR_ACK(csr, temp); 397184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 398184610Salfred td->status_reg, csr); 399184610Salfred return (0); /* complete */ 400184610Salfred 401184610Salfrednot_complete: 402184610Salfred /* clear interrupts, if any */ 403184610Salfred if (temp) { 404184610Salfred DPRINTFN(5, "clearing 0x%08x\n", temp); 405184610Salfred AT91_CSR_ACK(csr, temp); 406184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 407184610Salfred td->status_reg, csr); 408184610Salfred } 409184610Salfred return (1); /* not complete */ 410184610Salfred 411184610Salfred} 412184610Salfred 413184610Salfredstatic uint8_t 414184610Salfredat91dci_data_rx(struct at91dci_td *td) 415184610Salfred{ 416184610Salfred struct usb2_page_search buf_res; 417184610Salfred uint32_t csr; 418184610Salfred uint32_t temp; 419184610Salfred uint16_t count; 420184610Salfred uint8_t to; 421184610Salfred uint8_t got_short; 422184610Salfred 423184610Salfred to = 2; /* don't loop forever! */ 424184610Salfred got_short = 0; 425184610Salfred 426184610Salfred /* check if any of the FIFO banks have data */ 427184610Salfredrepeat: 428184610Salfred /* read out FIFO status */ 429184610Salfred csr = bus_space_read_4(td->io_tag, td->io_hdl, 430184610Salfred td->status_reg); 431184610Salfred 432184610Salfred DPRINTFN(5, "csr=0x%08x rem=%u\n", csr, td->remainder); 433184610Salfred 434184610Salfred if (csr & AT91_UDP_CSR_RXSETUP) { 435184610Salfred if (td->remainder == 0) { 436184610Salfred /* 437184610Salfred * We are actually complete and have 438184610Salfred * received the next SETUP 439184610Salfred */ 440184610Salfred DPRINTFN(5, "faking complete\n"); 441184610Salfred return (0); /* complete */ 442184610Salfred } 443184610Salfred /* 444184610Salfred * USB Host Aborted the transfer. 445184610Salfred */ 446184610Salfred td->error = 1; 447184610Salfred return (0); /* complete */ 448184610Salfred } 449184610Salfred /* Make sure that "STALLSENT" gets cleared */ 450184610Salfred temp = csr; 451184610Salfred temp &= AT91_UDP_CSR_STALLSENT; 452184610Salfred 453184610Salfred /* check status */ 454184610Salfred if (!(csr & (AT91_UDP_CSR_RX_DATA_BK0 | 455184610Salfred AT91_UDP_CSR_RX_DATA_BK1))) { 456184610Salfred if (temp) { 457184610Salfred /* write command */ 458184610Salfred AT91_CSR_ACK(csr, temp); 459184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 460184610Salfred td->status_reg, csr); 461184610Salfred } 462184610Salfred return (1); /* not complete */ 463184610Salfred } 464184610Salfred /* get the packet byte count */ 465184610Salfred count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16; 466184610Salfred 467184610Salfred /* verify the packet byte count */ 468184610Salfred if (count != td->max_packet_size) { 469184610Salfred if (count < td->max_packet_size) { 470184610Salfred /* we have a short packet */ 471184610Salfred td->short_pkt = 1; 472184610Salfred got_short = 1; 473184610Salfred } else { 474184610Salfred /* invalid USB packet */ 475184610Salfred td->error = 1; 476184610Salfred return (0); /* we are complete */ 477184610Salfred } 478184610Salfred } 479184610Salfred /* verify the packet byte count */ 480184610Salfred if (count > td->remainder) { 481184610Salfred /* invalid USB packet */ 482184610Salfred td->error = 1; 483184610Salfred return (0); /* we are complete */ 484184610Salfred } 485184610Salfred while (count > 0) { 486184610Salfred usb2_get_page(td->pc, td->offset, &buf_res); 487184610Salfred 488184610Salfred /* get correct length */ 489184610Salfred if (buf_res.length > count) { 490184610Salfred buf_res.length = count; 491184610Salfred } 492184610Salfred /* receive data */ 493184610Salfred bus_space_read_multi_1(td->io_tag, td->io_hdl, 494184610Salfred td->fifo_reg, buf_res.buffer, buf_res.length); 495184610Salfred 496184610Salfred /* update counters */ 497184610Salfred count -= buf_res.length; 498184610Salfred td->offset += buf_res.length; 499184610Salfred td->remainder -= buf_res.length; 500184610Salfred } 501184610Salfred 502184610Salfred /* clear status bits */ 503184610Salfred if (td->support_multi_buffer) { 504184610Salfred if (td->fifo_bank) { 505184610Salfred td->fifo_bank = 0; 506184610Salfred temp |= AT91_UDP_CSR_RX_DATA_BK1; 507184610Salfred } else { 508184610Salfred td->fifo_bank = 1; 509184610Salfred temp |= AT91_UDP_CSR_RX_DATA_BK0; 510184610Salfred } 511184610Salfred } else { 512184610Salfred temp |= (AT91_UDP_CSR_RX_DATA_BK0 | 513184610Salfred AT91_UDP_CSR_RX_DATA_BK1); 514184610Salfred } 515184610Salfred 516184610Salfred /* write command */ 517184610Salfred AT91_CSR_ACK(csr, temp); 518184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 519184610Salfred td->status_reg, csr); 520184610Salfred 521184610Salfred /* 522184610Salfred * NOTE: We may have to delay a little bit before 523184610Salfred * proceeding after clearing the DATA_BK bits. 524184610Salfred */ 525184610Salfred 526184610Salfred /* check if we are complete */ 527184610Salfred if ((td->remainder == 0) || got_short) { 528184610Salfred if (td->short_pkt) { 529184610Salfred /* we are complete */ 530184610Salfred return (0); 531184610Salfred } 532184610Salfred /* else need to receive a zero length packet */ 533184610Salfred } 534184610Salfred if (--to) { 535184610Salfred goto repeat; 536184610Salfred } 537184610Salfred return (1); /* not complete */ 538184610Salfred} 539184610Salfred 540184610Salfredstatic uint8_t 541184610Salfredat91dci_data_tx(struct at91dci_td *td) 542184610Salfred{ 543184610Salfred struct usb2_page_search buf_res; 544184610Salfred uint32_t csr; 545184610Salfred uint32_t temp; 546184610Salfred uint16_t count; 547184610Salfred uint8_t to; 548184610Salfred 549184610Salfred to = 2; /* don't loop forever! */ 550184610Salfred 551184610Salfredrepeat: 552184610Salfred 553184610Salfred /* read out FIFO status */ 554184610Salfred csr = bus_space_read_4(td->io_tag, td->io_hdl, 555184610Salfred td->status_reg); 556184610Salfred 557184610Salfred DPRINTFN(5, "csr=0x%08x rem=%u\n", csr, td->remainder); 558184610Salfred 559184610Salfred if (csr & AT91_UDP_CSR_RXSETUP) { 560184610Salfred /* 561184610Salfred * The current transfer was aborted 562184610Salfred * by the USB Host 563184610Salfred */ 564184610Salfred td->error = 1; 565184610Salfred return (0); /* complete */ 566184610Salfred } 567184610Salfred /* Make sure that "STALLSENT" gets cleared */ 568184610Salfred temp = csr; 569184610Salfred temp &= AT91_UDP_CSR_STALLSENT; 570184610Salfred 571184610Salfred if (csr & AT91_UDP_CSR_TXPKTRDY) { 572184610Salfred if (temp) { 573184610Salfred /* write command */ 574184610Salfred AT91_CSR_ACK(csr, temp); 575184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 576184610Salfred td->status_reg, csr); 577184610Salfred } 578184610Salfred return (1); /* not complete */ 579184610Salfred } else { 580184610Salfred /* clear TXCOMP and set TXPKTRDY */ 581184610Salfred temp |= (AT91_UDP_CSR_TXCOMP | 582184610Salfred AT91_UDP_CSR_TXPKTRDY); 583184610Salfred } 584184610Salfred 585184610Salfred count = td->max_packet_size; 586184610Salfred if (td->remainder < count) { 587184610Salfred /* we have a short packet */ 588184610Salfred td->short_pkt = 1; 589184610Salfred count = td->remainder; 590184610Salfred } 591184610Salfred while (count > 0) { 592184610Salfred 593184610Salfred usb2_get_page(td->pc, td->offset, &buf_res); 594184610Salfred 595184610Salfred /* get correct length */ 596184610Salfred if (buf_res.length > count) { 597184610Salfred buf_res.length = count; 598184610Salfred } 599184610Salfred /* transmit data */ 600184610Salfred bus_space_write_multi_1(td->io_tag, td->io_hdl, 601184610Salfred td->fifo_reg, buf_res.buffer, buf_res.length); 602184610Salfred 603184610Salfred /* update counters */ 604184610Salfred count -= buf_res.length; 605184610Salfred td->offset += buf_res.length; 606184610Salfred td->remainder -= buf_res.length; 607184610Salfred } 608184610Salfred 609184610Salfred /* write command */ 610184610Salfred AT91_CSR_ACK(csr, temp); 611184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 612184610Salfred td->status_reg, csr); 613184610Salfred 614184610Salfred /* check remainder */ 615184610Salfred if (td->remainder == 0) { 616184610Salfred if (td->short_pkt) { 617184610Salfred return (0); /* complete */ 618184610Salfred } 619184610Salfred /* else we need to transmit a short packet */ 620184610Salfred } 621184610Salfred if (--to) { 622184610Salfred goto repeat; 623184610Salfred } 624184610Salfred return (1); /* not complete */ 625184610Salfred} 626184610Salfred 627184610Salfredstatic uint8_t 628184610Salfredat91dci_data_tx_sync(struct at91dci_td *td) 629184610Salfred{ 630184610Salfred struct at91dci_softc *sc; 631184610Salfred uint32_t csr; 632184610Salfred uint32_t temp; 633184610Salfred 634184610Salfred#if 0 635184610Salfredrepeat: 636184610Salfred#endif 637184610Salfred 638184610Salfred /* read out FIFO status */ 639184610Salfred csr = bus_space_read_4(td->io_tag, td->io_hdl, 640184610Salfred td->status_reg); 641184610Salfred 642184610Salfred DPRINTFN(5, "csr=0x%08x\n", csr); 643184610Salfred 644184610Salfred if (csr & AT91_UDP_CSR_RXSETUP) { 645184610Salfred DPRINTFN(5, "faking complete\n"); 646184610Salfred /* Race condition */ 647184610Salfred return (0); /* complete */ 648184610Salfred } 649184610Salfred temp = csr; 650184610Salfred temp &= (AT91_UDP_CSR_STALLSENT | 651184610Salfred AT91_UDP_CSR_TXCOMP); 652184610Salfred 653184610Salfred /* check status */ 654184610Salfred if (csr & AT91_UDP_CSR_TXPKTRDY) { 655184610Salfred goto not_complete; 656184610Salfred } 657184610Salfred if (!(csr & AT91_UDP_CSR_TXCOMP)) { 658184610Salfred goto not_complete; 659184610Salfred } 660184610Salfred sc = AT9100_DCI_PC2SC(td->pc); 661184610Salfred if (sc->sc_dv_addr != 0xFF) { 662184610Salfred /* 663184610Salfred * The AT91 has a special requirement with regard to 664184610Salfred * setting the address and that is to write the new 665184610Salfred * address before clearing TXCOMP: 666184610Salfred */ 667184610Salfred at91dci_set_address(sc, sc->sc_dv_addr); 668184610Salfred } 669184610Salfred /* write command */ 670184610Salfred AT91_CSR_ACK(csr, temp); 671184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 672184610Salfred td->status_reg, csr); 673184610Salfred 674184610Salfred return (0); /* complete */ 675184610Salfred 676184610Salfrednot_complete: 677184610Salfred if (temp) { 678184610Salfred /* write command */ 679184610Salfred AT91_CSR_ACK(csr, temp); 680184610Salfred bus_space_write_4(td->io_tag, td->io_hdl, 681184610Salfred td->status_reg, csr); 682184610Salfred } 683184610Salfred return (1); /* not complete */ 684184610Salfred} 685184610Salfred 686184610Salfredstatic uint8_t 687184610Salfredat91dci_xfer_do_fifo(struct usb2_xfer *xfer) 688184610Salfred{ 689184610Salfred struct at91dci_softc *sc; 690184610Salfred struct at91dci_td *td; 691184610Salfred uint8_t temp; 692184610Salfred 693184610Salfred DPRINTFN(9, "\n"); 694184610Salfred 695184610Salfred td = xfer->td_transfer_cache; 696184610Salfred while (1) { 697184610Salfred if ((td->func) (td)) { 698184610Salfred /* operation in progress */ 699184610Salfred break; 700184610Salfred } 701184610Salfred if (((void *)td) == xfer->td_transfer_last) { 702184610Salfred goto done; 703184610Salfred } 704184610Salfred if (td->error) { 705184610Salfred goto done; 706184610Salfred } else if (td->remainder > 0) { 707184610Salfred /* 708184610Salfred * We had a short transfer. If there is no alternate 709184610Salfred * next, stop processing ! 710184610Salfred */ 711184610Salfred if (!td->alt_next) { 712184610Salfred goto done; 713184610Salfred } 714184610Salfred } 715184610Salfred /* 716184610Salfred * Fetch the next transfer descriptor and transfer 717184610Salfred * some flags to the next transfer descriptor 718184610Salfred */ 719184610Salfred temp = 0; 720184610Salfred if (td->fifo_bank) 721184610Salfred temp |= 1; 722184610Salfred td = td->obj_next; 723184610Salfred xfer->td_transfer_cache = td; 724184610Salfred if (temp & 1) 725184610Salfred td->fifo_bank = 1; 726184610Salfred } 727184610Salfred return (1); /* not complete */ 728184610Salfred 729184610Salfreddone: 730184610Salfred sc = xfer->usb2_sc; 731184610Salfred temp = (xfer->endpoint & UE_ADDR); 732184610Salfred 733184610Salfred /* update FIFO bank flag and multi buffer */ 734184610Salfred if (td->fifo_bank) { 735184610Salfred sc->sc_ep_flags[temp].fifo_bank = 1; 736184610Salfred } else { 737184610Salfred sc->sc_ep_flags[temp].fifo_bank = 0; 738184610Salfred } 739184610Salfred 740184610Salfred /* compute all actual lengths */ 741184610Salfred 742184610Salfred at91dci_standard_done(xfer); 743184610Salfred 744184610Salfred return (0); /* complete */ 745184610Salfred} 746184610Salfred 747184610Salfredstatic void 748184610Salfredat91dci_interrupt_poll(struct at91dci_softc *sc) 749184610Salfred{ 750184610Salfred struct usb2_xfer *xfer; 751184610Salfred 752184610Salfredrepeat: 753184610Salfred TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { 754184610Salfred if (!at91dci_xfer_do_fifo(xfer)) { 755184610Salfred /* queue has been modified */ 756184610Salfred goto repeat; 757184610Salfred } 758184610Salfred } 759184610Salfred return; 760184610Salfred} 761184610Salfred 762184610Salfredstatic void 763184610Salfredat91dci_vbus_interrupt(struct usb2_bus *bus, uint8_t is_on) 764184610Salfred{ 765184610Salfred struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus); 766184610Salfred 767184610Salfred DPRINTFN(5, "vbus = %u\n", is_on); 768184610Salfred 769184824Sthompsa USB_BUS_LOCK(&sc->sc_bus); 770184610Salfred if (is_on) { 771184610Salfred if (!sc->sc_flags.status_vbus) { 772184610Salfred sc->sc_flags.status_vbus = 1; 773184610Salfred 774184610Salfred /* complete root HUB interrupt endpoint */ 775184610Salfred 776184610Salfred usb2_sw_transfer(&sc->sc_root_intr, 777184610Salfred &at91dci_root_intr_done); 778184610Salfred } 779184610Salfred } else { 780184610Salfred if (sc->sc_flags.status_vbus) { 781184610Salfred sc->sc_flags.status_vbus = 0; 782184610Salfred sc->sc_flags.status_bus_reset = 0; 783184610Salfred sc->sc_flags.status_suspend = 0; 784184610Salfred sc->sc_flags.change_suspend = 0; 785184610Salfred sc->sc_flags.change_connect = 1; 786184610Salfred 787184610Salfred /* complete root HUB interrupt endpoint */ 788184610Salfred 789184610Salfred usb2_sw_transfer(&sc->sc_root_intr, 790184610Salfred &at91dci_root_intr_done); 791184610Salfred } 792184610Salfred } 793184610Salfred 794184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 795184610Salfred 796184610Salfred return; 797184610Salfred} 798184610Salfred 799184610Salfredvoid 800184610Salfredat91dci_interrupt(struct at91dci_softc *sc) 801184610Salfred{ 802184610Salfred uint32_t status; 803184610Salfred 804184824Sthompsa USB_BUS_LOCK(&sc->sc_bus); 805184610Salfred 806184610Salfred status = AT91_UDP_READ_4(sc, AT91_UDP_ISR); 807184610Salfred status &= AT91_UDP_INT_DEFAULT; 808184610Salfred 809184610Salfred if (!status) { 810184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 811184610Salfred return; 812184610Salfred } 813184610Salfred /* acknowledge interrupts */ 814184610Salfred 815184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_ICR, status); 816184610Salfred 817184610Salfred /* check for any bus state change interrupts */ 818184610Salfred 819184610Salfred if (status & AT91_UDP_INT_BUS) { 820184610Salfred 821184610Salfred DPRINTFN(5, "real bus interrupt 0x%08x\n", status); 822184610Salfred 823184610Salfred if (status & AT91_UDP_INT_END_BR) { 824184610Salfred 825184610Salfred /* set correct state */ 826184610Salfred sc->sc_flags.status_bus_reset = 1; 827184610Salfred sc->sc_flags.status_suspend = 0; 828184610Salfred sc->sc_flags.change_suspend = 0; 829184610Salfred sc->sc_flags.change_connect = 1; 830184610Salfred 831184610Salfred /* disable resume interrupt */ 832184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 833184610Salfred AT91_UDP_INT_RXRSM); 834184610Salfred /* enable suspend interrupt */ 835184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IER, 836184610Salfred AT91_UDP_INT_RXSUSP); 837184610Salfred } 838184610Salfred /* 839184610Salfred * If RXRSM and RXSUSP is set at the same time we interpret 840184610Salfred * that like RESUME. Resume is set when there is at least 3 841184610Salfred * milliseconds of inactivity on the USB BUS. 842184610Salfred */ 843184610Salfred if (status & AT91_UDP_INT_RXRSM) { 844184610Salfred if (sc->sc_flags.status_suspend) { 845184610Salfred sc->sc_flags.status_suspend = 0; 846184610Salfred sc->sc_flags.change_suspend = 1; 847184610Salfred 848184610Salfred /* disable resume interrupt */ 849184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 850184610Salfred AT91_UDP_INT_RXRSM); 851184610Salfred /* enable suspend interrupt */ 852184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IER, 853184610Salfred AT91_UDP_INT_RXSUSP); 854184610Salfred } 855184610Salfred } else if (status & AT91_UDP_INT_RXSUSP) { 856184610Salfred if (!sc->sc_flags.status_suspend) { 857184610Salfred sc->sc_flags.status_suspend = 1; 858184610Salfred sc->sc_flags.change_suspend = 1; 859184610Salfred 860184610Salfred /* disable suspend interrupt */ 861184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 862184610Salfred AT91_UDP_INT_RXSUSP); 863184610Salfred 864184610Salfred /* enable resume interrupt */ 865184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IER, 866184610Salfred AT91_UDP_INT_RXRSM); 867184610Salfred } 868184610Salfred } 869184610Salfred /* complete root HUB interrupt endpoint */ 870184610Salfred 871184610Salfred usb2_sw_transfer(&sc->sc_root_intr, 872184610Salfred &at91dci_root_intr_done); 873184610Salfred } 874184610Salfred /* check for any endpoint interrupts */ 875184610Salfred 876184610Salfred if (status & AT91_UDP_INT_EPS) { 877184610Salfred 878184610Salfred DPRINTFN(5, "real endpoint interrupt 0x%08x\n", status); 879184610Salfred 880184610Salfred at91dci_interrupt_poll(sc); 881184610Salfred } 882184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 883184610Salfred 884184610Salfred return; 885184610Salfred} 886184610Salfred 887184610Salfredstatic void 888184610Salfredat91dci_setup_standard_chain_sub(struct at91dci_std_temp *temp) 889184610Salfred{ 890184610Salfred struct at91dci_td *td; 891184610Salfred 892184610Salfred /* get current Transfer Descriptor */ 893184610Salfred td = temp->td_next; 894184610Salfred temp->td = td; 895184610Salfred 896184610Salfred /* prepare for next TD */ 897184610Salfred temp->td_next = td->obj_next; 898184610Salfred 899184610Salfred /* fill out the Transfer Descriptor */ 900184610Salfred td->func = temp->func; 901184610Salfred td->pc = temp->pc; 902184610Salfred td->offset = temp->offset; 903184610Salfred td->remainder = temp->len; 904184610Salfred td->fifo_bank = 0; 905184610Salfred td->error = 0; 906184610Salfred td->did_stall = 0; 907184610Salfred td->short_pkt = temp->short_pkt; 908184610Salfred td->alt_next = temp->setup_alt_next; 909184610Salfred return; 910184610Salfred} 911184610Salfred 912184610Salfredstatic void 913184610Salfredat91dci_setup_standard_chain(struct usb2_xfer *xfer) 914184610Salfred{ 915184610Salfred struct at91dci_std_temp temp; 916184610Salfred struct at91dci_softc *sc; 917184610Salfred struct at91dci_td *td; 918184610Salfred uint32_t x; 919184610Salfred uint8_t ep_no; 920184610Salfred uint8_t need_sync; 921184610Salfred 922184610Salfred DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n", 923184610Salfred xfer->address, UE_GET_ADDR(xfer->endpoint), 924184610Salfred xfer->sumlen, usb2_get_speed(xfer->udev)); 925184610Salfred 926184610Salfred temp.max_frame_size = xfer->max_frame_size; 927184610Salfred 928184610Salfred td = xfer->td_start[0]; 929184610Salfred xfer->td_transfer_first = td; 930184610Salfred xfer->td_transfer_cache = td; 931184610Salfred 932184610Salfred /* setup temp */ 933184610Salfred 934184610Salfred temp.td = NULL; 935184610Salfred temp.td_next = xfer->td_start[0]; 936184610Salfred temp.setup_alt_next = xfer->flags_int.short_frames_ok; 937184610Salfred temp.offset = 0; 938184610Salfred 939184610Salfred sc = xfer->usb2_sc; 940184610Salfred ep_no = (xfer->endpoint & UE_ADDR); 941184610Salfred 942184610Salfred /* check if we should prepend a setup message */ 943184610Salfred 944184610Salfred if (xfer->flags_int.control_xfr) { 945184610Salfred if (xfer->flags_int.control_hdr) { 946184610Salfred 947184610Salfred temp.func = &at91dci_setup_rx; 948184610Salfred temp.len = xfer->frlengths[0]; 949184610Salfred temp.pc = xfer->frbuffers + 0; 950184610Salfred temp.short_pkt = temp.len ? 1 : 0; 951184610Salfred 952184610Salfred at91dci_setup_standard_chain_sub(&temp); 953184610Salfred } 954184610Salfred x = 1; 955184610Salfred } else { 956184610Salfred x = 0; 957184610Salfred } 958184610Salfred 959184610Salfred if (x != xfer->nframes) { 960184610Salfred if (xfer->endpoint & UE_DIR_IN) { 961184610Salfred temp.func = &at91dci_data_tx; 962184610Salfred need_sync = 1; 963184610Salfred } else { 964184610Salfred temp.func = &at91dci_data_rx; 965184610Salfred need_sync = 0; 966184610Salfred } 967184610Salfred 968184610Salfred /* setup "pc" pointer */ 969184610Salfred temp.pc = xfer->frbuffers + x; 970184610Salfred } else { 971184610Salfred need_sync = 0; 972184610Salfred } 973184610Salfred while (x != xfer->nframes) { 974184610Salfred 975184610Salfred /* DATA0 / DATA1 message */ 976184610Salfred 977184610Salfred temp.len = xfer->frlengths[x]; 978184610Salfred 979184610Salfred x++; 980184610Salfred 981184610Salfred if (x == xfer->nframes) { 982184610Salfred temp.setup_alt_next = 0; 983184610Salfred } 984184610Salfred if (temp.len == 0) { 985184610Salfred 986184610Salfred /* make sure that we send an USB packet */ 987184610Salfred 988184610Salfred temp.short_pkt = 0; 989184610Salfred 990184610Salfred } else { 991184610Salfred 992184610Salfred /* regular data transfer */ 993184610Salfred 994184610Salfred temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1; 995184610Salfred } 996184610Salfred 997184610Salfred at91dci_setup_standard_chain_sub(&temp); 998184610Salfred 999184610Salfred if (xfer->flags_int.isochronous_xfr) { 1000184610Salfred temp.offset += temp.len; 1001184610Salfred } else { 1002184610Salfred /* get next Page Cache pointer */ 1003184610Salfred temp.pc = xfer->frbuffers + x; 1004184610Salfred } 1005184610Salfred } 1006184610Salfred 1007184610Salfred /* always setup a valid "pc" pointer for status and sync */ 1008184610Salfred temp.pc = xfer->frbuffers + 0; 1009184610Salfred 1010184610Salfred /* check if we need to sync */ 1011184610Salfred if (need_sync && xfer->flags_int.control_xfr) { 1012184610Salfred 1013184610Salfred /* we need a SYNC point after TX */ 1014184610Salfred temp.func = &at91dci_data_tx_sync; 1015184610Salfred temp.len = 0; 1016184610Salfred temp.short_pkt = 0; 1017184610Salfred 1018184610Salfred at91dci_setup_standard_chain_sub(&temp); 1019184610Salfred } 1020184610Salfred /* check if we should append a status stage */ 1021184610Salfred if (xfer->flags_int.control_xfr && 1022184610Salfred !xfer->flags_int.control_act) { 1023184610Salfred 1024184610Salfred /* 1025184610Salfred * Send a DATA1 message and invert the current 1026184610Salfred * endpoint direction. 1027184610Salfred */ 1028184610Salfred if (xfer->endpoint & UE_DIR_IN) { 1029184610Salfred temp.func = &at91dci_data_rx; 1030184610Salfred need_sync = 0; 1031184610Salfred } else { 1032184610Salfred temp.func = &at91dci_data_tx; 1033184610Salfred need_sync = 1; 1034184610Salfred } 1035184610Salfred temp.len = 0; 1036184610Salfred temp.short_pkt = 0; 1037184610Salfred 1038184610Salfred at91dci_setup_standard_chain_sub(&temp); 1039184610Salfred if (need_sync) { 1040184610Salfred /* we need a SYNC point after TX */ 1041184610Salfred temp.func = &at91dci_data_tx_sync; 1042184610Salfred temp.len = 0; 1043184610Salfred temp.short_pkt = 0; 1044184610Salfred 1045184610Salfred at91dci_setup_standard_chain_sub(&temp); 1046184610Salfred } 1047184610Salfred } 1048184610Salfred /* must have at least one frame! */ 1049184610Salfred td = temp.td; 1050184610Salfred xfer->td_transfer_last = td; 1051184610Salfred 1052184610Salfred /* setup the correct fifo bank */ 1053184610Salfred if (sc->sc_ep_flags[ep_no].fifo_bank) { 1054184610Salfred td = xfer->td_transfer_first; 1055184610Salfred td->fifo_bank = 1; 1056184610Salfred } 1057184610Salfred return; 1058184610Salfred} 1059184610Salfred 1060184610Salfredstatic void 1061184610Salfredat91dci_timeout(void *arg) 1062184610Salfred{ 1063184610Salfred struct usb2_xfer *xfer = arg; 1064184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1065184610Salfred 1066184610Salfred DPRINTF("xfer=%p\n", xfer); 1067184610Salfred 1068184824Sthompsa USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1069184610Salfred 1070184610Salfred /* transfer is transferred */ 1071184610Salfred at91dci_device_done(xfer, USB_ERR_TIMEOUT); 1072184610Salfred 1073184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 1074184610Salfred 1075184610Salfred return; 1076184610Salfred} 1077184610Salfred 1078184610Salfredstatic void 1079184610Salfredat91dci_start_standard_chain(struct usb2_xfer *xfer) 1080184610Salfred{ 1081184610Salfred DPRINTFN(9, "\n"); 1082184610Salfred 1083184610Salfred /* poll one time */ 1084184610Salfred if (at91dci_xfer_do_fifo(xfer)) { 1085184610Salfred 1086184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1087184610Salfred uint8_t ep_no = xfer->endpoint & UE_ADDR; 1088184610Salfred 1089184610Salfred /* 1090184610Salfred * Only enable the endpoint interrupt when we are actually 1091184610Salfred * waiting for data, hence we are dealing with level 1092184610Salfred * triggered interrupts ! 1093184610Salfred */ 1094184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IER, AT91_UDP_INT_EP(ep_no)); 1095184610Salfred 1096184610Salfred DPRINTFN(15, "enable interrupts on endpoint %d\n", ep_no); 1097184610Salfred 1098184610Salfred /* put transfer on interrupt queue */ 1099184610Salfred usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer); 1100184610Salfred 1101184610Salfred /* start timeout, if any */ 1102184610Salfred if (xfer->timeout != 0) { 1103184610Salfred usb2_transfer_timeout_ms(xfer, 1104184610Salfred &at91dci_timeout, xfer->timeout); 1105184610Salfred } 1106184610Salfred } 1107184610Salfred return; 1108184610Salfred} 1109184610Salfred 1110184610Salfredstatic void 1111184610Salfredat91dci_root_intr_done(struct usb2_xfer *xfer, 1112184610Salfred struct usb2_sw_transfer *std) 1113184610Salfred{ 1114184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1115184610Salfred 1116184610Salfred DPRINTFN(9, "\n"); 1117184610Salfred 1118184824Sthompsa USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1119184610Salfred 1120184610Salfred if (std->state != USB_SW_TR_PRE_DATA) { 1121184610Salfred if (std->state == USB_SW_TR_PRE_CALLBACK) { 1122184610Salfred /* transfer transferred */ 1123184610Salfred at91dci_device_done(xfer, std->err); 1124184610Salfred } 1125184610Salfred goto done; 1126184610Salfred } 1127184610Salfred /* setup buffer */ 1128184610Salfred std->ptr = sc->sc_hub_idata; 1129184610Salfred std->len = sizeof(sc->sc_hub_idata); 1130184610Salfred 1131184610Salfred /* set port bit */ 1132184610Salfred sc->sc_hub_idata[0] = 0x02; /* we only have one port */ 1133184610Salfred 1134184610Salfreddone: 1135184610Salfred return; 1136184610Salfred} 1137184610Salfred 1138184610Salfredstatic usb2_error_t 1139184610Salfredat91dci_standard_done_sub(struct usb2_xfer *xfer) 1140184610Salfred{ 1141184610Salfred struct at91dci_td *td; 1142184610Salfred uint32_t len; 1143184610Salfred uint8_t error; 1144184610Salfred 1145184610Salfred DPRINTFN(9, "\n"); 1146184610Salfred 1147184610Salfred td = xfer->td_transfer_cache; 1148184610Salfred 1149184610Salfred do { 1150184610Salfred len = td->remainder; 1151184610Salfred 1152184610Salfred if (xfer->aframes != xfer->nframes) { 1153184610Salfred /* 1154184610Salfred * Verify the length and subtract 1155184610Salfred * the remainder from "frlengths[]": 1156184610Salfred */ 1157184610Salfred if (len > xfer->frlengths[xfer->aframes]) { 1158184610Salfred td->error = 1; 1159184610Salfred } else { 1160184610Salfred xfer->frlengths[xfer->aframes] -= len; 1161184610Salfred } 1162184610Salfred } 1163184610Salfred /* Check for transfer error */ 1164184610Salfred if (td->error) { 1165184610Salfred /* the transfer is finished */ 1166184610Salfred error = 1; 1167184610Salfred td = NULL; 1168184610Salfred break; 1169184610Salfred } 1170184610Salfred /* Check for short transfer */ 1171184610Salfred if (len > 0) { 1172184610Salfred if (xfer->flags_int.short_frames_ok) { 1173184610Salfred /* follow alt next */ 1174184610Salfred if (td->alt_next) { 1175184610Salfred td = td->obj_next; 1176184610Salfred } else { 1177184610Salfred td = NULL; 1178184610Salfred } 1179184610Salfred } else { 1180184610Salfred /* the transfer is finished */ 1181184610Salfred td = NULL; 1182184610Salfred } 1183184610Salfred error = 0; 1184184610Salfred break; 1185184610Salfred } 1186184610Salfred td = td->obj_next; 1187184610Salfred 1188184610Salfred /* this USB frame is complete */ 1189184610Salfred error = 0; 1190184610Salfred break; 1191184610Salfred 1192184610Salfred } while (0); 1193184610Salfred 1194184610Salfred /* update transfer cache */ 1195184610Salfred 1196184610Salfred xfer->td_transfer_cache = td; 1197184610Salfred 1198184610Salfred return (error ? 1199184610Salfred USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION); 1200184610Salfred} 1201184610Salfred 1202184610Salfredstatic void 1203184610Salfredat91dci_standard_done(struct usb2_xfer *xfer) 1204184610Salfred{ 1205184610Salfred usb2_error_t err = 0; 1206184610Salfred 1207184610Salfred DPRINTFN(13, "xfer=%p pipe=%p transfer done\n", 1208184610Salfred xfer, xfer->pipe); 1209184610Salfred 1210184610Salfred /* reset scanner */ 1211184610Salfred 1212184610Salfred xfer->td_transfer_cache = xfer->td_transfer_first; 1213184610Salfred 1214184610Salfred if (xfer->flags_int.control_xfr) { 1215184610Salfred 1216184610Salfred if (xfer->flags_int.control_hdr) { 1217184610Salfred 1218184610Salfred err = at91dci_standard_done_sub(xfer); 1219184610Salfred } 1220184610Salfred xfer->aframes = 1; 1221184610Salfred 1222184610Salfred if (xfer->td_transfer_cache == NULL) { 1223184610Salfred goto done; 1224184610Salfred } 1225184610Salfred } 1226184610Salfred while (xfer->aframes != xfer->nframes) { 1227184610Salfred 1228184610Salfred err = at91dci_standard_done_sub(xfer); 1229184610Salfred xfer->aframes++; 1230184610Salfred 1231184610Salfred if (xfer->td_transfer_cache == NULL) { 1232184610Salfred goto done; 1233184610Salfred } 1234184610Salfred } 1235184610Salfred 1236184610Salfred if (xfer->flags_int.control_xfr && 1237184610Salfred !xfer->flags_int.control_act) { 1238184610Salfred 1239184610Salfred err = at91dci_standard_done_sub(xfer); 1240184610Salfred } 1241184610Salfreddone: 1242184610Salfred at91dci_device_done(xfer, err); 1243184610Salfred return; 1244184610Salfred} 1245184610Salfred 1246184610Salfred/*------------------------------------------------------------------------* 1247184610Salfred * at91dci_device_done 1248184610Salfred * 1249184610Salfred * NOTE: this function can be called more than one time on the 1250184610Salfred * same USB transfer! 1251184610Salfred *------------------------------------------------------------------------*/ 1252184610Salfredstatic void 1253184610Salfredat91dci_device_done(struct usb2_xfer *xfer, usb2_error_t error) 1254184610Salfred{ 1255184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1256184610Salfred uint8_t ep_no; 1257184610Salfred 1258184824Sthompsa USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1259184610Salfred 1260184610Salfred DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n", 1261184610Salfred xfer, xfer->pipe, error); 1262184610Salfred 1263184610Salfred if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE) { 1264184610Salfred ep_no = (xfer->endpoint & UE_ADDR); 1265184610Salfred 1266184610Salfred /* disable endpoint interrupt */ 1267184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, AT91_UDP_INT_EP(ep_no)); 1268184610Salfred 1269184610Salfred DPRINTFN(15, "disable interrupts on endpoint %d\n", ep_no); 1270184610Salfred } 1271184610Salfred /* dequeue transfer and start next transfer */ 1272184610Salfred usb2_transfer_done(xfer, error); 1273184610Salfred return; 1274184610Salfred} 1275184610Salfred 1276184610Salfredstatic void 1277184610Salfredat91dci_set_stall(struct usb2_device *udev, struct usb2_xfer *xfer, 1278184610Salfred struct usb2_pipe *pipe) 1279184610Salfred{ 1280184610Salfred struct at91dci_softc *sc; 1281184610Salfred uint32_t csr_val; 1282184610Salfred uint8_t csr_reg; 1283184610Salfred 1284184824Sthompsa USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 1285184610Salfred 1286184610Salfred DPRINTFN(5, "pipe=%p\n", pipe); 1287184610Salfred 1288184610Salfred if (xfer) { 1289184610Salfred /* cancel any ongoing transfers */ 1290184610Salfred at91dci_device_done(xfer, USB_ERR_STALLED); 1291184610Salfred } 1292184610Salfred /* set FORCESTALL */ 1293184610Salfred sc = AT9100_DCI_BUS2SC(udev->bus); 1294184610Salfred csr_reg = (pipe->edesc->bEndpointAddress & UE_ADDR); 1295184610Salfred csr_reg = AT91_UDP_CSR(csr_reg); 1296184610Salfred csr_val = AT91_UDP_READ_4(sc, csr_reg); 1297184610Salfred AT91_CSR_ACK(csr_val, AT91_UDP_CSR_FORCESTALL); 1298184610Salfred AT91_UDP_WRITE_4(sc, csr_reg, csr_val); 1299184610Salfred return; 1300184610Salfred} 1301184610Salfred 1302184610Salfredstatic void 1303184610Salfredat91dci_clear_stall_sub(struct at91dci_softc *sc, uint8_t ep_no, 1304184610Salfred uint8_t ep_type, uint8_t ep_dir) 1305184610Salfred{ 1306184610Salfred const struct usb2_hw_ep_profile *pf; 1307184610Salfred uint32_t csr_val; 1308184610Salfred uint32_t temp; 1309184610Salfred uint8_t csr_reg; 1310184610Salfred uint8_t to; 1311184610Salfred 1312184610Salfred if (ep_type == UE_CONTROL) { 1313184610Salfred /* clearing stall is not needed */ 1314184610Salfred return; 1315184610Salfred } 1316184610Salfred /* compute CSR register offset */ 1317184610Salfred csr_reg = AT91_UDP_CSR(ep_no); 1318184610Salfred 1319184610Salfred /* compute default CSR value */ 1320184610Salfred csr_val = 0; 1321184610Salfred AT91_CSR_ACK(csr_val, 0); 1322184610Salfred 1323184610Salfred /* disable endpoint */ 1324184610Salfred AT91_UDP_WRITE_4(sc, csr_reg, csr_val); 1325184610Salfred 1326184610Salfred /* get endpoint profile */ 1327184610Salfred at91dci_get_hw_ep_profile(NULL, &pf, ep_no); 1328184610Salfred 1329184610Salfred /* reset FIFO */ 1330184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_RST, AT91_UDP_RST_EP(ep_no)); 1331184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_RST, 0); 1332184610Salfred 1333184610Salfred /* 1334184610Salfred * NOTE: One would assume that a FIFO reset would release the 1335184610Salfred * FIFO banks aswell, but it doesn't! We have to do this 1336184610Salfred * manually! 1337184610Salfred */ 1338184610Salfred 1339184610Salfred /* release FIFO banks, if any */ 1340184610Salfred for (to = 0; to != 2; to++) { 1341184610Salfred 1342184610Salfred /* get csr value */ 1343184610Salfred csr_val = AT91_UDP_READ_4(sc, csr_reg); 1344184610Salfred 1345184610Salfred if (csr_val & (AT91_UDP_CSR_RX_DATA_BK0 | 1346184610Salfred AT91_UDP_CSR_RX_DATA_BK1)) { 1347184610Salfred /* clear status bits */ 1348184610Salfred if (pf->support_multi_buffer) { 1349184610Salfred if (sc->sc_ep_flags[ep_no].fifo_bank) { 1350184610Salfred sc->sc_ep_flags[ep_no].fifo_bank = 0; 1351184610Salfred temp = AT91_UDP_CSR_RX_DATA_BK1; 1352184610Salfred } else { 1353184610Salfred sc->sc_ep_flags[ep_no].fifo_bank = 1; 1354184610Salfred temp = AT91_UDP_CSR_RX_DATA_BK0; 1355184610Salfred } 1356184610Salfred } else { 1357184610Salfred temp = (AT91_UDP_CSR_RX_DATA_BK0 | 1358184610Salfred AT91_UDP_CSR_RX_DATA_BK1); 1359184610Salfred } 1360184610Salfred } else { 1361184610Salfred temp = 0; 1362184610Salfred } 1363184610Salfred 1364184610Salfred /* clear FORCESTALL */ 1365184610Salfred temp |= AT91_UDP_CSR_STALLSENT; 1366184610Salfred 1367184610Salfred AT91_CSR_ACK(csr_val, temp); 1368184610Salfred AT91_UDP_WRITE_4(sc, csr_reg, csr_val); 1369184610Salfred } 1370184610Salfred 1371184610Salfred /* compute default CSR value */ 1372184610Salfred csr_val = 0; 1373184610Salfred AT91_CSR_ACK(csr_val, 0); 1374184610Salfred 1375184610Salfred /* enable endpoint */ 1376184610Salfred csr_val &= ~AT91_UDP_CSR_ET_MASK; 1377184610Salfred csr_val |= AT91_UDP_CSR_EPEDS; 1378184610Salfred 1379184610Salfred if (ep_type == UE_CONTROL) { 1380184610Salfred csr_val |= AT91_UDP_CSR_ET_CTRL; 1381184610Salfred } else { 1382184610Salfred if (ep_type == UE_BULK) { 1383184610Salfred csr_val |= AT91_UDP_CSR_ET_BULK; 1384184610Salfred } else if (ep_type == UE_INTERRUPT) { 1385184610Salfred csr_val |= AT91_UDP_CSR_ET_INT; 1386184610Salfred } else { 1387184610Salfred csr_val |= AT91_UDP_CSR_ET_ISO; 1388184610Salfred } 1389184610Salfred if (ep_dir & UE_DIR_IN) { 1390184610Salfred csr_val |= AT91_UDP_CSR_ET_DIR_IN; 1391184610Salfred } 1392184610Salfred } 1393184610Salfred 1394184610Salfred /* enable endpoint */ 1395184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_CSR(ep_no), csr_val); 1396184610Salfred 1397184610Salfred return; 1398184610Salfred} 1399184610Salfred 1400184610Salfredstatic void 1401184610Salfredat91dci_clear_stall(struct usb2_device *udev, struct usb2_pipe *pipe) 1402184610Salfred{ 1403184610Salfred struct at91dci_softc *sc; 1404184610Salfred struct usb2_endpoint_descriptor *ed; 1405184610Salfred 1406184610Salfred DPRINTFN(5, "pipe=%p\n", pipe); 1407184610Salfred 1408184824Sthompsa USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 1409184610Salfred 1410184610Salfred /* check mode */ 1411184610Salfred if (udev->flags.usb2_mode != USB_MODE_DEVICE) { 1412184610Salfred /* not supported */ 1413184610Salfred return; 1414184610Salfred } 1415184610Salfred /* get softc */ 1416184610Salfred sc = AT9100_DCI_BUS2SC(udev->bus); 1417184610Salfred 1418184610Salfred /* get endpoint descriptor */ 1419184610Salfred ed = pipe->edesc; 1420184610Salfred 1421184610Salfred /* reset endpoint */ 1422184610Salfred at91dci_clear_stall_sub(sc, 1423184610Salfred (ed->bEndpointAddress & UE_ADDR), 1424184610Salfred (ed->bmAttributes & UE_XFERTYPE), 1425184610Salfred (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); 1426184610Salfred return; 1427184610Salfred} 1428184610Salfred 1429184610Salfredusb2_error_t 1430184610Salfredat91dci_init(struct at91dci_softc *sc) 1431184610Salfred{ 1432184610Salfred uint32_t csr_val; 1433184610Salfred uint8_t n; 1434184610Salfred 1435184610Salfred DPRINTF("start\n"); 1436184610Salfred 1437184610Salfred /* set up the bus structure */ 1438184610Salfred sc->sc_bus.usbrev = USB_REV_1_1; 1439184610Salfred sc->sc_bus.methods = &at91dci_bus_methods; 1440184610Salfred 1441184824Sthompsa USB_BUS_LOCK(&sc->sc_bus); 1442184610Salfred 1443184610Salfred /* turn on clocks */ 1444184610Salfred 1445184610Salfred if (sc->sc_clocks_on) { 1446184610Salfred (sc->sc_clocks_on) (sc->sc_clocks_arg); 1447184610Salfred } 1448184610Salfred /* wait a little for things to stabilise */ 1449184824Sthompsa usb2_pause_mtx(&sc->sc_bus.bus_mtx, 1); 1450184610Salfred 1451184610Salfred /* disable and clear all interrupts */ 1452184610Salfred 1453184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 0xFFFFFFFF); 1454184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_ICR, 0xFFFFFFFF); 1455184610Salfred 1456184610Salfred /* compute default CSR value */ 1457184610Salfred 1458184610Salfred csr_val = 0; 1459184610Salfred AT91_CSR_ACK(csr_val, 0); 1460184610Salfred 1461184610Salfred /* disable all endpoints */ 1462184610Salfred 1463184610Salfred for (n = 0; n != AT91_UDP_EP_MAX; n++) { 1464184610Salfred 1465184610Salfred /* disable endpoint */ 1466184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_CSR(n), csr_val); 1467184610Salfred } 1468184610Salfred 1469184610Salfred /* enable the control endpoint */ 1470184610Salfred 1471184610Salfred AT91_CSR_ACK(csr_val, AT91_UDP_CSR_ET_CTRL | 1472184610Salfred AT91_UDP_CSR_EPEDS); 1473184610Salfred 1474184610Salfred /* write to FIFO control register */ 1475184610Salfred 1476184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_CSR(0), csr_val); 1477184610Salfred 1478184610Salfred /* enable the interrupts we want */ 1479184610Salfred 1480184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IER, AT91_UDP_INT_BUS); 1481184610Salfred 1482184610Salfred /* turn off clocks */ 1483184610Salfred 1484184610Salfred at91dci_clocks_off(sc); 1485184610Salfred 1486184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 1487184610Salfred 1488184610Salfred /* catch any lost interrupts */ 1489184610Salfred 1490184610Salfred at91dci_do_poll(&sc->sc_bus); 1491184610Salfred 1492184610Salfred return (0); /* success */ 1493184610Salfred} 1494184610Salfred 1495184610Salfredvoid 1496184610Salfredat91dci_uninit(struct at91dci_softc *sc) 1497184610Salfred{ 1498184824Sthompsa USB_BUS_LOCK(&sc->sc_bus); 1499184610Salfred 1500184610Salfred /* disable and clear all interrupts */ 1501184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 0xFFFFFFFF); 1502184610Salfred AT91_UDP_WRITE_4(sc, AT91_UDP_ICR, 0xFFFFFFFF); 1503184610Salfred 1504184610Salfred sc->sc_flags.port_powered = 0; 1505184610Salfred sc->sc_flags.status_vbus = 0; 1506184610Salfred sc->sc_flags.status_bus_reset = 0; 1507184610Salfred sc->sc_flags.status_suspend = 0; 1508184610Salfred sc->sc_flags.change_suspend = 0; 1509184610Salfred sc->sc_flags.change_connect = 1; 1510184610Salfred 1511184610Salfred at91dci_pull_down(sc); 1512184610Salfred at91dci_clocks_off(sc); 1513184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 1514184610Salfred 1515184610Salfred return; 1516184610Salfred} 1517184610Salfred 1518184610Salfredvoid 1519184610Salfredat91dci_suspend(struct at91dci_softc *sc) 1520184610Salfred{ 1521184610Salfred return; 1522184610Salfred} 1523184610Salfred 1524184610Salfredvoid 1525184610Salfredat91dci_resume(struct at91dci_softc *sc) 1526184610Salfred{ 1527184610Salfred return; 1528184610Salfred} 1529184610Salfred 1530184610Salfredstatic void 1531184610Salfredat91dci_do_poll(struct usb2_bus *bus) 1532184610Salfred{ 1533184610Salfred struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus); 1534184610Salfred 1535184824Sthompsa USB_BUS_LOCK(&sc->sc_bus); 1536184610Salfred at91dci_interrupt_poll(sc); 1537184610Salfred at91dci_root_ctrl_poll(sc); 1538184824Sthompsa USB_BUS_UNLOCK(&sc->sc_bus); 1539184610Salfred return; 1540184610Salfred} 1541184610Salfred 1542184610Salfred/*------------------------------------------------------------------------* 1543184610Salfred * at91dci bulk support 1544184610Salfred *------------------------------------------------------------------------*/ 1545184610Salfredstatic void 1546184610Salfredat91dci_device_bulk_open(struct usb2_xfer *xfer) 1547184610Salfred{ 1548184610Salfred return; 1549184610Salfred} 1550184610Salfred 1551184610Salfredstatic void 1552184610Salfredat91dci_device_bulk_close(struct usb2_xfer *xfer) 1553184610Salfred{ 1554184610Salfred at91dci_device_done(xfer, USB_ERR_CANCELLED); 1555184610Salfred return; 1556184610Salfred} 1557184610Salfred 1558184610Salfredstatic void 1559184610Salfredat91dci_device_bulk_enter(struct usb2_xfer *xfer) 1560184610Salfred{ 1561184610Salfred return; 1562184610Salfred} 1563184610Salfred 1564184610Salfredstatic void 1565184610Salfredat91dci_device_bulk_start(struct usb2_xfer *xfer) 1566184610Salfred{ 1567184610Salfred /* setup TDs */ 1568184610Salfred at91dci_setup_standard_chain(xfer); 1569184610Salfred at91dci_start_standard_chain(xfer); 1570184610Salfred return; 1571184610Salfred} 1572184610Salfred 1573184610Salfredstruct usb2_pipe_methods at91dci_device_bulk_methods = 1574184610Salfred{ 1575184610Salfred .open = at91dci_device_bulk_open, 1576184610Salfred .close = at91dci_device_bulk_close, 1577184610Salfred .enter = at91dci_device_bulk_enter, 1578184610Salfred .start = at91dci_device_bulk_start, 1579184610Salfred .enter_is_cancelable = 1, 1580184610Salfred .start_is_cancelable = 1, 1581184610Salfred}; 1582184610Salfred 1583184610Salfred/*------------------------------------------------------------------------* 1584184610Salfred * at91dci control support 1585184610Salfred *------------------------------------------------------------------------*/ 1586184610Salfredstatic void 1587184610Salfredat91dci_device_ctrl_open(struct usb2_xfer *xfer) 1588184610Salfred{ 1589184610Salfred return; 1590184610Salfred} 1591184610Salfred 1592184610Salfredstatic void 1593184610Salfredat91dci_device_ctrl_close(struct usb2_xfer *xfer) 1594184610Salfred{ 1595184610Salfred at91dci_device_done(xfer, USB_ERR_CANCELLED); 1596184610Salfred return; 1597184610Salfred} 1598184610Salfred 1599184610Salfredstatic void 1600184610Salfredat91dci_device_ctrl_enter(struct usb2_xfer *xfer) 1601184610Salfred{ 1602184610Salfred return; 1603184610Salfred} 1604184610Salfred 1605184610Salfredstatic void 1606184610Salfredat91dci_device_ctrl_start(struct usb2_xfer *xfer) 1607184610Salfred{ 1608184610Salfred /* setup TDs */ 1609184610Salfred at91dci_setup_standard_chain(xfer); 1610184610Salfred at91dci_start_standard_chain(xfer); 1611184610Salfred return; 1612184610Salfred} 1613184610Salfred 1614184610Salfredstruct usb2_pipe_methods at91dci_device_ctrl_methods = 1615184610Salfred{ 1616184610Salfred .open = at91dci_device_ctrl_open, 1617184610Salfred .close = at91dci_device_ctrl_close, 1618184610Salfred .enter = at91dci_device_ctrl_enter, 1619184610Salfred .start = at91dci_device_ctrl_start, 1620184610Salfred .enter_is_cancelable = 1, 1621184610Salfred .start_is_cancelable = 1, 1622184610Salfred}; 1623184610Salfred 1624184610Salfred/*------------------------------------------------------------------------* 1625184610Salfred * at91dci interrupt support 1626184610Salfred *------------------------------------------------------------------------*/ 1627184610Salfredstatic void 1628184610Salfredat91dci_device_intr_open(struct usb2_xfer *xfer) 1629184610Salfred{ 1630184610Salfred return; 1631184610Salfred} 1632184610Salfred 1633184610Salfredstatic void 1634184610Salfredat91dci_device_intr_close(struct usb2_xfer *xfer) 1635184610Salfred{ 1636184610Salfred at91dci_device_done(xfer, USB_ERR_CANCELLED); 1637184610Salfred return; 1638184610Salfred} 1639184610Salfred 1640184610Salfredstatic void 1641184610Salfredat91dci_device_intr_enter(struct usb2_xfer *xfer) 1642184610Salfred{ 1643184610Salfred return; 1644184610Salfred} 1645184610Salfred 1646184610Salfredstatic void 1647184610Salfredat91dci_device_intr_start(struct usb2_xfer *xfer) 1648184610Salfred{ 1649184610Salfred /* setup TDs */ 1650184610Salfred at91dci_setup_standard_chain(xfer); 1651184610Salfred at91dci_start_standard_chain(xfer); 1652184610Salfred return; 1653184610Salfred} 1654184610Salfred 1655184610Salfredstruct usb2_pipe_methods at91dci_device_intr_methods = 1656184610Salfred{ 1657184610Salfred .open = at91dci_device_intr_open, 1658184610Salfred .close = at91dci_device_intr_close, 1659184610Salfred .enter = at91dci_device_intr_enter, 1660184610Salfred .start = at91dci_device_intr_start, 1661184610Salfred .enter_is_cancelable = 1, 1662184610Salfred .start_is_cancelable = 1, 1663184610Salfred}; 1664184610Salfred 1665184610Salfred/*------------------------------------------------------------------------* 1666184610Salfred * at91dci full speed isochronous support 1667184610Salfred *------------------------------------------------------------------------*/ 1668184610Salfredstatic void 1669184610Salfredat91dci_device_isoc_fs_open(struct usb2_xfer *xfer) 1670184610Salfred{ 1671184610Salfred return; 1672184610Salfred} 1673184610Salfred 1674184610Salfredstatic void 1675184610Salfredat91dci_device_isoc_fs_close(struct usb2_xfer *xfer) 1676184610Salfred{ 1677184610Salfred at91dci_device_done(xfer, USB_ERR_CANCELLED); 1678184610Salfred return; 1679184610Salfred} 1680184610Salfred 1681184610Salfredstatic void 1682184610Salfredat91dci_device_isoc_fs_enter(struct usb2_xfer *xfer) 1683184610Salfred{ 1684184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1685184610Salfred uint32_t temp; 1686184610Salfred uint32_t nframes; 1687184610Salfred 1688184610Salfred DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", 1689184610Salfred xfer, xfer->pipe->isoc_next, xfer->nframes); 1690184610Salfred 1691184610Salfred /* get the current frame index */ 1692184610Salfred 1693184610Salfred nframes = AT91_UDP_READ_4(sc, AT91_UDP_FRM); 1694184610Salfred 1695184610Salfred /* 1696184610Salfred * check if the frame index is within the window where the frames 1697184610Salfred * will be inserted 1698184610Salfred */ 1699184610Salfred temp = (nframes - xfer->pipe->isoc_next) & AT91_UDP_FRM_MASK; 1700184610Salfred 1701184610Salfred if ((xfer->pipe->is_synced == 0) || 1702184610Salfred (temp < xfer->nframes)) { 1703184610Salfred /* 1704184610Salfred * If there is data underflow or the pipe queue is 1705184610Salfred * empty we schedule the transfer a few frames ahead 1706184610Salfred * of the current frame position. Else two isochronous 1707184610Salfred * transfers might overlap. 1708184610Salfred */ 1709184610Salfred xfer->pipe->isoc_next = (nframes + 3) & AT91_UDP_FRM_MASK; 1710184610Salfred xfer->pipe->is_synced = 1; 1711184610Salfred DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next); 1712184610Salfred } 1713184610Salfred /* 1714184610Salfred * compute how many milliseconds the insertion is ahead of the 1715184610Salfred * current frame position: 1716184610Salfred */ 1717184610Salfred temp = (xfer->pipe->isoc_next - nframes) & AT91_UDP_FRM_MASK; 1718184610Salfred 1719184610Salfred /* 1720184610Salfred * pre-compute when the isochronous transfer will be finished: 1721184610Salfred */ 1722184610Salfred xfer->isoc_time_complete = 1723184610Salfred usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp + 1724184610Salfred xfer->nframes; 1725184610Salfred 1726184610Salfred /* compute frame number for next insertion */ 1727184610Salfred xfer->pipe->isoc_next += xfer->nframes; 1728184610Salfred 1729184610Salfred /* setup TDs */ 1730184610Salfred at91dci_setup_standard_chain(xfer); 1731184610Salfred return; 1732184610Salfred} 1733184610Salfred 1734184610Salfredstatic void 1735184610Salfredat91dci_device_isoc_fs_start(struct usb2_xfer *xfer) 1736184610Salfred{ 1737184610Salfred /* start TD chain */ 1738184610Salfred at91dci_start_standard_chain(xfer); 1739184610Salfred return; 1740184610Salfred} 1741184610Salfred 1742184610Salfredstruct usb2_pipe_methods at91dci_device_isoc_fs_methods = 1743184610Salfred{ 1744184610Salfred .open = at91dci_device_isoc_fs_open, 1745184610Salfred .close = at91dci_device_isoc_fs_close, 1746184610Salfred .enter = at91dci_device_isoc_fs_enter, 1747184610Salfred .start = at91dci_device_isoc_fs_start, 1748184610Salfred .enter_is_cancelable = 1, 1749184610Salfred .start_is_cancelable = 1, 1750184610Salfred}; 1751184610Salfred 1752184610Salfred/*------------------------------------------------------------------------* 1753184610Salfred * at91dci root control support 1754184610Salfred *------------------------------------------------------------------------* 1755184610Salfred * simulate a hardware HUB by handling 1756184610Salfred * all the necessary requests 1757184610Salfred *------------------------------------------------------------------------*/ 1758184610Salfred 1759184610Salfredstatic void 1760184610Salfredat91dci_root_ctrl_open(struct usb2_xfer *xfer) 1761184610Salfred{ 1762184610Salfred return; 1763184610Salfred} 1764184610Salfred 1765184610Salfredstatic void 1766184610Salfredat91dci_root_ctrl_close(struct usb2_xfer *xfer) 1767184610Salfred{ 1768184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1769184610Salfred 1770184610Salfred if (sc->sc_root_ctrl.xfer == xfer) { 1771184610Salfred sc->sc_root_ctrl.xfer = NULL; 1772184610Salfred } 1773184610Salfred at91dci_device_done(xfer, USB_ERR_CANCELLED); 1774184610Salfred return; 1775184610Salfred} 1776184610Salfred 1777184610Salfred/* 1778184610Salfred * USB descriptors for the virtual Root HUB: 1779184610Salfred */ 1780184610Salfred 1781184610Salfredstatic const struct usb2_device_descriptor at91dci_devd = { 1782184610Salfred .bLength = sizeof(struct usb2_device_descriptor), 1783184610Salfred .bDescriptorType = UDESC_DEVICE, 1784184610Salfred .bcdUSB = {0x00, 0x02}, 1785184610Salfred .bDeviceClass = UDCLASS_HUB, 1786184610Salfred .bDeviceSubClass = UDSUBCLASS_HUB, 1787184610Salfred .bDeviceProtocol = UDPROTO_HSHUBSTT, 1788184610Salfred .bMaxPacketSize = 64, 1789184610Salfred .bcdDevice = {0x00, 0x01}, 1790184610Salfred .iManufacturer = 1, 1791184610Salfred .iProduct = 2, 1792184610Salfred .bNumConfigurations = 1, 1793184610Salfred}; 1794184610Salfred 1795184610Salfredstatic const struct usb2_device_qualifier at91dci_odevd = { 1796184610Salfred .bLength = sizeof(struct usb2_device_qualifier), 1797184610Salfred .bDescriptorType = UDESC_DEVICE_QUALIFIER, 1798184610Salfred .bcdUSB = {0x00, 0x02}, 1799184610Salfred .bDeviceClass = UDCLASS_HUB, 1800184610Salfred .bDeviceSubClass = UDSUBCLASS_HUB, 1801184610Salfred .bDeviceProtocol = UDPROTO_FSHUB, 1802184610Salfred .bMaxPacketSize0 = 0, 1803184610Salfred .bNumConfigurations = 0, 1804184610Salfred}; 1805184610Salfred 1806184610Salfredstatic const struct at91dci_config_desc at91dci_confd = { 1807184610Salfred .confd = { 1808184610Salfred .bLength = sizeof(struct usb2_config_descriptor), 1809184610Salfred .bDescriptorType = UDESC_CONFIG, 1810184610Salfred .wTotalLength[0] = sizeof(at91dci_confd), 1811184610Salfred .bNumInterface = 1, 1812184610Salfred .bConfigurationValue = 1, 1813184610Salfred .iConfiguration = 0, 1814184610Salfred .bmAttributes = UC_SELF_POWERED, 1815184610Salfred .bMaxPower = 0, 1816184610Salfred }, 1817184610Salfred .ifcd = { 1818184610Salfred .bLength = sizeof(struct usb2_interface_descriptor), 1819184610Salfred .bDescriptorType = UDESC_INTERFACE, 1820184610Salfred .bNumEndpoints = 1, 1821184610Salfred .bInterfaceClass = UICLASS_HUB, 1822184610Salfred .bInterfaceSubClass = UISUBCLASS_HUB, 1823184610Salfred .bInterfaceProtocol = UIPROTO_HSHUBSTT, 1824184610Salfred }, 1825184610Salfred 1826184610Salfred .endpd = { 1827184610Salfred .bLength = sizeof(struct usb2_endpoint_descriptor), 1828184610Salfred .bDescriptorType = UDESC_ENDPOINT, 1829184610Salfred .bEndpointAddress = (UE_DIR_IN | AT9100_DCI_INTR_ENDPT), 1830184610Salfred .bmAttributes = UE_INTERRUPT, 1831184610Salfred .wMaxPacketSize[0] = 8, 1832184610Salfred .bInterval = 255, 1833184610Salfred }, 1834184610Salfred}; 1835184610Salfred 1836184610Salfredstatic const struct usb2_hub_descriptor_min at91dci_hubd = { 1837184610Salfred .bDescLength = sizeof(at91dci_hubd), 1838184610Salfred .bDescriptorType = UDESC_HUB, 1839184610Salfred .bNbrPorts = 1, 1840184610Salfred .wHubCharacteristics[0] = 1841184610Salfred (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF, 1842184610Salfred .wHubCharacteristics[1] = 1843184610Salfred (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 16, 1844184610Salfred .bPwrOn2PwrGood = 50, 1845184610Salfred .bHubContrCurrent = 0, 1846184610Salfred .DeviceRemovable = {0}, /* port is removable */ 1847184610Salfred}; 1848184610Salfred 1849184610Salfred#define STRING_LANG \ 1850184610Salfred 0x09, 0x04, /* American English */ 1851184610Salfred 1852184610Salfred#define STRING_VENDOR \ 1853184610Salfred 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'L', 0 1854184610Salfred 1855184610Salfred#define STRING_PRODUCT \ 1856184610Salfred 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \ 1857184610Salfred 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \ 1858184610Salfred 'U', 0, 'B', 0, 1859184610Salfred 1860184610SalfredUSB_MAKE_STRING_DESC(STRING_LANG, at91dci_langtab); 1861184610SalfredUSB_MAKE_STRING_DESC(STRING_VENDOR, at91dci_vendor); 1862184610SalfredUSB_MAKE_STRING_DESC(STRING_PRODUCT, at91dci_product); 1863184610Salfred 1864184610Salfredstatic void 1865184610Salfredat91dci_root_ctrl_enter(struct usb2_xfer *xfer) 1866184610Salfred{ 1867184610Salfred return; 1868184610Salfred} 1869184610Salfred 1870184610Salfredstatic void 1871184610Salfredat91dci_root_ctrl_start(struct usb2_xfer *xfer) 1872184610Salfred{ 1873184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1874184610Salfred 1875184610Salfred sc->sc_root_ctrl.xfer = xfer; 1876184610Salfred 1877184610Salfred usb2_config_td_queue_command( 1878184610Salfred &sc->sc_config_td, NULL, &at91dci_root_ctrl_task, 0, 0); 1879184610Salfred 1880184610Salfred return; 1881184610Salfred} 1882184610Salfred 1883184610Salfredstatic void 1884184610Salfredat91dci_root_ctrl_task(struct at91dci_softc *sc, 1885184610Salfred struct at91dci_config_copy *cc, uint16_t refcount) 1886184610Salfred{ 1887184610Salfred at91dci_root_ctrl_poll(sc); 1888184610Salfred return; 1889184610Salfred} 1890184610Salfred 1891184610Salfredstatic void 1892184610Salfredat91dci_root_ctrl_done(struct usb2_xfer *xfer, 1893184610Salfred struct usb2_sw_transfer *std) 1894184610Salfred{ 1895184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 1896184610Salfred uint16_t value; 1897184610Salfred uint16_t index; 1898184610Salfred uint8_t use_polling; 1899184610Salfred 1900184824Sthompsa USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1901184610Salfred 1902184610Salfred if (std->state != USB_SW_TR_SETUP) { 1903184610Salfred if (std->state == USB_SW_TR_PRE_CALLBACK) { 1904184610Salfred /* transfer transferred */ 1905184610Salfred at91dci_device_done(xfer, std->err); 1906184610Salfred } 1907184610Salfred goto done; 1908184610Salfred } 1909184610Salfred /* buffer reset */ 1910184610Salfred std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0); 1911184610Salfred std->len = 0; 1912184610Salfred 1913184610Salfred value = UGETW(std->req.wValue); 1914184610Salfred index = UGETW(std->req.wIndex); 1915184610Salfred 1916184824Sthompsa use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0; 1917184610Salfred 1918184610Salfred /* demultiplex the control request */ 1919184610Salfred 1920184610Salfred switch (std->req.bmRequestType) { 1921184610Salfred case UT_READ_DEVICE: 1922184610Salfred switch (std->req.bRequest) { 1923184610Salfred case UR_GET_DESCRIPTOR: 1924184610Salfred goto tr_handle_get_descriptor; 1925184610Salfred case UR_GET_CONFIG: 1926184610Salfred goto tr_handle_get_config; 1927184610Salfred case UR_GET_STATUS: 1928184610Salfred goto tr_handle_get_status; 1929184610Salfred default: 1930184610Salfred goto tr_stalled; 1931184610Salfred } 1932184610Salfred break; 1933184610Salfred 1934184610Salfred case UT_WRITE_DEVICE: 1935184610Salfred switch (std->req.bRequest) { 1936184610Salfred case UR_SET_ADDRESS: 1937184610Salfred goto tr_handle_set_address; 1938184610Salfred case UR_SET_CONFIG: 1939184610Salfred goto tr_handle_set_config; 1940184610Salfred case UR_CLEAR_FEATURE: 1941184610Salfred goto tr_valid; /* nop */ 1942184610Salfred case UR_SET_DESCRIPTOR: 1943184610Salfred goto tr_valid; /* nop */ 1944184610Salfred case UR_SET_FEATURE: 1945184610Salfred default: 1946184610Salfred goto tr_stalled; 1947184610Salfred } 1948184610Salfred break; 1949184610Salfred 1950184610Salfred case UT_WRITE_ENDPOINT: 1951184610Salfred switch (std->req.bRequest) { 1952184610Salfred case UR_CLEAR_FEATURE: 1953184610Salfred switch (UGETW(std->req.wValue)) { 1954184610Salfred case UF_ENDPOINT_HALT: 1955184610Salfred goto tr_handle_clear_halt; 1956184610Salfred case UF_DEVICE_REMOTE_WAKEUP: 1957184610Salfred goto tr_handle_clear_wakeup; 1958184610Salfred default: 1959184610Salfred goto tr_stalled; 1960184610Salfred } 1961184610Salfred break; 1962184610Salfred case UR_SET_FEATURE: 1963184610Salfred switch (UGETW(std->req.wValue)) { 1964184610Salfred case UF_ENDPOINT_HALT: 1965184610Salfred goto tr_handle_set_halt; 1966184610Salfred case UF_DEVICE_REMOTE_WAKEUP: 1967184610Salfred goto tr_handle_set_wakeup; 1968184610Salfred default: 1969184610Salfred goto tr_stalled; 1970184610Salfred } 1971184610Salfred break; 1972184610Salfred case UR_SYNCH_FRAME: 1973184610Salfred goto tr_valid; /* nop */ 1974184610Salfred default: 1975184610Salfred goto tr_stalled; 1976184610Salfred } 1977184610Salfred break; 1978184610Salfred 1979184610Salfred case UT_READ_ENDPOINT: 1980184610Salfred switch (std->req.bRequest) { 1981184610Salfred case UR_GET_STATUS: 1982184610Salfred goto tr_handle_get_ep_status; 1983184610Salfred default: 1984184610Salfred goto tr_stalled; 1985184610Salfred } 1986184610Salfred break; 1987184610Salfred 1988184610Salfred case UT_WRITE_INTERFACE: 1989184610Salfred switch (std->req.bRequest) { 1990184610Salfred case UR_SET_INTERFACE: 1991184610Salfred goto tr_handle_set_interface; 1992184610Salfred case UR_CLEAR_FEATURE: 1993184610Salfred goto tr_valid; /* nop */ 1994184610Salfred case UR_SET_FEATURE: 1995184610Salfred default: 1996184610Salfred goto tr_stalled; 1997184610Salfred } 1998184610Salfred break; 1999184610Salfred 2000184610Salfred case UT_READ_INTERFACE: 2001184610Salfred switch (std->req.bRequest) { 2002184610Salfred case UR_GET_INTERFACE: 2003184610Salfred goto tr_handle_get_interface; 2004184610Salfred case UR_GET_STATUS: 2005184610Salfred goto tr_handle_get_iface_status; 2006184610Salfred default: 2007184610Salfred goto tr_stalled; 2008184610Salfred } 2009184610Salfred break; 2010184610Salfred 2011184610Salfred case UT_WRITE_CLASS_INTERFACE: 2012184610Salfred case UT_WRITE_VENDOR_INTERFACE: 2013184610Salfred /* XXX forward */ 2014184610Salfred break; 2015184610Salfred 2016184610Salfred case UT_READ_CLASS_INTERFACE: 2017184610Salfred case UT_READ_VENDOR_INTERFACE: 2018184610Salfred /* XXX forward */ 2019184610Salfred break; 2020184610Salfred 2021184610Salfred case UT_WRITE_CLASS_DEVICE: 2022184610Salfred switch (std->req.bRequest) { 2023184610Salfred case UR_CLEAR_FEATURE: 2024184610Salfred goto tr_valid; 2025184610Salfred case UR_SET_DESCRIPTOR: 2026184610Salfred case UR_SET_FEATURE: 2027184610Salfred break; 2028184610Salfred default: 2029184610Salfred goto tr_stalled; 2030184610Salfred } 2031184610Salfred break; 2032184610Salfred 2033184610Salfred case UT_WRITE_CLASS_OTHER: 2034184610Salfred switch (std->req.bRequest) { 2035184610Salfred case UR_CLEAR_FEATURE: 2036184610Salfred goto tr_handle_clear_port_feature; 2037184610Salfred case UR_SET_FEATURE: 2038184610Salfred goto tr_handle_set_port_feature; 2039184610Salfred case UR_CLEAR_TT_BUFFER: 2040184610Salfred case UR_RESET_TT: 2041184610Salfred case UR_STOP_TT: 2042184610Salfred goto tr_valid; 2043184610Salfred 2044184610Salfred default: 2045184610Salfred goto tr_stalled; 2046184610Salfred } 2047184610Salfred break; 2048184610Salfred 2049184610Salfred case UT_READ_CLASS_OTHER: 2050184610Salfred switch (std->req.bRequest) { 2051184610Salfred case UR_GET_TT_STATE: 2052184610Salfred goto tr_handle_get_tt_state; 2053184610Salfred case UR_GET_STATUS: 2054184610Salfred goto tr_handle_get_port_status; 2055184610Salfred default: 2056184610Salfred goto tr_stalled; 2057184610Salfred } 2058184610Salfred break; 2059184610Salfred 2060184610Salfred case UT_READ_CLASS_DEVICE: 2061184610Salfred switch (std->req.bRequest) { 2062184610Salfred case UR_GET_DESCRIPTOR: 2063184610Salfred goto tr_handle_get_class_descriptor; 2064184610Salfred case UR_GET_STATUS: 2065184610Salfred goto tr_handle_get_class_status; 2066184610Salfred 2067184610Salfred default: 2068184610Salfred goto tr_stalled; 2069184610Salfred } 2070184610Salfred break; 2071184610Salfred default: 2072184610Salfred goto tr_stalled; 2073184610Salfred } 2074184610Salfred goto tr_valid; 2075184610Salfred 2076184610Salfredtr_handle_get_descriptor: 2077184610Salfred switch (value >> 8) { 2078184610Salfred case UDESC_DEVICE: 2079184610Salfred if (value & 0xff) { 2080184610Salfred goto tr_stalled; 2081184610Salfred } 2082184610Salfred std->len = sizeof(at91dci_devd); 2083184610Salfred std->ptr = USB_ADD_BYTES(&at91dci_devd, 0); 2084184610Salfred goto tr_valid; 2085184610Salfred case UDESC_CONFIG: 2086184610Salfred if (value & 0xff) { 2087184610Salfred goto tr_stalled; 2088184610Salfred } 2089184610Salfred std->len = sizeof(at91dci_confd); 2090184610Salfred std->ptr = USB_ADD_BYTES(&at91dci_confd, 0); 2091184610Salfred goto tr_valid; 2092184610Salfred case UDESC_STRING: 2093184610Salfred switch (value & 0xff) { 2094184610Salfred case 0: /* Language table */ 2095184610Salfred std->len = sizeof(at91dci_langtab); 2096184610Salfred std->ptr = USB_ADD_BYTES(&at91dci_langtab, 0); 2097184610Salfred goto tr_valid; 2098184610Salfred 2099184610Salfred case 1: /* Vendor */ 2100184610Salfred std->len = sizeof(at91dci_vendor); 2101184610Salfred std->ptr = USB_ADD_BYTES(&at91dci_vendor, 0); 2102184610Salfred goto tr_valid; 2103184610Salfred 2104184610Salfred case 2: /* Product */ 2105184610Salfred std->len = sizeof(at91dci_product); 2106184610Salfred std->ptr = USB_ADD_BYTES(&at91dci_product, 0); 2107184610Salfred goto tr_valid; 2108184610Salfred default: 2109184610Salfred break; 2110184610Salfred } 2111184610Salfred break; 2112184610Salfred default: 2113184610Salfred goto tr_stalled; 2114184610Salfred } 2115184610Salfred goto tr_stalled; 2116184610Salfred 2117184610Salfredtr_handle_get_config: 2118184610Salfred std->len = 1; 2119184610Salfred sc->sc_hub_temp.wValue[0] = sc->sc_conf; 2120184610Salfred goto tr_valid; 2121184610Salfred 2122184610Salfredtr_handle_get_status: 2123184610Salfred std->len = 2; 2124184610Salfred USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED); 2125184610Salfred goto tr_valid; 2126184610Salfred 2127184610Salfredtr_handle_set_address: 2128184610Salfred if (value & 0xFF00) { 2129184610Salfred goto tr_stalled; 2130184610Salfred } 2131184610Salfred sc->sc_rt_addr = value; 2132184610Salfred goto tr_valid; 2133184610Salfred 2134184610Salfredtr_handle_set_config: 2135184610Salfred if (value >= 2) { 2136184610Salfred goto tr_stalled; 2137184610Salfred } 2138184610Salfred sc->sc_conf = value; 2139184610Salfred goto tr_valid; 2140184610Salfred 2141184610Salfredtr_handle_get_interface: 2142184610Salfred std->len = 1; 2143184610Salfred sc->sc_hub_temp.wValue[0] = 0; 2144184610Salfred goto tr_valid; 2145184610Salfred 2146184610Salfredtr_handle_get_tt_state: 2147184610Salfredtr_handle_get_class_status: 2148184610Salfredtr_handle_get_iface_status: 2149184610Salfredtr_handle_get_ep_status: 2150184610Salfred std->len = 2; 2151184610Salfred USETW(sc->sc_hub_temp.wValue, 0); 2152184610Salfred goto tr_valid; 2153184610Salfred 2154184610Salfredtr_handle_set_halt: 2155184610Salfredtr_handle_set_interface: 2156184610Salfredtr_handle_set_wakeup: 2157184610Salfredtr_handle_clear_wakeup: 2158184610Salfredtr_handle_clear_halt: 2159184610Salfred goto tr_valid; 2160184610Salfred 2161184610Salfredtr_handle_clear_port_feature: 2162184610Salfred if (index != 1) { 2163184610Salfred goto tr_stalled; 2164184610Salfred } 2165184610Salfred DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index); 2166184610Salfred 2167184610Salfred switch (value) { 2168184610Salfred case UHF_PORT_SUSPEND: 2169184610Salfred at91dci_wakeup_peer(sc); 2170184610Salfred break; 2171184610Salfred 2172184610Salfred case UHF_PORT_ENABLE: 2173184610Salfred sc->sc_flags.port_enabled = 0; 2174184610Salfred break; 2175184610Salfred 2176184610Salfred case UHF_PORT_TEST: 2177184610Salfred case UHF_PORT_INDICATOR: 2178184610Salfred case UHF_C_PORT_ENABLE: 2179184610Salfred case UHF_C_PORT_OVER_CURRENT: 2180184610Salfred case UHF_C_PORT_RESET: 2181184610Salfred /* nops */ 2182184610Salfred break; 2183184610Salfred case UHF_PORT_POWER: 2184184610Salfred sc->sc_flags.port_powered = 0; 2185184610Salfred at91dci_pull_down(sc); 2186184610Salfred at91dci_clocks_off(sc); 2187184610Salfred break; 2188184610Salfred case UHF_C_PORT_CONNECTION: 2189184610Salfred sc->sc_flags.change_connect = 0; 2190184610Salfred break; 2191184610Salfred case UHF_C_PORT_SUSPEND: 2192184610Salfred sc->sc_flags.change_suspend = 0; 2193184610Salfred break; 2194184610Salfred default: 2195184610Salfred std->err = USB_ERR_IOERROR; 2196184610Salfred goto done; 2197184610Salfred } 2198184610Salfred goto tr_valid; 2199184610Salfred 2200184610Salfredtr_handle_set_port_feature: 2201184610Salfred if (index != 1) { 2202184610Salfred goto tr_stalled; 2203184610Salfred } 2204184610Salfred DPRINTFN(9, "UR_SET_PORT_FEATURE\n"); 2205184610Salfred 2206184610Salfred switch (value) { 2207184610Salfred case UHF_PORT_ENABLE: 2208184610Salfred sc->sc_flags.port_enabled = 1; 2209184610Salfred break; 2210184610Salfred case UHF_PORT_SUSPEND: 2211184610Salfred case UHF_PORT_RESET: 2212184610Salfred case UHF_PORT_TEST: 2213184610Salfred case UHF_PORT_INDICATOR: 2214184610Salfred /* nops */ 2215184610Salfred break; 2216184610Salfred case UHF_PORT_POWER: 2217184610Salfred sc->sc_flags.port_powered = 1; 2218184610Salfred break; 2219184610Salfred default: 2220184610Salfred std->err = USB_ERR_IOERROR; 2221184610Salfred goto done; 2222184610Salfred } 2223184610Salfred goto tr_valid; 2224184610Salfred 2225184610Salfredtr_handle_get_port_status: 2226184610Salfred 2227184610Salfred DPRINTFN(9, "UR_GET_PORT_STATUS\n"); 2228184610Salfred 2229184610Salfred if (index != 1) { 2230184610Salfred goto tr_stalled; 2231184610Salfred } 2232184610Salfred if (sc->sc_flags.status_vbus) { 2233184610Salfred at91dci_clocks_on(sc); 2234184610Salfred at91dci_pull_up(sc); 2235184610Salfred } else { 2236184610Salfred at91dci_pull_down(sc); 2237184610Salfred at91dci_clocks_off(sc); 2238184610Salfred } 2239184610Salfred 2240184610Salfred /* Select FULL-speed and Device Side Mode */ 2241184610Salfred 2242184610Salfred value = UPS_PORT_MODE_DEVICE; 2243184610Salfred 2244184610Salfred if (sc->sc_flags.port_powered) { 2245184610Salfred value |= UPS_PORT_POWER; 2246184610Salfred } 2247184610Salfred if (sc->sc_flags.port_enabled) { 2248184610Salfred value |= UPS_PORT_ENABLED; 2249184610Salfred } 2250184610Salfred if (sc->sc_flags.status_vbus && 2251184610Salfred sc->sc_flags.status_bus_reset) { 2252184610Salfred value |= UPS_CURRENT_CONNECT_STATUS; 2253184610Salfred } 2254184610Salfred if (sc->sc_flags.status_suspend) { 2255184610Salfred value |= UPS_SUSPEND; 2256184610Salfred } 2257184610Salfred USETW(sc->sc_hub_temp.ps.wPortStatus, value); 2258184610Salfred 2259184610Salfred value = 0; 2260184610Salfred 2261184610Salfred if (sc->sc_flags.change_connect) { 2262184610Salfred value |= UPS_C_CONNECT_STATUS; 2263184610Salfred 2264184610Salfred if (sc->sc_flags.status_vbus && 2265184610Salfred sc->sc_flags.status_bus_reset) { 2266184610Salfred /* reset endpoint flags */ 2267184610Salfred bzero(sc->sc_ep_flags, sizeof(sc->sc_ep_flags)); 2268184610Salfred } 2269184610Salfred } 2270184610Salfred if (sc->sc_flags.change_suspend) { 2271184610Salfred value |= UPS_C_SUSPEND; 2272184610Salfred } 2273184610Salfred USETW(sc->sc_hub_temp.ps.wPortChange, value); 2274184610Salfred std->len = sizeof(sc->sc_hub_temp.ps); 2275184610Salfred goto tr_valid; 2276184610Salfred 2277184610Salfredtr_handle_get_class_descriptor: 2278184610Salfred if (value & 0xFF) { 2279184610Salfred goto tr_stalled; 2280184610Salfred } 2281184610Salfred std->ptr = USB_ADD_BYTES(&at91dci_hubd, 0); 2282184610Salfred std->len = sizeof(at91dci_hubd); 2283184610Salfred goto tr_valid; 2284184610Salfred 2285184610Salfredtr_stalled: 2286184610Salfred std->err = USB_ERR_STALLED; 2287184610Salfredtr_valid: 2288184610Salfreddone: 2289184610Salfred return; 2290184610Salfred} 2291184610Salfred 2292184610Salfredstatic void 2293184610Salfredat91dci_root_ctrl_poll(struct at91dci_softc *sc) 2294184610Salfred{ 2295184610Salfred usb2_sw_transfer(&sc->sc_root_ctrl, 2296184610Salfred &at91dci_root_ctrl_done); 2297184610Salfred return; 2298184610Salfred} 2299184610Salfred 2300184610Salfredstruct usb2_pipe_methods at91dci_root_ctrl_methods = 2301184610Salfred{ 2302184610Salfred .open = at91dci_root_ctrl_open, 2303184610Salfred .close = at91dci_root_ctrl_close, 2304184610Salfred .enter = at91dci_root_ctrl_enter, 2305184610Salfred .start = at91dci_root_ctrl_start, 2306184610Salfred .enter_is_cancelable = 1, 2307184610Salfred .start_is_cancelable = 0, 2308184610Salfred}; 2309184610Salfred 2310184610Salfred/*------------------------------------------------------------------------* 2311184610Salfred * at91dci root interrupt support 2312184610Salfred *------------------------------------------------------------------------*/ 2313184610Salfredstatic void 2314184610Salfredat91dci_root_intr_open(struct usb2_xfer *xfer) 2315184610Salfred{ 2316184610Salfred return; 2317184610Salfred} 2318184610Salfred 2319184610Salfredstatic void 2320184610Salfredat91dci_root_intr_close(struct usb2_xfer *xfer) 2321184610Salfred{ 2322184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 2323184610Salfred 2324184610Salfred if (sc->sc_root_intr.xfer == xfer) { 2325184610Salfred sc->sc_root_intr.xfer = NULL; 2326184610Salfred } 2327184610Salfred at91dci_device_done(xfer, USB_ERR_CANCELLED); 2328184610Salfred return; 2329184610Salfred} 2330184610Salfred 2331184610Salfredstatic void 2332184610Salfredat91dci_root_intr_enter(struct usb2_xfer *xfer) 2333184610Salfred{ 2334184610Salfred return; 2335184610Salfred} 2336184610Salfred 2337184610Salfredstatic void 2338184610Salfredat91dci_root_intr_start(struct usb2_xfer *xfer) 2339184610Salfred{ 2340184610Salfred struct at91dci_softc *sc = xfer->usb2_sc; 2341184610Salfred 2342184610Salfred sc->sc_root_intr.xfer = xfer; 2343184610Salfred return; 2344184610Salfred} 2345184610Salfred 2346184610Salfredstruct usb2_pipe_methods at91dci_root_intr_methods = 2347184610Salfred{ 2348184610Salfred .open = at91dci_root_intr_open, 2349184610Salfred .close = at91dci_root_intr_close, 2350184610Salfred .enter = at91dci_root_intr_enter, 2351184610Salfred .start = at91dci_root_intr_start, 2352184610Salfred .enter_is_cancelable = 1, 2353184610Salfred .start_is_cancelable = 1, 2354184610Salfred}; 2355184610Salfred 2356184610Salfredstatic void 2357184610Salfredat91dci_xfer_setup(struct usb2_setup_params *parm) 2358184610Salfred{ 2359184610Salfred const struct usb2_hw_ep_profile *pf; 2360184610Salfred struct at91dci_softc *sc; 2361184610Salfred struct usb2_xfer *xfer; 2362184610Salfred void *last_obj; 2363184610Salfred uint32_t ntd; 2364184610Salfred uint32_t n; 2365184610Salfred uint8_t ep_no; 2366184610Salfred 2367184610Salfred sc = AT9100_DCI_BUS2SC(parm->udev->bus); 2368184610Salfred xfer = parm->curr_xfer; 2369184610Salfred 2370184610Salfred /* 2371184610Salfred * setup xfer 2372184610Salfred */ 2373184610Salfred xfer->usb2_sc = sc; 2374184610Salfred 2375184610Salfred /* 2376184610Salfred * NOTE: This driver does not use any of the parameters that 2377184610Salfred * are computed from the following values. Just set some 2378184610Salfred * reasonable dummies: 2379184610Salfred */ 2380184610Salfred parm->hc_max_packet_size = 0x500; 2381184610Salfred parm->hc_max_packet_count = 1; 2382184610Salfred parm->hc_max_frame_size = 0x500; 2383184610Salfred 2384184610Salfred usb2_transfer_setup_sub(parm); 2385184610Salfred 2386184610Salfred /* 2387184610Salfred * compute maximum number of TDs 2388184610Salfred */ 2389184610Salfred if (parm->methods == &at91dci_device_ctrl_methods) { 2390184610Salfred 2391184610Salfred ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */ 2392184610Salfred + 1 /* SYNC 2 */ ; 2393184610Salfred 2394184610Salfred } else if (parm->methods == &at91dci_device_bulk_methods) { 2395184610Salfred 2396184610Salfred ntd = xfer->nframes + 1 /* SYNC */ ; 2397184610Salfred 2398184610Salfred } else if (parm->methods == &at91dci_device_intr_methods) { 2399184610Salfred 2400184610Salfred ntd = xfer->nframes + 1 /* SYNC */ ; 2401184610Salfred 2402184610Salfred } else if (parm->methods == &at91dci_device_isoc_fs_methods) { 2403184610Salfred 2404184610Salfred ntd = xfer->nframes + 1 /* SYNC */ ; 2405184610Salfred 2406184610Salfred } else { 2407184610Salfred 2408184610Salfred ntd = 0; 2409184610Salfred } 2410184610Salfred 2411184610Salfred /* 2412184610Salfred * check if "usb2_transfer_setup_sub" set an error 2413184610Salfred */ 2414184610Salfred if (parm->err) { 2415184610Salfred return; 2416184610Salfred } 2417184610Salfred /* 2418184610Salfred * allocate transfer descriptors 2419184610Salfred */ 2420184610Salfred last_obj = NULL; 2421184610Salfred 2422184610Salfred /* 2423184610Salfred * get profile stuff 2424184610Salfred */ 2425184610Salfred if (ntd) { 2426184610Salfred 2427184610Salfred ep_no = xfer->endpoint & UE_ADDR; 2428184610Salfred at91dci_get_hw_ep_profile(parm->udev, &pf, ep_no); 2429184610Salfred 2430184610Salfred if (pf == NULL) { 2431184610Salfred /* should not happen */ 2432184610Salfred parm->err = USB_ERR_INVAL; 2433184610Salfred return; 2434184610Salfred } 2435184610Salfred } else { 2436184610Salfred ep_no = 0; 2437184610Salfred pf = NULL; 2438184610Salfred } 2439184610Salfred 2440184610Salfred /* align data */ 2441184610Salfred parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); 2442184610Salfred 2443184610Salfred for (n = 0; n != ntd; n++) { 2444184610Salfred 2445184610Salfred struct at91dci_td *td; 2446184610Salfred 2447184610Salfred if (parm->buf) { 2448184610Salfred 2449184610Salfred td = USB_ADD_BYTES(parm->buf, parm->size[0]); 2450184610Salfred 2451184610Salfred /* init TD */ 2452184610Salfred td->io_tag = sc->sc_io_tag; 2453184610Salfred td->io_hdl = sc->sc_io_hdl; 2454184610Salfred td->max_packet_size = xfer->max_packet_size; 2455184610Salfred td->status_reg = AT91_UDP_CSR(ep_no); 2456184610Salfred td->fifo_reg = AT91_UDP_FDR(ep_no); 2457184610Salfred if (pf->support_multi_buffer) { 2458184610Salfred td->support_multi_buffer = 1; 2459184610Salfred } 2460184610Salfred td->obj_next = last_obj; 2461184610Salfred 2462184610Salfred last_obj = td; 2463184610Salfred } 2464184610Salfred parm->size[0] += sizeof(*td); 2465184610Salfred } 2466184610Salfred 2467184610Salfred xfer->td_start[0] = last_obj; 2468184610Salfred return; 2469184610Salfred} 2470184610Salfred 2471184610Salfredstatic void 2472184610Salfredat91dci_xfer_unsetup(struct usb2_xfer *xfer) 2473184610Salfred{ 2474184610Salfred return; 2475184610Salfred} 2476184610Salfred 2477184610Salfredstatic void 2478184610Salfredat91dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc, 2479184610Salfred struct usb2_pipe *pipe) 2480184610Salfred{ 2481184610Salfred struct at91dci_softc *sc = AT9100_DCI_BUS2SC(udev->bus); 2482184610Salfred 2483184610Salfred DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n", 2484184610Salfred pipe, udev->address, 2485184610Salfred edesc->bEndpointAddress, udev->flags.usb2_mode, 2486184610Salfred sc->sc_rt_addr); 2487184610Salfred 2488184610Salfred if (udev->device_index == sc->sc_rt_addr) { 2489184610Salfred 2490184610Salfred if (udev->flags.usb2_mode != USB_MODE_HOST) { 2491184610Salfred /* not supported */ 2492184610Salfred return; 2493184610Salfred } 2494184610Salfred switch (edesc->bEndpointAddress) { 2495184610Salfred case USB_CONTROL_ENDPOINT: 2496184610Salfred pipe->methods = &at91dci_root_ctrl_methods; 2497184610Salfred break; 2498184610Salfred case UE_DIR_IN | AT9100_DCI_INTR_ENDPT: 2499184610Salfred pipe->methods = &at91dci_root_intr_methods; 2500184610Salfred break; 2501184610Salfred default: 2502184610Salfred /* do nothing */ 2503184610Salfred break; 2504184610Salfred } 2505184610Salfred } else { 2506184610Salfred 2507184610Salfred if (udev->flags.usb2_mode != USB_MODE_DEVICE) { 2508184610Salfred /* not supported */ 2509184610Salfred return; 2510184610Salfred } 2511184610Salfred if (udev->speed != USB_SPEED_FULL) { 2512184610Salfred /* not supported */ 2513184610Salfred return; 2514184610Salfred } 2515184610Salfred switch (edesc->bmAttributes & UE_XFERTYPE) { 2516184610Salfred case UE_CONTROL: 2517184610Salfred pipe->methods = &at91dci_device_ctrl_methods; 2518184610Salfred break; 2519184610Salfred case UE_INTERRUPT: 2520184610Salfred pipe->methods = &at91dci_device_intr_methods; 2521184610Salfred break; 2522184610Salfred case UE_ISOCHRONOUS: 2523184610Salfred pipe->methods = &at91dci_device_isoc_fs_methods; 2524184610Salfred break; 2525184610Salfred case UE_BULK: 2526184610Salfred pipe->methods = &at91dci_device_bulk_methods; 2527184610Salfred break; 2528184610Salfred default: 2529184610Salfred /* do nothing */ 2530184610Salfred break; 2531184610Salfred } 2532184610Salfred } 2533184610Salfred return; 2534184610Salfred} 2535184610Salfred 2536184610Salfredstruct usb2_bus_methods at91dci_bus_methods = 2537184610Salfred{ 2538184610Salfred .pipe_init = &at91dci_pipe_init, 2539184610Salfred .xfer_setup = &at91dci_xfer_setup, 2540184610Salfred .xfer_unsetup = &at91dci_xfer_unsetup, 2541184610Salfred .do_poll = &at91dci_do_poll, 2542184610Salfred .get_hw_ep_profile = &at91dci_get_hw_ep_profile, 2543184610Salfred .set_stall = &at91dci_set_stall, 2544184610Salfred .clear_stall = &at91dci_clear_stall, 2545184610Salfred .vbus_interrupt = &at91dci_vbus_interrupt, 2546184610Salfred .rem_wakeup_set = &at91dci_rem_wakeup_set, 2547184610Salfred}; 2548