Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
USBHALHost_RZ_A1.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #if defined(TARGET_RZ_A1H) || defined(TARGET_VK_RZ_A1H) 00018 00019 #include "mbed.h" 00020 #include "USBHALHost.h" 00021 #include "dbg.h" 00022 00023 #include "ohci_wrapp_RZ_A1.h" 00024 00025 00026 #define HCCA_SIZE sizeof(HCCA) 00027 #define ED_SIZE sizeof(HCED) 00028 #define TD_SIZE sizeof(HCTD) 00029 00030 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) 00031 #define ALIGNE_MSK (0x0000000F) 00032 00033 static volatile uint8_t usb_buf[TOTAL_SIZE + ALIGNE_MSK]; //16 bytes aligned! 00034 00035 USBHALHost * USBHALHost::instHost; 00036 00037 USBHALHost::USBHALHost() { 00038 instHost = this; 00039 memInit(); 00040 memset((void*)usb_hcca, 0, HCCA_SIZE); 00041 for (int i = 0; i < MAX_ENDPOINT; i++) { 00042 edBufAlloc[i] = false; 00043 } 00044 for (int i = 0; i < MAX_TD; i++) { 00045 tdBufAlloc[i] = false; 00046 } 00047 } 00048 00049 void USBHALHost::init() { 00050 ohciwrapp_init(&_usbisr); 00051 00052 ohciwrapp_reg_w(OHCI_REG_CONTROL, 1); // HARDWARE RESET 00053 ohciwrapp_reg_w(OHCI_REG_CONTROLHEADED, 0); // Initialize Control list head to Zero 00054 ohciwrapp_reg_w(OHCI_REG_BULKHEADED, 0); // Initialize Bulk list head to Zero 00055 00056 // Wait 100 ms before apply reset 00057 wait_ms(100); 00058 00059 // software reset 00060 ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS, OR_CMD_STATUS_HCR); 00061 00062 // Write Fm Interval and Largest Data Packet Counter 00063 ohciwrapp_reg_w(OHCI_REG_FMINTERVAL, DEFAULT_FMINTERVAL); 00064 ohciwrapp_reg_w(OHCI_REG_PERIODICSTART, FI * 90 / 100); 00065 00066 // Put HC in operational state 00067 ohciwrapp_reg_w(OHCI_REG_CONTROL, (ohciwrapp_reg_r(OHCI_REG_CONTROL) & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER); 00068 // Set Global Power 00069 ohciwrapp_reg_w(OHCI_REG_RHSTATUS, OR_RH_STATUS_LPSC); 00070 00071 ohciwrapp_reg_w(OHCI_REG_HCCA, (uint32_t)(usb_hcca)); 00072 00073 // Clear Interrrupt Status 00074 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS, ohciwrapp_reg_r(OHCI_REG_INTERRUPTSTATUS)); 00075 00076 ohciwrapp_reg_w(OHCI_REG_INTERRUPTENABLE, OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC); 00077 00078 // Enable the USB Interrupt 00079 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_CSC); 00080 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRSC); 00081 00082 // Check for any connected devices 00083 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_CCS) { 00084 //Device connected 00085 wait_ms(150); 00086 USB_DBG("Device connected (%08x)\n\r", ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1)); 00087 deviceConnected(0, 1, ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_LSDA); 00088 } 00089 } 00090 00091 uint32_t USBHALHost::controlHeadED() { 00092 return ohciwrapp_reg_r(OHCI_REG_CONTROLHEADED); 00093 } 00094 00095 uint32_t USBHALHost::bulkHeadED() { 00096 return ohciwrapp_reg_r(OHCI_REG_BULKHEADED); 00097 } 00098 00099 uint32_t USBHALHost::interruptHeadED() { 00100 return usb_hcca->IntTable[0]; 00101 } 00102 00103 void USBHALHost::updateBulkHeadED(uint32_t addr) { 00104 ohciwrapp_reg_w(OHCI_REG_BULKHEADED, addr); 00105 } 00106 00107 00108 void USBHALHost::updateControlHeadED(uint32_t addr) { 00109 ohciwrapp_reg_w(OHCI_REG_CONTROLHEADED, addr); 00110 } 00111 00112 void USBHALHost::updateInterruptHeadED(uint32_t addr) { 00113 usb_hcca->IntTable[0] = addr; 00114 } 00115 00116 00117 void USBHALHost::enableList(ENDPOINT_TYPE type) { 00118 uint32_t wk_data; 00119 00120 switch(type) { 00121 case CONTROL_ENDPOINT: 00122 ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS, OR_CMD_STATUS_CLF); 00123 wk_data = (ohciwrapp_reg_r(OHCI_REG_CONTROL) | OR_CONTROL_CLE); 00124 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data); 00125 break; 00126 case ISOCHRONOUS_ENDPOINT: 00127 break; 00128 case BULK_ENDPOINT: 00129 ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS, OR_CMD_STATUS_BLF); 00130 wk_data = (ohciwrapp_reg_r(OHCI_REG_CONTROL) | OR_CONTROL_BLE); 00131 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data); 00132 break; 00133 case INTERRUPT_ENDPOINT: 00134 wk_data = (ohciwrapp_reg_r(OHCI_REG_CONTROL) | OR_CONTROL_PLE); 00135 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data); 00136 break; 00137 } 00138 } 00139 00140 00141 bool USBHALHost::disableList(ENDPOINT_TYPE type) { 00142 uint32_t wk_data; 00143 00144 switch(type) { 00145 case CONTROL_ENDPOINT: 00146 wk_data = ohciwrapp_reg_r(OHCI_REG_CONTROL); 00147 if(wk_data & OR_CONTROL_CLE) { 00148 wk_data &= ~OR_CONTROL_CLE; 00149 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data); 00150 return true; 00151 } 00152 return false; 00153 case ISOCHRONOUS_ENDPOINT: 00154 return false; 00155 case BULK_ENDPOINT: 00156 wk_data = ohciwrapp_reg_r(OHCI_REG_CONTROL); 00157 if(wk_data & OR_CONTROL_BLE) { 00158 wk_data &= ~OR_CONTROL_BLE; 00159 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data); 00160 return true; 00161 } 00162 return false; 00163 case INTERRUPT_ENDPOINT: 00164 wk_data = ohciwrapp_reg_r(OHCI_REG_CONTROL); 00165 if(wk_data & OR_CONTROL_PLE) { 00166 wk_data &= ~OR_CONTROL_PLE; 00167 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data); 00168 return true; 00169 } 00170 return false; 00171 } 00172 return false; 00173 } 00174 00175 00176 void USBHALHost::memInit() { 00177 volatile uint8_t *p_wk_buf = (uint8_t *)(((uint32_t)usb_buf + ALIGNE_MSK) & ~ALIGNE_MSK); 00178 00179 usb_hcca = (volatile HCCA *)p_wk_buf; 00180 usb_edBuf = (volatile uint8_t *)(p_wk_buf + HCCA_SIZE); 00181 usb_tdBuf = (volatile uint8_t *)(p_wk_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE)); 00182 } 00183 00184 volatile uint8_t * USBHALHost::getED() { 00185 for (int i = 0; i < MAX_ENDPOINT; i++) { 00186 if ( !edBufAlloc[i] ) { 00187 edBufAlloc[i] = true; 00188 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE); 00189 } 00190 } 00191 perror("Could not allocate ED\r\n"); 00192 return NULL; //Could not alloc ED 00193 } 00194 00195 volatile uint8_t * USBHALHost::getTD() { 00196 int i; 00197 for (i = 0; i < MAX_TD; i++) { 00198 if ( !tdBufAlloc[i] ) { 00199 tdBufAlloc[i] = true; 00200 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE); 00201 } 00202 } 00203 perror("Could not allocate TD\r\n"); 00204 return NULL; //Could not alloc TD 00205 } 00206 00207 00208 void USBHALHost::freeED(volatile uint8_t * ed) { 00209 int i; 00210 i = (ed - usb_edBuf) / ED_SIZE; 00211 edBufAlloc[i] = false; 00212 } 00213 00214 void USBHALHost::freeTD(volatile uint8_t * td) { 00215 int i; 00216 i = (td - usb_tdBuf) / TD_SIZE; 00217 tdBufAlloc[i] = false; 00218 } 00219 00220 00221 void USBHALHost::resetRootHub() { 00222 // Initiate port reset 00223 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRS); 00224 00225 while (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_PRS); 00226 00227 // ...and clear port reset signal 00228 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRSC); 00229 } 00230 00231 00232 void USBHALHost::_usbisr(void) { 00233 if (instHost) { 00234 instHost->UsbIrqhandler(); 00235 } 00236 } 00237 00238 void USBHALHost::UsbIrqhandler() { 00239 uint32_t int_status = ohciwrapp_reg_r(OHCI_REG_INTERRUPTSTATUS) & ohciwrapp_reg_r(OHCI_REG_INTERRUPTENABLE); 00240 uint32_t data; 00241 00242 if (int_status != 0) { //Is there something to actually process? 00243 // Root hub status change interrupt 00244 if (int_status & OR_INTR_STATUS_RHSC) { 00245 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_CSC) { 00246 if (ohciwrapp_reg_r(OHCI_REG_RHSTATUS) & OR_RH_STATUS_DRWE) { 00247 // When DRWE is on, Connect Status Change 00248 // means a remote wakeup event. 00249 } else { 00250 00251 //Root device connected 00252 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_CCS) { 00253 00254 // wait 150ms to avoid bounce 00255 wait_ms(150); 00256 00257 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed 00258 data = ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_LSDA; 00259 deviceConnected(0, 1, data); 00260 } 00261 00262 //Root device disconnected 00263 else { 00264 deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE); 00265 } 00266 } 00267 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_CSC); 00268 } 00269 if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_PRSC) { 00270 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRSC); 00271 } 00272 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS, OR_INTR_STATUS_RHSC); 00273 } 00274 00275 // Writeback Done Head interrupt 00276 if (int_status & OR_INTR_STATUS_WDH) { 00277 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE); 00278 ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS, OR_INTR_STATUS_WDH); 00279 } 00280 } 00281 } 00282 #endif
Generated on Tue Jul 12 2022 13:16:18 by
