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