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 #include "dwc3.h"
6 #include "dwc3-regs.h"
7
8 #include <fbl/auto_lock.h>
9
10 #include <stdio.h>
11 #include <unistd.h>
12
dwc3_cmd_start_new_config(dwc3_t * dwc,unsigned ep_num,unsigned rsrc_id)13 void dwc3_cmd_start_new_config(dwc3_t* dwc, unsigned ep_num, unsigned rsrc_id) {
14 auto* mmio = dwc3_mmio(dwc);
15
16 fbl::AutoLock lock(&dwc->lock);
17
18 DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
19 DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
20 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
21 DEPCMD::Get(ep_num)
22 .FromValue(0)
23 .set_CMDTYP(DEPCMD::DEPSTARTCFG)
24 .set_COMMANDPARAM(rsrc_id)
25 .set_CMDACT(1)
26 .WriteTo(mmio);
27 }
28
dwc3_cmd_ep_set_config(dwc3_t * dwc,unsigned ep_num,unsigned ep_type,unsigned max_packet_size,unsigned interval,bool modify)29 void dwc3_cmd_ep_set_config(dwc3_t* dwc, unsigned ep_num, unsigned ep_type,
30 unsigned max_packet_size, unsigned interval, bool modify) {
31 auto* mmio = dwc3_mmio(dwc);
32
33 fbl::AutoLock lock(&dwc->lock);
34
35 // fifo number is zero for OUT endpoints and EP0_IN
36 uint32_t fifo_num = (EP_OUT(ep_num) || ep_num == EP0_IN ? 0 : ep_num >> 1);
37 uint32_t action = (modify ? DEPCFG_DEPCMDPAR0::ACTION_MODIFY
38 : DEPCFG_DEPCMDPAR0::ACTION_INITIALIZE);
39
40 DEPCFG_DEPCMDPAR0::Get(ep_num)
41 .FromValue(0)
42 .set_FIFO_NUM(fifo_num)
43 .set_MAX_PACKET_SIZE(max_packet_size)
44 .set_EP_TYPE(ep_type)
45 .set_ACTION(action)
46 .WriteTo(mmio);
47 DEPCFG_DEPCMDPAR1::Get(ep_num)
48 .FromValue(0)
49 .set_EP_NUMBER(ep_num)
50 .set_INTERVAL(interval)
51 .set_XFER_NOT_READY_EN(1)
52 .set_XFER_COMPLETE_EN(1)
53 .set_INTR_NUM(0)
54 .WriteTo(mmio);
55 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
56 DEPCMD::Get(ep_num).FromValue(0).set_CMDTYP(DEPCMD::DEPCFG).set_CMDACT(1).WriteTo(mmio);
57 }
58
dwc3_cmd_ep_transfer_config(dwc3_t * dwc,unsigned ep_num)59 void dwc3_cmd_ep_transfer_config(dwc3_t* dwc, unsigned ep_num) {
60 auto* mmio = dwc3_mmio(dwc);
61
62 fbl::AutoLock lock(&dwc->lock);
63
64 DEPCMDPAR0::Get(ep_num).FromValue(0).set_PARAMETER(1).WriteTo(mmio);
65 DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
66 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
67 DEPCMD::Get(ep_num).FromValue(0).set_CMDTYP(DEPCMD::DEPXFERCFG).set_CMDACT(1).WriteTo(mmio);
68 }
69
dwc3_cmd_ep_start_transfer(dwc3_t * dwc,unsigned ep_num,zx_paddr_t trb_phys)70 void dwc3_cmd_ep_start_transfer(dwc3_t* dwc, unsigned ep_num, zx_paddr_t trb_phys) {
71 auto* mmio = dwc3_mmio(dwc);
72
73 fbl::AutoLock lock(&dwc->lock);
74
75 DEPCMDPAR0::Get(ep_num)
76 .FromValue(0)
77 .set_PARAMETER(static_cast<uint32_t>(trb_phys >> 32))
78 .WriteTo(mmio);
79 DEPCMDPAR1::Get(ep_num)
80 .FromValue(0)
81 .set_PARAMETER(static_cast<uint32_t>(trb_phys))
82 .WriteTo(mmio);
83 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
84 DEPCMD::Get(ep_num)
85 .FromValue(0)
86 .set_CMDTYP(DEPCMD::DEPSTRTXFER)
87 .set_CMDACT(1)
88 .set_CMDIOC(1)
89 .WriteTo(mmio);
90
91 while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
92 usleep(1000);
93 }
94 }
95
dwc3_cmd_ep_end_transfer(dwc3_t * dwc,unsigned ep_num)96 void dwc3_cmd_ep_end_transfer(dwc3_t* dwc, unsigned ep_num) {
97 auto* mmio = dwc3_mmio(dwc);
98
99 fbl::AutoLock lock(&dwc->lock);
100
101 unsigned rsrc_id = dwc->eps[ep_num].rsrc_id;
102
103 DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
104 DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
105 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
106 DEPCMD::Get(ep_num)
107 .FromValue(0)
108 .set_CMDTYP(DEPCMD::DEPENDXFER)
109 .set_COMMANDPARAM(rsrc_id)
110 .set_CMDACT(1)
111 .set_CMDIOC(1)
112 .set_HIPRI_FORCERM(1)
113 .WriteTo(mmio);
114
115 while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
116 usleep(1000);
117 }
118 }
119
dwc3_cmd_ep_set_stall(dwc3_t * dwc,unsigned ep_num)120 void dwc3_cmd_ep_set_stall(dwc3_t* dwc, unsigned ep_num) {
121 auto* mmio = dwc3_mmio(dwc);
122
123 fbl::AutoLock lock(&dwc->lock);
124
125 DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
126 DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
127 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
128 DEPCMD::Get(ep_num)
129 .FromValue(0)
130 .set_CMDTYP(DEPCMD::DEPSSTALL)
131 .set_CMDACT(1)
132 .set_CMDIOC(1)
133 .WriteTo(mmio);
134
135 while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
136 usleep(1000);
137 }
138 }
139
dwc3_cmd_ep_clear_stall(dwc3_t * dwc,unsigned ep_num)140 void dwc3_cmd_ep_clear_stall(dwc3_t* dwc, unsigned ep_num) {
141 auto* mmio = dwc3_mmio(dwc);
142
143 fbl::AutoLock lock(&dwc->lock);
144
145 DEPCMDPAR0::Get(ep_num).FromValue(0).WriteTo(mmio);
146 DEPCMDPAR1::Get(ep_num).FromValue(0).WriteTo(mmio);
147 DEPCMDPAR2::Get(ep_num).FromValue(0).WriteTo(mmio);
148 DEPCMD::Get(ep_num)
149 .FromValue(0)
150 .set_CMDTYP(DEPCMD::DEPCSTALL)
151 .set_CMDACT(1).set_CMDIOC(1)
152 .WriteTo(mmio);
153
154 while (DEPCMD::Get(ep_num).ReadFrom(mmio).CMDACT()) {
155 usleep(1000);
156 }
157 }
158