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/protocol/platform-device-lib.h>
10 #include <ddk/protocol/platform/device.h>
11 #include <ddk/protocol/usb/dci.h>
12 #include <ddk/protocol/usb/modeswitch.h>
13 #include <ddktl/mmio.h>
14 #include <fbl/mutex.h>
15 #include <lib/zx/handle.h>
16 #include <lib/zx/interrupt.h>
17 #include <zircon/device/usb-peripheral.h>
18 #include <zircon/hw/usb.h>
19 #include <zircon/listnode.h>
20 #include <zircon/types.h>
21 
22 #include <threads.h>
23 
24 #include <optional>
25 
26 #include "dwc3-types.h"
27 
28 // physical endpoint numbers for ep0
29 #define EP0_OUT             0
30 #define EP0_IN              1
31 #define EP0_FIFO            EP0_OUT
32 
33 #define EP_OUT(ep_num)      (((ep_num) & 1) == 0)
34 #define EP_IN(ep_num)       (((ep_num) & 1) == 1)
35 
36 #define EVENT_BUFFER_SIZE   PAGE_SIZE
37 #define EP0_MAX_PACKET_SIZE 512
38 #define DWC3_MAX_EPS    32
39 
40 // converts a USB endpoint address to 0 - 31 index
41 #define dwc3_ep_num(addr) ((((addr) & 0xF) << 1) | !!((addr) & USB_DIR_IN))
42 
43 typedef enum {
44     EP0_STATE_NONE,
45     EP0_STATE_SETUP,            // Queued setup phase
46     EP0_STATE_DATA_OUT,         // Queued data on EP0_OUT
47     EP0_STATE_DATA_IN,          // Queued data on EP0_IN
48     EP0_STATE_WAIT_NRDY_OUT,    // Waiting for not-ready on EP0_OUT
49     EP0_STATE_WAIT_NRDY_IN,     // Waiting for not-ready on EP0_IN
50     EP0_STATE_STATUS,           // Waiting for status to complete
51 } dwc3_ep0_state;
52 
53 typedef struct {
54     io_buffer_t buffer;
55     dwc3_trb_t* first;      // first TRB in the fifo
56     dwc3_trb_t* next;       // next free TRB in the fifo
57     dwc3_trb_t* current;    // TRB for currently pending transaction
58     dwc3_trb_t* last;       // last TRB in the fifo (link TRB)
59 } dwc3_fifo_t;
60 
61 typedef struct {
62     dwc3_fifo_t fifo;
63     list_node_t queued_reqs;    // requests waiting to be processed
64     usb_request_t* current_req; // request currently being processed
65     unsigned rsrc_id;           // resource ID for current_req
66 
67     // Used for synchronizing endpoint state
68     // and ep specific hardware registers
69     // This should be acquired before dwc3_t.lock
70     // if acquiring both locks.
71     fbl::Mutex lock;
72 
73     uint16_t max_packet_size;
74     uint8_t ep_num;
75     bool enabled;
76     uint8_t type;           // control, bulk, interrupt or isochronous
77     uint8_t interval;
78     // TODO(voydanoff) USB 3 specific stuff here
79 
80     bool got_not_ready;
81     bool stalled;
82 } dwc3_endpoint_t;
83 
84 typedef struct {
85     zx_device_t* zxdev;
86     zx_device_t* xhci_dev;
87     zx_device_t* parent;
88     pdev_protocol_t pdev;
89     usb_mode_switch_protocol_t ums;
90     usb_dci_interface_t dci_intf;
91     std::optional<ddk::MmioBuffer> mmio;
92     zx::handle bti_handle;
93 
94     usb_mode_t usb_mode;
95     bool start_device_on_xhci_release;
96     fbl::Mutex usb_mode_lock; // protects usb_mode and start_device_on_xhci_release
97 
98     // event stuff
99     io_buffer_t event_buffer;
100     zx::interrupt irq_handle;
101     thrd_t irq_thread;
102 
103     dwc3_endpoint_t eps[DWC3_MAX_EPS];
104 
105     // connection state
106     usb_speed_t speed;
107 
108     // ep0 stuff
109     usb_setup_t cur_setup;      // current setup request
110     io_buffer_t ep0_buffer;
111     dwc3_ep0_state ep0_state;
112 
113     // Used for synchronizing global state
114     // and non ep specific hardware registers.
115     // dwc3_endpoint_t.lock should be acquired first
116     // if acquiring both locks.
117     fbl::Mutex lock;
118     bool configured;
119 } dwc3_t;
120 
121 // Internal context for USB requests
122 typedef struct {
123      // callback to the upper layer
124      usb_request_complete_t complete_cb;
125      // for queueing requests internally
126      list_node_t node;
127 } dwc_usb_req_internal_t;
128 
129 #define USB_REQ_TO_INTERNAL(req) \
130     ((dwc_usb_req_internal_t *)((uintptr_t)(req) + sizeof(usb_request_t)))
131 #define INTERNAL_TO_USB_REQ(ctx) ((usb_request_t *)((uintptr_t)(ctx) - sizeof(usb_request_t)))
132 
dwc3_mmio(dwc3_t * dwc)133 static inline ddk::MmioBuffer* dwc3_mmio(dwc3_t* dwc) {
134     return &*dwc->mmio;
135 }
136 
137 void dwc3_usb_reset(dwc3_t* dwc);
138 void dwc3_disconnected(dwc3_t* dwc);
139 void dwc3_connection_done(dwc3_t* dwc);
140 void dwc3_set_address(dwc3_t* dwc, unsigned address);
141 void dwc3_reset_configuration(dwc3_t* dwc);
142 
143 // Commands
144 void dwc3_cmd_start_new_config(dwc3_t* dwc, unsigned ep_num, unsigned resource_index);
145 void dwc3_cmd_ep_set_config(dwc3_t* dwc, unsigned ep_num, unsigned ep_type,
146                             unsigned max_packet_size, unsigned interval, bool modify);
147 void dwc3_cmd_ep_transfer_config(dwc3_t* dwc, unsigned ep_num);
148 void dwc3_cmd_ep_start_transfer(dwc3_t* dwc, unsigned ep_num, zx_paddr_t trb_phys);
149 void dwc3_cmd_ep_end_transfer(dwc3_t* dwc, unsigned ep_num);
150 void dwc3_cmd_ep_set_stall(dwc3_t* dwc, unsigned ep_num);
151 void dwc3_cmd_ep_clear_stall(dwc3_t* dwc, unsigned ep_num);
152 
153 // Endpoints
154 zx_status_t dwc3_ep_fifo_init(dwc3_t* dwc, unsigned ep_num);
155 void dwc3_ep_fifo_release(dwc3_t* dwc, unsigned ep_num);
156 zx_status_t dwc3_ep_config(dwc3_t* dwc, const usb_endpoint_descriptor_t* ep_desc,
157                            const usb_ss_ep_comp_descriptor_t* ss_comp_desc);
158 void dwc3_ep_set_config(dwc3_t* dwc, unsigned ep_num, bool enable);
159 zx_status_t dwc3_ep_disable(dwc3_t* dwc, uint8_t ep_addr);
160 void dwc3_start_eps(dwc3_t* dwc);
161 void dwc3_ep_queue(dwc3_t* dwc, unsigned ep_num, usb_request_t* req);
162 void dwc3_ep_start_transfer(dwc3_t* dwc, unsigned ep_num, unsigned type, zx_paddr_t buffer,
163                             size_t length, bool send_zlp);
164 void dwc3_ep_xfer_started(dwc3_t* dwc, unsigned ep_num, unsigned rsrc_id);
165 void dwc3_ep_xfer_complete(dwc3_t* dwc, unsigned ep_num);
166 void dwc3_ep_xfer_not_ready(dwc3_t* dwc, unsigned ep_num, unsigned stage);
167 zx_status_t dwc3_ep_set_stall(dwc3_t* dwc, unsigned ep_num, bool stall);
168 void dwc3_ep_end_transfers(dwc3_t* dwc, unsigned ep_num, zx_status_t reason);
169 void dwc_ep_read_trb(dwc3_endpoint_t* ep, dwc3_trb_t* trb, dwc3_trb_t* out_trb);
170 
171 // Endpoint 0
172 zx_status_t dwc3_ep0_init(dwc3_t* dwc);
173 void dwc3_ep0_reset(dwc3_t* dwc);
174 void dwc3_ep0_start(dwc3_t* dwc);
175 void dwc3_ep0_xfer_not_ready(dwc3_t* dwc, unsigned ep_num, unsigned stage);
176 void dwc3_ep0_xfer_complete(dwc3_t* dwc, unsigned ep_num);
177 
178 // Events
179 void dwc3_events_start(dwc3_t* dwc);
180 void dwc3_events_stop(dwc3_t* dwc);
181 
182 // Utils
183 void dwc3_print_status(dwc3_t* dwc);
184 
185 __BEGIN_CDECLS
186 zx_status_t dwc3_bind(void* ctx, zx_device_t* parent);
187 __END_CDECLS
188