summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Moń <desowin@gmail.com>2021-06-05 09:22:27 +0200
committerTomasz Moń <desowin@gmail.com>2021-06-06 07:57:38 +0000
commit474293a12b6152041404378abd932ac495e5e18d (patch)
tree752c777a4b326d40216da1868e5c7aedaccfa7bd
parent77603c344dd4946d0319688c3b58bf9e1507d9aa (diff)
downloadrockbox-474293a12b6152041404378abd932ac495e5e18d.tar.gz
rockbox-474293a12b6152041404378abd932ac495e5e18d.zip
Sansa Connect: Initial TNETV105 driver port
Port USB driver from Sansa Connect Linux kernel sources. The device successfully enumerates and responds to SCSI commands but actual disk access does not work. The SCSI response sent to host mentions that both internal storage and microsd card are not present. Change-Id: Ic6c07da12382c15c0b069f23a75f7df9765b7525
-rw-r--r--bootloader/sansaconnect.c20
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/export/config.h6
-rw-r--r--firmware/export/config/sansaconnect.h11
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.c1044
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.h144
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c1489
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.h335
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c67
-rw-r--r--firmware/target/arm/tms320dm320/system-dm320.c7
-rw-r--r--firmware/target/arm/tms320dm320/system-target.h1
11 files changed, 3066 insertions, 60 deletions
diff --git a/bootloader/sansaconnect.c b/bootloader/sansaconnect.c
index a87b23745f..c5dbca717d 100644
--- a/bootloader/sansaconnect.c
+++ b/bootloader/sansaconnect.c
@@ -7,7 +7,7 @@
7* \/ \/ \/ \/ \/ 7* \/ \/ \/ \/ \/
8* $Id: $ 8* $Id: $
9* 9*
10* Copyright (C) 2011 by Tomasz Moń 10* Copyright (C) 2011-2021 by Tomasz Moń
11* 11*
12* All files in this archive are subject to the GNU General Public License. 12* All files in this archive are subject to the GNU General Public License.
13* See the file COPYING in the source tree root for full license agreement. 13* See the file COPYING in the source tree root for full license agreement.
@@ -32,6 +32,7 @@
32#include "uart-target.h" 32#include "uart-target.h"
33#include "power.h" 33#include "power.h"
34#include "loader_strerror.h" 34#include "loader_strerror.h"
35#include "usb.h"
35 36
36#define FLASH_BASE 0x00100000 37#define FLASH_BASE 0x00100000
37#define PARAMETERS_FLASH_OFFSET 0x00010000 38#define PARAMETERS_FLASH_OFFSET 0x00010000
@@ -206,6 +207,8 @@ void main(void)
206 207
207 printf("Rockbox boot loader"); 208 printf("Rockbox boot loader");
208 printf("Version %s", rbversion); 209 printf("Version %s", rbversion);
210 usb_init();
211 usb_start_monitoring();
209 212
210 clear_recoverzap(); 213 clear_recoverzap();
211 214
@@ -215,6 +218,17 @@ void main(void)
215 218
216 filesystem_init(); 219 filesystem_init();
217 220
221 if (usb_detect() == USB_INSERTED)
222 {
223 usb_enable(true);
224 while (usb_detect() == USB_INSERTED)
225 {
226 sleep(HZ);
227 storage_spin();
228 }
229 usb_enable(false);
230 }
231
218 ret = disk_mount_all(); 232 ret = disk_mount_all();
219 if (ret <= 0) 233 if (ret <= 0)
220 error(EDISK, ret, true); 234 error(EDISK, ret, true);
@@ -269,8 +283,8 @@ void main(void)
269 ret = kernel_entry(); 283 ret = kernel_entry();
270 printf("FAILED!"); 284 printf("FAILED!");
271 } 285 }
272 286
273 storage_sleepnow(); 287 storage_sleepnow();
274 288
275 while(1); 289 while(1);
276} 290}
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 0d93439ff8..4c1fa7bf46 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1264,6 +1264,8 @@ target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
1264target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c 1264target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c
1265target/arm/tms320dm320/sansa-connect/power-sansaconnect.c 1265target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
1266target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c 1266target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c
1267target/arm/tms320dm320/sansa-connect/tnetv105_cppi.c
1268target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c
1267target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c 1269target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
1268target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c 1270target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
1269target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c 1271target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c
diff --git a/firmware/export/config.h b/firmware/export/config.h
index b758bef49d..0242045450 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -938,6 +938,9 @@ Lyre prototype 1 */
938#define USB_DETECT_BY_REQUEST 938#define USB_DETECT_BY_REQUEST
939#elif CONFIG_USBOTG == USBOTG_RK27XX 939#elif CONFIG_USBOTG == USBOTG_RK27XX
940#define USB_DETECT_BY_REQUEST 940#define USB_DETECT_BY_REQUEST
941#elif CONFIG_USBOTG == USBOTG_TNETV105
942#define USB_STATUS_BY_EVENT
943#define USB_DETECT_BY_REQUEST
941#endif /* CONFIG_USB == */ 944#endif /* CONFIG_USB == */
942#endif /* HAVE_USBSTACK */ 945#endif /* HAVE_USBSTACK */
943 946
@@ -1171,7 +1174,8 @@ Lyre prototype 1 */
1171 (CONFIG_USBOTG == USBOTG_M66591) || \ 1174 (CONFIG_USBOTG == USBOTG_M66591) || \
1172 (CONFIG_USBOTG == USBOTG_DESIGNWARE) || \ 1175 (CONFIG_USBOTG == USBOTG_DESIGNWARE) || \
1173 (CONFIG_USBOTG == USBOTG_AS3525) || \ 1176 (CONFIG_USBOTG == USBOTG_AS3525) || \
1174 (CONFIG_USBOTG == USBOTG_RK27XX) 1177 (CONFIG_USBOTG == USBOTG_RK27XX) || \
1178 (CONFIG_USBOTG == USBOTG_TNETV105)
1175#define USB_HAS_BULK 1179#define USB_HAS_BULK
1176#define USB_HAS_INTERRUPT 1180#define USB_HAS_INTERRUPT
1177#elif defined(CPU_TCC780X) 1181#elif defined(CPU_TCC780X)
diff --git a/firmware/export/config/sansaconnect.h b/firmware/export/config/sansaconnect.h
index 465a576664..5ae2be1b16 100644
--- a/firmware/export/config/sansaconnect.h
+++ b/firmware/export/config/sansaconnect.h
@@ -182,11 +182,18 @@
182/* Offset ( in the firmware file's header ) to the real data */ 182/* Offset ( in the firmware file's header ) to the real data */
183#define FIRMWARE_OFFSET_FILE_DATA 8 183#define FIRMWARE_OFFSET_FILE_DATA 8
184 184
185#if 0 185/* Hardware controlled charging */
186#define CONFIG_CHARGING CHARGING_SIMPLE
187
188#define CONFIG_USBOTG USBOTG_TNETV105
189
186#define HAVE_USBSTACK 190#define HAVE_USBSTACK
191#define HAVE_USB_POWER
192#define HAVE_USB_CHARGING_ENABLE
193#define HAVE_BOOTLOADER_USB_MODE
187#define USB_VENDOR_ID 0x0781 194#define USB_VENDOR_ID 0x0781
188#define USB_PRODUCT_ID 0x7480 195#define USB_PRODUCT_ID 0x7480
189#endif 196#define USB_NUM_ENDPOINTS 5
190 197
191#define INCLUDE_TIMEOUT_API 198#define INCLUDE_TIMEOUT_API
192 199
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.c b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.c
new file mode 100644
index 0000000000..93477bed9e
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.c
@@ -0,0 +1,1044 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2021 by Tomasz Moń
11 * Copied with minor modifications from Sansa Connect Linux driver
12 * Copyright (c) 2005,2006 Zermatt Systems, Inc.
13 * Written by: Ben Bostwick
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include <string.h>
26#include "config.h"
27#include "system.h"
28#include "kernel.h"
29#include "panic.h"
30#include "logf.h"
31#include "tnetv105_usb_drv.h"
32#include "tnetv105_cppi.h"
33
34/* This file is pretty much directly copied from the Sansa Connect
35 * Linux kernel source code. This is because the functionality is
36 * nicely separated from actual kernel specific code and CPPI seems
37 * complex (atleast without access to the datasheet).
38 *
39 * The only non cosmetic change was changing the dynamic allocations
40 * to static allocations.
41 *
42 * It seems that the only way to get interrupt on non-control endpoint
43 * acticity is to use the CPPI. This sounds like a plausible explanation
44 * for the fake DMA buffers mentioned in CPPI code.
45 */
46
47/* Translate Linux consistent_sync() to Rockbox functions */
48#define DMA_TO_DEVICE commit_discard_dcache_range
49#define DMA_FROM_DEVICE discard_dcache_range
50#define consistent_sync(ptr, size, func) func(ptr, size)
51/* Rockbox TMS320DM320 crt0.S maps everything to itself */
52#define __virt_to_phys(ptr) ptr
53#define __phys_to_virt(ptr) ptr
54
55// CPPI functions
56#define CB_SOF_BIT (1<<31)
57#define CB_EOF_BIT (1<<30)
58#define CB_OWNERSHIP_BIT (1<<29)
59#define CB_EOQ_BIT (1<<28)
60#define CB_ZLP_GARBAGE (1<<23)
61#define CB_SIZE_MASK 0x0000ffff
62#define CB_OFFSET_MASK 0xffff0000
63#define TEARDOWN_VAL 0xfffffffc
64
65#define MAX_BUF_SIZE 512
66
67#define CPPI_DMA_RX_BUF_SIZE (MAX_BUF_SIZE * CPPI_RX_NUM_BUFS)
68
69static uint8_t *dma_recv_buf[CPPI_NUM_CHANNELS];
70static uint8_t ch0_rx_buf[CPPI_DMA_RX_BUF_SIZE];
71static uint8_t ch1_rx_buf[CPPI_DMA_RX_BUF_SIZE];
72
73#if USB_CPPI_LOGGING
74#define cppi_log_event0(msg) usb_log_event(msg, LOG_EVENT_D0, 0, 0, 0, 0)
75#define cppi_log_event1(msg, data0) usb_log_event(msg, LOG_EVENT_D1, data0, 0, 0, 0)
76#define cppi_log_event2(msg, data0, data1) usb_log_event(msg, LOG_EVENT_D2, data0, data1, 0, 0)
77#define cppi_log_event3(msg, data0, data1, data2) usb_log_event(msg, LOG_EVENT_D3, data0, data1, data2, 0)
78#define cppi_log_event4(msg, data0, data1, data2, data3) usb_log_event(msg, LOG_EVENT_D4, data0, data1, data2, data3)
79#else
80#define cppi_log_event0(x)
81#define cppi_log_event1(x, y)
82#define cppi_log_event2(x, y, z)
83#define cppi_log_event3(x, y, z, w)
84#define cppi_log_event4(x, y, z, w, u)
85#endif
86
87/*
88 * This function processes transmit interrupts. It traverses the
89 * transmit buffer queue, detecting sent data buffers
90 *
91 * @return 0 if OK, non-zero otherwise.
92 */
93int tnetv_cppi_tx_int(struct cppi_info *cppi, int ch)
94{
95 cppi_tcb *CurrentTcb,*LastTcbProcessed;
96 uint32_t TxFrameStatus;
97 cppi_txcntl *pTxCtl = &cppi->tx_ctl[ch];
98 int bytes_sent = 0;
99
100 cppi_log_event1("[cppi]TxInt ch", ch);
101
102 CurrentTcb = pTxCtl->TxActQueueHead;
103
104 if (CurrentTcb == 0)
105 {
106 cppi_log_event0("[cppi] tx int: no current tcb");
107 return -1;
108 }
109
110 // sync up the tcb from memory
111 consistent_sync(CurrentTcb, sizeof(*CurrentTcb), DMA_FROM_DEVICE);
112
113 TxFrameStatus = CurrentTcb->mode;
114 LastTcbProcessed = NULL;
115
116 cppi_log_event3("[cppi] int tcb status", (uint32_t) CurrentTcb, TxFrameStatus, CurrentTcb->Off_BLen);
117
118 while(CurrentTcb && (TxFrameStatus & CB_OWNERSHIP_BIT) == 0)
119 {
120 cppi_log_event3("[cppi] tx int: tcb (mode) (len)", (uint32_t) CurrentTcb, CurrentTcb->mode, CurrentTcb->Off_BLen);
121
122 // calculate the amount of bytes sent.
123 // don't count the fake ZLP byte
124 if (CurrentTcb->Off_BLen > 0x1)
125 {
126 bytes_sent += CurrentTcb->Off_BLen & 0xFFFF;
127 }
128
129 if (CurrentTcb->mode & CB_EOQ_BIT)
130 {
131 if (CurrentTcb->Next)
132 {
133 cppi_log_event0(" [cppi] misqueue!");
134
135 // Misqueued packet
136 tnetv_usb_reg_write(TNETV_DMA_TX_STATE(ch, TNETV_CPPI_TX_WORD_HDP), CurrentTcb->HNext);
137 }
138 else
139 {
140 cppi_log_event0("[cppi] eoq");
141
142 /* Tx End of Queue */
143 pTxCtl->TxActive = 0;
144 }
145 }
146
147 cppi_log_event1("[cppi]SendComplete: ", CurrentTcb->Off_BLen & 0xFFFF);
148
149 // Write the completion pointer
150 tnetv_usb_reg_write(TNETV_DMA_TX_CMPL(ch), __dma_to_vlynq_phys(CurrentTcb->dma_handle));
151
152
153 LastTcbProcessed = CurrentTcb;
154 CurrentTcb = CurrentTcb->Next;
155
156 // clean up TCB fields
157 LastTcbProcessed->HNext = 0;
158 LastTcbProcessed->Next = 0;
159 LastTcbProcessed->BufPtr = 0;
160 LastTcbProcessed->Off_BLen = 0;
161 LastTcbProcessed->mode = 0;
162 LastTcbProcessed->Eop = 0;
163
164 /* Push Tcb(s) back onto the list */
165 if (pTxCtl->TcbPool)
166 {
167 LastTcbProcessed->Next = pTxCtl->TcbPool->Next;
168 pTxCtl->TcbPool->Next = LastTcbProcessed;
169 }
170 else
171 {
172 pTxCtl->TcbPool = LastTcbProcessed;
173 }
174
175 consistent_sync(LastTcbProcessed, sizeof(*LastTcbProcessed), DMA_TO_DEVICE);
176
177 // get the status of the next packet
178 if (CurrentTcb)
179 {
180 // sync up the tcb from memory
181 consistent_sync(CurrentTcb, sizeof(*CurrentTcb), DMA_FROM_DEVICE);
182
183 TxFrameStatus = CurrentTcb->mode;
184 }
185
186
187 }
188
189 pTxCtl->TxActQueueHead = CurrentTcb;
190
191 if (!LastTcbProcessed)
192 {
193 cppi_log_event1(" [cppi]No Tx packets serviced on int! ch", ch);
194 return -1;
195 }
196
197 return bytes_sent;
198}
199
200int tnetv_cppi_flush_tx_queue(struct cppi_info *cppi, int ch)
201{
202 cppi_txcntl *pTxCtl = &cppi->tx_ctl[ch];
203 cppi_tcb *tcb, *next_tcb;
204
205 tcb = pTxCtl->TxActQueueHead;
206
207 cppi_log_event1("[cppi] flush TX ", (uint32_t) pTxCtl->TxActQueueHead);
208
209 while (tcb)
210 {
211 tcb->mode = 0;
212 tcb->BufPtr = 0;
213 tcb->Off_BLen = 0;
214 tcb->Eop = 0;
215 tcb->HNext = 0;
216
217 next_tcb = tcb->Next;
218
219 tcb->Next = pTxCtl->TcbPool;
220 pTxCtl->TcbPool = tcb;
221
222 tcb = next_tcb;
223 }
224
225 pTxCtl->TxActQueueHead = 0;
226 pTxCtl->TxActQueueTail = 0;
227 pTxCtl->TxActive = 0;
228
229 return 0;
230}
231
232
233/**
234 * @ingroup CPHAL_Functions
235 * This function transmits the data in FragList using available transmit
236 * buffer descriptors. More information on the use of the Mode parameter
237 * is available in the module-specific appendices. Note: The OS should
238 * not call Send() for a channel that has been requested to be torndown.
239 *
240 */
241int tnetv_cppi_send(struct cppi_info *cppi, int ch, dma_addr_t buf, unsigned length, int send_zlp)
242{
243 cppi_txcntl *pTxCtl;
244 cppi_tcb *first_tcb;
245 cppi_tcb *tcb;
246 int queued_len;
247 dma_addr_t buf_to_send;
248 dma_addr_t buf_ptr;
249 int total_len = length;
250 int pktlen;
251
252 pTxCtl = &cppi->tx_ctl[ch];
253
254 if (length == 0)
255 {
256 cppi_log_event0("[cppi] len = 0, nothing to send");
257 return -1;
258 }
259
260 // no send buffers.. try again later
261 if (!pTxCtl->TcbPool)
262 {
263 cppi_log_event0("[cppi] out of cppi buffers");
264 return -1;
265 }
266
267 // only send 1 packet at a time
268 if (pTxCtl->TxActQueueHead || pTxCtl->TxActive)
269 {
270 cppi_log_event0("[cppi] already sending!");
271 return -1;
272 }
273
274 buf_to_send = buf;
275
276 // usb_requests can have a 32 bit length, but CPPI DMA fragments
277 // have a (64k - 1) limit. Split the usb_request up into fragments here.
278 first_tcb = pTxCtl->TcbPool;
279 tcb = first_tcb;
280
281 cppi_log_event4("[cppi]cppi_send (buf) (len) (pool) (dma)", (uint32_t) buf_to_send, total_len, (uint32_t) first_tcb, first_tcb->dma_handle);
282
283 queued_len = 0;
284
285 do
286 {
287 buf_ptr = buf_to_send + queued_len;
288 tcb->BufPtr = __dma_to_vlynq_phys(buf_ptr);
289 tcb->HNext = 0;
290
291 // can't transfer more that 64k-1 bytes in 1 CPPI transfer
292 // need to queue up transfers if it's greater than that
293 pktlen = ((total_len - queued_len) > CPPI_MAX_FRAG) ? CPPI_MAX_FRAG : (total_len - queued_len);
294 tcb->Off_BLen = pktlen;
295 tcb->mode = (CB_OWNERSHIP_BIT | CB_SOF_BIT | CB_EOF_BIT | pktlen);
296
297 queued_len += pktlen;
298
299 if (queued_len < total_len)
300 {
301 tcb->HNext = __dma_to_vlynq_phys(((cppi_tcb *) tcb->Next)->dma_handle);
302
303 // write out the buffer to memory
304 consistent_sync(tcb, sizeof(*tcb), DMA_TO_DEVICE);
305
306 cppi_log_event4("[cppi] q tcb", (uint32_t) tcb, ((uint32_t *) tcb)[0], ((uint32_t *) tcb)[1], ((uint32_t *) tcb)[2]);
307 cppi_log_event4("[cppi] ", ((uint32_t *) tcb)[3], ((uint32_t *) tcb)[4], ((uint32_t *) tcb)[5], ((uint32_t *) tcb)[6]);
308
309 tcb = tcb->Next;
310 }
311 } while (queued_len < total_len);
312
313 /* In the Tx Interrupt handler, we will need to know which TCB is EOP,
314 so we can save that information in the SOP */
315 first_tcb->Eop = tcb;
316
317 // set the secret ZLP bit if necessary, this will be a completely separate packet
318 if (send_zlp)
319 {
320#if defined(AUTO_ZLP) && AUTO_ZLP
321 // add an extra buffer at the end to hold the ZLP
322 tcb->HNext = __dma_to_vlynq_phys(((cppi_tcb *) tcb->Next)->dma_handle);
323
324 // write out the buffer to memory
325 consistent_sync(tcb, sizeof(*tcb), DMA_TO_DEVICE);
326
327 tcb = tcb->Next;
328
329 /* In the Tx Interrupt handler, we will need to know which TCB is EOP,
330 so we can save that information in the SOP */
331 first_tcb->Eop = tcb;
332#endif
333
334 buf_ptr = buf_to_send + queued_len;
335 tcb->BufPtr = __dma_to_vlynq_phys(buf_ptr); // not used, but can't be zero
336 tcb->HNext = 0;
337 tcb->Off_BLen = 0x1; // device will send (((len - 1) / maxpacket) + 1) ZLPs
338 tcb->mode = (CB_SOF_BIT | CB_EOF_BIT | CB_OWNERSHIP_BIT | CB_ZLP_GARBAGE | 0x1); // send 1 ZLP
339 tcb->Eop = tcb;
340
341 cppi_log_event0("[cppi] Send ZLP!");
342 }
343
344 pTxCtl->TcbPool = tcb->Next;
345
346 tcb->Next = 0;
347 tcb->HNext = 0;
348
349 // write out the buffer to memory
350 consistent_sync(tcb, sizeof(*tcb), DMA_TO_DEVICE);
351
352 cppi_log_event4("[cppi] q tcb", (uint32_t) tcb, ((uint32_t *) tcb)[0], ((uint32_t *) tcb)[1], ((uint32_t *) tcb)[2]);
353 cppi_log_event4("[cppi] ", ((uint32_t *) tcb)[3], ((uint32_t *) tcb)[4], ((uint32_t *) tcb)[5], ((uint32_t *) tcb)[6]);
354
355 cppi_log_event4("[cppi] send queued (ptr) (len) (ftcb, ltcb)", (uint32_t) tcb->BufPtr, tcb->Off_BLen, (uint32_t) first_tcb, (uint32_t) tcb);
356
357 /* put it on the queue */
358 pTxCtl->TxActQueueHead = first_tcb;
359 pTxCtl->TxActQueueTail = tcb;
360
361 cppi_log_event3("[cppi] setting state (head) (virt) (next)", (uint32_t) first_tcb, __dma_to_vlynq_phys(first_tcb->dma_handle), (uint32_t) first_tcb->HNext);
362
363 /* write CPPI TX HDP - cache is cleaned above */
364 tnetv_usb_reg_write(TNETV_DMA_TX_STATE(ch, TNETV_CPPI_TX_WORD_HDP), __dma_to_vlynq_phys(first_tcb->dma_handle));
365
366 pTxCtl->TxActive = 1;
367
368 return 0;
369}
370
371/*
372 * This function allocates transmit buffer descriptors (internal CPHAL function).
373 * It creates a high priority transmit queue by default for a single Tx
374 * channel. If QoS is enabled for the given CPHAL device, this function
375 * will also allocate a low priority transmit queue.
376 *
377 * @return 0 OK, Non-Zero Not OK
378 */
379int tnetv_cppi_init_tcb(struct cppi_info *cppi, int ch)
380{
381 int i, num;
382 cppi_tcb *pTcb = 0;
383 char *AllTcb;
384 int tcbSize;
385 cppi_txcntl *pTxCtl = &cppi->tx_ctl[ch];
386
387 num = pTxCtl->TxNumBuffers;
388 tcbSize = (sizeof(cppi_tcb) + 0xf) & ~0xf;
389
390 cppi_log_event4("[cppi] init_tcb (ch) (num) (dma) (tcbsz)", ch, num, pTxCtl->tcb_start_dma_addr, tcbSize);
391
392 if (pTxCtl->TxNumBuffers == 0)
393 {
394 return -1;
395 }
396
397 /* if the memory has already been allocated, simply reuse it! */
398 AllTcb = pTxCtl->TcbStart;
399
400 // now reinitialize the TCB pool
401 pTxCtl->TcbPool = 0;
402 for (i = 0; i < num; i++)
403 {
404 pTcb = (cppi_tcb *)(AllTcb + (i * tcbSize));
405 pTcb->dma_handle = pTxCtl->tcb_start_dma_addr + (i * tcbSize);
406
407 pTcb->BufPtr = 0;
408 pTcb->mode = 0;
409 pTcb->HNext = 0;
410 pTcb->Off_BLen = 0;
411 pTcb->Eop = 0;
412
413 pTcb->Next = (void *) pTxCtl->TcbPool;
414
415 pTxCtl->TcbPool = pTcb;
416 }
417
418 cppi_log_event2(" [cppi]TcbPool", (uint32_t) pTxCtl->TcbPool, pTxCtl->TcbPool->dma_handle);
419
420#if USB_CPPI_LOGGING
421 {
422 // BEN DEBUG
423 cppi_tcb *first_tcb = pTxCtl->TcbPool;
424 cppi_log_event4("[cppi] init tcb", (uint32_t) first_tcb, ((uint32_t *) first_tcb)[0], ((uint32_t *) first_tcb)[1], ((uint32_t *) first_tcb)[2]);
425 cppi_log_event4("[cppi] ", ((uint32_t *) first_tcb)[3], ((uint32_t *) first_tcb)[4], ((uint32_t *) first_tcb)[5], ((uint32_t *) first_tcb)[6]);
426 }
427#endif
428
429 return 0;
430}
431
432// BEN DEBUG
433void tnetv_cppi_dump_info(struct cppi_info *cppi)
434{
435 int ch;
436 cppi_rxcntl *pRxCtl;
437 cppi_txcntl *pTxCtl;
438 cppi_tcb *tcb;
439 cppi_rcb *rcb;
440
441 logf("CPPI struct:\n");
442 logf("Buf mem: %x Buf size: %d int: %x %x\n\n", (uint32_t) cppi->dma_mem, cppi->dma_size, tnetv_usb_reg_read(TNETV_USB_RX_INT_STATUS), tnetv_usb_reg_read(DM320_VLYNQ_INTST));
443
444 for (ch = 0; ch < CPPI_NUM_CHANNELS; ch++)
445 {
446 pRxCtl = &cppi->rx_ctl[ch];
447 pTxCtl = &cppi->tx_ctl[ch];
448
449 logf("ch: %d\n", ch);
450 logf(" rx_numbufs: %d active %d free_buf_cnt %d\n", pRxCtl->RxNumBuffers, pRxCtl->RxActive, tnetv_usb_reg_read(TNETV_USB_RX_FREE_BUF_CNT(ch)));
451 logf(" q_cnt %d head %x tail %x\n", pRxCtl->RxActQueueCount, (uint32_t) pRxCtl->RxActQueueHead, (uint32_t) pRxCtl->RxActQueueTail);
452 logf(" fake_head: %x fake_tail: %x\n", (uint32_t) pRxCtl->RxFakeRcvHead, (uint32_t) pRxCtl->RxFakeRcvTail);
453
454 rcb = (cppi_rcb *) pRxCtl->RcbStart;
455 do
456 {
457 if (!rcb)
458 break;
459
460 logf(" Rcb: %x\n", (uint32_t) rcb);
461 logf(" HNext %x BufPtr %x Off_BLen %x mode %x\n", rcb->HNext, rcb->BufPtr, rcb->Off_BLen, rcb->mode);
462 logf(" Next %x Eop %x dma_handle %x fake_bytes %x\n", (uint32_t) rcb->Next, (uint32_t) rcb->Eop, rcb->dma_handle, rcb->fake_bytes);
463 rcb = rcb->Next;
464
465 } while (rcb && rcb != (cppi_rcb *) pRxCtl->RcbStart);
466
467 logf("\n");
468 logf(" tx_numbufs: %d active %d\n", pTxCtl->TxNumBuffers, pTxCtl->TxActive);
469 logf(" q_cnt %d head %x tail %x\n", pTxCtl->TxActQueueCount, (uint32_t) pTxCtl->TxActQueueHead, (uint32_t) pTxCtl->TxActQueueTail);
470
471 tcb = (cppi_tcb *) pTxCtl->TcbPool;
472 do
473 {
474 if (!tcb)
475 break;
476
477 logf(" Tcb (pool): %x\n", (uint32_t) tcb);
478 logf(" HNext %x BufPtr %x Off_BLen %x mode %x\n", tcb->HNext, tcb->BufPtr, tcb->Off_BLen, tcb->mode);
479 logf(" Next %x Eop %x dma_handle %x\n", (uint32_t) tcb->Next, (uint32_t) tcb->Eop, tcb->dma_handle);
480 tcb = tcb->Next;
481
482 } while (tcb && tcb != (cppi_tcb *) pTxCtl->TcbPool);
483
484 tcb = (cppi_tcb *) pTxCtl->TxActQueueHead;
485 do
486 {
487 if (!tcb)
488 break;
489
490 logf(" Tcb (act): %x\n", (uint32_t) tcb);
491 logf(" HNext %x BufPtr %x Off_BLen %x mode %x\n", tcb->HNext, tcb->BufPtr, tcb->Off_BLen, tcb->mode);
492 logf(" Next %x Eop %x dma_handle %x\n", (uint32_t) tcb->Next, (uint32_t) tcb->Eop, tcb->dma_handle);
493 tcb = tcb->Next;
494
495 } while (tcb && tcb != (cppi_tcb *) pTxCtl->TxActQueueTail);
496
497 }
498}
499
500/**
501 *
502 * This function is called to indicate to the CPHAL that the upper layer
503 * software has finished processing the receive data (given to it by
504 * osReceive()). The CPHAL will then return the appropriate receive buffers
505 * and buffer descriptors to the available pool.
506 *
507 */
508int tnetv_cppi_rx_return(struct cppi_info *cppi, int ch, cppi_rcb *done_rcb)
509{
510 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
511 cppi_rcb *curRcb, *lastRcb, *endRcb;
512 int num_bufs = 0;
513
514 if (!done_rcb)
515 return -1;
516
517 //cppi_log_event3("[cppi] rx_return (last) (first) bufinq", (uint32_t) done_rcb, (uint32_t) done_rcb->Eop, tnetv_usb_reg_read(TNETV_USB_RX_FREE_BUF_CNT(ch)));
518
519 curRcb = done_rcb;
520 endRcb = done_rcb->Eop;
521 do
522 {
523 curRcb->mode = CB_OWNERSHIP_BIT;
524 curRcb->Off_BLen = MAX_BUF_SIZE;
525 curRcb->Eop = 0;
526
527 pRxCtl->RxActQueueCount++;
528 num_bufs++;
529
530 lastRcb = curRcb;
531 curRcb = lastRcb->Next;
532
533 consistent_sync(lastRcb, sizeof(*lastRcb), DMA_TO_DEVICE);
534
535 } while (lastRcb != endRcb);
536
537 cppi_log_event1("[cppi] rx_return done", num_bufs);
538
539 // let the hardware know about the buffer(s)
540 tnetv_usb_reg_write(TNETV_USB_RX_FREE_BUF_CNT(ch), num_bufs);
541
542 return 0;
543}
544
545int tnetv_cppi_rx_int_recv(struct cppi_info *cppi, int ch, int *buf_size, void *buf, int maxpacket)
546{
547 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
548 cppi_rcb *CurrentRcb, *LastRcb = 0, *SopRcb;
549 uint8_t *cur_buf_data_addr;
550 int cur_buf_bytes;
551 int copy_buf_size = *buf_size;
552 int ret = -EAGAIN;
553
554 *buf_size = 0;
555
556 CurrentRcb = pRxCtl->RxFakeRcvHead;
557 if (!CurrentRcb)
558 {
559 cppi_log_event2("[cppi] rx_int recv: nothing in q", tnetv_usb_reg_read(TNETV_USB_RX_INT_STATUS), tnetv_usb_reg_read(DM320_VLYNQ_INTST));
560 return -1;
561 }
562
563 cppi_log_event1("[cppi] rx_int recv (ch)", ch);
564 cppi_log_event4(" [cppi] recv - Processing SOP descriptor fb hd tl", (uint32_t) CurrentRcb, CurrentRcb->fake_bytes, (uint32_t) pRxCtl->RxFakeRcvHead, (uint32_t) pRxCtl->RxFakeRcvTail);
565
566 SopRcb = CurrentRcb;
567 LastRcb = 0;
568
569 do
570 {
571 // convert from vlynq phys to virt
572 cur_buf_data_addr = (uint8_t *) __vlynq_phys_to_dma(CurrentRcb->BufPtr);
573 cur_buf_data_addr = (uint8_t *) __phys_to_virt(cur_buf_data_addr);
574 cur_buf_bytes = (CurrentRcb->mode) & CB_SIZE_MASK;
575
576 // make sure we don't overflow the buffer.
577 if (cur_buf_bytes > copy_buf_size)
578 {
579 ret = 0;
580 break;
581 }
582
583 // BEN - packet can be ZLP
584 if (cur_buf_bytes)
585 {
586 consistent_sync(cur_buf_data_addr, MAX_BUF_SIZE, DMA_FROM_DEVICE);
587
588 memcpy((buf + *buf_size), cur_buf_data_addr, cur_buf_bytes);
589
590 copy_buf_size -= cur_buf_bytes;
591 *buf_size += cur_buf_bytes;
592 CurrentRcb->fake_bytes -= cur_buf_bytes;
593 }
594 else
595 {
596 CurrentRcb->fake_bytes = 0;
597 }
598
599 cppi_log_event4(" [cppi] bytes totrcvd amtleft fake", cur_buf_bytes, *buf_size, copy_buf_size, CurrentRcb->fake_bytes);
600
601 LastRcb = CurrentRcb;
602 CurrentRcb = LastRcb->Next;
603
604 // sync out fake bytes info
605 consistent_sync(LastRcb, sizeof(*LastRcb), DMA_TO_DEVICE);
606
607 // make sure each packet processed individually
608 if (cur_buf_bytes < maxpacket)
609 {
610 ret = 0;
611 break;
612 }
613
614 } while (LastRcb != pRxCtl->RxFakeRcvTail && CurrentRcb->fake_bytes && copy_buf_size > 0);
615
616 // make sure that the CurrentRcb isn't in the cache
617 consistent_sync(CurrentRcb, sizeof(*CurrentRcb), DMA_FROM_DEVICE);
618
619 if (copy_buf_size == 0)
620 {
621 ret = 0;
622 }
623
624 if (LastRcb)
625 {
626 SopRcb->Eop = LastRcb;
627
628 cppi_log_event3(" [cppi] rcv end", *buf_size, (uint32_t) CurrentRcb, (uint32_t) SopRcb->Eop);
629
630 if (LastRcb == pRxCtl->RxFakeRcvTail)
631 {
632 pRxCtl->RxFakeRcvHead = 0;
633 pRxCtl->RxFakeRcvTail = 0;
634 }
635 else
636 {
637 pRxCtl->RxFakeRcvHead = CurrentRcb;
638 }
639
640 cppi_log_event1(" [cppi] st rx return", ch);
641 cppi_log_event2(" rcv fake hd tl", (uint32_t) pRxCtl->RxFakeRcvHead, (uint32_t) pRxCtl->RxFakeRcvTail);
642
643 // all done, clean up the RCBs
644 tnetv_cppi_rx_return(cppi, ch, SopRcb);
645 }
646
647 return ret;
648}
649
650/*
651 * This function processes receive interrupts. It traverses the receive
652 * buffer queue, extracting the data and passing it to the upper layer software via
653 * osReceive(). It handles all error conditions and fragments without valid data by
654 * immediately returning the RCB's to the RCB pool.
655 */
656int tnetv_cppi_rx_int(struct cppi_info *cppi, int ch)
657{
658 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
659 cppi_rcb *CurrentRcb, *LastRcb = 0, *SopRcb;
660 uint32_t RxBufStatus,PacketsServiced;
661 int TotalFrags;
662
663 cppi_log_event1("[cppi] rx_int (ch)", ch);
664
665 CurrentRcb = pRxCtl->RxActQueueHead;
666
667 if (!CurrentRcb)
668 {
669 cppi_log_event1("[cppi] rx_int no bufs!", (uint32_t) CurrentRcb);
670 return -1;
671 }
672
673 // make sure that all of the buffers get an invalidated cache
674 consistent_sync(pRxCtl->RcbStart, sizeof(cppi_rcb) * CPPI_RX_NUM_BUFS, DMA_FROM_DEVICE);
675
676 RxBufStatus = CurrentRcb->mode;
677 PacketsServiced = 0;
678
679 cppi_log_event4("[cppi] currentrcb, mode numleft fake", (uint32_t) CurrentRcb, CurrentRcb->mode, pRxCtl->RxActQueueCount, CurrentRcb->fake_bytes);
680 cppi_log_event4("[cppi]", ((uint32_t *) CurrentRcb)[0], ((uint32_t *) CurrentRcb)[1], ((uint32_t *) CurrentRcb)[2], ((uint32_t *) CurrentRcb)[3]);
681
682 while(((RxBufStatus & CB_OWNERSHIP_BIT) == 0) && (pRxCtl->RxActQueueCount > 0))
683 {
684 cppi_log_event2(" [cppi]Processing SOP descriptor st", (uint32_t) CurrentRcb, RxBufStatus);
685
686 SopRcb = CurrentRcb;
687
688 TotalFrags = 0;
689
690 do
691 {
692 TotalFrags++;
693 PacketsServiced++;
694
695 // Write the completion pointer
696 tnetv_usb_reg_write(TNETV_DMA_RX_CMPL(ch), __dma_to_vlynq_phys(CurrentRcb->dma_handle));
697
698 CurrentRcb->fake_bytes = (CurrentRcb->mode) & 0xFFFF;
699
700 // BEN - make sure this gets marked!
701 if (!CurrentRcb->fake_bytes || (CurrentRcb->mode & CB_ZLP_GARBAGE))
702 {
703 CurrentRcb->mode &= 0xFFFF0000;
704 CurrentRcb->fake_bytes = 0x10000;
705 }
706
707 cppi_log_event1(" fake_bytes:", CurrentRcb->fake_bytes);
708
709 RxBufStatus = CurrentRcb->mode;
710 LastRcb = CurrentRcb;
711 CurrentRcb = LastRcb->Next;
712
713 // sync the fake_bytes value back to mem
714 consistent_sync(LastRcb, sizeof(*LastRcb), DMA_TO_DEVICE);
715
716 } while (((CurrentRcb->mode & CB_OWNERSHIP_BIT) == 0) && ((RxBufStatus & CB_EOF_BIT) == 0));
717
718 SopRcb->Eop = LastRcb;
719
720 pRxCtl->RxActQueueHead = CurrentRcb;
721 pRxCtl->RxActQueueCount -= TotalFrags;
722
723 if (LastRcb->mode & CB_EOQ_BIT)
724 {
725 if (CurrentRcb)
726 {
727 cppi_log_event1(" [cppi] rcv done q next", LastRcb->HNext);
728 tnetv_usb_reg_write(TNETV_DMA_RX_STATE(ch, TNETV_CPPI_RX_WORD_HDP), LastRcb->HNext);
729 }
730 else
731 {
732 cppi_log_event0(" [cppi] rcv done");
733
734 pRxCtl->RxActive = 0;
735 }
736 }
737
738 // BEN - add to the list of buffers we need to deal with
739 if (!pRxCtl->RxFakeRcvHead)
740 {
741 pRxCtl->RxFakeRcvHead = SopRcb;
742 pRxCtl->RxFakeRcvTail = SopRcb->Eop;
743 }
744 else
745 {
746 pRxCtl->RxFakeRcvTail = SopRcb->Eop;
747 }
748
749 // make sure we have enough buffers
750 cppi_log_event1(" nextrcb", CurrentRcb->mode);
751
752 if (CurrentRcb)
753 {
754 // continue the loop
755 RxBufStatus = CurrentRcb->mode;
756 }
757
758 } /* while */
759
760 cppi_log_event2("[cppi] fake hd tl", (uint32_t) pRxCtl->RxFakeRcvHead, (uint32_t) pRxCtl->RxFakeRcvTail);
761
762 // sync out all buffers before leaving
763 consistent_sync(pRxCtl->RcbStart, (CPPI_RX_NUM_BUFS * sizeof(cppi_rcb)), DMA_FROM_DEVICE);
764
765 return PacketsServiced;
766}
767
768static void tnetv_cppi_rx_queue_init(struct cppi_info *cppi, int ch, dma_addr_t buf, unsigned length)
769{
770 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
771 cppi_rcb *rcb, *first_rcb;
772 unsigned int queued_len = 0;
773 int rcblen;
774 int num_frags = 0;
775 dma_addr_t buf_ptr;
776
777 if (length == 0)
778 {
779 cppi_log_event0("[cppi] len = 0, nothing to recv");
780 return;
781 }
782
783 // usb_requests can have a 32 bit length, but CPPI DMA fragments
784 // have a 64k limit. Split the usb_request up into fragments here.
785 first_rcb = pRxCtl->RcbPool;
786 rcb = first_rcb;
787
788 cppi_log_event2("[cppi] Rx queue add: head len", (uint32_t) first_rcb, length);
789
790 while (queued_len < length)
791 {
792 buf_ptr = buf + queued_len;
793 rcb->BufPtr = __dma_to_vlynq_phys(buf_ptr);
794
795 rcb->HNext = 0;
796 rcb->mode = CB_OWNERSHIP_BIT;
797
798 rcblen = ((length - queued_len) > MAX_BUF_SIZE) ? MAX_BUF_SIZE : (length - queued_len);
799 rcb->Off_BLen = rcblen;
800
801 queued_len += rcblen;
802 if (queued_len < length)
803 {
804 rcb->HNext = __dma_to_vlynq_phys(((cppi_rcb *) (rcb->Next))->dma_handle);
805 rcb = rcb->Next;
806 }
807
808 num_frags++;
809 }
810
811 pRxCtl->RcbPool = rcb->Next;
812 rcb->Next = 0;
813
814 cppi_log_event4("[cppi] Adding Rcb (dma) (paddr) (buf)", (uint32_t) rcb, rcb->dma_handle, __dma_to_vlynq_phys(rcb->dma_handle), (uint32_t) rcb->BufPtr);
815 cppi_log_event4("[cppi] Next HNext (len) of (total)", (uint32_t) rcb->Next, rcb->HNext, queued_len, length);
816
817 pRxCtl->RxActQueueCount += num_frags;
818
819 cppi_log_event4("[cppi] rx queued (ptr) (len) (ftcb, ltcb)", (uint32_t) rcb->BufPtr, rcb->Off_BLen, (uint32_t) first_rcb, (uint32_t) rcb);
820 cppi_log_event2(" [cppi] mode num_frags", rcb->mode, num_frags);
821
822 pRxCtl->RxActQueueHead = first_rcb;
823 pRxCtl->RxActQueueTail = rcb;
824
825 cppi_log_event2("[cppi] setting rx (head) (virt)", (uint32_t) first_rcb, __dma_to_vlynq_phys(first_rcb->dma_handle));
826 cppi_log_event4("[cppi] ", ((uint32_t *) first_rcb)[0], ((uint32_t *) first_rcb)[1], ((uint32_t *) first_rcb)[2], ((uint32_t *) first_rcb)[3]);
827
828 // make this into a circular buffer so we never get caught with
829 // no free buffers left
830 rcb->Next = pRxCtl->RxActQueueHead;
831 rcb->HNext = (uint32_t) (__dma_to_vlynq_phys(pRxCtl->RxActQueueHead->dma_handle));
832}
833
834int tnetv_cppi_rx_queue_add(struct cppi_info *cppi, int ch, dma_addr_t buf, unsigned length)
835{
836 (void)buf;
837 (void)length;
838 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
839 unsigned int cur_bufs;
840
841 cur_bufs = tnetv_usb_reg_read(TNETV_USB_RX_FREE_BUF_CNT(ch));
842
843 if (!pRxCtl->RxActive)
844 {
845 cppi_log_event0("[cppi] queue add - not active");
846
847 pRxCtl->RcbPool = (cppi_rcb *) pRxCtl->RcbStart;
848
849 // add all the buffers to the active (circular) queue
850 tnetv_cppi_rx_queue_init(cppi, ch, (dma_addr_t) __virt_to_phys(dma_recv_buf[ch]), (MAX_BUF_SIZE * pRxCtl->RxNumBuffers));
851
852 /* write Rx Queue Head Descriptor Pointer */
853 tnetv_usb_reg_write(TNETV_DMA_RX_STATE(ch, TNETV_CPPI_RX_WORD_HDP), __dma_to_vlynq_phys(pRxCtl->RxActQueueHead->dma_handle));
854
855 pRxCtl->RxActive = 1;
856
857 // sync out all buffers before starting
858 consistent_sync(pRxCtl->RcbStart, (CPPI_RX_NUM_BUFS * sizeof(cppi_rcb)), DMA_TO_DEVICE);
859
860 // sync out temp rx buffer
861 consistent_sync(dma_recv_buf[ch], CPPI_DMA_RX_BUF_SIZE, DMA_FROM_DEVICE);
862
863 if (cur_bufs < pRxCtl->RxActQueueCount)
864 {
865 // let the hardware know about the buffer(s)
866 tnetv_usb_reg_write(TNETV_USB_RX_FREE_BUF_CNT(ch), pRxCtl->RxActQueueCount - cur_bufs);
867 }
868 }
869
870 cppi_log_event3("[cppi] rx add: (cur_bufs) (avail_bufs) (now)", cur_bufs, pRxCtl->RxActQueueCount, tnetv_usb_reg_read(TNETV_USB_RX_FREE_BUF_CNT(ch)));
871
872 return 0;
873}
874
875int tnetv_cppi_flush_rx_queue(struct cppi_info *cppi, int ch)
876{
877 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
878 cppi_rcb *rcb;
879 int num_bufs;
880
881 cppi_log_event1("[cppi] flush RX ", (uint32_t) pRxCtl->RxActQueueHead);
882
883 // flush out any pending receives
884 tnetv_cppi_rx_int(cppi, ch);
885
886 // now discard all received data
887 rcb = pRxCtl->RxFakeRcvHead;
888
889 if (rcb)
890 {
891 rcb->Eop = pRxCtl->RxFakeRcvTail;
892
893 // clean up any unreceived RCBs
894 tnetv_cppi_rx_return(cppi, ch, rcb);
895 }
896
897 pRxCtl->RxFakeRcvHead = 0;
898 pRxCtl->RxFakeRcvTail = 0;
899
900 pRxCtl->RxActive = 0;
901
902 // drain the HW free buffer count
903 num_bufs = tnetv_usb_reg_read(TNETV_USB_RX_FREE_BUF_CNT(ch));
904 tnetv_usb_reg_write(TNETV_USB_RX_FREE_BUF_CNT(ch), -num_bufs);
905
906 cppi_log_event2("[cppi] flush RX queue done (freed) act: ", num_bufs, (uint32_t) pRxCtl->RxActQueueCount);
907
908 return 0;
909}
910
911
912/*
913 * This function allocates receive buffer descriptors (internal CPHAL function).
914 * After allocation, the function 'queues' (gives to the hardware) the newly
915 * created receive buffers to enable packet reception.
916 *
917 * @param ch Channel number.
918 *
919 * @return 0 OK, Non-Zero Not OK
920 */
921int tnetv_cppi_init_rcb(struct cppi_info *cppi, int ch)
922{
923 int i, num;
924 cppi_rcb *pRcb;
925 char *AllRcb;
926 int rcbSize;
927 cppi_rxcntl *pRxCtl = &cppi->rx_ctl[ch];
928
929 num = pRxCtl->RxNumBuffers;
930 rcbSize = (sizeof(cppi_rcb) + 0xf) & ~0xf;
931
932 cppi_log_event2("[cppi] init_rcb ch num", ch, num);
933
934 if (pRxCtl->RxNumBuffers == 0)
935 {
936 return -1;
937 }
938
939 /* if the memory has already been allocated, simply reuse it! */
940 AllRcb = pRxCtl->RcbStart;
941
942 // now reinitialize the RCB pool
943 pRxCtl->RcbPool = 0;
944 for (i = (num - 1); i >= 0; i--)
945 {
946 pRcb = (cppi_rcb *)(AllRcb + (i * rcbSize));
947
948 pRcb->dma_handle = pRxCtl->rcb_start_dma_addr + (i * rcbSize);
949
950 pRcb->BufPtr = 0;
951 pRcb->mode = 0;
952 pRcb->HNext = 0;
953 pRcb->Next = (void *) pRxCtl->RcbPool;
954 pRcb->Off_BLen = 0;
955 pRcb->Eop = 0;
956 pRcb->fake_bytes = 0;
957
958 pRxCtl->RcbPool = pRcb;
959 }
960
961 cppi_log_event2(" [cppi]RcbPool (dma)", (uint32_t) pRxCtl->RcbPool, pRxCtl->RcbPool->dma_handle);
962
963 pRxCtl->RxActQueueCount = 0;
964 pRxCtl->RxActQueueHead = 0;
965 pRxCtl->RxActive = 0;
966
967 pRxCtl->RxFakeRcvHead = 0;
968 pRxCtl->RxFakeRcvTail = 0;
969
970 return 0;
971}
972
973static uint8_t ch_buf_cnt[][2] = {
974 {CPPI_RX_NUM_BUFS, 2}, // ch0: bulk out/in
975 {CPPI_RX_NUM_BUFS, 2}, // ch1: bulk out/in
976 {0, 2}, // ch2: interrupt
977 {0, 2} // ch3: interrupt
978};
979
980void tnetv_cppi_init(struct cppi_info *cppi)
981{
982 int ch;
983 uint8_t *alloc_ptr;
984 int ch_mem_size[CPPI_NUM_CHANNELS];
985
986 // wipe cppi memory
987 memset(cppi, 0, sizeof(*cppi));
988
989 // find out how much memory we need to allocate
990 cppi->dma_size = 0;
991 for (ch = 0; ch < CPPI_NUM_CHANNELS; ch++)
992 {
993 ch_mem_size[ch] = (ch_buf_cnt[ch][0] * sizeof(cppi_rcb)) + (ch_buf_cnt[ch][1] * sizeof(cppi_tcb));
994 cppi->dma_size += ch_mem_size[ch];
995 }
996
997 // allocate DMA-able memory
998 if (cppi->dma_size != CPPI_INFO_MEM_SIZE)
999 {
1000 panicf("Invalid dma size expected %d got %d", cppi->dma_size, CPPI_INFO_MEM_SIZE);
1001 }
1002 cppi->dma_handle = (dma_addr_t) __virt_to_phys(cppi->dma_mem);
1003
1004 memset(cppi->dma_mem, 0, cppi->dma_size);
1005
1006 cppi_log_event2("[cppi] all CBs sz mem", cppi->dma_size, (uint32_t) cppi->dma_mem);
1007
1008 // now set up the pointers
1009 alloc_ptr = cppi->dma_mem;
1010 for (ch = 0; ch < CPPI_NUM_CHANNELS; ch++)
1011 {
1012 cppi->rx_ctl[ch].RxNumBuffers = ch_buf_cnt[ch][0];
1013 cppi->rx_ctl[ch].RcbStart = alloc_ptr;
1014 cppi->rx_ctl[ch].rcb_start_dma_addr = (dma_addr_t) __virt_to_phys(alloc_ptr);
1015 alloc_ptr += (ch_buf_cnt[ch][0] * sizeof(cppi_rcb));
1016
1017 cppi->tx_ctl[ch].TxNumBuffers = ch_buf_cnt[ch][1];
1018 cppi->tx_ctl[ch].TcbStart = alloc_ptr;
1019 cppi->tx_ctl[ch].tcb_start_dma_addr = (dma_addr_t) __virt_to_phys(alloc_ptr);
1020 alloc_ptr += (ch_buf_cnt[ch][1] * sizeof(cppi_tcb));
1021
1022 cppi_log_event3("[cppi] alloc bufs: ch dmarcb dmatcb", ch, cppi->rx_ctl[ch].rcb_start_dma_addr, cppi->tx_ctl[ch].tcb_start_dma_addr);
1023
1024 // set up receive buffer
1025 if (ch_buf_cnt[ch][0])
1026 {
1027 dma_recv_buf[ch] = (ch == 0) ? ch0_rx_buf : ((ch == 1) ? ch1_rx_buf : 0);
1028 cppi_log_event3("[cppi] Alloc fake DMA buf ch", ch, (uint32_t) dma_recv_buf[ch], (uint32_t) __virt_to_phys(dma_recv_buf[ch]));
1029 }
1030 else
1031 {
1032 dma_recv_buf[ch] = 0;
1033 }
1034 }
1035
1036}
1037
1038void tnetv_cppi_cleanup(struct cppi_info *cppi)
1039{
1040 cppi_log_event0("wipe cppi mem");
1041
1042 // wipe cppi memory
1043 memset(cppi, 0, sizeof(*cppi));
1044}
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.h b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.h
new file mode 100644
index 0000000000..9d0ac37cd0
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_cppi.h
@@ -0,0 +1,144 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2021 by Tomasz Moń
11 * Copied with minor modifications from Sansa Connect Linux driver
12 * Copyright (c) 2005 Zermatt Systems, Inc.
13 * Written by: Ben Bostwick
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#ifndef TNETV105_CPPI_H
26#define TNETV105_CPPI_H
27
28#include <stdint.h>
29
30typedef uint32_t dma_addr_t;
31#define USB_CPPI_LOGGING 0
32#define EAGAIN 11 /* Try again */
33#define CPPI_RX_NUM_BUFS 129
34#define CPPI_INFO_MEM_SIZE (2 * CPPI_RX_NUM_BUFS * sizeof(cppi_rcb) + 4 * 2 * sizeof(cppi_tcb))
35
36#define CPPI_NUM_CHANNELS 4
37#define CPPI_MAX_FRAG 0xFE00
38
39struct cppi_info;
40
41typedef struct
42{
43 uint32_t HNext; /*< Hardware's pointer to next buffer descriptor */
44 uint32_t BufPtr; /*< Pointer to the data buffer */
45 uint32_t Off_BLen; /*< Contains buffer offset and buffer length */
46 uint32_t mode; /*< SOP, EOP, Ownership, EOQ, Teardown, Q Starv, Length */
47 void *Next;
48 void *Eop;
49 dma_addr_t dma_handle;
50 uint32_t dummy;
51
52} cppi_tcb;
53
54typedef struct
55{
56 uint32_t HNext; /*< Hardware's pointer to next buffer descriptor */
57 uint32_t BufPtr; /*< Pointer to the data buffer */
58 uint32_t Off_BLen; /*< Contains buffer offset and buffer length */
59 uint32_t mode; /*< SOP, EOP, Ownership, EOQ, Teardown Complete bits */
60 void *Next;
61 void *Eop;
62 dma_addr_t dma_handle;
63 uint32_t fake_bytes;
64
65} cppi_rcb;
66
67typedef struct cppi_txcntl
68{
69 cppi_tcb *TcbPool;
70 cppi_tcb *TxActQueueHead;
71 cppi_tcb *TxActQueueTail;
72 uint32_t TxActQueueCount;
73 uint32_t TxActive;
74 cppi_tcb *LastTcbProcessed;
75 char *TcbStart;
76 dma_addr_t tcb_start_dma_addr;
77 int TxNumBuffers;
78
79#ifdef _CPHAL_STATS
80 uint32_t TxMisQCnt;
81 uint32_t TxEOQCnt;
82 uint32_t TxPacketsServiced;
83 uint32_t TxMaxServiced;
84 uint32_t NumTxInt;
85#endif
86} cppi_txcntl;
87
88
89typedef struct cppi_rxcntl
90{
91 cppi_rcb *RcbPool;
92 cppi_rcb *RxActQueueHead;
93 cppi_rcb *RxActQueueTail;
94 uint32_t RxActQueueCount;
95 uint32_t RxActive;
96 char *RcbStart;
97 dma_addr_t rcb_start_dma_addr;
98 int RxNumBuffers;
99
100 cppi_rcb *RxFakeRcvHead;
101 cppi_rcb *RxFakeRcvTail;
102
103#ifdef _CPHAL_STATS
104 uint32_t RxMisQCnt;
105 uint32_t RxEOQCnt;
106 uint32_t RxMaxServiced;
107 uint32_t RxPacketsServiced;
108 uint32_t NumRxInt;
109#endif
110} cppi_rxcntl;
111
112typedef struct cppi_info
113{
114 struct cppi_txcntl tx_ctl[CPPI_NUM_CHANNELS];
115 struct cppi_rxcntl rx_ctl[CPPI_NUM_CHANNELS];
116
117 uint8_t dma_mem[CPPI_INFO_MEM_SIZE];
118 int dma_size;
119 dma_addr_t dma_handle;
120
121} cppi_info;
122
123#define tnetv_cppi_rx_int_recv_check(cppi, ch) (((cppi)->rx_ctl[(ch)].RxFakeRcvHead) ? 1 : 0)
124
125int tnetv_cppi_init_tcb(struct cppi_info *cppi, int ch);
126int tnetv_cppi_flush_tx_queue(struct cppi_info *cppi, int ch);
127int tnetv_cppi_send(struct cppi_info *cppi, int ch, dma_addr_t buf, unsigned length, int send_zlp);
128int tnetv_cppi_tx_int(struct cppi_info *cppi, int ch);
129void tnetv_cppi_free_tcb(struct cppi_info *cppi, int ch);
130
131int tnetv_cppi_init_rcb(struct cppi_info *cppi, int ch);
132int tnetv_cppi_flush_rx_queue(struct cppi_info *cppi, int ch);
133int tnetv_cppi_rx_return(struct cppi_info *cppi, int ch, cppi_rcb *done_rcb);
134int tnetv_cppi_rx_queue_add(struct cppi_info *cppi, int ch, dma_addr_t buf, unsigned length);
135int tnetv_cppi_rx_int(struct cppi_info *cppi, int ch);
136int tnetv_cppi_rx_int_recv(struct cppi_info *cppi, int ch, int *buf_size, void *buf, int maxpacket);
137void tnetv_cppi_free_rcb(struct cppi_info *cppi, int ch);
138
139void tnetv_cppi_init(struct cppi_info *cppi);
140void tnetv_cppi_cleanup(struct cppi_info *cppi);
141
142void tnetv_cppi_dump_info(struct cppi_info *cppi);
143
144#endif
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c
new file mode 100644
index 0000000000..4fdf73cb50
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c
@@ -0,0 +1,1489 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2021 by Tomasz Moń
11 * Ported from Sansa Connect TNETV105 UDC Linux driver
12 * Copyright (c) 2005,2006 Zermatt Systems, Inc.
13 * Written by: Ben Bostwick
14 * Linux driver was modeled strongly after the pxa usb driver.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
23 *
24 ****************************************************************************/
25
26#include "config.h"
27#include "system.h"
28#include "kernel.h"
29#include "panic.h"
30#include "logf.h"
31#include "usb.h"
32#include "usb_drv.h"
33#include "usb_core.h"
34#include <string.h>
35#include "tnetv105_usb_drv.h"
36#include "tnetv105_cppi.h"
37
38#ifdef SANSA_CONNECT
39#define SDRAM_SIZE 0x04000000
40
41static void set_tnetv_reset(bool high)
42{
43 if (high)
44 {
45 IO_GIO_BITSET0 = (1 << 7);
46 }
47 else
48 {
49 IO_GIO_BITCLR0 = (1 << 7);
50 }
51}
52
53static bool is_tnetv_reset_high(void)
54{
55 return (IO_GIO_BITSET0 & (1 << 7)) ? true : false;
56}
57#endif
58
59static bool setup_is_set_address;
60
61static cppi_info cppi;
62
63static struct ep_runtime_t
64{
65 int max_packet_size;
66 bool in_allocated;
67 bool out_allocated;
68 uint8_t *rx_buf; /* OUT */
69 int rx_remaining;
70 int rx_size;
71 uint8_t *tx_buf; /* IN */
72 int tx_remaining;
73 int tx_size;
74 volatile bool block; /* flag indicating that transfer is blocking */
75 struct semaphore complete; /* semaphore for blocking transfers */
76}
77ep_runtime[USB_NUM_ENDPOINTS];
78
79static const struct
80{
81 int type;
82 int hs_max_packet_size;
83 /* Not sure what xyoff[1] is for. Presumably it is double buffer, but how
84 * the double buffering works is not so clear from the Sansa Connect Linux
85 * kernel patch. As TNETV105 datasheet is not available, the values are
86 * simply taken from the Linux patch as potential constraints are unknown.
87 *
88 * Linux kernel has 9 endpoints:
89 * * 0: ep0
90 * * 1: ep1in-bulk
91 * * 2: ep2out-bulk
92 * * 3: ep3in-int
93 * * 4: ep4in-int
94 * * 5: ep1out-bulk
95 * * 6: ep2in-bulk
96 * * 7: ep3out-int
97 * * 8: ep4out-int
98 */
99 uint16_t xyoff_in[2];
100 uint16_t xyoff_out[2];
101}
102ep_const_data[USB_NUM_ENDPOINTS] =
103{
104 {
105 .type = USB_ENDPOINT_XFER_CONTROL,
106 .hs_max_packet_size = EP0_MAX_PACKET_SIZE,
107 /* Do not set xyoff as it likely does not apply here.
108 * Linux simply hardcodes the offsets when needed.
109 */
110 },
111 {
112 .type = USB_ENDPOINT_XFER_BULK,
113 .hs_max_packet_size = EP1_MAX_PACKET_SIZE,
114 .xyoff_in = {EP1_XBUFFER_ADDRESS, EP1_YBUFFER_ADDRESS},
115 .xyoff_out = {EP5_XBUFFER_ADDRESS, EP5_YBUFFER_ADDRESS},
116 },
117 {
118 .type = USB_ENDPOINT_XFER_BULK,
119 .hs_max_packet_size = EP2_MAX_PACKET_SIZE,
120 .xyoff_in = {EP6_XBUFFER_ADDRESS, EP6_YBUFFER_ADDRESS},
121 .xyoff_out = {EP2_XBUFFER_ADDRESS, EP2_YBUFFER_ADDRESS},
122 },
123 {
124 .type = USB_ENDPOINT_XFER_INT,
125 .hs_max_packet_size = EP3_MAX_PACKET_SIZE,
126 .xyoff_in = {EP3_XBUFFER_ADDRESS, EP3_YBUFFER_ADDRESS},
127 .xyoff_out = {EP7_XBUFFER_ADDRESS, EP7_YBUFFER_ADDRESS},
128 },
129 {
130 .type = USB_ENDPOINT_XFER_INT,
131 .hs_max_packet_size = EP4_MAX_PACKET_SIZE,
132 .xyoff_in = {EP4_XBUFFER_ADDRESS, EP4_YBUFFER_ADDRESS},
133 .xyoff_out = {EP8_XBUFFER_ADDRESS, EP8_YBUFFER_ADDRESS},
134 },
135};
136
137#define VLYNQ_CTL_RESET_MASK 0x0001
138#define VLYNQ_CTL_CLKDIR_MASK 0x8000
139#define VLYNQ_STS_LINK_MASK 0x0001
140
141#define DM320_VLYNQ_CTRL_RESET (1 << 0)
142#define DM320_VLYNQ_CTRL_LOOP (1 << 1)
143#define DM320_VLYNQ_CTRL_ADR_OPT (1 << 2)
144#define DM320_VLYNQ_CTRL_INT_CFG (1 << 7)
145#define DM320_VLYNQ_CTRL_INT_VEC_MASK (0x00001F00)
146#define DM320_VLYNQ_CTRL_INT_EN (1 << 13)
147#define DM320_VLYNQ_CTRL_INT_LOC (1 << 14)
148#define DM320_VLYNQ_CTRL_CLKDIR (1 << 15)
149#define DM320_VLYNQ_CTRL_CLKDIV_MASK (0x00070000)
150#define DM320_VLYNQ_CTRL_PWR_MAN (1 << 31)
151
152#define DM320_VLYNQ_STAT_LINK (1 << 0)
153#define DM320_VLYNQ_STAT_MST_PEND (1 << 1)
154#define DM320_VLYNQ_STAT_SLV_PEND (1 << 2)
155#define DM320_VLYNQ_STAT_F0_NE (1 << 3)
156#define DM320_VLYNQ_STAT_F1_NE (1 << 4)
157#define DM320_VLYNQ_STAT_F2_NE (1 << 5)
158#define DM320_VLYNQ_STAT_F3_NE (1 << 6)
159#define DM320_VLYNQ_STAT_LOC_ERR (1 << 7)
160#define DM320_VLYNQ_STAT_REM_ERR (1 << 8)
161#define DM320_VLYNQ_STAT_FC_OUT (1 << 9)
162#define DM320_VLYNQ_STAT_FC_IN (1 << 10)
163
164#define MAX_PACKET(epn, speed) ((((speed) == USB_SPEED_HIGH) && (((epn) == 1) || ((epn) == 2))) ? USB_HIGH_SPEED_MAXPACKET : USB_FULL_SPEED_MAXPACKET)
165
166#define VLYNQ_INTR_USB20 (1 << 0)
167#define VLYNQ_INTR_CPPI (1 << 1)
168
169static inline void set_vlynq_clock(bool enable)
170{
171 if (enable)
172 {
173 IO_CLK_MOD2 |= (1 << 13);
174 }
175 else
176 {
177 IO_CLK_MOD2 &= ~(1 << 13);
178 }
179}
180
181static inline void set_vlynq_irq(bool enabled)
182{
183 if (enabled)
184 {
185 /* Enable VLYNQ interrupt */
186 IO_INTC_EINT1 |= (1 << 0);
187 }
188 else
189 {
190 IO_INTC_EINT1 &= ~(1 << 0);
191 }
192}
193
194static int tnetv_hw_reset(void)
195{
196 int timeout;
197
198 /* hold down the reset pin on the USB chip */
199 set_tnetv_reset(false);
200
201 /* Turn on VLYNQ clock. */
202 set_vlynq_clock(true);
203
204 /* now reset the VLYNQ module */
205 VL_CTRL |= (VLYNQ_CTL_CLKDIR_MASK | DM320_VLYNQ_CTRL_PWR_MAN);
206 VL_CTRL |= VLYNQ_CTL_RESET_MASK;
207
208 mdelay(10);
209
210 /* pull up the reset pin */
211 set_tnetv_reset(true);
212
213 /* take the VLYNQ out of reset */
214 VL_CTRL &= ~VLYNQ_CTL_RESET_MASK;
215
216 timeout = 0;
217 while (!(VL_STAT & VLYNQ_STS_LINK_MASK) && timeout++ < 50);
218 {
219 mdelay(40);
220 }
221
222 if (!(VL_STAT & VLYNQ_STS_LINK_MASK))
223 {
224 logf("ERROR: VLYNQ not initialized!\n");
225 return -1;
226 }
227
228 /* set up vlynq local map */
229 VL_TXMAP = DM320_VLYNQ_PADDR;
230 VL_RXMAPOF1 = CONFIG_SDRAM_START;
231 VL_RXMAPSZ1 = SDRAM_SIZE;
232
233 /* set up vlynq remote map for tnetv105 */
234 VL_TXMAP_R = 0x00000000;
235 VL_RXMAPOF1_R = 0x0C000000;
236 VL_RXMAPSZ1_R = 0x00030000;
237
238 /* clear TNETV gpio state */
239 tnetv_usb_reg_write(TNETV_V2USB_GPIO_FS, 0);
240
241 /* set USB_CHARGE_EN pin (gpio 1) - output, disable pullup */
242 tnetv_usb_reg_write(TNETV_V2USB_GPIO_DOUT, 0);
243 tnetv_usb_reg_write(TNETV_V2USB_GPIO_DIR, 0xffff);
244
245 return 0;
246}
247
248static int tnetv_xcvr_on(void)
249{
250 return tnetv_hw_reset();
251}
252
253static void tnetv_xcvr_off(void)
254{
255 /* turn off vlynq module clock */
256 set_vlynq_clock(false);
257
258 /* hold down the reset pin on the USB chip */
259 set_tnetv_reset(false);
260}
261
262/* Copy data from the usb data memory. The memory reads should be done 32 bits at a time.
263 * We do not assume that the dst data is aligned.
264 */
265static void tnetv_copy_from_data_mem(void *dst, const volatile uint32_t *sp, int size)
266{
267 uint8_t *dp = (uint8_t *) dst;
268 uint32_t value;
269
270 while (size >= 4)
271 {
272 value = *sp++;
273 dp[0] = value;
274 dp[1] = value >> 8;
275 dp[2] = value >> 16;
276 dp[3] = value >> 24;
277 dp += 4;
278 size -= 4;
279 }
280
281 if (size)
282 {
283 value = sp[0];
284 switch (size)
285 {
286 case 3:
287 dp[2] = value >> 16;
288 case 2:
289 dp[1] = value >> 8;
290 case 1:
291 dp[0] = value;
292 break;
293 }
294 }
295}
296
297/* Copy data into the usb data memory. The memory writes must be done 32 bits at a time.
298 * We do not assume that the src data is aligned.
299*/
300static void tnetv_copy_to_data_mem(volatile uint32_t *dp, const void *src, int size)
301{
302 const uint8_t *sp = (const uint8_t *) src;
303 uint32_t value;
304
305 while (size >= 4)
306 {
307 value = sp[0] | (sp[1] << 8) | (sp[2] << 16) | (sp[3] << 24);
308 *dp++ = value;
309 sp += 4;
310 size -= 4;
311 }
312
313 switch (size)
314 {
315 case 3:
316 value = sp[0] | (sp[1] << 8) | (sp[2] << 16);
317 *dp = value;
318 break;
319 case 2:
320 value = sp[0] | (sp[1] << 8);
321 *dp = value;
322 break;
323 case 1:
324 value = sp[0];
325 *dp = value;
326 break;
327 }
328}
329
330static void tnetv_init_endpoints(void)
331{
332 UsbEp0CtrlType ep0Cfg;
333 UsbEp0ByteCntType ep0Cnt;
334 UsbEpCfgCtrlType epCfg;
335 UsbEpStartAddrType epStartAddr;
336 int ch, wd, epn;
337
338 ep0Cnt.val = 0;
339 ep0Cnt.f.out_ybuf_nak = 1;
340 ep0Cnt.f.out_xbuf_nak = 1;
341 ep0Cnt.f.in_ybuf_nak = 1;
342 ep0Cnt.f.in_xbuf_nak = 1;
343 tnetv_usb_reg_write(TNETV_USB_EP0_CNT, ep0Cnt.val);
344
345 /* Setup endpoint zero */
346 ep0Cfg.val = 0;
347 ep0Cfg.f.buf_size = EP0_BUF_SIZE_64; /* must be 64 bytes for USB 2.0 */
348 ep0Cfg.f.dbl_buf = 0;
349 ep0Cfg.f.in_en = 1;
350 ep0Cfg.f.in_int_en = 1;
351 ep0Cfg.f.out_en = 1;
352 ep0Cfg.f.out_int_en = 1;
353 tnetv_usb_reg_write(TNETV_USB_EP0_CFG, ep0Cfg.val);
354
355 /* disable cell dma */
356 tnetv_usb_reg_write(TNETV_USB_CELL_DMA_EN, 0);
357
358 /* turn off dma engines */
359 tnetv_usb_reg_write(TNETV_USB_TX_CTL, 0);
360 tnetv_usb_reg_write(TNETV_USB_RX_CTL, 0);
361
362 /* clear out DMA registers */
363 for (ch = 0; ch < TNETV_DMA_NUM_CHANNELS; ch++)
364 {
365 for (wd = 0; wd < TNETV_DMA_TX_NUM_WORDS; wd++)
366 {
367 tnetv_usb_reg_write(TNETV_DMA_TX_STATE(ch, wd), 0);
368 }
369
370 for (wd = 0; wd < TNETV_DMA_RX_NUM_WORDS; wd++)
371 {
372 tnetv_usb_reg_write(TNETV_DMA_RX_STATE(ch, wd), 0);
373 }
374
375 /* flush the free buf count */
376 while (tnetv_usb_reg_read(TNETV_USB_RX_FREE_BUF_CNT(ch)) != 0)
377 {
378 tnetv_usb_reg_write(TNETV_USB_RX_FREE_BUF_CNT(ch), 0xFFFF);
379 }
380 }
381
382 for (epn = 1; epn < USB_NUM_ENDPOINTS; epn++)
383 {
384 tnetv_usb_reg_write(TNETV_USB_EPx_ADR(epn),0);
385 tnetv_usb_reg_write(TNETV_USB_EPx_CFG(epn), 0);
386 tnetv_usb_reg_write(TNETV_USB_EPx_IN_CNT(epn), 0x80008000);
387 tnetv_usb_reg_write(TNETV_USB_EPx_OUT_CNT(epn), 0x80008000);
388 }
389
390 /* Setup the other endpoints */
391 for (epn = 1; epn < USB_NUM_ENDPOINTS; epn++)
392 {
393 epCfg.val = tnetv_usb_reg_read(TNETV_USB_EPx_CFG(epn));
394 epStartAddr.val = tnetv_usb_reg_read(TNETV_USB_EPx_ADR(epn));
395
396 epCfg.f.in_dbl_buf = 1;
397 epCfg.f.in_toggle_rst = 1;
398 epCfg.f.in_ack_int = 0;
399 epCfg.f.in_stall = 0;
400 epCfg.f.in_nak_int = 0;
401 epCfg.f.out_dbl_buf = 1;
402 epCfg.f.out_toggle_rst = 1;
403 epCfg.f.out_ack_int = 0;
404 epCfg.f.out_stall = 0;
405 epCfg.f.out_nak_int = 0;
406
407 /* buf_size is specified "in increments of 8 bytes" */
408 epCfg.f.in_buf_size = ep_const_data[epn].hs_max_packet_size >> 3;
409 epCfg.f.out_buf_size = ep_const_data[epn].hs_max_packet_size >> 3;
410
411 epStartAddr.f.xBuffStartAddrIn = ep_const_data[epn].xyoff_in[0] >> 4;
412 epStartAddr.f.yBuffStartAddrIn = ep_const_data[epn].xyoff_in[1] >> 4;
413 epStartAddr.f.xBuffStartAddrOut = ep_const_data[epn].xyoff_out[0] >> 4;
414 epStartAddr.f.yBuffStartAddrOut = ep_const_data[epn].xyoff_out[1] >> 4;
415
416 /* allocate memory for DMA */
417 tnetv_cppi_init_rcb(&cppi, (epn - 1));
418 /* set up DMA queue */
419 tnetv_cppi_init_tcb(&cppi, (epn - 1));
420
421 /* now write out the config to the TNETV (write enable bits last) */
422 tnetv_usb_reg_write(TNETV_USB_EPx_ADR(epn), epStartAddr.val);
423 tnetv_usb_reg_write(TNETV_USB_EPx_CFG(epn), epCfg.val);
424 tnetv_usb_reg_write(TNETV_USB_EPx_IN_CNT(epn), 0x80008000);
425 tnetv_usb_reg_write(TNETV_USB_EPx_OUT_CNT(epn), 0x80008000);
426 }
427
428 /* turn on dma engines */
429 tnetv_usb_reg_write(TNETV_USB_TX_CTL, 1);
430 tnetv_usb_reg_write(TNETV_USB_RX_CTL, 1);
431
432 /* enable cell dma */
433 tnetv_usb_reg_write(TNETV_USB_CELL_DMA_EN, (TNETV_USB_CELL_DMA_EN_RX | TNETV_USB_CELL_DMA_EN_TX));
434}
435
436static void tnetv_udc_enable_interrupts(void)
437{
438 UsbCtrlType usb_ctl;
439 uint8_t tx_int_en, rx_int_en;
440 int ep, chan;
441
442 /* set up the system interrupts */
443 usb_ctl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
444 usb_ctl.f.vbus_int_en = 1;
445 usb_ctl.f.reset_int_en = 1;
446 usb_ctl.f.suspend_int_en = 1;
447 usb_ctl.f.resume_int_en = 1;
448 usb_ctl.f.ep0_in_int_en = 1;
449 usb_ctl.f.ep0_out_int_en = 1;
450 usb_ctl.f.setup_int_en = 1;
451 usb_ctl.f.setupow_int_en = 1;
452 tnetv_usb_reg_write(TNETV_USB_CTRL, usb_ctl.val);
453
454 /* Enable the DMA endpoint interrupts */
455 tx_int_en = 0;
456 rx_int_en = 0;
457
458 for (ep = 1; ep < USB_NUM_ENDPOINTS; ep++)
459 {
460 chan = ep - 1;
461 rx_int_en |= (1 << chan); /* OUT */
462 tx_int_en |= (1 << chan); /* IN */
463 }
464
465 /* enable rx interrupts */
466 tnetv_usb_reg_write(TNETV_USB_RX_INT_EN, rx_int_en);
467 /* enable tx interrupts */
468 tnetv_usb_reg_write(TNETV_USB_TX_INT_EN, tx_int_en);
469
470 set_vlynq_irq(true);
471}
472
473static void tnetv_udc_disable_interrupts(void)
474{
475 UsbCtrlType usb_ctl;
476
477 /* disable interrupts from linux */
478 set_vlynq_irq(false);
479
480 /* Disable Endpoint Interrupts */
481 tnetv_usb_reg_write(TNETV_USB_RX_INT_DIS, 0x3);
482 tnetv_usb_reg_write(TNETV_USB_TX_INT_DIS, 0x3);
483
484 /* Disable USB system interrupts */
485 usb_ctl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
486 usb_ctl.f.vbus_int_en = 0;
487 usb_ctl.f.reset_int_en = 0;
488 usb_ctl.f.suspend_int_en = 0;
489 usb_ctl.f.resume_int_en = 0;
490 usb_ctl.f.ep0_in_int_en = 0;
491 usb_ctl.f.ep0_out_int_en = 0;
492 usb_ctl.f.setup_int_en = 0;
493 usb_ctl.f.setupow_int_en = 0;
494 tnetv_usb_reg_write(TNETV_USB_CTRL, usb_ctl.val);
495}
496
497static void tnetv_ep_halt(int epn, bool in)
498{
499 if (in)
500 {
501 tnetv_usb_reg_write(TNETV_USB_EPx_IN_CNT(epn), 0x80008000);
502 }
503 else
504 {
505 tnetv_usb_reg_write(TNETV_USB_EPx_OUT_CNT(epn), 0x80008000);
506 }
507}
508
509/* Reset the TNETV usb2.0 controller and configure it to run in function mode */
510static void tnetv_usb_reset(void)
511{
512 uint32_t timeout = 0;
513 int wd;
514 int ch;
515
516 /* configure function clock */
517 tnetv_usb_reg_write(TNETV_V2USB_CLK_CFG, 0x80);
518
519 /* Reset the USB 2.0 function module */
520 tnetv_usb_reg_write(TNETV_V2USB_RESET, 0x01);
521
522 /* now poll the module ready register until the 2.0 controller finishes resetting */
523 while (!(tnetv_usb_reg_read(TNETV_USB_RESET_CMPL) & 0x1) && (timeout < 1000000))
524 {
525 timeout++;
526 }
527
528 if (!(tnetv_usb_reg_read(TNETV_USB_RESET_CMPL) & 0x1))
529 {
530 logf("tnetv105_udc: VLYNQ USB module reset failed!\n");
531 return;
532 }
533
534 /* turn off external clock */
535 tnetv_usb_reg_write(TNETV_V2USB_CLK_PERF, 0);
536
537 /* clear out USB data memory */
538 for (wd = 0; wd < TNETV_EP_DATA_SIZE; wd += 4)
539 {
540 tnetv_usb_reg_write(TNETV_EP_DATA_ADDR(wd), 0);
541 }
542
543 /* clear out DMA memory */
544 for (ch = 0; ch < TNETV_DMA_NUM_CHANNELS; ch++)
545 {
546 for (wd = 0; wd < TNETV_DMA_TX_NUM_WORDS; wd++)
547 {
548 tnetv_usb_reg_write(TNETV_DMA_TX_STATE(ch, wd), 0);
549 }
550
551 for (wd = 0; wd < TNETV_DMA_RX_NUM_WORDS; wd++)
552 {
553
554 tnetv_usb_reg_write(TNETV_DMA_RX_STATE(ch, wd), 0);
555 }
556 }
557
558 /* point VLYNQ interrupts at the pending register */
559 VL_INTPTR = DM320_VLYNQ_INTPND_PHY;
560
561 /* point VLYNQ remote interrupts at the pending register */
562 VL_INTPTR_R = 0;
563
564 /* clear out interrupt register */
565 VL_INTST |= 0xFFFFFFFF;
566
567 /* enable interrupts on remote device */
568 VL_CTRL_R |= (DM320_VLYNQ_CTRL_INT_EN);
569 VL_INTVEC30_R = 0x8180;
570
571 /* enable VLYNQ interrupts & set interrupts to trigger VLYNQ int */
572 VL_CTRL |= (DM320_VLYNQ_CTRL_INT_LOC | DM320_VLYNQ_CTRL_INT_CFG);
573}
574
575static int tnetv_ep_start_xmit(int epn, void *buf, int size)
576{
577 UsbEp0ByteCntType ep0Cnt;
578
579 if (epn == 0)
580 {
581 /* Write the Control Data packet to the EP0 IN memory area */
582 tnetv_copy_to_data_mem(TNETV_EP_DATA_ADDR(EP0_INPKT_ADDRESS), buf, size);
583
584 /* start xmitting */
585 ep0Cnt.val = tnetv_usb_reg_read(TNETV_USB_EP0_CNT);
586 ep0Cnt.f.in_xbuf_cnt = size;
587 ep0Cnt.f.in_xbuf_nak = 0;
588 tnetv_usb_reg_write(TNETV_USB_EP0_CNT, ep0Cnt.val);
589 }
590 else
591 {
592 dma_addr_t buffer = (dma_addr_t)buf;
593 commit_discard_dcache_range(buf, size);
594 if ((buffer >= CONFIG_SDRAM_START) && (buffer <= CONFIG_SDRAM_START + SDRAM_SIZE))
595 {
596 if (tnetv_cppi_send(&cppi, (epn - 1), buffer, size, 0))
597 {
598 panicf("tnetv_cppi_send() failed");
599 }
600 }
601 else
602 {
603 panicf("USB xmit buf outside SDRAM %p", buf);
604 }
605 }
606
607 return 0;
608}
609
610static void tnetv_gadget_req_nuke(int epn, bool in)
611{
612 struct ep_runtime_t *ep = &ep_runtime[epn];
613 uint32_t old_rx_int = 0;
614 uint32_t old_tx_int = 0;
615 int ch;
616 int flags;
617
618 /* don't nuke control ep */
619 if (epn == 0)
620 {
621 return;
622 }
623
624 flags = disable_irq_save();
625
626 /* save and disable interrupts before nuking request */
627 old_rx_int = tnetv_usb_reg_read(TNETV_USB_RX_INT_EN);
628 old_tx_int = tnetv_usb_reg_read(TNETV_USB_TX_INT_EN);
629 tnetv_usb_reg_write(TNETV_USB_RX_INT_DIS, 0x3);
630 tnetv_usb_reg_write(TNETV_USB_TX_INT_DIS, 0x3);
631
632 ch = epn - 1;
633
634 if (in)
635 {
636 tnetv_cppi_flush_tx_queue(&cppi, ch);
637
638 tnetv_usb_reg_write(TNETV_USB_EPx_IN_CNT(epn), 0x80008000);
639 if (ep->tx_remaining > 0)
640 {
641 usb_core_transfer_complete(epn, USB_DIR_IN, -1, 0);
642 }
643 ep->tx_buf = NULL;
644 ep->tx_remaining = 0;
645 ep->tx_size = 0;
646
647 if (ep->block)
648 {
649 semaphore_release(&ep->complete);
650 ep->block = false;
651 }
652 }
653 else
654 {
655 tnetv_cppi_flush_rx_queue(&cppi, ch);
656
657 tnetv_usb_reg_write(TNETV_USB_EPx_OUT_CNT(epn), 0x80008000);
658 if (ep->rx_remaining > 0)
659 {
660 usb_core_transfer_complete(epn, USB_DIR_OUT, -1, 0);
661 }
662 ep->rx_buf = NULL;
663 ep->rx_remaining = 0;
664 ep->rx_size = 0;
665 }
666
667 /* reenable any interrupts */
668 tnetv_usb_reg_write(TNETV_USB_RX_INT_EN, old_rx_int);
669 tnetv_usb_reg_write(TNETV_USB_TX_INT_EN, old_tx_int);
670
671 restore_irq(flags);
672}
673
674static int tnetv_gadget_ep_enable(int epn, bool in)
675{
676 UsbEpCfgCtrlType epCfg;
677 int flags;
678
679 if (epn == 0 || epn >= USB_NUM_ENDPOINTS)
680 {
681 return 0;
682 }
683
684 flags = disable_irq_save();
685
686 /* set the maxpacket for this endpoint based on the current speed */
687 ep_runtime[epn].max_packet_size = MAX_PACKET(epn, usb_drv_port_speed());
688
689 /* Enable the endpoint */
690 epCfg.val = tnetv_usb_reg_read(TNETV_USB_EPx_CFG(epn));
691 if (in)
692 {
693 epCfg.f.in_en = 1;
694 epCfg.f.in_stall = 0;
695 epCfg.f.in_toggle_rst = 1;
696 epCfg.f.in_buf_size = ep_runtime[epn].max_packet_size >> 3;
697 tnetv_usb_reg_write(TNETV_USB_EPx_IN_CNT(epn), 0x80008000);
698 }
699 else
700 {
701 epCfg.f.out_en = 1;
702 epCfg.f.out_stall = 0;
703 epCfg.f.out_toggle_rst = 1;
704 epCfg.f.out_buf_size = ep_runtime[epn].max_packet_size >> 3;
705 tnetv_usb_reg_write(TNETV_USB_EPx_OUT_CNT(epn), 0x80008000);
706 }
707 tnetv_usb_reg_write(TNETV_USB_EPx_CFG(epn), epCfg.val);
708
709 restore_irq(flags);
710
711 return 0;
712}
713
714static int tnetv_gadget_ep_disable(int epn, bool in)
715{
716 UsbEpCfgCtrlType epCfg;
717 int flags;
718
719 if (epn == 0 || epn >= USB_NUM_ENDPOINTS)
720 {
721 return 0;
722 }
723
724 flags = disable_irq_save();
725
726 /* Disable the endpoint */
727 epCfg.val = tnetv_usb_reg_read(TNETV_USB_EPx_CFG(epn));
728 if (in)
729 {
730 epCfg.f.in_en = 0;
731 }
732 else
733 {
734 epCfg.f.out_en = 0;
735 }
736 tnetv_usb_reg_write(TNETV_USB_EPx_CFG(epn), epCfg.val);
737
738 /* Turn off the endpoint and unready it */
739 tnetv_ep_halt(epn, in);
740
741 restore_irq(flags);
742
743 /* Clear out all the pending requests */
744 tnetv_gadget_req_nuke(epn, in);
745
746 return 0;
747}
748
749/* TNETV udc goo
750 * Power up and enable the udc. This includes resetting the hardware, turn on the appropriate clocks
751 * and initializing things so that the first setup packet can be received.
752 */
753static void tnetv_udc_enable(void)
754{
755 /* Enable M48XI crystal resonator */
756 IO_CLK_LPCTL1 &= ~(0x01);
757
758 /* Set GIO33 as CLKOUT1B */
759 IO_GIO_FSEL3 |= 0x0003;
760
761 if (tnetv_xcvr_on())
762 return;
763
764 tnetv_usb_reset();
765
766 /* BEN - RNDIS mode is assuming zlps after packets that are multiples of buffer endpoints
767 * zlps are not required by the spec and many controllers don't send them.
768 * set DMA to RNDIS mode (packet concatenation, less interrupts)
769 * tnetv_usb_reg_write(TNETV_USB_RNDIS_MODE, 0xFF);
770 */
771 tnetv_usb_reg_write(TNETV_USB_RNDIS_MODE, 0);
772
773 tnetv_init_endpoints();
774
775 tnetv_udc_enable_interrupts();
776}
777
778static void tnetv_udc_disable(void)
779{
780 tnetv_udc_disable_interrupts();
781
782 tnetv_hw_reset();
783
784 tnetv_xcvr_off();
785
786 /* Set GIO33 as normal output, drive it low */
787 IO_GIO_FSEL3 &= ~(0x0003);
788 IO_GIO_BITCLR2 = (1 << 1);
789
790 /* Disable M48XI crystal resonator */
791 IO_CLK_LPCTL1 |= 0x01;
792}
793
794static void tnetv_udc_handle_reset(void)
795{
796 UsbCtrlType usbCtrl;
797
798 /* disable USB interrupts */
799 tnetv_udc_disable_interrupts();
800
801 usbCtrl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
802 usbCtrl.f.func_addr = 0;
803 tnetv_usb_reg_write(TNETV_USB_CTRL, usbCtrl.val);
804
805 /* Reset endpoints */
806 tnetv_init_endpoints();
807
808 /* Re-enable interrupts */
809 tnetv_udc_enable_interrupts();
810}
811
812static void ep_write(int epn)
813{
814 struct ep_runtime_t *ep = &ep_runtime[epn];
815 int tx_size;
816 if (epn == 0)
817 {
818 tx_size = MIN(ep->max_packet_size, ep->tx_remaining);
819 }
820 else
821 {
822 /* DMA takes care of splitting the buffer into packets */
823 tx_size = ep->tx_remaining;
824 }
825 tnetv_ep_start_xmit(epn, ep->tx_buf, tx_size);
826 ep->tx_remaining -= tx_size;
827 ep->tx_buf += tx_size;
828}
829
830static void in_interrupt(int epn)
831{
832 struct ep_runtime_t *ep = &ep_runtime[epn];
833
834 if (ep->tx_remaining <= 0)
835 {
836 usb_core_transfer_complete(epn, USB_DIR_IN, 0, ep->tx_size);
837 /* release semaphore for blocking transfer */
838 if (ep->block)
839 {
840 semaphore_release(&ep->complete);
841 ep->tx_buf = NULL;
842 ep->tx_size = 0;
843 ep->tx_remaining = 0;
844 ep->block = false;
845 }
846 }
847 else if (ep->tx_buf)
848 {
849 ep_write(epn);
850 }
851}
852
853static void ep_read(int epn)
854{
855 if (epn == 0)
856 {
857 UsbEp0ByteCntType ep0Cnt;
858 ep0Cnt.val = tnetv_usb_reg_read(TNETV_USB_EP0_CNT);
859 ep0Cnt.f.out_xbuf_nak = 0;
860 tnetv_usb_reg_write(TNETV_USB_EP0_CNT, ep0Cnt.val);
861 }
862 else
863 {
864 struct ep_runtime_t *ep = &ep_runtime[epn];
865 tnetv_cppi_rx_queue_add(&cppi, (epn - 1), 0, ep->rx_remaining);
866 }
867}
868
869static void out_interrupt(int epn)
870{
871 struct ep_runtime_t *ep = &ep_runtime[epn];
872 int is_short;
873 int rcv_len;
874
875 if (epn == 0)
876 {
877 UsbEp0ByteCntType ep0Cnt;
878
879 /* get the length of the received data */
880 ep0Cnt.val = tnetv_usb_reg_read(TNETV_USB_EP0_CNT);
881 rcv_len = ep0Cnt.f.out_xbuf_cnt;
882
883 if (rcv_len > ep->rx_remaining)
884 {
885 rcv_len = ep->rx_remaining;
886 }
887
888 tnetv_copy_from_data_mem(ep->rx_buf, TNETV_EP_DATA_ADDR(EP0_OUTPKT_ADDRESS), rcv_len);
889 ep->rx_buf += rcv_len;
890 ep->rx_remaining -= rcv_len;
891
892 /* See if we are done */
893 is_short = rcv_len && (rcv_len < ep->max_packet_size);
894 if (is_short || (ep->rx_remaining == 0))
895 {
896 usb_core_transfer_complete(epn, USB_DIR_OUT, 0, ep->rx_size - ep->rx_remaining);
897 ep->rx_remaining = 0;
898 ep->rx_size = 0;
899 ep->rx_buf = 0;
900 return;
901 }
902
903 /* make sure nak is cleared only if we expect more data */
904 ep0Cnt.f.out_xbuf_nak = 0;
905 tnetv_usb_reg_write(TNETV_USB_EP0_CNT, ep0Cnt.val);
906 ep_read(epn);
907 }
908 else if (ep->rx_remaining > 0)
909 {
910 int ret, bytes_rcvd;
911
912 /* copy the data from the DMA buffers */
913 bytes_rcvd = ep->rx_remaining;
914 ret = tnetv_cppi_rx_int_recv(&cppi, (epn - 1), &bytes_rcvd, ep->rx_buf, ep->max_packet_size);
915 if (ret == 0 || ret == -EAGAIN)
916 {
917 ep->rx_buf += bytes_rcvd;
918 ep->rx_remaining -= bytes_rcvd;
919 }
920
921 /* complete the request if we got a short packet or an error
922 * make sure we don't complete a request with zero bytes.
923 */
924 if ((ret == 0) && (ep->rx_remaining != ep->rx_size))
925 {
926 usb_core_transfer_complete(epn, USB_DIR_OUT, 0, ep->rx_size - ep->rx_remaining);
927 ep->rx_remaining = 0;
928 ep->rx_size = 0;
929 ep->rx_buf = 0;
930 }
931 }
932}
933
934static bool tnetv_handle_cppi(void)
935{
936 int ret;
937 int ch;
938 uint32_t tx_intstatus;
939 uint32_t rx_intstatus;
940 uint32_t status;
941 int rcv_sched = 0;
942
943 rx_intstatus = tnetv_usb_reg_read(TNETV_USB_RX_INT_STATUS);
944 tx_intstatus = tnetv_usb_reg_read(TNETV_USB_TX_INT_STATUS);
945
946 /* handle any transmit interrupts */
947 status = tx_intstatus;
948 for (ch = 0; ch < CPPI_NUM_CHANNELS && status; ch++)
949 {
950 if (status & 0x1)
951 {
952 ret = tnetv_cppi_tx_int(&cppi, ch);
953 if (ret >= 0)
954 {
955 in_interrupt(ch + 1);
956 }
957 }
958
959 status = status >> 1;
960 }
961
962 rcv_sched = 0;
963 status = rx_intstatus;
964 for (ch = 0; ch < CPPI_NUM_CHANNELS; ch++)
965 {
966 if (status & 0x1 || tnetv_cppi_rx_int_recv_check(&cppi, ch))
967 {
968 ret = tnetv_cppi_rx_int(&cppi, ch);
969 if (ret < 0)
970 {
971 /* only an error if interrupt bit is set */
972 logf("CPPI Rx: failed to ACK int!\n");
973 }
974 else
975 {
976 if (tnetv_cppi_rx_int_recv_check(&cppi, ch))
977 {
978 out_interrupt(ch + 1);
979 }
980 }
981 }
982
983 if (tnetv_cppi_rx_int_recv_check(&cppi, ch))
984 {
985 rcv_sched = 1;
986 }
987
988 status = status >> 1;
989 }
990
991 rx_intstatus = tnetv_usb_reg_read(TNETV_USB_RX_INT_STATUS);
992 tx_intstatus = tnetv_usb_reg_read(TNETV_USB_TX_INT_STATUS);
993
994 if (rx_intstatus || tx_intstatus || rcv_sched)
995 {
996 /* Request calling again after short delay
997 * Needed when for example when OUT endpoint has pending
998 * data but the USB task did not call usb_drv_recv() yet.
999 */
1000 return true;
1001 }
1002 return false;
1003}
1004
1005static int cppi_timeout_cb(struct timeout *tmo)
1006{
1007 (void)tmo;
1008 int flags = disable_irq_save();
1009 bool requeue = tnetv_handle_cppi();
1010 restore_irq(flags);
1011 return requeue ? HZ/10 : 0;
1012}
1013
1014void VLYNQ(void) __attribute__ ((section(".icode")));
1015void VLYNQ(void)
1016{
1017 UsbStatusType sysIntrStatus;
1018 UsbStatusType sysIntClear;
1019 UsbCtrlType usbCtrl;
1020 volatile uint32_t *reg;
1021 uint32_t vlynq_intr;
1022
1023 /* Clear interrupt */
1024 IO_INTC_IRQ1 = (1 << 0);
1025
1026 /* clear out VLYNQ interrupt register */
1027 vlynq_intr = VL_INTST;
1028
1029 if (vlynq_intr & VLYNQ_INTR_USB20)
1030 {
1031 VL_INTST = VLYNQ_INTR_USB20;
1032
1033 /* Examine system interrupt status */
1034 sysIntrStatus.val = tnetv_usb_reg_read(TNETV_USB_STATUS);
1035
1036 if (sysIntrStatus.f.reset)
1037 {
1038 sysIntClear.val = 0;
1039 sysIntClear.f.reset = 1;
1040 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1041
1042 tnetv_udc_handle_reset();
1043 usb_core_bus_reset();
1044 }
1045
1046 if (sysIntrStatus.f.suspend)
1047 {
1048 sysIntClear.val = 0;
1049 sysIntClear.f.suspend = 1;
1050 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1051 }
1052
1053 if (sysIntrStatus.f.resume)
1054 {
1055 sysIntClear.val = 0;
1056 sysIntClear.f.resume = 1;
1057 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1058 }
1059
1060 if (sysIntrStatus.f.vbus)
1061 {
1062 sysIntClear.val = 0;
1063 sysIntClear.f.vbus = 1;
1064 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1065
1066 if (*((uint32_t *) TNETV_USB_IF_STATUS) & 0x40)
1067 {
1068 /* write out connect bit */
1069 reg = (volatile uint32_t *) TNETV_USB_CTRL;
1070 *reg |= 0x80;
1071
1072 /* write to wakeup bit in clock config */
1073 reg = (volatile uint32_t *) TNETV_V2USB_CLK_WKUP;
1074 *reg |= TNETV_V2USB_CLK_WKUP_VBUS;
1075 }
1076 else
1077 {
1078 /* clear out connect bit */
1079 reg = (volatile uint32_t *) TNETV_USB_CTRL;
1080 *reg &= ~0x80;
1081 }
1082 }
1083
1084 if (sysIntrStatus.f.setup_ow)
1085 {
1086 sysIntrStatus.f.setup_ow = 0;
1087 sysIntClear.val = 0;
1088 sysIntClear.f.setup_ow = 1;
1089 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1090 }
1091 if (sysIntrStatus.f.setup)
1092 {
1093 UsbEp0ByteCntType ep0Cnt;
1094 static struct usb_ctrlrequest setup;
1095
1096 sysIntrStatus.f.setup = 0;
1097
1098 /* Copy setup packet into buffer */
1099 tnetv_copy_from_data_mem(&setup, TNETV_EP_DATA_ADDR(EP0_OUTPKT_ADDRESS), sizeof(setup));
1100
1101 /* Determine next stage of the control message */
1102 if (setup.bRequestType & USB_DIR_IN)
1103 {
1104 /* This is a control-read. Switch directions to send the response.
1105 * set the dir bit before clearing the interrupt
1106 */
1107 usbCtrl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
1108 usbCtrl.f.dir = 1;
1109 tnetv_usb_reg_write(TNETV_USB_CTRL, usbCtrl.val);
1110 }
1111 else
1112 {
1113 /* This is a control-write. Remain using USB_DIR_OUT to receive the rest of the data.
1114 * set the NAK bits according to supplement doc
1115 */
1116 ep0Cnt.val = 0;
1117 ep0Cnt.f.in_xbuf_nak = 1;
1118 ep0Cnt.f.out_xbuf_nak = 1;
1119 tnetv_usb_reg_write(TNETV_USB_EP0_CNT, ep0Cnt.val);
1120
1121 /* clear the dir bit before clearing the interrupt */
1122 usbCtrl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
1123 usbCtrl.f.dir = 0;
1124 tnetv_usb_reg_write(TNETV_USB_CTRL, usbCtrl.val);
1125 }
1126
1127 /* Clear interrupt */
1128 sysIntClear.val = 0;
1129 sysIntClear.f.setup = 1;
1130 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1131
1132 if (((setup.bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) &&
1133 (setup.bRequest == USB_REQ_SET_ADDRESS))
1134 {
1135 /* Rockbox USB core works according to USB specification, i.e.
1136 * it first acknowledges the control transfer and then sets
1137 * the address. However, Linux TNETV105 driver first sets the
1138 * address and then acknowledges the transfer. At first,
1139 * it seemed that Linux driver was wrong, but it seems that
1140 * TNETV105 simply requires such order. It might be documented
1141 * in the datasheet and thus there is no comment in the Linux
1142 * driver about this.
1143 */
1144 setup_is_set_address = true;
1145 }
1146 else
1147 {
1148 setup_is_set_address = false;
1149 }
1150
1151 /* Process control packet */
1152 usb_core_control_request(&setup);
1153 }
1154
1155 if (sysIntrStatus.f.ep0_in_ack)
1156 {
1157 sysIntClear.val = 0;
1158 sysIntClear.f.ep0_in_ack = 1;
1159 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1160
1161 in_interrupt(0);
1162 }
1163
1164 if (sysIntrStatus.f.ep0_out_ack)
1165 {
1166 sysIntClear.val = 0;
1167 sysIntClear.f.ep0_out_ack = 1;
1168 tnetv_usb_reg_write(TNETV_USB_STATUS, sysIntClear.val);
1169
1170 out_interrupt(0);
1171 }
1172 }
1173
1174 if (vlynq_intr & VLYNQ_INTR_CPPI)
1175 {
1176 static struct timeout cppi_timeout;
1177
1178 VL_INTST = VLYNQ_INTR_CPPI;
1179
1180 if (tnetv_handle_cppi())
1181 {
1182 timeout_register(&cppi_timeout, cppi_timeout_cb, HZ/10, 0);
1183 }
1184 }
1185}
1186
1187void usb_charging_maxcurrent_change(int maxcurrent)
1188{
1189 uint32_t wreg;
1190
1191 if (!is_tnetv_reset_high())
1192 {
1193 /* TNETV105 is in reset, it is not getting more than 100 mA */
1194 return;
1195 }
1196
1197 wreg = tnetv_usb_reg_read(TNETV_V2USB_GPIO_DOUT);
1198 if (maxcurrent < 500)
1199 {
1200 /* set tnetv into low power mode */
1201 tnetv_usb_reg_write(TNETV_V2USB_GPIO_DOUT, (wreg & ~0x2));
1202 }
1203 else
1204 {
1205 /* set tnetv into high power mode */
1206 tnetv_usb_reg_write(TNETV_V2USB_GPIO_DOUT, (wreg | 0x2));
1207 }
1208}
1209
1210void usb_drv_init(void)
1211{
1212 int epn;
1213 memset(ep_runtime, 0, sizeof(ep_runtime));
1214 ep_runtime[0].max_packet_size = EP0_MAX_PACKET_SIZE;
1215 ep_runtime[0].in_allocated = true;
1216 ep_runtime[0].out_allocated = true;
1217 for (epn = 0; epn < USB_NUM_ENDPOINTS; epn++)
1218 {
1219 semaphore_init(&ep_runtime[epn].complete, 1, 0);
1220 }
1221 tnetv_cppi_init(&cppi);
1222 tnetv_udc_enable();
1223}
1224
1225void usb_drv_exit(void)
1226{
1227 tnetv_udc_disable();
1228 tnetv_cppi_cleanup(&cppi);
1229}
1230
1231void usb_drv_stall(int endpoint, bool stall, bool in)
1232{
1233 int epn = EP_NUM(endpoint);
1234
1235 if (epn == 0)
1236 {
1237 UsbEp0CtrlType ep0Ctrl;
1238 ep0Ctrl.val = tnetv_usb_reg_read(TNETV_USB_EP0_CFG);
1239 if (in)
1240 {
1241 ep0Ctrl.f.in_stall = stall ? 1 : 0;
1242 }
1243 else
1244 {
1245 ep0Ctrl.f.out_stall = stall ? 1 : 0;
1246 }
1247 tnetv_usb_reg_write(TNETV_USB_EP0_CFG, ep0Ctrl.val);
1248 }
1249 else
1250 {
1251 UsbEpCfgCtrlType epCfg;
1252 epCfg.val = tnetv_usb_reg_read(TNETV_USB_EPx_CFG(epn));
1253 if (in)
1254 {
1255 epCfg.f.in_stall = stall ? 1 : 0;
1256 }
1257 else
1258 {
1259 epCfg.f.out_stall = stall ? 1 : 0;
1260 }
1261 tnetv_usb_reg_write(TNETV_USB_EPx_CFG(epn), epCfg.val);
1262 }
1263}
1264
1265bool usb_drv_stalled(int endpoint, bool in)
1266{
1267 int epn = EP_NUM(endpoint);
1268 if (epn == 0)
1269 {
1270 UsbEp0CtrlType ep0Ctrl;
1271 ep0Ctrl.val = tnetv_usb_reg_read(TNETV_USB_EP0_CFG);
1272 if (in)
1273 {
1274 return ep0Ctrl.f.in_stall;
1275 }
1276 else
1277 {
1278 return ep0Ctrl.f.out_stall;
1279 }
1280 }
1281 else
1282 {
1283 UsbEpCfgCtrlType epCfg;
1284 epCfg.val = tnetv_usb_reg_read(TNETV_USB_EPx_CFG(epn));
1285 if (in)
1286 {
1287 return epCfg.f.in_stall;
1288 }
1289 else
1290 {
1291 return epCfg.f.out_stall;
1292 }
1293 }
1294}
1295
1296static int _usb_drv_send(int endpoint, void *ptr, int length, bool block)
1297{
1298 int epn = EP_NUM(endpoint);
1299 struct ep_runtime_t *ep;
1300 int flags;
1301
1302 ep = &ep_runtime[epn];
1303
1304 flags = disable_irq_save();
1305 ep->tx_buf = ptr;
1306 ep->tx_remaining = ep->tx_size = length;
1307 ep->block = block;
1308 ep_write(epn);
1309 restore_irq(flags);
1310
1311 /* wait for transfer to end */
1312 if (block)
1313 {
1314 semaphore_wait(&ep->complete, TIMEOUT_BLOCK);
1315 }
1316 return 0;
1317}
1318
1319int usb_drv_send(int endpoint, void* ptr, int length)
1320{
1321 if ((EP_NUM(endpoint) == 0) && (length == 0))
1322 {
1323 if (setup_is_set_address)
1324 {
1325 /* usb_drv_set_address() will call us later */
1326 return 0;
1327 }
1328 /* HACK: Do not wait for status stage ZLP
1329 * This seems to be the only way to get through SET ADDRESS
1330 * and retain ability to receive SETUP packets.
1331 */
1332 return _usb_drv_send(endpoint, ptr, length, false);
1333 }
1334 return _usb_drv_send(endpoint, ptr, length, false);
1335}
1336
1337int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
1338{
1339 return _usb_drv_send(endpoint, ptr, length, false);
1340}
1341
1342int usb_drv_recv(int endpoint, void* ptr, int length)
1343{
1344 int epn = EP_NUM(endpoint);
1345 struct ep_runtime_t *ep;
1346 int flags;
1347
1348 ep = &ep_runtime[epn];
1349
1350 flags = disable_irq_save();
1351 ep->rx_buf = ptr;
1352 ep->rx_remaining = ep->rx_size = length;
1353 ep_read(epn);
1354 restore_irq(flags);
1355
1356 return 0;
1357}
1358
1359void usb_drv_ack(struct usb_ctrlrequest* req);
1360
1361void usb_drv_set_address(int address)
1362{
1363 UsbCtrlType usbCtrl;
1364 usbCtrl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
1365 usbCtrl.f.func_addr = address;
1366 tnetv_usb_reg_write(TNETV_USB_CTRL, usbCtrl.val);
1367
1368 /* This seems to be the only working order */
1369 setup_is_set_address = false;
1370 usb_drv_send(EP_CONTROL, NULL, 0);
1371 usb_drv_cancel_all_transfers();
1372}
1373
1374/* return port speed FS=0, HS=1 */
1375int usb_drv_port_speed(void)
1376{
1377 UsbCtrlType usbCtrl;
1378 usbCtrl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
1379 return usbCtrl.f.speed ? 1 : 0;
1380}
1381
1382void usb_drv_cancel_all_transfers(void)
1383{
1384 int epn;
1385 if (setup_is_set_address)
1386 {
1387 return;
1388 }
1389 for (epn = 1; epn < USB_NUM_ENDPOINTS; epn++)
1390 {
1391 tnetv_gadget_req_nuke(epn, false);
1392 tnetv_gadget_req_nuke(epn, true);
1393 }
1394}
1395
1396static const uint8_t TestPacket[] =
1397{
1398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1399 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1400 0xAA, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
1401 0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1402 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF,
1403 0xEF, 0xF7, 0xFB, 0xFD, 0xFC, 0x7E, 0xBF, 0xDF,
1404 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
1405};
1406
1407void usb_drv_set_test_mode(int mode)
1408{
1409 UsbCtrlType usbCtrl;
1410 if (mode == 4)
1411 {
1412 volatile uint32_t *reg;
1413 UsbEp0ByteCntType ep0Cnt;
1414 UsbEp0CtrlType ep0Cfg;
1415 uint8_t *addr;
1416 size_t i;
1417
1418 /* set up the xnak for ep0 */
1419 reg = (volatile uint32_t *) TNETV_USB_EP0_CNT;
1420 *reg &= ~0xFF;
1421
1422 /* Setup endpoint zero */
1423 ep0Cfg.val = 0;
1424 ep0Cfg.f.buf_size = EP0_BUF_SIZE_64; /* must be 64 bytes for USB 2.0 */
1425 ep0Cfg.f.dbl_buf = 0;
1426 ep0Cfg.f.in_en = 1;
1427 ep0Cfg.f.in_int_en = 0;
1428 ep0Cfg.f.out_en = 0;
1429 ep0Cfg.f.out_int_en = 0;
1430 tnetv_usb_reg_write(TNETV_USB_EP0_CFG, ep0Cfg.val);
1431
1432 addr = (uint8_t *) TNETV_EP_DATA_ADDR(EP0_INPKT_ADDRESS);
1433 for (i = 0; i < sizeof(TestPacket); i++)
1434 {
1435 *addr++ = TestPacket[i];
1436 }
1437
1438 /* start xmitting (only 53 bytes are used) */
1439 ep0Cnt.val = 0;
1440 ep0Cnt.f.in_xbuf_cnt = 53;
1441 ep0Cnt.f.in_xbuf_nak = 0;
1442 tnetv_usb_reg_write(TNETV_USB_EP0_CNT, ep0Cnt.val);
1443 }
1444
1445 /* write the config */
1446 usbCtrl.val = tnetv_usb_reg_read(TNETV_USB_CTRL);
1447 usbCtrl.f.hs_test_mode = mode;
1448 usbCtrl.f.dir = 1;
1449 tnetv_usb_reg_write(TNETV_USB_CTRL, usbCtrl.val);
1450}
1451
1452int usb_drv_request_endpoint(int type, int dir)
1453{
1454 int epn;
1455 for (epn = 1; epn < USB_NUM_ENDPOINTS; epn++)
1456 {
1457 if (type == ep_const_data[epn].type)
1458 {
1459 if ((dir == USB_DIR_IN) && (!ep_runtime[epn].in_allocated))
1460 {
1461 ep_runtime[epn].in_allocated = true;
1462 tnetv_gadget_ep_enable(epn, true);
1463 return epn | USB_DIR_IN;
1464 }
1465 if ((dir == USB_DIR_OUT) && (!ep_runtime[epn].out_allocated))
1466 {
1467 ep_runtime[epn].out_allocated = true;
1468 tnetv_gadget_ep_enable(epn, false);
1469 return epn | USB_DIR_OUT;
1470 }
1471 }
1472 }
1473 return -1;
1474}
1475
1476void usb_drv_release_endpoint(int ep)
1477{
1478 int epn = EP_NUM(ep);
1479 if (EP_DIR(ep) == DIR_IN)
1480 {
1481 ep_runtime[epn].in_allocated = false;
1482 tnetv_gadget_ep_disable(epn, true);
1483 }
1484 else
1485 {
1486 ep_runtime[epn].out_allocated = false;
1487 tnetv_gadget_ep_disable(epn, false);
1488 }
1489}
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.h b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.h
new file mode 100644
index 0000000000..c31c9c6505
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.h
@@ -0,0 +1,335 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2021 by Tomasz Moń
11 * Ported from Sansa Connect TNETV105 UDC Linux driver
12 * Copyright (c) 2005 Zermatt Systems, Inc.
13 * Written by: Ben Bostwick
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#ifndef TNETV105_USB_DRV_H
26#define TNETV105_USB_DRV_H
27
28#include <stdint.h>
29
30#define DM320_AHB_PADDR 0x00060000
31#define DM320_VLYNQ_PADDR 0x70000000
32
33/* TNETV105 Memory Map */
34#define VLYNQ_BASE (0x70000000)
35
36#define TNETV_BASE (VLYNQ_BASE)
37#define TNETV_V2USB_BASE (TNETV_BASE + 0x00000200)
38#define TNETV_WDOG_BASE (TNETV_BASE + 0x00000280)
39#define TNETV_USB_HOST_BASE (TNETV_BASE + 0x00010000)
40#define TNETV_USB_DEVICE_BASE (TNETV_BASE + 0x00020000)
41
42#define TNETV_V2USB_REG(x) (TNETV_V2USB_BASE + (x))
43
44#define TNETV_V2USB_RESET (TNETV_V2USB_REG(0x00))
45#define TNETV_V2USB_CLK_PERF (TNETV_V2USB_REG(0x04))
46#define TNETV_V2USB_CLK_MODE (TNETV_V2USB_REG(0x08))
47#define TNETV_V2USB_CLK_CFG (TNETV_V2USB_REG(0x0C))
48#define TNETV_V2USB_CLK_WKUP (TNETV_V2USB_REG(0x10))
49#define TNETV_V2USB_CLK_PWR (TNETV_V2USB_REG(0x14))
50
51#define TNETV_V2USB_PID_VID (TNETV_V2USB_REG(0x28))
52
53#define TNETV_V2USB_GPIO_DOUT (TNETV_V2USB_REG(0x40))
54#define TNETV_V2USB_GPIO_DIN (TNETV_V2USB_REG(0x44))
55#define TNETV_V2USB_GPIO_DIR (TNETV_V2USB_REG(0x48))
56#define TNETV_V2USB_GPIO_FS (TNETV_V2USB_REG(0x4C))
57#define TNETV_V2USB_GPIO_INTF (TNETV_V2USB_REG(0x50))
58#define TNETV_V2USB_GPIO_EOI (TNETV_V2USB_REG(0x54))
59
60#define TNETV_USB_DEVICE_REG(x) (TNETV_USB_DEVICE_BASE + (x))
61
62#define TNETV_USB_REV (TNETV_USB_DEVICE_REG(0x00))
63#define TNETV_USB_TX_CTL (TNETV_USB_DEVICE_REG(0x04))
64#define TNETV_USB_TX_TEARDOWN (TNETV_USB_DEVICE_REG(0x08))
65#define TNETV_USB_RX_CTL (TNETV_USB_DEVICE_REG(0x14))
66#define TNETV_USB_RX_TEARDOWN (TNETV_USB_DEVICE_REG(0x18))
67#define TNETV_USB_TX_ENDIAN_CTL (TNETV_USB_DEVICE_REG(0x40))
68#define TNETV_USB_RX_ENDIAN_CTL (TNETV_USB_DEVICE_REG(0x44))
69
70#define TNETV_USB_RX_FREE_BUF_CNT(ch) (TNETV_USB_DEVICE_REG(0x140 + ((ch) * 4)))
71
72#define TNETV_USB_TX_INT_STATUS (TNETV_USB_DEVICE_REG(0x170))
73#define TNETV_USB_TX_INT_EN (TNETV_USB_DEVICE_REG(0x178))
74#define TNETV_USB_TX_INT_DIS (TNETV_USB_DEVICE_REG(0x17C))
75#define TNETV_USB_VBUS_INT (TNETV_USB_DEVICE_REG(0x180))
76#define TNETV_USB_VBUS_EOI (TNETV_USB_DEVICE_REG(0x184))
77#define TNETV_USB_RX_INT_STATUS (TNETV_USB_DEVICE_REG(0x190))
78#define TNETV_USB_RX_INT_EN (TNETV_USB_DEVICE_REG(0x198))
79#define TNETV_USB_RX_INT_DIS (TNETV_USB_DEVICE_REG(0x19C))
80
81#define TNETV_USB_RESET_CMPL (TNETV_USB_DEVICE_REG(0x1A0))
82#define TNETV_CPPI_STATE (TNETV_USB_DEVICE_REG(0x1A4))
83
84#define TNETV_USB_STATUS (TNETV_USB_DEVICE_REG(0x200))
85#define TNETV_USB_CTRL (TNETV_USB_DEVICE_REG(0x204))
86#define TNETV_USB_IF_STATUS (TNETV_USB_DEVICE_REG(0x210))
87#define TNETV_USB_IF_ERR (TNETV_USB_DEVICE_REG(0x214))
88#define TNETV_USB_IF_SM (TNETV_USB_DEVICE_REG(0x218))
89
90#define TNETV_USB_EP0_CFG (TNETV_USB_DEVICE_REG(0x220))
91#define TNETV_USB_EP0_CNT (TNETV_USB_DEVICE_REG(0x224))
92
93#define TNETV_USB_EPx_CFG(x) (TNETV_USB_DEVICE_REG(0x220 + (0x10 * (x))))
94#define TNETV_USB_EPx_IN_CNT(x) (TNETV_USB_DEVICE_REG(0x224 + (0x10 * (x))))
95#define TNETV_USB_EPx_OUT_CNT(x) (TNETV_USB_DEVICE_REG(0x228 + (0x10 * (x))))
96#define TNETV_USB_EPx_ADR(x) (TNETV_USB_DEVICE_REG(0x22C + (0x10 * (x))))
97
98/* USB CPPI Config registers (0x300 - 0x30C) */
99#define TNETV_USB_RNDIS_MODE (TNETV_USB_DEVICE_REG(0x300))
100#define TNETV_USB_CELL_DMA_EN (TNETV_USB_DEVICE_REG(0x30C))
101
102#define TNETV_USB_RAW_INT (TNETV_USB_DEVICE_REG(0x310))
103#define TNETV_USB_RAW_EOI (TNETV_USB_DEVICE_REG(0x314))
104
105/* USB DMA setup RAM (0x800 - 0x8FF) */
106#define TNETV_DMA_BASE (TNETV_USB_DEVICE_BASE + 0x800)
107#define TNETV_DMA_TX_STATE(ch, wd) ((uint32_t *) ((TNETV_DMA_BASE) + ((ch) * 0x40) + ((wd) * 4)))
108#define TNETV_DMA_TX_CMPL(ch) ((TNETV_DMA_BASE) + ((ch) * 0x40) + 0x1C)
109
110#define TNETV_CPPI_TX_WORD_HDP 0
111
112#define TNETV_DMA_RX_STATE(ch, wd) ((uint32_t *) ((TNETV_DMA_BASE) + ((ch) * 0x40) + 0x20 + ((wd) * 4)))
113#define TNETV_DMA_RX_CMPL(ch) ((TNETV_DMA_BASE) + ((ch) * 0x40) + 0x3C)
114
115#define TNETV_CPPI_RX_WORD_HDP 1
116
117#define TNETV_DMA_NUM_CHANNELS 3
118
119#define TNETV_DMA_TX_NUM_WORDS 6
120#define TNETV_DMA_RX_NUM_WORDS 7
121
122
123/* USB Buffer RAM (0x1000 - 0x1A00) */
124#define TNETV_EP_DATA_ADDR(x) ((uint32_t *) ((TNETV_USB_DEVICE_BASE) + 0x1000 + (x)))
125
126#define TNETV_EP_DATA_SIZE (0xA00)
127
128#define TNETV_V2USB_RESET_DEV (1 << 0)
129
130#define TNETV_USB_CELL_DMA_EN_RX (1 << 0)
131#define TNETV_USB_CELL_DMA_EN_TX (1 << 1)
132
133#define TNETV_V2USB_CLK_WKUP_VBUS (1 << 12)
134
135#define DM320_VLYNQ_INTPND_PHY ((DM320_AHB_PADDR) + 0x0314)
136
137
138/* macro to convert from a linux pointer to a physical address
139 * to be sent over the VLYNQ bus. The dm320 vlynq rx registers are
140 * set up so the base address is the physical address of RAM
141 */
142#define __dma_to_vlynq_phys(addr) ((((uint32_t) (addr)) - 0x01000000))
143#define __vlynq_phys_to_dma(addr) ((((uint32_t) (addr)) + 0x01000000))
144
145//----------------------------------------------------------------------
146
147#define USB_FULL_SPEED_MAXPACKET 64
148#define USB_HIGH_SPEED_MAXPACKET 512
149
150/* WORD offsets into the data memory */
151#define EP0_MAX_PACKET_SIZE 64 /* Control ep - 64 bytes */
152#define EP1_MAX_PACKET_SIZE 512 /* Bulk ep - 512 bytes */
153#define EP2_MAX_PACKET_SIZE 512 /* Bulk ep - 512 bytes */
154#define EP3_MAX_PACKET_SIZE 64 /* Int ep - 64 bytes */
155#define EP4_MAX_PACKET_SIZE 64 /* Int ep - 64 bytes */
156
157/* BEN TODO: fix this crap */
158#define EP0_OUTPKT_ADDRESS 0
159#define EP0_INPKT_ADDRESS (EP0_MAX_PACKET_SIZE)
160#define EP1_XBUFFER_ADDRESS (EP0_MAX_PACKET_SIZE << 1)
161#define EP1_YBUFFER_ADDRESS (EP1_XBUFFER_ADDRESS + EP1_MAX_PACKET_SIZE)
162#define EP2_XBUFFER_ADDRESS (EP1_XBUFFER_ADDRESS + (EP1_MAX_PACKET_SIZE << 1))
163#define EP2_YBUFFER_ADDRESS (EP2_XBUFFER_ADDRESS + EP2_MAX_PACKET_SIZE)
164#define EP3_XBUFFER_ADDRESS (EP2_XBUFFER_ADDRESS + (EP2_MAX_PACKET_SIZE << 1))
165#define EP3_YBUFFER_ADDRESS (EP3_XBUFFER_ADDRESS + EP3_MAX_PACKET_SIZE)
166#define EP4_XBUFFER_ADDRESS (EP3_XBUFFER_ADDRESS + (EP3_MAX_PACKET_SIZE << 1))
167#define EP4_YBUFFER_ADDRESS (EP4_XBUFFER_ADDRESS + EP4_MAX_PACKET_SIZE)
168#define EP5_XBUFFER_ADDRESS (EP4_XBUFFER_ADDRESS + (EP4_MAX_PACKET_SIZE << 1))
169#define EP5_YBUFFER_ADDRESS (EP5_XBUFFER_ADDRESS + EP1_MAX_PACKET_SIZE)
170#define EP6_XBUFFER_ADDRESS (EP5_XBUFFER_ADDRESS + (EP1_MAX_PACKET_SIZE << 1))
171#define EP6_YBUFFER_ADDRESS (EP6_XBUFFER_ADDRESS + EP2_MAX_PACKET_SIZE)
172#define EP7_XBUFFER_ADDRESS (EP6_XBUFFER_ADDRESS + (EP2_MAX_PACKET_SIZE << 1))
173#define EP7_YBUFFER_ADDRESS (EP7_XBUFFER_ADDRESS + EP3_MAX_PACKET_SIZE)
174#define EP8_XBUFFER_ADDRESS (EP7_XBUFFER_ADDRESS + (EP3_MAX_PACKET_SIZE << 1))
175#define EP8_YBUFFER_ADDRESS (EP8_XBUFFER_ADDRESS + EP4_MAX_PACKET_SIZE)
176
177#define SETUP_PKT_DATA_SIZE 8
178
179#define EP0_BUF_SIZE_8 0
180#define EP0_BUF_SIZE_16 1
181#define EP0_BUF_SIZE_32 2
182#define EP0_BUF_SIZE_64 3
183
184/* USB Status register */
185typedef struct {
186 uint32_t rsvd1 : 5;
187 uint32_t ep0_out_ack : 1;
188 uint32_t rsvd2 : 1;
189 uint32_t ep0_in_ack : 1;
190 uint32_t rsvd3 : 16;
191 uint32_t setup_ow : 1;
192 uint32_t setup : 1;
193 uint32_t vbus : 1;
194 uint32_t resume : 1;
195 uint32_t suspend : 1;
196 uint32_t reset : 1;
197 uint32_t sof : 1;
198 uint32_t any_int : 1;
199} UsbStatusStruct;
200
201typedef union {
202 uint32_t val;
203 UsbStatusStruct f;
204} UsbStatusType;
205
206/* USB Function control register */
207typedef struct {
208 uint32_t dir : 1;
209 uint32_t hs_test_mode : 3;
210 uint32_t rsvd1 : 1;
211 uint32_t wkup_en : 1;
212 uint32_t low_pwr_en : 1;
213 uint32_t connect : 1;
214 uint32_t rsvd2 : 4;
215 uint32_t ep0_in_int_en : 1;
216 uint32_t ep0_out_int_en : 1;
217 uint32_t err_cnt_en : 2;
218 uint32_t func_addr : 7;
219 uint32_t speed : 1;
220 uint32_t setupow_int_en : 1;
221 uint32_t setup_int_en : 1;
222 uint32_t vbus_int_en : 1;
223 uint32_t resume_int_en : 1;
224 uint32_t suspend_int_en : 1;
225 uint32_t reset_int_en : 1;
226 uint32_t sof_int_en : 1;
227 uint32_t rsvd3 : 1;
228} UsbCtrlStruct;
229
230typedef union {
231 uint32_t val;
232 UsbCtrlStruct f;
233} UsbCtrlType;
234
235/* Endpoint 0 Control Register */
236typedef struct {
237 uint32_t buf_size : 2;
238 uint32_t in_int_en : 1;
239 uint32_t in_stall : 1;
240 uint32_t dbl_buf : 1;
241 uint32_t in_toggle : 1;
242 uint32_t in_nak_int_en : 1;
243 uint32_t in_en : 1;
244 uint32_t res3 : 10;
245 uint32_t out_int_en : 1;
246 uint32_t out_stall : 1;
247 uint32_t res4 : 1;
248 uint32_t out_toggle : 1;
249 uint32_t out_nak_int_en : 1;
250 uint32_t out_en : 1;
251 uint32_t res6 : 8;
252} UsbEp0CtrlStruct;
253
254typedef union {
255 uint32_t val;
256 UsbEp0CtrlStruct f;
257} UsbEp0CtrlType;
258
259/* Endpoint 0 current packet size register */
260typedef struct {
261 uint32_t in_xbuf_cnt : 7;
262 uint32_t in_xbuf_nak : 1;
263 uint32_t in_ybuf_cnt : 7;
264 uint32_t in_ybuf_nak : 1;
265 uint32_t out_xbuf_cnt : 7;
266 uint32_t out_xbuf_nak : 1;
267 uint32_t out_ybuf_cnt : 7;
268 uint32_t out_ybuf_nak : 1;
269} UsbEp0ByteCntStruct;
270
271typedef union {
272 uint32_t val;
273 UsbEp0ByteCntStruct f;
274} UsbEp0ByteCntType;
275
276/* Endpoint n Configuration and Control register */
277typedef struct {
278 uint32_t res1 : 1;
279 uint32_t in_toggle_rst : 1;
280 uint32_t in_ack_int : 1;
281 uint32_t in_stall : 1;
282 uint32_t in_dbl_buf : 1;
283 uint32_t in_toggle : 1;
284 uint32_t in_nak_int : 1;
285 uint32_t in_en : 1;
286 uint32_t res2 : 1;
287 uint32_t out_toggle_rst : 1;
288 uint32_t out_ack_int : 1;
289 uint32_t out_stall : 1;
290 uint32_t out_dbl_buf : 1;
291 uint32_t out_toggle : 1;
292 uint32_t out_nak_int : 1;
293 uint32_t out_en : 1;
294 uint32_t in_buf_size : 8;
295 uint32_t out_buf_size : 8;
296} UsbEpCfgCtrlStruct;
297
298typedef union {
299 uint32_t val;
300 UsbEpCfgCtrlStruct f;
301} UsbEpCfgCtrlType;
302
303/* Endpoint n XY Buffer Start Address register */
304typedef struct {
305 uint8_t xBuffStartAddrIn;
306 uint8_t yBuffStartAddrIn;
307 uint8_t xBuffStartAddrOut;
308 uint8_t yBuffStartAddrOut;
309} UsbEpStartAddrStruct;
310
311typedef union {
312 uint32_t val;
313 UsbEpStartAddrStruct f;
314} UsbEpStartAddrType;
315
316/* Endpoint n Packet Control register */
317typedef struct {
318 uint32_t xBufPacketCount : 11;
319 uint32_t res1 : 4;
320 uint32_t xbuf_nak : 1;
321 uint32_t yBufPacketCount : 11;
322 uint32_t res2 : 4;
323 uint32_t ybuf_nak : 1;
324} UsbEpByteCntStruct;
325
326typedef union {
327 uint32_t val;
328 UsbEpByteCntStruct f;
329} UsbEpByteCntType;
330
331#define tnetv_usb_reg_read(x) (*((volatile uint32_t *) (x)))
332#define tnetv_usb_reg_write(x, val) (*((volatile uint32_t *) (x)) = (uint32_t) (val))
333
334
335#endif
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
index abe6622f0b..986efe374c 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
+++ b/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id: $ 8 * $Id: $
9 * 9 *
10 * Copyright (C) 2011 by Tomasz Moń 10 * Copyright (C) 2011-2021 by Tomasz Moń
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
@@ -22,52 +22,12 @@
22#include "config.h" 22#include "config.h"
23#include "system.h" 23#include "system.h"
24#include "kernel.h" 24#include "kernel.h"
25#include "usb.h"
26#ifdef HAVE_USBSTACK
27#include "usb_drv.h"
28#include "usb_core.h" 25#include "usb_core.h"
29#endif
30
31static bool usb_is_connected = false;
32 26
33static int usb_detect_callback(struct timeout *tmo) 27static int usb_detect_callback(struct timeout *tmo)
34{ 28{
35 (void)tmo; 29 (void)tmo;
36 30 usb_status_event(usb_detect());
37 if (IO_GIO_BITSET0 & (1 << 9))
38 {
39 /* Set GIO33 as normal output, drive it low */
40 IO_GIO_FSEL3 &= ~(0x0003);
41 IO_GIO_BITCLR2 = (1 << 1);
42
43 /* Disable M48XI crystal resonator */
44 IO_CLK_LPCTL1 |= 0x01;
45
46 /* Drive reset low */
47 IO_GIO_BITCLR0 = (1 << 7);
48
49 /* Disable VLYNQ clock */
50 IO_CLK_MOD2 &= ~(1 << 13);
51
52 usb_is_connected = false;
53 }
54 else
55 {
56 /* Enable M48XI crystal resonator */
57 IO_CLK_LPCTL1 &= ~(0x01);
58
59 /* Set GIO33 as CLKOUT1B */
60 IO_GIO_FSEL3 |= 0x0003;
61
62 /* Drive reset high */
63 IO_GIO_BITSET0 = (1 << 7);
64
65 /* Enable VLYNQ clock */
66 IO_CLK_MOD2 |= (1 << 13);
67
68 usb_is_connected = true;
69 }
70
71 return 0; 31 return 0;
72} 32}
73 33
@@ -82,20 +42,15 @@ void GIO9(void)
82 timeout_register(&usb_oneshot, usb_detect_callback, HZ, 0); 42 timeout_register(&usb_oneshot, usb_detect_callback, HZ, 0);
83} 43}
84 44
85bool usb_drv_connected(void)
86{
87 return false;
88}
89
90int usb_detect(void) 45int usb_detect(void)
91{ 46{
92 if (usb_is_connected == true) 47 if (IO_GIO_BITSET0 & (1 << 9))
93 { 48 {
94 return USB_INSERTED; 49 return USB_EXTRACTED;
95 } 50 }
96 else 51 else
97 { 52 {
98 return USB_EXTRACTED; 53 return USB_INSERTED;
99 } 54 }
100} 55}
101 56
@@ -127,14 +82,18 @@ void usb_init_device(void)
127 82
128 /* Enable USB insert detection interrupt */ 83 /* Enable USB insert detection interrupt */
129 IO_INTC_EINT1 |= (1 << 14); 84 IO_INTC_EINT1 |= (1 << 14);
130
131 /* Check if USB is connected */
132 usb_detect_callback(NULL);
133} 85}
134 86
135void usb_enable(bool on) 87void usb_enable(bool on)
136{ 88{
137 (void)on; 89 if (on)
90 {
91 usb_core_init();
92 }
93 else
94 {
95 usb_core_exit();
96 }
138} 97}
139 98
140void usb_attach(void) 99void usb_attach(void)
diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c
index 93cf3c51c4..935f3609a6 100644
--- a/firmware/target/arm/tms320dm320/system-dm320.c
+++ b/firmware/target/arm/tms320dm320/system-dm320.c
@@ -494,6 +494,13 @@ void udelay(int usec) {
494 } 494 }
495} 495}
496 496
497void mdelay(int msec)
498{
499 int ms_per_tick = 1000 / HZ;
500 /* Round up to next full tick */
501 sleep((msec + ms_per_tick - 1) / ms_per_tick);
502}
503
497#ifdef BOOTLOADER 504#ifdef BOOTLOADER
498void system_prepare_fw_start(void) 505void system_prepare_fw_start(void)
499{ 506{
diff --git a/firmware/target/arm/tms320dm320/system-target.h b/firmware/target/arm/tms320dm320/system-target.h
index 59ae61f8df..1c46e909ed 100644
--- a/firmware/target/arm/tms320dm320/system-target.h
+++ b/firmware/target/arm/tms320dm320/system-target.h
@@ -30,6 +30,7 @@
30#define CPUFREQ_MAX 175000000 30#define CPUFREQ_MAX 175000000
31 31
32void udelay(int usec); 32void udelay(int usec);
33void mdelay(int msec);
33 34
34#if defined(CREATIVE_ZVx) && defined(BOOTLOADER) 35#if defined(CREATIVE_ZVx) && defined(BOOTLOADER)
35 /* hacky.. */ 36 /* hacky.. */