libpayload: Drop usb_fatal()
[coreboot.git] / payloads / libpayload / drivers / usb / xhci.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2010 Patrick Georgi
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #define USB_DEBUG
31
32 #include <arch/virtual.h>
33 #include "xhci.h"
34 #include "xhci_private.h"
35
36 static void xhci_start (hci_t *controller);
37 static void xhci_stop (hci_t *controller);
38 static void xhci_reset (hci_t *controller);
39 static void xhci_shutdown (hci_t *controller);
40 static int xhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize);
41 static int xhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq,
42                          int dalen, u8 *data);
43 static void* xhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
44 static void xhci_destroy_intr_queue (endpoint_t *ep, void *queue);
45 static u8* xhci_poll_intr_queue (void *queue);
46
47 static void
48 xhci_reset (hci_t *controller)
49 {
50 }
51
52 hci_t *
53 xhci_init (pcidev_t addr)
54 {
55         int i;
56
57         hci_t *controller = new_controller ();
58
59         if (!controller)
60                 fatal("Could not create USB controller instance.\n");
61
62         controller->instance = malloc (sizeof (xhci_t));
63         if(!controller->instance)
64                 fatal("Not enough memory creating USB controller instance.\n");
65
66         controller->start = xhci_start;
67         controller->stop = xhci_stop;
68         controller->reset = xhci_reset;
69         controller->shutdown = xhci_shutdown;
70         controller->bulk = xhci_bulk;
71         controller->control = xhci_control;
72         controller->create_intr_queue = xhci_create_intr_queue;
73         controller->destroy_intr_queue = xhci_destroy_intr_queue;
74         controller->poll_intr_queue = xhci_poll_intr_queue;
75         for (i = 0; i < 128; i++) {
76                 controller->devices[i] = 0;
77         }
78         init_device_entry (controller, 0);
79         XHCI_INST (controller)->roothub = controller->devices[0];
80
81         controller->bus_address = addr;
82         controller->reg_base = (u32)phys_to_virt(pci_read_config32 (controller->bus_address, 0x10) & ~0xf);
83         //controller->reg_base = pci_read_config32 (controller->bus_address, 0x14) & ~0xf;
84         if (pci_read_config32 (controller->bus_address, 0x14) > 0) {
85                 fatal("We don't do 64bit addressing.\n");
86         }
87         debug("regbase: %lx\n", controller->reg_base);
88
89         XHCI_INST (controller)->capreg = (void*)controller->reg_base;
90         XHCI_INST (controller)->opreg = (void*)(controller->reg_base + XHCI_INST (controller)->capreg->caplength);
91         XHCI_INST (controller)->hcrreg = (void*)(controller->reg_base + XHCI_INST (controller)->capreg->rtsoff);
92         XHCI_INST (controller)->dbreg = (void*)(controller->reg_base + XHCI_INST (controller)->capreg->dboff);
93         debug("caplen: %lx\nrtsoff: %lx\ndboff: %lx\n", XHCI_INST (controller)->capreg->caplength, XHCI_INST (controller)->capreg->rtsoff, XHCI_INST (controller)->capreg->dboff);
94         debug("caplength: %x\n", XHCI_INST (controller)->capreg->caplength);
95         debug("hciversion: %x.%x\n", XHCI_INST (controller)->capreg->hciver_hi, XHCI_INST (controller)->capreg->hciver_lo);
96         if ((XHCI_INST (controller)->capreg->hciversion < 0x96) || (XHCI_INST (controller)->capreg->hciversion > 0x100)) {
97                 fatal("Unsupported xHCI version\n");
98         }
99         debug("maxslots: %x\n", XHCI_INST (controller)->capreg->MaxSlots);
100         debug("maxports: %x\n", XHCI_INST (controller)->capreg->MaxPorts);
101         int pagesize = XHCI_INST (controller)->opreg->pagesize << 12;
102         debug("pagesize: %x\n", pagesize);
103
104         XHCI_INST (controller)->dcbaa = memalign(64, (XHCI_INST (controller)->capreg->MaxSlots+1)*sizeof(devctxp_t));
105         memset((void*)XHCI_INST (controller)->dcbaa, 0, (XHCI_INST (controller)->capreg->MaxSlots+1)*sizeof(devctxp_t));
106
107         debug("max scratchpad bufs: %x\n", XHCI_INST (controller)->capreg->Max_Scratchpad_Bufs);
108         if (XHCI_INST (controller)->capreg->Max_Scratchpad_Bufs > 0) {
109                 XHCI_INST (controller)->dcbaa->ptr = memalign(64, XHCI_INST (controller)->capreg->Max_Scratchpad_Bufs * 8);
110         }
111
112         XHCI_INST (controller)->opreg->dcbaap_lo = virt_to_phys(XHCI_INST (controller)->dcbaa);
113         XHCI_INST (controller)->opreg->dcbaap_hi = 0;
114
115         printf("waiting for controller to be ready - ");
116         while ((XHCI_INST (controller)->opreg->usbsts & USBSTS_CNR) != 0) mdelay(1);
117         printf("ok.\n");
118
119         debug("ERST Max: %lx -> %lx entries\n", XHCI_INST (controller)->capreg->ERST_Max, 1<<(XHCI_INST (controller)->capreg->ERST_Max));
120
121         // enable all available slots
122         XHCI_INST (controller)->opreg->config = XHCI_INST (controller)->capreg->MaxSlots & CONFIG_MASK_MaxSlotsEn;
123
124         XHCI_INST (controller)->cmd_ring = memalign(64, 16*sizeof(trb_t)); /* TODO: make sure not to cross 64k page boundary */
125         memset((void*)XHCI_INST (controller)->cmd_ring, 0, 16*sizeof(trb_t));
126
127         XHCI_INST (controller)->ev_ring = memalign(64, 16*sizeof(trb_t)); /* TODO: make sure not to cross 64k page boundary */
128         memset((void*)XHCI_INST (controller)->ev_ring, 0, 16*sizeof(trb_t));
129
130         XHCI_INST (controller)->ev_ring_table = memalign(64, sizeof(erst_entry_t));
131         memset((void*)XHCI_INST (controller)->ev_ring_table, 0, sizeof(erst_entry_t));
132         XHCI_INST (controller)->ev_ring_table[0].seg_base_lo = virt_to_phys(XHCI_INST (controller)->ev_ring);
133         XHCI_INST (controller)->ev_ring_table[0].seg_base_hi = 0;
134         XHCI_INST (controller)->ev_ring_table[0].seg_size = 16;
135
136         // init command ring
137         XHCI_INST (controller)->opreg->crcr_lo = virt_to_phys(XHCI_INST (controller)->cmd_ring) | CRCR_RCS;
138         XHCI_INST (controller)->opreg->crcr_hi = 0;
139         XHCI_INST (controller)->cmd_ccs = 1;
140         XHCI_INST (controller)->ev_ccs = 1;
141
142         // init primary interrupter
143         XHCI_INST (controller)->hcrreg->intrrs[0].erstsz = 1;
144         XHCI_INST (controller)->hcrreg->intrrs[0].erdp_lo = virt_to_phys(XHCI_INST (controller)->ev_ring);
145         XHCI_INST (controller)->hcrreg->intrrs[0].erdp_hi = 0;
146         XHCI_INST (controller)->hcrreg->intrrs[0].erstba_lo = virt_to_phys(XHCI_INST (controller)->ev_ring_table);
147         XHCI_INST (controller)->hcrreg->intrrs[0].erstba_hi = 0;
148
149         XHCI_INST (controller)->opreg->usbcmd |= USBCMD_RS; /* start USB controller */
150         XHCI_INST (controller)->dbreg[0] = 0; // and tell controller to consume commands
151
152         /* TODO: TEST */
153         // setup noop command
154         trb_t *cmd = &XHCI_INST (controller)->cmd_ring[0];
155         ((u32*)cmd)[3] = 1-XHCI_INST (controller)->cmd_ccs; // disable command descriptor
156         ((u32*)cmd)[0] = 0;
157         ((u32*)cmd)[1] = 0;
158         ((u32*)cmd)[2] = 0;
159         cmd->cmd_No_Op.TRB_Type = TRB_CMD_NOOP;
160
161         // ring the HC doorbell
162         debug("Posting command at %lx\n", virt_to_phys(cmd));
163         cmd->cmd_No_Op.C = XHCI_INST (controller)->cmd_ccs; // enable command
164         XHCI_INST (controller)->dbreg[0] = 0; // and tell controller to consume commands
165
166         // wait for result in event ring
167         trb_t *ev = &XHCI_INST (controller)->ev_ring[0];
168         trb_t *ev1 = &XHCI_INST (controller)->ev_ring[1];
169         while (ev->event_cmd_cmpl.C != XHCI_INST (controller)->ev_ccs) {
170                 debug("CRCR: %lx, USBSTS: %lx\n",  XHCI_INST (controller)->opreg->crcr_lo, XHCI_INST (controller)->opreg->usbsts);
171                 debug("ev0.C %x, ev1.C %x\n", ev->event_cmd_cmpl.C, ev1->event_cmd_cmpl.C);
172                 mdelay(100);
173         }
174         debug("command ring is %srunning\n", (XHCI_INST (controller)->opreg->crcr_lo & CRCR_CRR)?"":"not ");
175         switch (ev->event_cmd_cmpl.TRB_Type) {
176                 case TRB_EV_CMD_CMPL:
177                         debug("Completed command TRB at %lx. Code: %d\n",
178                                 ev->event_cmd_cmpl.Cmd_TRB_Pointer_lo, ev->event_cmd_cmpl.Completion_Code);
179                         break;
180                 case TRB_EV_PORTSC:
181                         debug("Port Status Change Event. Completion Code: %d\n Port: %d. Ignoring.\n",
182                                 ev->event_cmd_cmpl.Completion_Code, ev->event_portsc.Port);
183                         // we ignore the event as we look for the PORTSC registers instead, at a time when it suits _us_
184                         break;
185                 default:
186                         debug("Unknown event: %d, Completion Code: %d\n", ev->event_cmd_cmpl.TRB_Type, ev->event_cmd_cmpl.Completion_Code);
187                         break;
188         }
189         debug("CRCR: %lx, USBSTS: %lx\n",  XHCI_INST (controller)->opreg->crcr_lo, XHCI_INST (controller)->opreg->usbsts);
190         debug("ev0.C %x, ev1.C %x, ev1.CC %d\n", ev->event_cmd_cmpl.C, ev1->event_cmd_cmpl.C, ev1->event_cmd_cmpl.Completion_Code);
191
192         controller->devices[0]->controller = controller;
193         controller->devices[0]->init = xhci_rh_init;
194         controller->devices[0]->init (controller->devices[0]);
195
196         xhci_reset (controller);
197         return controller;
198 }
199
200 static void
201 xhci_shutdown (hci_t *controller)
202 {
203         if (controller == 0)
204                 return;
205         detach_controller (controller);
206         XHCI_INST (controller)->roothub->destroy (XHCI_INST (controller)->
207                                                   roothub);
208         /* TODO: stop hardware, kill data structures */
209         free (XHCI_INST (controller));
210         free (controller);
211 }
212
213 static void
214 xhci_start (hci_t *controller)
215 {
216 }
217
218 static void
219 xhci_stop (hci_t *controller)
220 {
221 }
222
223 static int
224 xhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen,
225               unsigned char *data)
226 {
227         return 1;
228 }
229
230 /* finalize == 1: if data is of packet aligned size, add a zero length packet */
231 static int
232 xhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
233 {
234         int maxpsize = ep->maxpacketsize;
235         if (maxpsize == 0)
236                 fatal("MaxPacketSize == 0!!!");
237         return 1;
238 }
239
240 /* create and hook-up an intr queue into device schedule */
241 static void*
242 xhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming)
243 {
244         return NULL;
245 }
246
247 /* remove queue from device schedule, dropping all data that came in */
248 static void
249 xhci_destroy_intr_queue (endpoint_t *ep, void *q_)
250 {
251         //free(q);
252 }
253
254 /* read one intr-packet from queue, if available. extend the queue for new input.
255    return NULL if nothing new available.
256    Recommended use: while (data=poll_intr_queue(q)) process(data);
257  */
258 static u8*
259 xhci_poll_intr_queue (void *q_)
260 {
261         return NULL;
262 }