2 Copyright � 2013-2015, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <proto/exec.h>
10 #include <proto/kernel.h>
11 #include <proto/utility.h>
13 #include <proto/alib.h>
14 #include <proto/mbox.h>
15 #include <hardware/videocore.h>
17 #include "usb2otg_intern.h"
19 #define DEVNAME "usb2otg.device"
21 const char devname
[] = MOD_NAME_STRING
;
23 AROS_INTP(FNAME_DEV(PendingInt
));
24 AROS_INTP(FNAME_DEV(NakTimeoutInt
));
26 IPTR __arm_periiobase
__attribute__((used
)) = 0 ;
30 static void DumpChannelRegs(int channel
)
32 D(bug("CHARBASE=%08x\n", rd32le(USB2OTG_CHANNEL_REG(channel
, CHARBASE
))));
33 D(bug("SPLITCTRL=%08x\n", rd32le(USB2OTG_CHANNEL_REG(channel
, SPLITCTRL
))));
34 D(bug("INTR=%08x\n", rd32le(USB2OTG_CHANNEL_REG(channel
, INTR
))));
35 D(bug("INTRMASK=%08x\n", rd32le(USB2OTG_CHANNEL_REG(channel
, INTRMASK
))));
36 D(bug("TRANSSIZE=%08x\n", rd32le(USB2OTG_CHANNEL_REG(channel
, TRANSSIZE
))));
37 D(bug("DMAADR=%08x\n", rd32le(USB2OTG_CHANNEL_REG(channel
, DMAADDR
))));
40 static void GlobalIRQHandler(struct USB2OTGUnit
*USBUnit
, struct ExecBase
*SysBase
)
42 volatile unsigned int otg_RegVal
;
43 struct USB2OTGDevice
* USB2OTGBase
= USBUnit
->hu_USB2OTGBase
;
44 ULONG frnm
= (rd32le(USB2OTG_HOSTFRAMENO
) & 0x3fff) >> 3;
46 // D(bug("[USB2OTG] %s: Received USB interrupt for Unit @ 0x%p\n",
47 // __PRETTY_FUNCTION__, USBUnit));
49 otg_RegVal
= rd32le(USB2OTG_INTR
);
50 wr32le(USB2OTG_INTR
, otg_RegVal
);
52 if (otg_RegVal
& USB2OTG_INTRCORE_DMASTARTOFFRAME
)
54 struct IOUsbHWReq
*req
, *next
;
56 wr32le(USB2OTG_INTR
, USB2OTG_INTRCORE_DMASTARTOFFRAME
);
58 if (frnm
< last_frame
)
60 D(bug("[USB2OTG] SOF, frame wrap %d %d\n", frnm
, last_frame
));
63 if (frnm
!= last_frame
)
65 ForeachNodeSafe(&USBUnit
->hu_IntXFerQueue
, req
, next
)
67 ULONG last_handled
= (ULONG
)req
->iouh_DriverPrivate1
;
68 ULONG next_to_handle
= (ULONG
)req
->iouh_DriverPrivate2
;
70 /* Is it time to handle the request? If yes, move it to Scheduled list */
71 if (frnm
== next_to_handle
)
73 //D(bug("[USB2OTG] schedule INT request on time, last=%d, next=%d, frnm=%d\n", last_handled, next_to_handle, frnm));
75 ADDTAIL(&USBUnit
->hu_IntXFerScheduled
, req
);
78 If the request is overdued several scenarios are possible:
79 1. frnm is larger than "last" and "next"
80 0......last....next...frnm....2047
81 2. frnm is smaller than "last" and "next"
82 0..frnm.....last....next......2047
83 3. frnm is bigger than "next" but smaller than "last"
84 0..next....frnm......last.....2047
87 (frnm
> next_to_handle
&& frnm
> last_handled
) ||
88 (frnm
< last_handled
&& frnm
> next_to_handle
) ||
89 (frnm
> next_to_handle
&& frnm
< last_handled
)
92 //D(bug("[USB2OTG] overdued INT request, scheduling. last=%d, next=%d, frnm=%d\n", last_handled, next_to_handle, frnm));
94 ADDTAIL(&USBUnit
->hu_IntXFerScheduled
, req
);
98 /* If the Scheduled list is not empty process it now */
99 if (!IsListEmpty(&USBUnit
->hu_IntXFerScheduled
))
100 FNAME_DEV(ScheduleIntTDs
)(USBUnit
);
106 if (otg_RegVal
& USB2OTG_INTRCORE_HOSTCHANNEL
)
108 unsigned int otg_ChanVal
;
111 otg_ChanVal
= rd32le(USB2OTG_HOSTINTR
);
112 wr32le(USB2OTG_HOSTINTR
, otg_ChanVal
);
114 //D(bug("[USB2OTG] HOSTCHANNEL %x frnm %d\n", otg_ChanVal, frnm));
116 for (chan
= 0; chan
< 8; chan
++)
118 if (otg_ChanVal
& (1 << chan
))
120 struct IOUsbHWReq
* req
= USBUnit
->hu_InProgressXFer
[chan
];
121 uint32_t tmp
= rd32le(USB2OTG_CHANNEL_REG(chan
, INTR
));
125 int do_split
= rd32le(USB2OTG_CHANNEL_REG(chan
, SPLITCTRL
)) & 0x80010000;
127 Channel closed with ACK but not comleted yet and split is active. Complete split now, do not continue with
128 normal processing of this channel
130 if (tmp
== 0x22 && do_split
)
133 uint32_t split
= rd32le(USB2OTG_CHANNEL_REG(chan
, SPLITCTRL
));
134 //D(bug("[USB2OTG] Completing split transaction in interrupt. SPLITCTRL=%08x\n", split));
136 split
|= 1 << 16; /* Set "do complete split" */
137 wr32le(USB2OTG_CHANNEL_REG(chan
, SPLITCTRL
), split
);
139 /* Clear interrupt flags */
140 wr32le(USB2OTG_CHANNEL_REG(chan
, INTR
), 0x7ff);
142 /* Enable channel again */
143 tmp
= rd32le(USB2OTG_CHANNEL_REG(chan
, CHARBASE
));
144 tmp
|= USB2OTG_HOSTCHAR_ENABLE
;
145 wr32le(USB2OTG_CHANNEL_REG(chan
, CHARBASE
), tmp
);
147 else if (tmp
== 0x42 && do_split
== 0x80010000)
149 ULONG last
= (ULONG
)req
->iouh_DriverPrivate1
;
150 ULONG thresh
= (last
+ (ULONG
)req
->iouh_Interval
/ 2) % 2047;
152 /* Clear interrupt flags */
153 wr32le(USB2OTG_CHANNEL_REG(chan
, INTR
), 0x7ff);
155 if ((chan
>= CHAN_INT1
&& chan
<= CHAN_INT3
) &&
156 ((frnm
> thresh
&& frnm
> last
) ||
157 (frnm
< thresh
&& frnm
< last
) ||
158 (frnm
> thresh
&& frnm
< last
)))
160 //D(bug("[USB2OTG] restarting transaction... %d, %d, %d\n", frnm, req->iouh_DriverPrivate1, req->iouh_DriverPrivate2));
162 /* Disable channel */
163 wr32le(USB2OTG_CHANNEL_REG(chan
, CHARBASE
), 0);
165 /* Put transfer back into queue */
166 if (req
->iouh_Req
.io_Command
== UHCMD_CONTROLXFER
)
167 ADDHEAD(&USBUnit
->hu_CtrlXFerQueue
, req
);
168 if (req
->iouh_Req
.io_Command
== UHCMD_BULKXFER
)
169 ADDHEAD(&USBUnit
->hu_BulkXFerQueue
, req
);
170 if (req
->iouh_Req
.io_Command
== UHCMD_INTXFER
)
171 ADDHEAD(&USBUnit
->hu_IntXFerQueue
, req
);
173 /* Mark channel free */
174 USBUnit
->hu_InProgressXFer
[chan
] = NULL
;
178 //D(bug("!!! Channel %d, Restarting CSPLIT phase! %d, %d, %d\n", chan, frnm, req->iouh_DriverPrivate1, req->iouh_DriverPrivate2));
179 /* Enable channel again */
180 tmp
= rd32le(USB2OTG_CHANNEL_REG(chan
, CHARBASE
));
181 tmp
|= USB2OTG_HOSTCHAR_ENABLE
;
182 wr32le(USB2OTG_CHANNEL_REG(chan
, CHARBASE
), tmp
);
186 else if (tmp
== 0x12 && do_split
)
187 //&& (chan < CHAN_INT1 || chan > CHAN_INT3))
189 /* NAK response from split transaction. Restart the request from beginning */
190 /* D(bug("[USB2OTG] Restarting split transaction\n"));
192 DumpChannelRegs(chan);*/
194 /* Clear interrupt flags */
195 wr32le(USB2OTG_CHANNEL_REG(chan
, INTR
), 0x7ff);
197 /* Disable channel */
198 wr32le(USB2OTG_CHANNEL_REG(chan
, CHARBASE
), 0);
200 /* Put transfer back into queue */
201 if (req
->iouh_Req
.io_Command
== UHCMD_CONTROLXFER
)
202 ADDHEAD(&USBUnit
->hu_CtrlXFerQueue
, req
);
203 if (req
->iouh_Req
.io_Command
== UHCMD_BULKXFER
)
204 ADDHEAD(&USBUnit
->hu_BulkXFerQueue
, req
);
205 if (req
->iouh_Req
.io_Command
== UHCMD_INTXFER
)
206 ADDHEAD(&USBUnit
->hu_IntXFerQueue
, req
);
208 /* Mark channel free */
209 USBUnit
->hu_InProgressXFer
[chan
] = NULL
;
213 /* Ignore NAK on INT channels when reporting closed channel */
214 if (tmp
!= 0x12 || (chan
< CHAN_INT1
&& chan
> CHAN_INT3
))
215 D(bug("[USB2OTG] Channel %d closed. INTR=%08x\n", chan
, tmp
));
220 USBUnit
->hu_PIDBits
[req
->iouh_DevAddr
] ^= (2 << (2 * req
->iouh_Endpoint
));
221 req
->iouh_Actual
= req
->iouh_Length
;
222 req
->iouh_Req
.io_Error
= 0;
226 req
->iouh_Actual
= 0;
227 req
->iouh_Req
.io_Error
= UHIOERR_TIMEOUT
;
228 DumpChannelRegs(chan
);
232 req
->iouh_Actual
= 0;
233 req
->iouh_Req
.io_Error
= UHIOERR_STALL
;
234 DumpChannelRegs(chan
);
238 /* In case of INT requests NAK is silently ignored. Just put the request back to the IntXferQueue */
239 if (chan
>= CHAN_INT1
&& chan
<= CHAN_INT3
)
241 ADDTAIL(&USBUnit
->hu_IntXFerQueue
, req
);
246 req
->iouh_Actual
= 0;
247 req
->iouh_Req
.io_Error
= UHIOERR_NAK
;
248 DumpChannelRegs(chan
);
251 else if (tmp
& 0x100)
253 req
->iouh_Actual
= 0;
254 req
->iouh_Req
.io_Error
= UHIOERR_BABBLE
;
255 DumpChannelRegs(chan
);
257 else if (tmp
& 0x400)
259 req
->iouh_Actual
= 0;
260 req
->iouh_Req
.io_Error
= UHIOERR_HOSTERROR
;
261 DumpChannelRegs(chan
);
264 USBUnit
->hu_InProgressXFer
[chan
] = NULL
;
265 if (req
) FNAME_DEV(TermIO
)(req
, USB2OTGBase
);
267 wr32le(USB2OTG_CHANNEL_REG(chan
, INTR
), tmp
);
274 FNAME_DEV(Cause
)(USB2OTGBase
, &USBUnit
->hu_PendingInt
);
276 if (USBUnit->hu_CtrlXFerQueue.lh_Head->ln_Succ)
278 D(bug("[USB2OTG] [0x%p:PEND] Process CtrlXFer ..\n", USBUnit));
279 FNAME_DEV(ScheduleCtrlTDs)(USBUnit);
284 *===========================================================
286 *===========================================================
288 static int FNAME_DEV(Init
)(LIBBASETYPEPTR USB2OTGBase
)
290 void *MBoxBase
= NULL
;
291 volatile unsigned int otg_RegVal
;
292 unsigned int otg_OperatingMode
= 0;
293 ULONG
*PwrOnMsg
, *pwron
= NULL
;
295 KernelBase
= OpenResource("kernel.resource");
296 MBoxBase
= OpenResource("mbox.resource");
298 __arm_periiobase
= KrnGetSystemAttr(KATTR_PeripheralBase
);
300 D(bug("[USB2OTG] %s: USB2OTGBase @ 0x%p, SysBase @ 0x%p\n",
301 __PRETTY_FUNCTION__
, USB2OTGBase
, SysBase
));
303 otg_RegVal
= rd32le(USB2OTG_VENDORID
);
305 if ((otg_RegVal
& 0xFFFFF000) != 0x4F542000)
307 bug("[USB2OTG] Unsupported HS OTG USB Core Found\n");
308 bug("[USB2OTG] Hardware: %c%c%x.%x%x%x\n",
309 ((otg_RegVal
>> 24) & 0xFF), ((otg_RegVal
>> 16) & 0xFF),
310 ((otg_RegVal
>> 12) & 0xF), ((otg_RegVal
>> 8) & 0xF), ((otg_RegVal
>> 4) & 0xF), (otg_RegVal
& 0xF)
317 USB2OTGBase
->hd_KernelBase
= OpenResource("kernel.resource");
318 D(bug("[USB2OTG] %s: kernel.resource opened @ 0x%p\n",
319 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_KernelBase
));
321 if((USB2OTGBase
->hd_MsgPort
= CreateMsgPort()))
323 if((USB2OTGBase
->hd_TimerReq
= (struct timerequest
*) CreateIORequest(USB2OTGBase
->hd_MsgPort
, sizeof(struct timerequest
))))
325 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) USB2OTGBase
->hd_TimerReq
, 0))
327 USB2OTGBase
->hd_TimerReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "USB2OTG Timer";
328 USB2OTGBase
->hd_TimerReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
329 D(bug("[USB2OTG] %s: timer.device opened\n",
330 __PRETTY_FUNCTION__
));
332 bug("[USB2OTG] HS OTG Core Release: %c%c%x.%x%x%x\n",
333 ((otg_RegVal
>> 24) & 0xFF), ((otg_RegVal
>> 16) & 0xFF),
334 ((otg_RegVal
>> 12) & 0xF), ((otg_RegVal
>> 8) & 0xF), ((otg_RegVal
>> 4) & 0xF), (otg_RegVal
& 0xF)
337 otg_RegVal
= rd32le(USB2OTG_HARDWARE2
);
338 bug("[USB2OTG] Architecture: %d - ", ((otg_RegVal
& (3 << 3)) >> 3));
339 switch (((otg_RegVal
& (3 << 3)) >> 3))
342 bug("Internal DMA\n");
345 bug("External DMA\n");
352 D(bug("[USB2OTG] %s: Disabling USB Interrupts (Globaly)..\n", __PRETTY_FUNCTION__
));
353 otg_RegVal
= rd32le(USB2OTG_AHB
);
354 otg_RegVal
&= ~USB2OTG_AHB_INTENABLE
;
355 wr32le(USB2OTG_INTRMASK
, 0);
356 wr32le(USB2OTG_AHB
, otg_RegVal
);
358 D(bug("[USB2OTG] Powering on USB controller\n"));
359 pwron
= AllocVec(9*sizeof(ULONG
), MEMF_CLEAR
);
360 PwrOnMsg
= (ULONG
*)(((IPTR
)pwron
+ 15) & ~15);
362 D(bug("[USB2OTG] pwron=%p, PwrOnMsg=%p\n", pwron
, PwrOnMsg
));
364 PwrOnMsg
[0] = AROS_LE2LONG(8 * sizeof(ULONG
));
365 PwrOnMsg
[1] = AROS_LE2LONG(VCTAG_REQ
);
366 PwrOnMsg
[2] = AROS_LE2LONG(VCTAG_SETPOWER
);
367 PwrOnMsg
[3] = AROS_LE2LONG(8);
368 PwrOnMsg
[4] = AROS_LE2LONG(0);
369 PwrOnMsg
[5] = AROS_LE2LONG(VCPOWER_USBHCD
);
370 PwrOnMsg
[6] = AROS_LE2LONG(VCPOWER_STATE_ON
| VCPOWER_STATE_WAIT
);
373 MBoxWrite((void*)VCMB_BASE
, VCMB_PROPCHAN
, PwrOnMsg
);
374 if (MBoxRead((void*)VCMB_BASE
, VCMB_PROPCHAN
) == PwrOnMsg
)
376 D(bug("[USB2OTG] Power on state: %08x\n", AROS_LE2LONG(PwrOnMsg
[6])));
377 if ((AROS_LE2LONG(PwrOnMsg
[6]) & 1) == 0)
379 bug("[USB2OTG] Failed to power on USB controller\n");
383 if ((AROS_LE2LONG(PwrOnMsg
[6]) & 2) != 0)
385 bug("[USB2OTG] USB HCD does not exist\n");
397 if ((USB2OTGBase
->hd_UtilityBase
= (APTR
)OpenLibrary("utility.library", 39)) != NULL
)
399 USB2OTGBase
->hd_MemPool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_SEM_PROTECTED
, 16384, 4096);
400 if (USB2OTGBase
->hd_MemPool
)
404 D(bug("[USB2OTG] %s: Allocated MemPool @ 0x%p\n",
405 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_MemPool
));
410 otg_RegVal
= rd32le(USB2OTG_HARDWARE
);
411 bug("[USB2OTG] %s: HWConfig: %08x-", __PRETTY_FUNCTION__
, otg_RegVal
);
412 otg_RegVal
= rd32le(USB2OTG_HARDWARE2
);
413 bug("%08x-", otg_RegVal
);
414 otg_RegVal
= rd32le(USB2OTG_HARDWARE3
);
415 bug("%08x-", otg_RegVal
);
416 otg_RegVal
= rd32le(USB2OTG_HARDWARE4
);
417 bug("%08x\n", otg_RegVal
);
420 if ((USB2OTGBase
->hd_Unit
= AllocPooled(USB2OTGBase
->hd_MemPool
, sizeof(struct USB2OTGUnit
))) != NULL
)
424 D(bug("[USB2OTG] %s: Unit Allocated at 0x%p\n",
425 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
));
427 NewList(&USB2OTGBase
->hd_Unit
->hu_IOPendingQueue
);
429 NewList(&USB2OTGBase
->hd_Unit
->hu_CtrlXFerQueue
);
430 NewList(&USB2OTGBase
->hd_Unit
->hu_IntXFerQueue
);
431 NewList(&USB2OTGBase
->hd_Unit
->hu_IntXFerScheduled
);
432 NewList(&USB2OTGBase
->hd_Unit
->hu_IsoXFerQueue
);
433 NewList(&USB2OTGBase
->hd_Unit
->hu_BulkXFerQueue
);
434 NewList(&USB2OTGBase
->hd_Unit
->hu_TDQueue
);
435 NewList(&USB2OTGBase
->hd_Unit
->hu_AbortQueue
);
436 NewList(&USB2OTGBase
->hd_Unit
->hu_PeriodicTDQueue
);
438 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
439 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Name
= "OTG2USB Pending Work Interrupt";
440 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Node
.ln_Pri
= 0;
441 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Data
= USB2OTGBase
->hd_Unit
;
442 USB2OTGBase
->hd_Unit
->hu_PendingInt
.is_Code
= (VOID_FUNC
)FNAME_DEV(PendingInt
);
444 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
445 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Name
= "OTG2USB NakTimeout Interrupt";
446 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Node
.ln_Pri
= -16;
447 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Data
= USB2OTGBase
->hd_Unit
;
448 USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
.is_Code
= (VOID_FUNC
)FNAME_DEV(NakTimeoutInt
);
450 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
451 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_SOFTINT
;
452 USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_SigTask
= &USB2OTGBase
->hd_Unit
->hu_NakTimeoutInt
;
453 NewList(&USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
.mp_MsgList
);
455 CopyMem(USB2OTGBase
->hd_TimerReq
, &USB2OTGBase
->hd_Unit
->hu_NakTimeoutReq
, sizeof(struct timerequest
));
456 USB2OTGBase
->hd_Unit
->hu_NakTimeoutReq
.tr_node
.io_Message
.mn_ReplyPort
= &USB2OTGBase
->hd_Unit
->hu_NakTimeoutMsgPort
;
458 USB2OTGBase
->hd_Unit
->hu_HubPortChanged
= FALSE
;
460 USB2OTGBase
->hd_Unit
->hu_OperatingMode
= (otg_OperatingMode
== (USB2OTG_USBHOSTMODE
|USB2OTG_USBDEVICEMODE
)) ? 0 : otg_OperatingMode
;
462 for (i
=0; i
< 128; i
++)
463 USB2OTGBase
->hd_Unit
->hu_PIDBits
[i
] = 0;
466 D(bug("[USB2OTG] %s: Unit Mode %d\n",
467 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
->hu_OperatingMode
));
469 USB2OTGBase
->hd_Unit
->hu_GlobalIRQHandle
= KrnAddIRQHandler(IRQ_VC_USB
, GlobalIRQHandler
, USB2OTGBase
->hd_Unit
, SysBase
);
471 USB2OTGBase
->hd_Unit
->hu_USB2OTGBase
= USB2OTGBase
;
473 D(bug("[USB2OTG] %s: Installed Global IRQ Handler [handle @ 0x%p] for IRQ #%ld\n",
474 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Unit
->hu_GlobalIRQHandle
, IRQ_HOSTPORT
));
476 otg_RegVal
= rd32le(USB2OTG_USB
);
477 otg_RegVal
&= ~(USB2OTG_USB_ULPIDRIVEEXTERNALVBUS
|USB2OTG_USB_TSDLINEPULSEENABLE
);
478 wr32le(USB2OTG_USB
, otg_RegVal
);
480 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__
));
481 wr32le(USB2OTG_RESET
, USB2OTG_RESET_CORESOFT
);
482 for (ns
= 0; ns
< 10000; ns
++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
483 if ((rd32le(USB2OTG_RESET
) & USB2OTG_RESET_CORESOFT
) != 0)
484 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__
);
486 D(bug("[USB2OTG] %s: Initialising PHY ..\n", __PRETTY_FUNCTION__
));
487 otg_RegVal
= rd32le(USB2OTG_USB
);
488 otg_RegVal
&= ~USB2OTG_USB_PHYINTERFACE
;
489 otg_RegVal
&= ~USB2OTG_USB_MODESELECT_UTMI
;
490 wr32le(USB2OTG_USB
, otg_RegVal
);
493 D(bug("[USB2OTG] %s: Reseting Controller ..\n", __PRETTY_FUNCTION__
));
494 wr32le(USB2OTG_RESET
, USB2OTG_RESET_CORESOFT
);
495 for (ns
= 0; ns
< 10000; ns
++) { asm volatile("mov r0, r0\n"); } // Wait 10ms
496 if ((rd32le(USB2OTG_RESET
) & USB2OTG_RESET_CORESOFT
) != 0)
497 bug("[USB2OTG] %s: Reset Timed-Out!\n", __PRETTY_FUNCTION__
);
500 otg_RegVal
= rd32le(USB2OTG_HARDWARE2
);
501 if (((otg_RegVal
& (3 << 6) >> 6) == 2) && ((otg_RegVal
& (3 << 8) >> 8) == 1))
503 D(bug("[USB2OTG] %s: ULPI FSLS configuration: enabled.\n", __PRETTY_FUNCTION__
));
504 otg_RegVal
= rd32le(USB2OTG_USB
);
505 otg_RegVal
|= (USB2OTG_USB_ULPIFSLS
|USB2OTG_USB_ULPI_CLK_SUS_M
);
506 wr32le(USB2OTG_USB
, otg_RegVal
);
508 D(bug("[USB2OTG] %s: ULPI FSLS configuration: disabled.\n", __PRETTY_FUNCTION__
));
509 otg_RegVal
= rd32le(USB2OTG_USB
);
510 otg_RegVal
&= ~(USB2OTG_USB_ULPIFSLS
|USB2OTG_USB_ULPI_CLK_SUS_M
);
511 wr32le(USB2OTG_USB
, otg_RegVal
);
514 D(bug("[USB2OTG] %s: Enabling DMA configuration..\n", __PRETTY_FUNCTION__
));
515 otg_RegVal
= rd32le(USB2OTG_AHB
);
516 otg_RegVal
&= ~(1 << USB2OTG_AHB_DMAREMAINDERMODE
);
517 otg_RegVal
|= (1 << 4) | (USB2OTG_AHB_DMAENABLE
|USB2OTG_AHB_DMAREMAINDERMODE_INCR
);
518 D(bug("[USB2OTG] %s: AHB reg: %08x..\n", __PRETTY_FUNCTION__
, otg_RegVal
));
519 wr32le(USB2OTG_AHB
, otg_RegVal
);
522 D(bug("[USB2OTG] %s: Operating Mode: ", __PRETTY_FUNCTION__
));
523 otg_RegVal
= rd32le(USB2OTG_HARDWARE2
);
524 switch (otg_RegVal
& 7)
528 otg_RegVal
= rd32le(USB2OTG_USB
);
529 otg_RegVal
|= (USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
530 wr32le(USB2OTG_USB
, otg_RegVal
);
536 otg_RegVal
= rd32le(USB2OTG_USB
);
537 otg_RegVal
&= ~USB2OTG_USB_HNPCAPABLE
;
538 otg_RegVal
|= USB2OTG_USB_SRPCAPABLE
;
539 wr32le(USB2OTG_USB
, otg_RegVal
);
544 D(bug("No HNP or SRP\n"));
545 otg_RegVal
= rd32le(USB2OTG_USB
);
546 otg_RegVal
&= ~(USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
547 wr32le(USB2OTG_USB
, otg_RegVal
);
551 D(bug("[USB2OTG] %s: Disable HNP/SRP\n", __PRETTY_FUNCTION__
));
552 otg_RegVal
= rd32le(USB2OTG_USB
);
553 otg_RegVal
&= ~(USB2OTG_USB_HNPCAPABLE
|USB2OTG_USB_SRPCAPABLE
);
554 wr32le(USB2OTG_USB
, otg_RegVal
);
557 D(bug("[USB2OTG] %s: Enabling Global Interrupts ...\n", __PRETTY_FUNCTION__
));
558 otg_RegVal
= rd32le(USB2OTG_INTR
);
560 wr32le(USB2OTG_INTR
, otg_RegVal
);
562 otg_RegVal
= rd32le(USB2OTG_INTRMASK
);
563 otg_RegVal
|= USB2OTG_INTRCORE_DMASTARTOFFRAME
;
564 wr32le(USB2OTG_INTRMASK
, otg_RegVal
);
566 otg_RegVal
= rd32le(USB2OTG_AHB
);
567 otg_RegVal
|= USB2OTG_AHB_INTENABLE
;
568 wr32le(USB2OTG_AHB
, otg_RegVal
);
570 bug("[USB2OTG] HS OTG USB Driver Initialised\n");
576 D(bug("[USB2OTG] %s: Failed to Create MemPool\n",
577 __PRETTY_FUNCTION__
));
579 CloseLibrary((struct Library
*) UtilityBase
);
585 D(bug("[USB2OTG] %s: OpenLibrary(\"utility.library\", 39) failed!\n",
586 __PRETTY_FUNCTION__
));
593 D(bug("[USB2OTG] %s: OpenDevice(\"timer.device\") failed!\n",
594 __PRETTY_FUNCTION__
));
601 D(bug("[USB2OTG] %s: Failed to allocate timer IORequest\n",
602 __PRETTY_FUNCTION__
));
609 D(bug("[USB2OTG] %s: Failed to create MsgPort\n",
610 __PRETTY_FUNCTION__
));
616 return USB2OTGBase
? TRUE
: FALSE
;
620 *===========================================================
621 * Open(ioreq, unit, flags, base)
622 *===========================================================
624 * This is the the DEV_OPEN function.
627 static int FNAME_DEV(Open
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
, ULONG otg_Unit
, ULONG flags
)
629 D(bug("[USB2OTG] %s: IOReq @ 0x%p, unit #%ld, flags = 0x%08lx, USB2OTGBase @ 0x%p\n",
630 __PRETTY_FUNCTION__
, ioreq
, otg_Unit
, flags
, USB2OTGBase
));
632 D(bug("[USB2OTG] %s: openCnt = %ld\n",
633 __PRETTY_FUNCTION__
, USB2OTGBase
->hd_Library
.lib_OpenCnt
));
635 if (ioreq
->iouh_Req
.io_Message
.mn_Length
< sizeof(struct IOUsbHWReq
))
637 D(bug("[USB2OTG] %s: invalid MN_LENGTH!\n",
638 __PRETTY_FUNCTION__
));
640 ioreq
->iouh_Req
.io_Error
= IOERR_BADLENGTH
;
644 ioreq
->iouh_Req
.io_Error
= IOERR_OPENFAIL
;
646 ioreq
->iouh_Req
.io_Unit
= FNAME_DEV(OpenUnit
)(ioreq
, otg_Unit
, USB2OTGBase
);
647 if (!(ioreq
->iouh_Req
.io_Unit
))
649 D(bug("[USB2OTG] %s: could not open unit!\n",
650 __PRETTY_FUNCTION__
));
655 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
656 ioreq
->iouh_Req
.io_Error
= 0;
667 *===========================================================
669 *===========================================================
671 * This is the the DEV_EXPUNGE function.
674 static int FNAME_DEV(Close
)(LIBBASETYPEPTR USB2OTGBase
, struct IOUsbHWReq
*ioreq
)
676 D(bug("[USB2OTG] %s: IOReq @ 0x%p, USB2OTGBase @ 0x%p\n",
677 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
));
679 FNAME_DEV(CloseUnit
)(ioreq
, (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
, USB2OTGBase
);
681 ioreq
->iouh_Req
.io_Unit
= (APTR
) -1;
682 ioreq
->iouh_Req
.io_Device
= (APTR
) -1;
686 static int FNAME_DEV(Expunge
)(LIBBASETYPEPTR USB2OTGBase
)
688 DeletePool(USB2OTGBase
->hd_MemPool
);
690 D(bug("[USB2OTG] %s: closing utility.library @ 0x%p\n",
691 __PRETTY_FUNCTION__
, UtilityBase
));
693 CloseLibrary((struct Library
*) UtilityBase
);
697 ADD2INITLIB(FNAME_DEV(Init
), 0)
698 ADD2OPENDEV(FNAME_DEV(Open
), 0)
699 ADD2CLOSEDEV(FNAME_DEV(Close
), 0)
700 ADD2EXPUNGELIB(FNAME_DEV(Expunge
), 0)
703 *===========================================================
704 * BeginIO(ioreq, base)
705 *===========================================================
707 * This is the DEV_BEGINIO vector of the device.
710 AROS_LH1(void, FNAME_DEV(BeginIO
),
711 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
712 LIBBASETYPEPTR
, USB2OTGBase
, 5, usb2otg
)
716 struct USB2OTGUnit
*otg_Unit
= (struct USB2OTGUnit
*) ioreq
->iouh_Req
.io_Unit
;
719 D(bug("[USB2OTG] %s: IOReq @ 0x%08lx, USB2OTGBase @ 0x%08lx [cmd:%lu]\n",
720 __PRETTY_FUNCTION__
, ioreq
, USB2OTGBase
, ioreq
->iouh_Req
.io_Command
));
722 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
723 ioreq
->iouh_Req
.io_Error
= UHIOERR_NO_ERROR
;
725 if (ioreq
->iouh_Req
.io_Command
< NSCMD_DEVICEQUERY
)
727 switch (ioreq
->iouh_Req
.io_Command
)
730 ret
= FNAME_DEV(cmdReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
734 ret
= FNAME_DEV(cmdFlush
)(ioreq
, otg_Unit
, USB2OTGBase
);
737 case UHCMD_QUERYDEVICE
:
738 ret
= FNAME_DEV(cmdQueryDevice
)(ioreq
, otg_Unit
, USB2OTGBase
);
742 ret
= FNAME_DEV(cmdUsbReset
)(ioreq
, otg_Unit
, USB2OTGBase
);
745 case UHCMD_USBRESUME
:
746 ret
= FNAME_DEV(cmdUsbResume
)(ioreq
, otg_Unit
, USB2OTGBase
);
749 case UHCMD_USBSUSPEND
:
750 ret
= FNAME_DEV(cmdUsbSuspend
)(ioreq
, otg_Unit
, USB2OTGBase
);
754 ret
= FNAME_DEV(cmdUsbOper
)(ioreq
, otg_Unit
, USB2OTGBase
);
757 case UHCMD_CONTROLXFER
:
758 ret
= FNAME_DEV(cmdControlXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
762 ret
= FNAME_DEV(cmdBulkXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
766 ret
= FNAME_DEV(cmdIntXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
770 ret
= FNAME_DEV(cmdIsoXFer
)(ioreq
, otg_Unit
, USB2OTGBase
);
780 switch(ioreq
->iouh_Req
.io_Command
)
782 case NSCMD_DEVICEQUERY
:
783 ret
= FNAME_DEV(cmdNSDeviceQuery
)((struct IOStdReq
*) ioreq
, otg_Unit
, USB2OTGBase
);
792 if (ret
!= RC_DONTREPLY
)
794 D(bug("[USB2OTG] %s: Terminating I/O..\n",
795 __PRETTY_FUNCTION__
));
799 ioreq
->iouh_Req
.io_Error
= ret
& 0xff;
801 FNAME_DEV(TermIO
)(ioreq
, USB2OTGBase
);
808 *===========================================================
809 * AbortIO(ioreq, base)
810 *===========================================================
812 * This is the DEV_ABORTIO vector of the device. It abort
813 * the given iorequest, and set
816 AROS_LH1(LONG
, FNAME_DEV(AbortIO
),
817 AROS_LHA(struct IOUsbHWReq
*, ioreq
, A1
),
818 LIBBASETYPEPTR
, USB2OTGBase
, 6, usb2otg
)
822 D(bug("[USB2OTG] %s: IOReq @ 0x%p, command %ld, status %ld\n",
823 __PRETTY_FUNCTION__
, ioreq
, ioreq
->iouh_Req
.io_Command
, ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
));
826 if (ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
829 if (FNAME_DEV(cmdAbortIO
)(ioreq
, USB2OTGBase
))
840 void FNAME_DEV(Cause
)(LIBBASETYPEPTR USB2OTGBase
, struct Interrupt
*interrupt
)
844 /* this is a workaround for the original Cause() function missing tailed calls */
847 if((interrupt
->is_Node
.ln_Type
== NT_SOFTINT
) || (interrupt
->is_Node
.ln_Type
== NT_USER
))
849 // signal tailed call
850 interrupt
->is_Node
.ln_Type
= NT_USER
;
854 interrupt
->is_Node
.ln_Type
= NT_SOFTINT
;
855 Forbid(); // make sure code is not interrupted by other tasks
857 AROS_INTC1(interrupt
->is_Code
, interrupt
->is_Data
);
860 } while(interrupt
->is_Node
.ln_Type
!= NT_SOFTINT
);
861 interrupt
->is_Node
.ln_Type
= NT_INTERRUPT
;