blob: 3d51e5e6aedb2ad7a7af84a352a0f6f7c4c0122f [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2013 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <err.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <trace.h>
27#include <debug.h>
28#include <platform.h>
29#include <reg.h>
30#include <dev/usb.h>
31#include <dev/usbc.h>
32#include <arch/arm/cm.h>
33
34#include "ti_driverlib.h"
35#include "inc/hw_usb.h"
36
37#define LOCAL_TRACE 0
38
39static bool pending_addr_change = false;
40static uint8_t addr;
41
42static void usbc_dump_regs(void)
43{
44 printf("USB0 reg dump:\n");
45#define DUMPREG8(r) printf("\t" #r ": 0x%hhx\n", *REG8(USB0_BASE + (r)));
46#define DUMPREG16(r) printf("\t" #r ": 0x%hx\n", *REG16(USB0_BASE + (r)));
47#define DUMPREG32(r) printf("\t" #r ": 0x%x\n", *REG32(USB0_BASE + (r)));
48
49 DUMPREG8(USB_O_FADDR);
50 DUMPREG8(USB_O_POWER);
51 DUMPREG16(USB_O_TXIS);
52 DUMPREG16(USB_O_RXIS);
53 DUMPREG16(USB_O_TXIE);
54 DUMPREG16(USB_O_RXIE);
55 DUMPREG8(USB_O_IS);
56 DUMPREG8(USB_O_IE);
57 DUMPREG16(USB_O_FRAME);
58 DUMPREG8(USB_O_EPIDX);
59 DUMPREG8(USB_O_TEST);
60 DUMPREG32(USB_O_FIFO0);
61 DUMPREG32(USB_O_FIFO1);
62 DUMPREG32(USB_O_FIFO2);
63 DUMPREG32(USB_O_FIFO3);
64 DUMPREG32(USB_O_FIFO4);
65 DUMPREG32(USB_O_FIFO5);
66 DUMPREG32(USB_O_FIFO6);
67 DUMPREG32(USB_O_FIFO7);
68 DUMPREG32(USB_O_FIFO8);
69 DUMPREG32(USB_O_FIFO9);
70 DUMPREG32(USB_O_FIFO10);
71 DUMPREG32(USB_O_FIFO11);
72 DUMPREG32(USB_O_FIFO12);
73 DUMPREG32(USB_O_FIFO13);
74 DUMPREG32(USB_O_FIFO14);
75 DUMPREG32(USB_O_FIFO15);
76 DUMPREG16(USB_O_DEVCTL);
77 DUMPREG8(USB_O_TXFIFOSZ);
78 DUMPREG8(USB_O_RXFIFOSZ);
79 DUMPREG16(USB_O_TXFIFOADD);
80 DUMPREG16(USB_O_RXFIFOADD);
81 DUMPREG32(USB_O_PP);
82
83#undef DUMPREG8
84#undef DUMPREG16
85#undef DUMPREG32
86}
87
88void stellaris_usbc_early_init(void)
89{
90 LTRACE_ENTRY;
91 LTRACE_EXIT;
92}
93
94void stellaris_usbc_init(void)
95{
96 LTRACE_ENTRY;
97
98 SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
99 SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
100
101 SysCtlUSBPLLEnable();
102
103 GPIOPinTypeUSBAnalog(GPIO_PORTD_AHB_BASE, GPIO_PIN_4 | GPIO_PIN_5);
104
105 USBDevMode(USB0_BASE);
106 USBPHYPowerOn(USB0_BASE);
107
108#if LOCAL_TRACE
109 usbc_dump_regs();
110
111 printf("addr %lu\n", USBDevAddrGet(USB0_BASE));
112 printf("ep0 status 0x%lx\n", USBEndpointStatus(USB0_BASE, USB_EP_0));
113#endif
114
115 NVIC_EnableIRQ(INT_USB0 - 16);
116 USBIntDisableControl(USB0_BASE, USB_INTCTRL_ALL);
117
118 LTRACE_EXIT;
119}
120
121static void ep0_irq(void)
122{
123 uint status = USBEndpointStatus(USB0_BASE, USB_EP_0);
124
125 LTRACEF("ep0 status 0x%x\n", status);
126
127 /* delay setting the address until the ack as completed */
128 if (pending_addr_change) {
129 LTRACEF("pending addr change\n");
130 USBDevAddrSet(USB0_BASE, addr);
131 pending_addr_change = false;
132 }
133
134 if (status & USB_DEV_EP0_OUT_PKTRDY) {
135 LTRACEF("pktrdy\n");
136
137 uchar buf[sizeof(struct usb_setup)];
138 ulong avail = sizeof(buf);
139
140 if (USBEndpointDataGet(USB0_BASE, USB_EP_0, buf, &avail) < 0 || avail != sizeof(buf)) {
141 LTRACEF("short setup packet, size %lu\n", avail);
142 } else {
143 union usb_callback_args args;
144 args.setup = (void *)buf;
145 usbc_callback(USB_CB_SETUP_MSG, &args);
146 }
147 }
148 if (status & USB_DEV_EP0_SENT_STALL) {
149 LTRACEF("stall complete\n");
150 USBDevEndpointStallClear(USB0_BASE, USB_EP_0, 0);
151 }
152}
153
154void stellaris_usb0_irq(void)
155{
156 arm_cm_irq_entry();
157
158 uint status = USBIntStatusControl(USB0_BASE);
159
160 //LTRACEF("usb irq, status 0x%x\n", status);
161
162 if (status & USB_INTCTRL_RESET) {
163 // reset
164 LTRACEF("reset\n");
165 pending_addr_change = false;
166 usbc_callback(USB_CB_RESET, NULL);
167 }
168 if (status & USB_INTCTRL_CONNECT) {
169 // reset
170 LTRACEF("connect\n");
171 }
172
173 status = USBIntStatusEndpoint(USB0_BASE);
174
175 if (status & USB_INTEP_0) {
176 // ep0
177 //LTRACEF("ep0\n");
178 ep0_irq();
179 }
180
181 arm_cm_irq_exit(true);
182}
183
184void usbc_ep0_ack(void)
185{
186 LTRACE_ENTRY;
187
188 USBDevEndpointDataAck(USB0_BASE, USB_EP_0, true);
189}
190
191void usbc_ep0_stall(void)
192{
193 LTRACE_ENTRY;
194
195 USBDevEndpointStall(USB0_BASE, USB_EP_0, 0);
196}
197
198void usbc_ep0_send(const void *buf, size_t len, size_t maxlen)
199{
200 LTRACEF("buf %p, len %zu, maxlen %zu\n", buf, len, maxlen);
201
202 USBEndpointDataPut(USB0_BASE, USB_EP_0, (void *)buf, MIN(len, maxlen));
203
204 USBEndpointDataSend(USB0_BASE, USB_EP_0, USB_TRANS_SETUP);
205}
206
207void usbc_set_address(uint8_t address)
208{
209 LTRACEF("address 0x%hhx\n", address);
210
211 addr = address;
212 pending_addr_change = true;
213}
214
215void usbc_ep0_recv(void *buf, size_t len, ep_callback cb)
216{
217 PANIC_UNIMPLEMENTED;
218}
219
220bool usbc_is_highspeed(void)
221{
222 return false;
223}
224
225status_t usbc_set_active(bool active)
226{
227 LTRACEF("active %d\n", active);
228 if (active) {
229 USBIntEnableControl(USB0_BASE, USB_INTCTRL_CONNECT | USB_INTCTRL_RESET);
230 USBIntEnableEndpoint(USB0_BASE, USB_INTEP_0);
231 USBDevConnect(USB0_BASE);
232 } else {
233 USBDevDisconnect(USB0_BASE);
234 }
235
236 return NO_ERROR;
237}
238
239status_t usbc_setup_endpoint(ep_t ep, ep_dir_t dir, uint width)
240{
241 PANIC_UNIMPLEMENTED;
242}
243
244status_t usbc_queue_rx(ep_t ep, usbc_transfer_t *transfer)
245{
246 PANIC_UNIMPLEMENTED;
247}
248
249status_t usbc_queue_tx(ep_t ep, usbc_transfer_t *transfer)
250{
251 PANIC_UNIMPLEMENTED;
252}
253
254// vim: set ts=4 sw=4 noexpandtab: