]>
git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/USBHost/USBHost/USBHALHost_RZ_A1.cpp
1 /* mbed USBHost Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #if defined(TARGET_RZ_A1H)
20 #include "USBHALHost.h"
23 #include "ohci_wrapp_RZ_A1.h"
26 #define HCCA_SIZE sizeof(HCCA)
27 #define ED_SIZE sizeof(HCED)
28 #define TD_SIZE sizeof(HCTD)
30 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
31 #define ALIGNE_MSK (0x0000000F)
33 static volatile uint8_t usb_buf
[TOTAL_SIZE
+ ALIGNE_MSK
]; //16 bytes aligned!
35 USBHALHost
* USBHALHost::instHost
;
37 USBHALHost::USBHALHost() {
40 memset((void*)usb_hcca
, 0, HCCA_SIZE
);
41 for (int i
= 0; i
< MAX_ENDPOINT
; i
++) {
42 edBufAlloc
[i
] = false;
44 for (int i
= 0; i
< MAX_TD
; i
++) {
45 tdBufAlloc
[i
] = false;
49 void USBHALHost::init() {
50 ohciwrapp_init(&_usbisr
);
52 ohciwrapp_reg_w(OHCI_REG_CONTROL
, 1); // HARDWARE RESET
53 ohciwrapp_reg_w(OHCI_REG_CONTROLHEADED
, 0); // Initialize Control list head to Zero
54 ohciwrapp_reg_w(OHCI_REG_BULKHEADED
, 0); // Initialize Bulk list head to Zero
56 // Wait 100 ms before apply reset
60 ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS
, OR_CMD_STATUS_HCR
);
62 // Write Fm Interval and Largest Data Packet Counter
63 ohciwrapp_reg_w(OHCI_REG_FMINTERVAL
, DEFAULT_FMINTERVAL
);
64 ohciwrapp_reg_w(OHCI_REG_PERIODICSTART
, FI
* 90 / 100);
66 // Put HC in operational state
67 ohciwrapp_reg_w(OHCI_REG_CONTROL
, (ohciwrapp_reg_r(OHCI_REG_CONTROL
) & (~OR_CONTROL_HCFS
)) | OR_CONTROL_HC_OPER
);
69 ohciwrapp_reg_w(OHCI_REG_RHSTATUS
, OR_RH_STATUS_LPSC
);
71 ohciwrapp_reg_w(OHCI_REG_HCCA
, (uint32_t)(usb_hcca
));
73 // Clear Interrrupt Status
74 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS
, ohciwrapp_reg_r(OHCI_REG_INTERRUPTSTATUS
));
76 ohciwrapp_reg_w(OHCI_REG_INTERRUPTENABLE
, OR_INTR_ENABLE_MIE
| OR_INTR_ENABLE_WDH
| OR_INTR_ENABLE_RHSC
);
78 // Enable the USB Interrupt
79 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1
, OR_RH_PORT_CSC
);
80 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1
, OR_RH_PORT_PRSC
);
82 // Check for any connected devices
83 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_CCS
) {
86 USB_DBG("Device connected (%08x)\n\r", ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
));
87 deviceConnected(0, 1, ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_LSDA
);
91 uint32_t USBHALHost::controlHeadED() {
92 return ohciwrapp_reg_r(OHCI_REG_CONTROLHEADED
);
95 uint32_t USBHALHost::bulkHeadED() {
96 return ohciwrapp_reg_r(OHCI_REG_BULKHEADED
);
99 uint32_t USBHALHost::interruptHeadED() {
100 return usb_hcca
->IntTable
[0];
103 void USBHALHost::updateBulkHeadED(uint32_t addr
) {
104 ohciwrapp_reg_w(OHCI_REG_BULKHEADED
, addr
);
108 void USBHALHost::updateControlHeadED(uint32_t addr
) {
109 ohciwrapp_reg_w(OHCI_REG_CONTROLHEADED
, addr
);
112 void USBHALHost::updateInterruptHeadED(uint32_t addr
) {
113 usb_hcca
->IntTable
[0] = addr
;
117 void USBHALHost::enableList(ENDPOINT_TYPE type
) {
121 case CONTROL_ENDPOINT
:
122 ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS
, OR_CMD_STATUS_CLF
);
123 wk_data
= (ohciwrapp_reg_r(OHCI_REG_CONTROL
) | OR_CONTROL_CLE
);
124 ohciwrapp_reg_w(OHCI_REG_CONTROL
, wk_data
);
126 case ISOCHRONOUS_ENDPOINT
:
129 ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS
, OR_CMD_STATUS_BLF
);
130 wk_data
= (ohciwrapp_reg_r(OHCI_REG_CONTROL
) | OR_CONTROL_BLE
);
131 ohciwrapp_reg_w(OHCI_REG_CONTROL
, wk_data
);
133 case INTERRUPT_ENDPOINT
:
134 wk_data
= (ohciwrapp_reg_r(OHCI_REG_CONTROL
) | OR_CONTROL_PLE
);
135 ohciwrapp_reg_w(OHCI_REG_CONTROL
, wk_data
);
141 bool USBHALHost::disableList(ENDPOINT_TYPE type
) {
145 case CONTROL_ENDPOINT
:
146 wk_data
= ohciwrapp_reg_r(OHCI_REG_CONTROL
);
147 if(wk_data
& OR_CONTROL_CLE
) {
148 wk_data
&= ~OR_CONTROL_CLE
;
149 ohciwrapp_reg_w(OHCI_REG_CONTROL
, wk_data
);
153 case ISOCHRONOUS_ENDPOINT
:
156 wk_data
= ohciwrapp_reg_r(OHCI_REG_CONTROL
);
157 if(wk_data
& OR_CONTROL_BLE
) {
158 wk_data
&= ~OR_CONTROL_BLE
;
159 ohciwrapp_reg_w(OHCI_REG_CONTROL
, wk_data
);
163 case INTERRUPT_ENDPOINT
:
164 wk_data
= ohciwrapp_reg_r(OHCI_REG_CONTROL
);
165 if(wk_data
& OR_CONTROL_PLE
) {
166 wk_data
&= ~OR_CONTROL_PLE
;
167 ohciwrapp_reg_w(OHCI_REG_CONTROL
, wk_data
);
176 void USBHALHost::memInit() {
177 volatile uint8_t *p_wk_buf
= (uint8_t *)(((uint32_t)usb_buf
+ ALIGNE_MSK
) & ~ALIGNE_MSK
);
179 usb_hcca
= (volatile HCCA
*)p_wk_buf
;
180 usb_edBuf
= (volatile uint8_t *)(p_wk_buf
+ HCCA_SIZE
);
181 usb_tdBuf
= (volatile uint8_t *)(p_wk_buf
+ HCCA_SIZE
+ (MAX_ENDPOINT
*ED_SIZE
));
184 volatile uint8_t * USBHALHost::getED() {
185 for (int i
= 0; i
< MAX_ENDPOINT
; i
++) {
186 if ( !edBufAlloc
[i
] ) {
187 edBufAlloc
[i
] = true;
188 return (volatile uint8_t *)(usb_edBuf
+ i
*ED_SIZE
);
191 perror("Could not allocate ED\r\n");
192 return NULL
; //Could not alloc ED
195 volatile uint8_t * USBHALHost::getTD() {
197 for (i
= 0; i
< MAX_TD
; i
++) {
198 if ( !tdBufAlloc
[i
] ) {
199 tdBufAlloc
[i
] = true;
200 return (volatile uint8_t *)(usb_tdBuf
+ i
*TD_SIZE
);
203 perror("Could not allocate TD\r\n");
204 return NULL
; //Could not alloc TD
208 void USBHALHost::freeED(volatile uint8_t * ed
) {
210 i
= (ed
- usb_edBuf
) / ED_SIZE
;
211 edBufAlloc
[i
] = false;
214 void USBHALHost::freeTD(volatile uint8_t * td
) {
216 i
= (td
- usb_tdBuf
) / TD_SIZE
;
217 tdBufAlloc
[i
] = false;
221 void USBHALHost::resetRootHub() {
222 // Initiate port reset
223 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1
, OR_RH_PORT_PRS
);
225 while (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_PRS
);
227 // ...and clear port reset signal
228 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1
, OR_RH_PORT_PRSC
);
232 void USBHALHost::_usbisr(void) {
234 instHost
->UsbIrqhandler();
238 void USBHALHost::UsbIrqhandler() {
239 uint32_t int_status
= ohciwrapp_reg_r(OHCI_REG_INTERRUPTSTATUS
) & ohciwrapp_reg_r(OHCI_REG_INTERRUPTENABLE
);
242 if (int_status
!= 0) { //Is there something to actually process?
243 // Root hub status change interrupt
244 if (int_status
& OR_INTR_STATUS_RHSC
) {
245 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_CSC
) {
246 if (ohciwrapp_reg_r(OHCI_REG_RHSTATUS
) & OR_RH_STATUS_DRWE
) {
247 // When DRWE is on, Connect Status Change
248 // means a remote wakeup event.
251 //Root device connected
252 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_CCS
) {
254 // wait 150ms to avoid bounce
257 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
258 data
= ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_LSDA
;
259 deviceConnected(0, 1, data
);
262 //Root device disconnected
265 if (!(int_status
& OR_INTR_STATUS_WDH
)) {
266 usb_hcca
->DoneHead
= 0;
269 deviceDisconnected(0, 1, NULL
, usb_hcca
->DoneHead
& 0xFFFFFFFE);
271 if (int_status
& OR_INTR_STATUS_WDH
) {
272 usb_hcca
->DoneHead
= 0;
273 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS
, OR_INTR_STATUS_WDH
);
277 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1
, OR_RH_PORT_CSC
);
279 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1
) & OR_RH_PORT_PRSC
) {
280 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1
, OR_RH_PORT_PRSC
);
282 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS
, OR_INTR_STATUS_RHSC
);
285 // Writeback Done Head interrupt
286 if (int_status
& OR_INTR_STATUS_WDH
) {
287 transferCompleted(usb_hcca
->DoneHead
& 0xFFFFFFFE);
288 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS
, OR_INTR_STATUS_WDH
);