mb/google/brya/var/omnigul: Modify NVMe and UFS Storage support
[coreboot.git] / payloads / libpayload / drivers / usb / xhci_commands.c
bloba4078030c6fe825a73e66eb37eab5058e3e53444
1 /*
3 * Copyright (C) 2013 secunet Security Networks AG
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <inttypes.h>
30 #include <arch/virtual.h>
31 #include "xhci_private.h"
33 trb_t *
34 xhci_next_command_trb(xhci_t *const xhci)
36 xhci_clear_trb(xhci->cr.cur, xhci->cr.pcs);
37 return xhci->cr.cur;
40 void
41 xhci_post_command(xhci_t *const xhci)
43 xhci_debug("Command %d (@%p)\n",
44 TRB_GET(TT, xhci->cr.cur), xhci->cr.cur);
46 TRB_SET(C, xhci->cr.cur, xhci->cr.pcs);
47 ++xhci->cr.cur;
49 /* pass command trb to hardware */
50 wmb();
51 /* Ring the doorbell */
52 xhci->dbreg[0] = 0;
54 while (TRB_GET(TT, xhci->cr.cur) == TRB_LINK) {
55 xhci_debug("Handling LINK pointer (@%p)\n", xhci->cr.cur);
56 const int tc = TRB_GET(TC, xhci->cr.cur);
57 TRB_SET(C, xhci->cr.cur, xhci->cr.pcs);
58 xhci->cr.cur = phys_to_virt(xhci->cr.cur->ptr_low);
59 if (tc)
60 xhci->cr.pcs ^= 1;
64 static int
65 xhci_wait_for_command(xhci_t *const xhci,
66 const trb_t *const cmd_trb,
67 const int clear_event)
69 int cc;
71 cc = xhci_wait_for_command_done(xhci, cmd_trb, clear_event);
72 if (cc != TIMEOUT)
73 return cc;
75 /* Abort command on timeout */
76 xhci_debug("Aborting command (@%p), CRCR: 0x%"PRIx32"\n",
77 cmd_trb, xhci->opreg->crcr_lo);
79 * Ref. xHCI Specification Revision 1.2, May 2019.
80 * Section 5.4.5, Table 5-24.
82 * Abort the command and stop the ring.
84 xhci->opreg->crcr_lo |= CRCR_CA;
85 xhci->opreg->crcr_hi = 0;
86 cc = xhci_wait_for_command_aborted(xhci, cmd_trb);
88 if (xhci->opreg->crcr_lo & CRCR_CRR)
89 fatal("xhci_wait_for_command: Command ring still running\n");
91 return cc;
95 * xhci_cmd_* return >= 0: xhci completion code (cc)
96 * < 0: driver error code
99 int
100 xhci_cmd_enable_slot(xhci_t *const xhci, int *const slot_id)
102 trb_t *const cmd = xhci_next_command_trb(xhci);
103 TRB_SET(TT, cmd, TRB_CMD_ENABLE_SLOT);
104 xhci_post_command(xhci);
106 int cc = xhci_wait_for_command(xhci, cmd, 0);
107 if (cc >= 0) {
108 if (cc == CC_SUCCESS) {
109 *slot_id = TRB_GET(ID, xhci->er.cur);
110 if (*slot_id > xhci->max_slots_en)
111 cc = CONTROLLER_ERROR;
113 xhci_advance_event_ring(xhci);
114 xhci_handle_events(xhci);
116 return cc;
120 xhci_cmd_disable_slot(xhci_t *const xhci, const int slot_id)
122 trb_t *const cmd = xhci_next_command_trb(xhci);
123 TRB_SET(TT, cmd, TRB_CMD_DISABLE_SLOT);
124 TRB_SET(ID, cmd, slot_id);
125 xhci_post_command(xhci);
127 return xhci_wait_for_command(xhci, cmd, 1);
131 xhci_cmd_address_device(xhci_t *const xhci,
132 const int slot_id,
133 inputctx_t *const ic)
135 trb_t *const cmd = xhci_next_command_trb(xhci);
136 TRB_SET(TT, cmd, TRB_CMD_ADDRESS_DEV);
137 TRB_SET(ID, cmd, slot_id);
138 cmd->ptr_low = virt_to_phys(ic->raw);
139 xhci_post_command(xhci);
141 return xhci_wait_for_command(xhci, cmd, 1);
145 xhci_cmd_configure_endpoint(xhci_t *const xhci,
146 const int slot_id,
147 const int config_id,
148 inputctx_t *const ic)
150 trb_t *const cmd = xhci_next_command_trb(xhci);
151 TRB_SET(TT, cmd, TRB_CMD_CONFIGURE_EP);
152 TRB_SET(ID, cmd, slot_id);
153 cmd->ptr_low = virt_to_phys(ic->raw);
154 if (config_id == 0)
155 TRB_SET(DC, cmd, 1);
156 xhci_post_command(xhci);
158 return xhci_wait_for_command(xhci, cmd, 1);
162 xhci_cmd_evaluate_context(xhci_t *const xhci,
163 const int slot_id,
164 inputctx_t *const ic)
166 trb_t *const cmd = xhci_next_command_trb(xhci);
167 TRB_SET(TT, cmd, TRB_CMD_EVAL_CTX);
168 TRB_SET(ID, cmd, slot_id);
169 cmd->ptr_low = virt_to_phys(ic->raw);
170 xhci_post_command(xhci);
172 return xhci_wait_for_command(xhci, cmd, 1);
176 xhci_cmd_reset_endpoint(xhci_t *const xhci, const int slot_id, const int ep)
178 trb_t *const cmd = xhci_next_command_trb(xhci);
179 TRB_SET(TT, cmd, TRB_CMD_RESET_EP);
180 TRB_SET(ID, cmd, slot_id);
181 TRB_SET(EP, cmd, ep);
182 xhci_post_command(xhci);
184 return xhci_wait_for_command(xhci, cmd, 1);
188 xhci_cmd_stop_endpoint(xhci_t *const xhci, const int slot_id, const int ep)
190 trb_t *const cmd = xhci_next_command_trb(xhci);
191 TRB_SET(TT, cmd, TRB_CMD_STOP_EP);
192 TRB_SET(ID, cmd, slot_id);
193 TRB_SET(EP, cmd, ep);
194 xhci_post_command(xhci);
196 return xhci_wait_for_command(xhci, cmd, 1);
200 xhci_cmd_set_tr_dq(xhci_t *const xhci, const int slot_id, const int ep,
201 trb_t *const dq_trb, const int dcs)
203 trb_t *const cmd = xhci_next_command_trb(xhci);
204 TRB_SET(TT, cmd, TRB_CMD_SET_TR_DQ);
205 TRB_SET(ID, cmd, slot_id);
206 TRB_SET(EP, cmd, ep);
207 cmd->ptr_low = virt_to_phys(dq_trb) | dcs;
208 xhci_post_command(xhci);
210 return xhci_wait_for_command(xhci, cmd, 1);