1 /*
2 * Copyright (c) 2013 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 #include <lk/err.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <lk/trace.h>
12 #include <lk/debug.h>
13 #include <platform.h>
14 #include <lk/reg.h>
15 #include <dev/usb.h>
16 #include <dev/usbc.h>
17 #include <arch/arm/cm.h>
18
19 #include "ti_driverlib.h"
20 #include "inc/hw_usb.h"
21
22 #define LOCAL_TRACE 0
23
24 static bool pending_addr_change = false;
25 static uint8_t addr;
26
usbc_dump_regs(void)27 static void usbc_dump_regs(void) {
28 printf("USB0 reg dump:\n");
29 #define DUMPREG8(r) printf("\t" #r ": 0x%hhx\n", *REG8(USB0_BASE + (r)));
30 #define DUMPREG16(r) printf("\t" #r ": 0x%hx\n", *REG16(USB0_BASE + (r)));
31 #define DUMPREG32(r) printf("\t" #r ": 0x%x\n", *REG32(USB0_BASE + (r)));
32
33 DUMPREG8(USB_O_FADDR);
34 DUMPREG8(USB_O_POWER);
35 DUMPREG16(USB_O_TXIS);
36 DUMPREG16(USB_O_RXIS);
37 DUMPREG16(USB_O_TXIE);
38 DUMPREG16(USB_O_RXIE);
39 DUMPREG8(USB_O_IS);
40 DUMPREG8(USB_O_IE);
41 DUMPREG16(USB_O_FRAME);
42 DUMPREG8(USB_O_EPIDX);
43 DUMPREG8(USB_O_TEST);
44 DUMPREG32(USB_O_FIFO0);
45 DUMPREG32(USB_O_FIFO1);
46 DUMPREG32(USB_O_FIFO2);
47 DUMPREG32(USB_O_FIFO3);
48 DUMPREG32(USB_O_FIFO4);
49 DUMPREG32(USB_O_FIFO5);
50 DUMPREG32(USB_O_FIFO6);
51 DUMPREG32(USB_O_FIFO7);
52 DUMPREG32(USB_O_FIFO8);
53 DUMPREG32(USB_O_FIFO9);
54 DUMPREG32(USB_O_FIFO10);
55 DUMPREG32(USB_O_FIFO11);
56 DUMPREG32(USB_O_FIFO12);
57 DUMPREG32(USB_O_FIFO13);
58 DUMPREG32(USB_O_FIFO14);
59 DUMPREG32(USB_O_FIFO15);
60 DUMPREG16(USB_O_DEVCTL);
61 DUMPREG8(USB_O_TXFIFOSZ);
62 DUMPREG8(USB_O_RXFIFOSZ);
63 DUMPREG16(USB_O_TXFIFOADD);
64 DUMPREG16(USB_O_RXFIFOADD);
65 DUMPREG32(USB_O_PP);
66
67 #undef DUMPREG8
68 #undef DUMPREG16
69 #undef DUMPREG32
70 }
71
stellaris_usbc_early_init(void)72 void stellaris_usbc_early_init(void) {
73 LTRACE_ENTRY;
74 LTRACE_EXIT;
75 }
76
stellaris_usbc_init(void)77 void stellaris_usbc_init(void) {
78 LTRACE_ENTRY;
79
80 SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
81 SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
82
83 SysCtlUSBPLLEnable();
84
85 GPIOPinTypeUSBAnalog(GPIO_PORTD_AHB_BASE, GPIO_PIN_4 | GPIO_PIN_5);
86
87 USBDevMode(USB0_BASE);
88 USBPHYPowerOn(USB0_BASE);
89
90 #if LOCAL_TRACE
91 usbc_dump_regs();
92
93 printf("addr %lu\n", USBDevAddrGet(USB0_BASE));
94 printf("ep0 status 0x%lx\n", USBEndpointStatus(USB0_BASE, USB_EP_0));
95 #endif
96
97 NVIC_EnableIRQ(INT_USB0 - 16);
98 USBIntDisableControl(USB0_BASE, USB_INTCTRL_ALL);
99
100 LTRACE_EXIT;
101 }
102
ep0_irq(void)103 static void ep0_irq(void) {
104 uint status = USBEndpointStatus(USB0_BASE, USB_EP_0);
105
106 LTRACEF("ep0 status 0x%x\n", status);
107
108 /* delay setting the address until the ack as completed */
109 if (pending_addr_change) {
110 LTRACEF("pending addr change\n");
111 USBDevAddrSet(USB0_BASE, addr);
112 pending_addr_change = false;
113 }
114
115 if (status & USB_DEV_EP0_OUT_PKTRDY) {
116 LTRACEF("pktrdy\n");
117
118 uchar buf[sizeof(struct usb_setup)];
119 ulong avail = sizeof(buf);
120
121 if (USBEndpointDataGet(USB0_BASE, USB_EP_0, buf, &avail) < 0 || avail != sizeof(buf)) {
122 LTRACEF("short setup packet, size %lu\n", avail);
123 } else {
124 union usb_callback_args args;
125 args.setup = (void *)buf;
126 usbc_callback(USB_CB_SETUP_MSG, &args);
127 }
128 }
129 if (status & USB_DEV_EP0_SENT_STALL) {
130 LTRACEF("stall complete\n");
131 USBDevEndpointStallClear(USB0_BASE, USB_EP_0, 0);
132 }
133 }
134
stellaris_usb0_irq(void)135 void stellaris_usb0_irq(void) {
136 arm_cm_irq_entry();
137
138 uint status = USBIntStatusControl(USB0_BASE);
139
140 //LTRACEF("usb irq, status 0x%x\n", status);
141
142 if (status & USB_INTCTRL_RESET) {
143 // reset
144 LTRACEF("reset\n");
145 pending_addr_change = false;
146 usbc_callback(USB_CB_RESET, NULL);
147 }
148 if (status & USB_INTCTRL_CONNECT) {
149 // reset
150 LTRACEF("connect\n");
151 }
152
153 status = USBIntStatusEndpoint(USB0_BASE);
154
155 if (status & USB_INTEP_0) {
156 // ep0
157 //LTRACEF("ep0\n");
158 ep0_irq();
159 }
160
161 arm_cm_irq_exit(true);
162 }
163
usbc_ep0_ack(void)164 void usbc_ep0_ack(void) {
165 LTRACE_ENTRY;
166
167 USBDevEndpointDataAck(USB0_BASE, USB_EP_0, true);
168 }
169
usbc_ep0_stall(void)170 void usbc_ep0_stall(void) {
171 LTRACE_ENTRY;
172
173 USBDevEndpointStall(USB0_BASE, USB_EP_0, 0);
174 }
175
usbc_ep0_send(const void * buf,size_t len,size_t maxlen)176 void usbc_ep0_send(const void *buf, size_t len, size_t maxlen) {
177 LTRACEF("buf %p, len %zu, maxlen %zu\n", buf, len, maxlen);
178
179 USBEndpointDataPut(USB0_BASE, USB_EP_0, (void *)buf, MIN(len, maxlen));
180
181 USBEndpointDataSend(USB0_BASE, USB_EP_0, USB_TRANS_SETUP);
182 }
183
usbc_set_address(uint8_t address)184 void usbc_set_address(uint8_t address) {
185 LTRACEF("address 0x%hhx\n", address);
186
187 addr = address;
188 pending_addr_change = true;
189 }
190
usbc_ep0_recv(void * buf,size_t len,ep_callback cb)191 void usbc_ep0_recv(void *buf, size_t len, ep_callback cb) {
192 PANIC_UNIMPLEMENTED;
193 }
194
usbc_is_highspeed(void)195 bool usbc_is_highspeed(void) {
196 return false;
197 }
198
usbc_set_active(bool active)199 status_t usbc_set_active(bool active) {
200 LTRACEF("active %d\n", active);
201 if (active) {
202 USBIntEnableControl(USB0_BASE, USB_INTCTRL_CONNECT | USB_INTCTRL_RESET);
203 USBIntEnableEndpoint(USB0_BASE, USB_INTEP_0);
204 USBDevConnect(USB0_BASE);
205 } else {
206 USBDevDisconnect(USB0_BASE);
207 }
208
209 return NO_ERROR;
210 }
211
usbc_setup_endpoint(ep_t ep,ep_dir_t dir,uint width,ep_type_t type)212 status_t usbc_setup_endpoint(ep_t ep, ep_dir_t dir, uint width, ep_type_t type) {
213 PANIC_UNIMPLEMENTED;
214 }
215
usbc_queue_rx(ep_t ep,usbc_transfer_t * transfer)216 status_t usbc_queue_rx(ep_t ep, usbc_transfer_t *transfer) {
217 PANIC_UNIMPLEMENTED;
218 }
219
usbc_queue_tx(ep_t ep,usbc_transfer_t * transfer)220 status_t usbc_queue_tx(ep_t ep, usbc_transfer_t *transfer) {
221 PANIC_UNIMPLEMENTED;
222 }
223
usbc_flush_ep(ep_t ep)224 status_t usbc_flush_ep(ep_t ep) {
225 PANIC_UNIMPLEMENTED;
226 }