1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <ddk/device.h> 8#include <ddk/io-buffer.h> 9#include <ddk/mmio-buffer.h> 10#include <ddk/protocol/platform-device.h> 11#include <ddk/protocol/usb-dci.h> 12#include <ddk/protocol/usb-mode-switch.h> 13#include <zircon/device/usb-peripheral.h> 14#include <zircon/listnode.h> 15#include <zircon/types.h> 16#include <zircon/hw/usb.h> 17 18#include <threads.h> 19 20#include "dwc3-types.h" 21 22// physical endpoint numbers for ep0 23#define EP0_OUT 0 24#define EP0_IN 1 25#define EP0_FIFO EP0_OUT 26 27#define EP_OUT(ep_num) (((ep_num) & 1) == 0) 28#define EP_IN(ep_num) (((ep_num) & 1) == 1) 29 30#define EVENT_BUFFER_SIZE PAGE_SIZE 31#define EP0_MAX_PACKET_SIZE 512 32#define DWC3_MAX_EPS 32 33 34// converts a USB endpoint address to 0 - 31 index 35#define dwc3_ep_num(addr) ((((addr) & 0xF) << 1) | !!((addr) & USB_DIR_IN)) 36 37typedef enum { 38 EP0_STATE_NONE, 39 EP0_STATE_SETUP, // Queued setup phase 40 EP0_STATE_DATA_OUT, // Queued data on EP0_OUT 41 EP0_STATE_DATA_IN, // Queued data on EP0_IN 42 EP0_STATE_WAIT_NRDY_OUT, // Waiting for not-ready on EP0_OUT 43 EP0_STATE_WAIT_NRDY_IN, // Waiting for not-ready on EP0_IN 44 EP0_STATE_STATUS, // Waiting for status to complete 45} dwc3_ep0_state; 46 47typedef struct { 48 io_buffer_t buffer; 49 dwc3_trb_t* first; // first TRB in the fifo 50 dwc3_trb_t* next; // next free TRB in the fifo 51 dwc3_trb_t* current; // TRB for currently pending transaction 52 dwc3_trb_t* last; // last TRB in the fifo (link TRB) 53} dwc3_fifo_t; 54 55typedef struct { 56 dwc3_fifo_t fifo; 57 list_node_t queued_reqs; // requests waiting to be processed 58 usb_request_t* current_req; // request currently being processed 59 unsigned rsrc_id; // resource ID for current_req 60 61 // Used for synchronizing endpoint state 62 // and ep specific hardware registers 63 // This should be acquired before dwc3_t.lock 64 // if acquiring both locks. 65 mtx_t lock; 66 67 uint16_t max_packet_size; 68 uint8_t ep_num; 69 bool enabled; 70 uint8_t type; // control, bulk, interrupt or isochronous 71 uint8_t interval; 72 // TODO(voydanoff) USB 3 specific stuff here 73 74 bool got_not_ready; 75 bool stalled; 76} dwc3_endpoint_t; 77 78typedef struct { 79 zx_device_t* zxdev; 80 zx_device_t* xhci_dev; 81 zx_device_t* parent; 82 platform_device_protocol_t pdev; 83 usb_mode_switch_protocol_t ums; 84 usb_dci_interface_t dci_intf; 85 mmio_buffer_t mmio; 86 zx_handle_t bti_handle; 87 88 usb_mode_t usb_mode; 89 bool start_device_on_xhci_release; 90 mtx_t usb_mode_lock; // protects usb_mode and start_device_on_xhci_release 91 92 // event stuff 93 io_buffer_t event_buffer; 94 zx_handle_t irq_handle; 95 thrd_t irq_thread; 96 97 dwc3_endpoint_t eps[DWC3_MAX_EPS]; 98 99 // connection state 100 usb_speed_t speed; 101 102 // ep0 stuff 103 usb_setup_t cur_setup; // current setup request 104 io_buffer_t ep0_buffer; 105 dwc3_ep0_state ep0_state; 106 107 // Used for synchronizing global state 108 // and non ep specific hardware registers. 109 // dwc3_endpoint_t.lock should be acquired first 110 // if acquiring both locks. 111 mtx_t lock; 112 bool configured; 113} dwc3_t; 114 115static inline volatile void* dwc3_mmio(dwc3_t* dwc) { 116 return dwc->mmio.vaddr; 117} 118 119void dwc3_usb_reset(dwc3_t* dwc); 120void dwc3_disconnected(dwc3_t* dwc); 121void dwc3_connection_done(dwc3_t* dwc); 122void dwc3_set_address(dwc3_t* dwc, unsigned address); 123void dwc3_reset_configuration(dwc3_t* dwc); 124 125// Commands 126void dwc3_cmd_start_new_config(dwc3_t* dwc, unsigned ep_num, unsigned resource_index); 127void dwc3_cmd_ep_set_config(dwc3_t* dwc, unsigned ep_num, unsigned ep_type, 128 unsigned max_packet_size, unsigned interval, bool modify); 129void dwc3_cmd_ep_transfer_config(dwc3_t* dwc, unsigned ep_num); 130void dwc3_cmd_ep_start_transfer(dwc3_t* dwc, unsigned ep_num, zx_paddr_t trb_phys); 131void dwc3_cmd_ep_end_transfer(dwc3_t* dwc, unsigned ep_num); 132void dwc3_cmd_ep_set_stall(dwc3_t* dwc, unsigned ep_num); 133void dwc3_cmd_ep_clear_stall(dwc3_t* dwc, unsigned ep_num); 134 135// Endpoints 136zx_status_t dwc3_ep_fifo_init(dwc3_t* dwc, unsigned ep_num); 137void dwc3_ep_fifo_release(dwc3_t* dwc, unsigned ep_num); 138zx_status_t dwc3_ep_config(dwc3_t* dwc, usb_endpoint_descriptor_t* ep_desc, 139 usb_ss_ep_comp_descriptor_t* ss_comp_desc); 140void dwc3_ep_set_config(dwc3_t* dwc, unsigned ep_num, bool enable); 141zx_status_t dwc3_ep_disable(dwc3_t* dwc, uint8_t ep_addr); 142void dwc3_start_eps(dwc3_t* dwc); 143void dwc3_ep_queue(dwc3_t* dwc, unsigned ep_num, usb_request_t* req); 144void dwc3_ep_start_transfer(dwc3_t* dwc, unsigned ep_num, unsigned type, zx_paddr_t buffer, 145 size_t length, bool send_zlp); 146void dwc3_ep_xfer_started(dwc3_t* dwc, unsigned ep_num, unsigned rsrc_id); 147void dwc3_ep_xfer_complete(dwc3_t* dwc, unsigned ep_num); 148void dwc3_ep_xfer_not_ready(dwc3_t* dwc, unsigned ep_num, unsigned stage); 149zx_status_t dwc3_ep_set_stall(dwc3_t* dwc, unsigned ep_num, bool stall); 150void dwc3_ep_end_transfers(dwc3_t* dwc, unsigned ep_num, zx_status_t reason); 151 152// Endpoint 0 153zx_status_t dwc3_ep0_init(dwc3_t* dwc); 154void dwc3_ep0_reset(dwc3_t* dwc); 155void dwc3_ep0_start(dwc3_t* dwc); 156void dwc3_ep0_xfer_not_ready(dwc3_t* dwc, unsigned ep_num, unsigned stage); 157void dwc3_ep0_xfer_complete(dwc3_t* dwc, unsigned ep_num); 158 159 160// Events 161void dwc3_events_start(dwc3_t* dwc); 162void dwc3_events_stop(dwc3_t* dwc); 163 164// Utils 165void dwc3_wait_bits(volatile uint32_t* ptr, uint32_t bits, uint32_t expected); 166void dwc3_print_status(dwc3_t* dwc); 167