rtt更新

This commit is contained in:
2025-01-18 13:25:25 +08:00
parent c6a7554b51
commit d6009a0773
726 changed files with 103376 additions and 6270 deletions

View File

@@ -1,18 +1,23 @@
# Note
This OHCI is a companion controller of EHCI.
This OHCI is a companion controller of EHCI. But you can use OHCI only without CONFIG_USB_EHCI_WITH_OHCI definition.
**And you need to pay for using OHCI driver**.
## Support Chip List
### AllwinnerTech
- F133
- F133(EHCI + OHCI)
### Nuvoton
- Nuvoton all series
- Nuvoton all series(EHCI + OHCI, OHCI only)
### Artinchip
- d13x, d21x
- d13x, d21x(EHCI + OHCI)
### NXP
- LPC4X/LPC5X(OHCI only)

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "fsl_device_registers.h"
#include "fsl_power.h"
#include "usbh_core.h"
#if defined(CONFIG_USB_EHCI_WITH_OHCI)
#error "lpc does not have ehci"
#endif
void usb_hc_low_level_init(struct usbh_bus *bus)
{
#if ((defined FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT))
SYSMPU_Enable(SYSMPU, 0);
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
NVIC_ClearPendingIRQ(USB0_IRQn);
NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn);
POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB0 Phy */
RESET_PeripheralReset(kUSB0D_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn);
CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbfsSrcPll1, 48000000U);
NVIC_SetPriority(USB0_IRQn, 3);
EnableIRQ(USB0_IRQn);
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
DisableIRQ(USB0_IRQn);
}
void USB0_IRQHandler(void)
{
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler(0);
}

View File

@@ -3,19 +3,59 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_ohci_priv.h"
#include "usb_ehci_priv.h"
#include "usb_hc_ohci.h"
/* Frame Interval / Periodic Start.
*
* At 12Mbps, there are 12000 bit time in each 1Msec frame.
*/
#define OHCI_FMINTERVAL_FI (12000 - 1)
#define OHCI_FMINTERVAL_FSMPS ((6 * (OHCI_FMINTERVAL_FI - 210)) / 7)
#define DEFAULT_FMINTERVAL ((OHCI_FMINTERVAL_FSMPS << OHCI_FMINT_FSMPS_SHIFT) | OHCI_FMINTERVAL_FI)
#define DEFAULT_PERSTART ((OHCI_FMINTERVAL_FI * 9) / 10)
struct ohci_hcd g_ohci_hcd[CONFIG_USBHOST_MAX_BUS];
USB_NOCACHE_RAM_SECTION struct ohci_ed_hw g_ohci_ed_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_OHCI_ED_NUM];
USB_NOCACHE_RAM_SECTION struct ohci_hcca ohci_hcca[CONFIG_USBHOST_MAX_BUS];
int ohci_init(struct usbh_bus *bus)
{
volatile uint32_t timeout = 0;
uint32_t regval;
struct ohci_ed_hw *ed;
memset(&g_ohci_hcd[bus->hcd.hcd_id], 0, sizeof(struct ohci_hcd));
memset(g_ohci_ed_pool[bus->hcd.hcd_id], 0, sizeof(struct ohci_ed_hw) * CONFIG_USB_OHCI_ED_NUM);
for (uint32_t i = 0; i < 32; i++) {
ohci_hcca[bus->hcd.hcd_id].inttbl[i] = 0;
}
for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) {
ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index];
if ((uint32_t)&ed->hw % 32) {
USB_LOG_ERR("struct ohci_ed_hw is not align 32\r\n");
return -USB_ERR_INVAL;
}
for (uint8_t i = 0; i < CONFIG_USB_OHCI_TD_NUM; i++) {
if ((uint32_t)&ed->td_pool[i] % 32) {
USB_LOG_ERR("struct ohci_td_hw is not align 32\r\n");
return -USB_ERR_INVAL;
}
}
}
for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) {
ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index];
ed->waitsem = usb_osal_sem_create(0);
}
USB_LOG_INFO("OHCI hcrevision:0x%02x\r\n", (unsigned int)OHCI_HCOR->hcrevision);
OHCI_HCOR->hcintdis = OHCI_INT_MIE;
OHCI_HCOR->hccontrol = 0;
OHCI_HCOR->hccontrolheaded = 0;
OHCI_HCOR->hcbulkheaded = 0;
OHCI_HCOR->hccmdsts = OHCI_CMDST_HCR;
while (OHCI_HCOR->hccmdsts & OHCI_CMDST_HCR) {
@@ -26,45 +66,39 @@ int ohci_init(struct usbh_bus *bus)
}
}
/* Frame Interval / Periodic Start.
*
* At 12Mbps, there are 12000 bit time in each 1Msec frame.
*/
#define BITS_PER_FRAME 12000
#define FI (BITS_PER_FRAME - 1)
#define FSMPS ((6 * (FI - 210)) / 7)
#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI)
#define DEFAULT_PERSTART (((9 * BITS_PER_FRAME) / 10) - 1)
OHCI_HCOR->hcfminterval = DEFAULT_FMINTERVAL;
OHCI_HCOR->hcperiodicstart = DEFAULT_PERSTART;
OHCI_HCOR->hclsthreshold = 0x628;
/* Put HC in operational state */
regval = OHCI_HCOR->hccontrol;
regval &= ~OHCI_CTRL_HCFS_MASK;
regval |= OHCI_CTRL_HCFS_OPER;
OHCI_HCOR->hccontrol = regval;
/* Set global power in HcRhStatus */
OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP;
/* Set HCCA base address */
OHCI_HCOR->hchcca = 0;
OHCI_HCOR->hccontrolheaded = 0;
OHCI_HCOR->hcbulkheaded = 0;
OHCI_HCOR->hchcca = (uintptr_t)&ohci_hcca[bus->hcd.hcd_id];
/* Clear pending interrupts */
regval = OHCI_HCOR->hcintsts;
OHCI_HCOR->hcintsts = regval;
for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) {
regval = OHCI_HCOR->hcrhportsts[port];
regval |= OHCI_RHPORTST_PPS;
OHCI_HCOR->hcrhportsts[port] = regval;
}
/* Put HC in operational state */
regval = OHCI_HCOR->hccontrol;
regval &= ~OHCI_CTRL_CBSR;
regval &= ~OHCI_CTRL_HCFS_MASK;
regval |= OHCI_CTRL_HCFS_OPER;
regval |= OHCI_CTRL_CBSR;
regval |= OHCI_CTRL_CLE;
OHCI_HCOR->hccontrol = regval;
g_ohci_hcd[bus->hcd.hcd_id].n_ports = OHCI_HCOR->hcrhdescriptora & OHCI_RHDESCA_NDP_MASK;
USB_LOG_INFO("OHCI n_ports:%d\r\n", g_ohci_hcd[bus->hcd.hcd_id].n_ports);
OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_PSM;
OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_NPS;
/* Set global power in HcRhStatus */
OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP;
usb_osal_msleep(20);
/* Enable OHCI interrupts */
OHCI_HCOR->hcinten = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC |
OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
OHCI_HCOR->hcinten = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
return 0;
}
@@ -72,15 +106,25 @@ int ohci_init(struct usbh_bus *bus)
int ohci_deinit(struct usbh_bus *bus)
{
uint32_t regval;
struct ohci_ed_hw *ed;
/* Disable OHCI interrupts */
OHCI_HCOR->hcintdis = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC |
OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
OHCI_HCOR->hcintdis = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE;
for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) {
regval = OHCI_HCOR->hcrhportsts[port];
regval &= ~OHCI_RHPORTST_PPS;
OHCI_HCOR->hcrhportsts[port] = regval;
/* Clear pending interrupts */
regval = OHCI_HCOR->hcintsts;
OHCI_HCOR->hcintsts = regval;
OHCI_HCOR->hcrhsts &= ~OHCI_RHSTATUS_SGP;
regval = OHCI_HCOR->hccontrol;
regval &= ~OHCI_CTRL_HCFS_MASK;
regval |= OHCI_CTRL_HCFS_SUSPEND;
OHCI_HCOR->hccontrol = regval;
for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) {
ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index];
usb_osal_sem_delete(ed->waitsem);
}
return 0;
@@ -97,7 +141,7 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
uint8_t port;
uint32_t temp;
nports = g_ehci_hcd[bus->hcd.hcd_id].n_pcc;
nports = g_ohci_hcd[bus->hcd.hcd_id].n_ports;
port = setup->wIndex;
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
@@ -139,28 +183,46 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
switch (setup->wValue) {
case HUB_PORT_FEATURE_ENABLE:
temp = OHCI_RHPORTST_CCS;
break;
case HUB_PORT_FEATURE_SUSPEND:
temp = OHCI_HCOR->hccontrol;
temp &= ~OHCI_CTRL_HCFS_MASK;
temp |= OHCI_CTRL_HCFS_RESUME;
OHCI_HCOR->hccontrol = temp;
usb_osal_msleep(20);
temp = OHCI_HCOR->hccontrol;
temp &= ~OHCI_CTRL_HCFS_MASK;
temp |= OHCI_CTRL_HCFS_OPER;
OHCI_HCOR->hccontrol = temp;
temp = OHCI_RHPORTST_POCI;
break;
case HUB_PORT_FEATURE_C_SUSPEND:
temp = OHCI_RHPORTST_PSSC;
break;
case HUB_PORT_FEATURE_POWER:
OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_CGP;
temp = OHCI_RHPORTST_LSDA;
break;
case HUB_PORT_FEATURE_C_CONNECTION:
OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_CSC;
temp = OHCI_RHPORTST_CSC;
break;
case HUB_PORT_FEATURE_C_ENABLE:
OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PESC;
temp = OHCI_RHPORTST_PESC;
break;
case HUB_PORT_FEATURE_C_OVER_CURREN:
OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_OCIC;
temp = OHCI_RHPORTST_OCIC;
break;
case HUB_PORT_FEATURE_C_RESET:
OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRSC;
temp = OHCI_RHPORTST_PRSC;
break;
default:
return -USB_ERR_NOTSUPP;
}
OHCI_HCOR->hcrhportsts[port - 1] = temp;
break;
case HUB_REQUEST_SET_FEATURE:
if (!port || port > nports) {
@@ -169,11 +231,17 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
switch (setup->wValue) {
case HUB_PORT_FEATURE_SUSPEND:
temp = OHCI_HCOR->hccontrol;
temp &= ~OHCI_CTRL_HCFS_MASK;
temp |= OHCI_CTRL_HCFS_SUSPEND;
OHCI_HCOR->hccontrol = temp;
break;
case HUB_PORT_FEATURE_POWER:
OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP;
break;
case HUB_PORT_FEATURE_RESET:
OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRS;
OHCI_HCOR->hcrhportsts[port - 1] = OHCI_RHPORTST_PRS;
while (OHCI_HCOR->hcrhportsts[port - 1] & OHCI_RHPORTST_PRS) {
}
@@ -188,7 +256,6 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u
return -USB_ERR_INVAL;
}
temp = OHCI_HCOR->hcrhportsts[port - 1];
memcpy(buf, &temp, 4);
break;
default:
@@ -216,9 +283,9 @@ void OHCI_IRQHandler(uint8_t busid)
bus = &g_usbhost_bus[busid];
usbsts = OHCI_HCOR->hcintsts & OHCI_HCOR->hcinten;
OHCI_HCOR->hcintsts = usbsts;
if (usbsts & OHCI_INT_RHSC) {
OHCI_HCOR->hcintsts = OHCI_INT_RHSC;
for (int port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) {
uint32_t portsc = OHCI_HCOR->hcrhportsts[port];
@@ -236,5 +303,51 @@ void OHCI_IRQHandler(uint8_t busid)
}
}
if (usbsts & OHCI_INT_WDH) {
OHCI_HCOR->hcintsts = OHCI_INT_WDH;
}
}
}
#ifndef CONFIG_USB_EHCI_WITH_OHCI
__WEAK void usb_hc_low_level_init(struct usbh_bus *bus)
{
(void)bus;
}
__WEAK void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
(void)bus;
}
int usb_hc_init(struct usbh_bus *bus)
{
usb_hc_low_level_init(bus);
return ohci_init(bus);
}
int usb_hc_deinit(struct usbh_bus *bus)
{
ohci_deinit(bus);
usb_hc_low_level_deinit(bus);
return 0;
}
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
{
return ohci_roothub_control(bus, setup, buf);
}
int usbh_submit_urb(struct usbh_urb *urb)
{
return ohci_submit_urb(urb);
}
int usbh_kill_urb(struct usbh_urb *urb)
{
return ohci_kill_urb(urb);
}
void USBH_IRQHandler(uint8_t busid)
{
OHCI_IRQHandler(busid);
}
#endif

View File

@@ -1,484 +1,56 @@
/****************************************************************************
* include/nuttx/usb/ohci.h
/*
* Copyright (c) 2024, sakumisu
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_USB_OHCI_H
#define __INCLUDE_NUTTX_USB_OHCI_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Register offsets *********************************************************/
/* Control and status registers (section 7.1) */
#define OHCI_HCIREV_OFFSET 0x0000 /* HcRevision: Version of HCI specification */
#define OHCI_CTRL_OFFSET 0x0004 /* HcControl: HC control */
#define OHCI_CMDST_OFFSET 0x0008 /* HcCommandStatus: HC command status */
#define OHCI_INTST_OFFSET 0x000c /* HcInterruptStatus: HC interrupt status */
#define OHCI_INTEN_OFFSET 0x0010 /* HcInterruptEnable: HC interrupt enable */
#define OHCI_INTDIS_OFFSET 0x0014 /* HcInterruptDisable: HC interrupt disable */
/* Memory pointer registers (section 7.2) */
#define OHCI_HCCA_OFFSET 0x0018 /* HcHCCA: HC communication area */
#define OHCI_PERED_OFFSET 0x001c /* HcPeriodCurrentED: Current isoc or int endpoint desc */
#define OHCI_CTRLHEADED_OFFSET 0x0020 /* HcControlHeadED: First EP desc in the control list */
#define OHCI_CTRLED_OFFSET 0x0024 /* HcControlCurrentED: Current EP desc in the control list */
#define OHCI_BULKHEADED_OFFSET 0x0028 /* HcBulkHeadED: First EP desc in the bulk list */
#define OHCI_BULKED_OFFSET 0x002c /* HcBulkCurrentED: Current EP desc in the bulk list */
#define OHCI_DONEHEAD_OFFSET 0x0030 /* HcDoneHead: Last transfer desc added to DONE queue */
/* Frame counter registers (section 7.3) */
#define OHCI_FMINT_OFFSET 0x0034 /* HcFmInterval: Bit time interval that would not cause overrun */
#define OHCI_FMREM_OFFSET 0x0038 /* HcFmRemaining: Bit time remaining in current frame */
#define OHCI_FMNO_OFFSET 0x003c /* HcFmNumber: Frame number counter */
#define OHCI_PERSTART_OFFSET 0x0040 /* HcPeriodicStart: Time to start processing periodic list */
/* Root hub registers (section 7.4) */
#define OHCI_LSTHRES_OFFSET 0x0044 /* HcLSThreshold: Commit to transfer threshold */
#define OHCI_RHDESCA_OFFSET 0x0048 /* HcRhDescriptorA: Describes root hub (part A) */
#define OHCI_RHDESCB_OFFSET 0x004c /* HcRhDescriptorB: Describes root hub (part B) */
#define OHCI_RHSTATUS_OFFSET 0x0050 /* HcRhStatus: Root hub status */
#define OHCI_MAX_RHPORT 15 /* Maximum number of OHCI root hub ports */
#define OHCI_RHPORTST_OFFSET(n) (0x0054 + (((n) - 1) << 2))
#define OHCI_RHPORTST1_OFFSET 0x0054 /* HcRhPort1Status: Root hub port status 1 */
#define OHCI_RHPORTST2_OFFSET 0x0058 /* HcRhPort2Status: Root hub port status 2 */
#define OHCI_RHPORTST3_OFFSET 0x005c /* HcRhPort3Status: Root hub port status 3 */
#define OHCI_RHPORTST4_OFFSET 0x0060 /* HcRhPort4Status: Root hub port status 4 */
#define OHCI_RHPORTST5_OFFSET 0x0064 /* HcRhPort5Status: Root hub port status 5 */
#define OHCI_RHPORTST6_OFFSET 0x0068 /* HcRhPort6Status: Root hub port status 6 */
#define OHCI_RHPORTST7_OFFSET 0x006c /* HcRhPort7Status: Root hub port status 7 */
#define OHCI_RHPORTST8_OFFSET 0x0070 /* HcRhPort8Status: Root hub port status 8 */
#define OHCI_RHPORTST9_OFFSET 0x0074 /* HcRhPort9Status: Root hub port status 9 */
#define OHCI_RHPORTST10_OFFSET 0x0078 /* HcRhPort10Status: Root hub port status 10 */
#define OHCI_RHPORTST11_OFFSET 0x007c /* HcRhPort11Status: Root hub port status 11 */
#define OHCI_RHPORTST12_OFFSET 0x0080 /* HcRhPort12Status: Root hub port status 12 */
#define OHCI_RHPORTST13_OFFSET 0x0084 /* HcRhPort13Status: Root hub port status 13 */
#define OHCI_RHPORTST14_OFFSET 0x0088 /* HcRhPort14Status: Root hub port status 14 */
#define OHCI_RHPORTST15_OFFSET 0x008c /* HcRhPort15Status: Root hub port status 15 */
/* Register bit definitions *************************************************/
/* HcRevision: Version of HCI specification (7.1.1) */
#define OHCI_HCIREV_SHIFT (0) /* Bits 0-7: HCI spec version (BCD) */
#define OHCI_HCIREV_MASK (0xff << OHCI_HCIREV_SHIFT)
/* HcControl: HC control (7.1.2) */
#define OHCI_CTRL_CBSR (3 << 0) /* Bit 0: Control/bulk service ratio */
#define OHCI_CTRL_PLE (1 << 2) /* Bit 1: Periodic list enable */
#define OHCI_CTRL_IE (1 << 3) /* Bit 2: Isochronous enable */
#define OHCI_CTRL_CLE (1 << 4) /* Bit 3: Control list enable */
#define OHCI_CTRL_BLE (1 << 5) /* Bit 4: Bulk list enable */
#define OHCI_CTRL_HCFS_SHIFT (6) /* Bits 6-7: Host controller functional state */
#define OHCI_CTRL_HCFS_MASK (3 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_RESET (0 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_RESUME (1 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_OPER (2 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_SUSPEND (3 << OHCI_CTRL_HCFS_SHIFT)
#define OHCI_CTRL_IR (1 << 8) /* Bit 8: Interrupt routing */
#define OHCI_CTRL_RWC (1 << 9) /* Bit 9: Remote wakeup connected */
#define OHCI_CTRL_RWE (1 << 10) /* Bit 10: Remote wakeup enable */
/* Bits 11-31: Reserved */
/* HcCommandStatus: HC command status (7.1.3) */
#define OHCI_CMDST_HCR (1 << 0) /* Bit 0: Host controller reset */
#define OHCI_CMDST_CLF (1 << 1) /* Bit 1: Control list filled */
#define OHCI_CMDST_BLF (1 << 2) /* Bit 2: Bulk list filled */
#define OHCI_CMDST_OCR (1 << 3) /* Bit 3: Ownership change request */
/* Bits 4-15: Reserved */
#define OHCI_CMDST_SOC (3 << 16) /* Bit 16: Scheduling overrun count */
/* Bits 17-31: Reserved */
/* HcInterruptStatus: HC interrupt status (7.1.4),
* HcInterruptEnable: HC interrupt enable (7.1.5), and
* HcInterruptDisable: HC interrupt disable (7.1.6)
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _USB_OHCI_PRIV_H
#define _USB_OHCI_PRIV_H
#define OHCI_INT_SO (1 << 0) /* Bit 0: Scheduling overrun */
#define OHCI_INT_WDH (1 << 1) /* Bit 1: Writeback done head */
#define OHCI_INT_SF (1 << 2) /* Bit 2: Start of frame */
#define OHCI_INT_RD (1 << 3) /* Bit 3: Resume detected */
#define OHCI_INT_UE (1 << 4) /* Bit 4: Unrecoverable error */
#define OHCI_INT_FNO (1 << 5) /* Bit 5: Frame number overflow */
#define OHCI_INT_RHSC (1 << 6) /* Bit 6: Root hub status change */
/* Bits 7-29: Reserved */
#define OHCI_INT_OC (1 << 30) /* Bit 30: Ownership change */
#define OHCI_INT_MIE (1 << 31) /* Bit 31: Master interrupt enable
* (Enable/disable only) */
#include "usbh_core.h"
#include "usbh_hub.h"
#include "usb_ohci_reg.h"
/* HcHCCA: HC communication area (7.2.1):
*
* 32-bits aligned to 256 byte boundary.
*/
#define OHCI_HCOR ((struct ohci_hcor *)(uintptr_t)(bus->hcd.reg_base + CONFIG_USB_OHCI_HCOR_OFFSET))
/* HcPeriodCurrentED: Current isoc or int endpoint desc (7.2.2),
* HcControlHeadED: First EP desc in the control list (7.2.3),
* HcControlCurrentED: Current EP desc in the control list (7.2.4),
* HcBulkHeadED: First EP desc in the bulk list (7.2.5),
* HcBulkCurrentED: Current EP desc in the bulk list (7.2.6), and
* HcDoneHead: Last transfer desc added to DONE queue (7.2.7):
*
* All 32-bits aligned to an 8-byte boundary
*/
#define OHCI_PTR2ADDR(x) ((uint32_t)(uintptr_t)(x) & ~0x0F)
#define OHCI_ADDR2ED(x) ((struct ohci_ed_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F))
#define OHCI_ADDR2TD(x) ((struct ohci_td_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F))
/* HcFmInterval: Bit time interval that would not cause overrun (7.3.1) */
#define OHCI_FMINT_FI_SHIFT (0) /* Bits 0-13: Frame interval */
#define OHCI_FMINT_FI_MASK (0x3fff << OHCI_FMINT_FI_SHIFT)
/* Bits 14-15: Reserved */
#define OHCI_FMINT_FSMPS_SHIFT (16) /* Bits 16-30: FS largest packet data */
#define OHCI_FMINT_FSMPS_MASK (0x7fff << OHCI_FMINT_FSMPS_SHIFT)
#define OHCI_FMINT_FIT (1 << 31) /* Bit 31: Frame interval toggle */
/* HcFmRemaining: Bit time remaining in current frame (7.3.2) */
#define OHCI_FMREM_FR_SHIFT (0) /* Bits 0-13: Frame remaining */
#define OHCI_FMREM_FR_MASK (0x3fff << OHCI_FMREM_FR_SHIFT)
/* Bits 16-30: Reserved */
#define OHCI_FMINT_FRT (1 << 31) /* Bit 31: Frame remaining toggle */
/* HcFmNumber: Frame number counter (7.3.3) */
#define OHCI_FMNO_FI_SHIFT (0) /* Bits 0-15: Frame number */
#define OHCI_FMNO_FI_MASK (0xffff << OHCI_FMINT_FI_SHIFT)
/* Bits 16-31: Reserved */
/* HcPeriodicStart: Time to start processing periodic list (7.3.4) */
#define OHCI_PERSTART_SHIFT (0) /* Bits 0-13: Periodic start */
#define OHCI_PERSTART_MASK (0x3fff << OHCI_PERSTART_SHIFT)
/* Bits 14-31: Reserved */
/* HcLSThreshold: Commit to transfer threshold (7.3.5) */
#define OHCI_LSTHRES_SHIFT (0) /* Bits 0-11: LS threshold */
#define OHCI_LSTHRES_MASK (0x0fff << OHCI_PERSTART_SHIFT)
/* Bits 12-31: Reserved */
/* HcRhDescriptorN: Describes root hub (part A) (7.4.1) */
#define OHCI_RHDESCA_NDP_SHIFT (0) /* Bits 0-7: Number downstream ports */
#define OHCI_RHDESCA_NDP_MASK (0xff << OHCI_RHDESCA_NDP_SHIFT)
#define OHCI_RHDESCA_PSM (1 << 8) /* Bit 8: Power switching mode */
#define OHCI_RHDESCA_NPS (1 << 9) /* Bit 9: No power switching */
#define OHCI_RHDESCA_DT (1 << 10) /* Bit 10: Device type */
#define OHCI_RHDESCA_OCPM (1 << 11) /* Bit 11: Over current protection mode */
#define OHCI_RHDESCA_NOCP (1 << 12) /* Bit 12: No over current protection */
/* Bits 13-23: Reserved */
#define OHCI_RHDESCA_POTPGT_SHIFT (24) /* Bits 24-31: Power on to power good time */
#define OHCI_RHDESCA_POTPGT_MASK (0xff << OHCI_RHDESCA_POTPGT_SHIFT)
/* HcRhDescriptorB: Describes root hub (part B) (7.4.2) */
#define OHCI_RHDESCB_DR_SHIFT (0) /* Bits 0-15: Device removable */
#define OHCI_RHDESCB_DR_MASK (0xffff << OHCI_RHDESCB_DR_SHIFT)
# define OHCI_RHDESCB_ATTACHED(n) (1 << (OHCI_RHDESCB_DR_SHIFT+(n)))
#define OHCI_RHDESCB_PPCM_SHIFT (16) /* Bits 16-31: Port power control mask */
#define OHCI_RHDESCB_PPCM_MASK (0xffff << OHCI_RHDESCB_PPCM_SHIFT)
# define OHCI_RHDESCB_POWERED(n) (1 << (OHCI_RHDESCB_DR_SHIFT+(n)))
/* HcRhStatus: Root hub status (7.4.3) */
#define OHCI_RHSTATUS_LPS (1 << 0) /* Bit 0: Local power status (read)*/
#define OHCI_RHSTATUS_CGP (1 << 0) /* Bit 0: Clear global power (write)*/
#define OHCI_RHSTATUS_OCI (1 << 1) /* Bit 1: Over current indicator */
/* Bits 2-14: Reserved */
#define OHCI_RHSTATUS_DRWE (1 << 15) /* Bit 15: Device remote wakeup enable */
#define OHCI_RHSTATUS_LPSC (1 << 16) /* Bit 16: Local power status change (read) */
#define OHCI_RHSTATUS_SGP (1 << 16) /* Bit 16: Set global power (write) */
#define OHCI_RHSTATUS_OCIC (1 << 17) /* Bit 17: Overcurrent indicator change */
/* Bits 18-30: Reserved */
#define OHCI_RHSTATUS_CRWE (1 << 31) /* Bit 31: Clear remote wakeup enable */
/* HcRhPortStatus: Root hub port status (7.4.4) */
#define OHCI_RHPORTST_CCS (1 << 0) /* Bit 0: Current connect status */
#define OHCI_RHPORTST_PES (1 << 1) /* Bit 1: Port enable status */
#define OHCI_RHPORTST_PSS (1 << 2) /* Bit 2: Port suspend status */
#define OHCI_RHPORTST_POCI (1 << 3) /* Bit 3: Port over current indicator */
#define OHCI_RHPORTST_PRS (1 << 4) /* Bit 4: Port reset status */
/* Bits 5-7: Reserved */
#define OHCI_RHPORTST_PPS (1 << 8) /* Bit 8: Port power status */
#define OHCI_RHPORTST_LSDA (1 << 9) /* Bit 9: Low speed device attached */
/* Bits 10-15: Reserved */
#define OHCI_RHPORTST_CSC (1 << 16) /* Bit 16: Connect status change */
#define OHCI_RHPORTST_PESC (1 << 17) /* Bit 17: Port enable status change */
#define OHCI_RHPORTST_PSSC (1 << 18) /* Bit 18: Port suspend status change */
#define OHCI_RHPORTST_OCIC (1 << 19) /* Bit 19: Port over current indicator change */
#define OHCI_RHPORTST_PRSC (1 << 20) /* Bit 20: Port reset status change */
/* Bits 21-31: Reserved */
/* Transfer Descriptors *****************************************************/
/* Endpoint Descriptor Offsets (4.2.1) */
#define ED_CONTROL_OFFSET (0x00) /* ED status/control bits */
#define ED_TAILP_OFFSET (0x04) /* TD Queue Tail Pointer (TailP) */
#define ED_HEADP_OFFSET (0x08) /* TD Queue Head Pointer (HeadP) */
#define ED_NEXTED_OFFSET (0x0c) /* Next Endpoint Descriptor (NextED) */
/* Endpoint Descriptor Bit Definitions (4.2.2) */
#define ED_CONTROL_FA_SHIFT (0) /* Bits 0-6: Function Address */
#define ED_CONTROL_FA_MASK (0x7f << ED_CONTROL_FA_SHIFT)
#define ED_CONTROL_EN_SHIFT (7) /* Bits 7-10: Endpoint number */
#define ED_CONTROL_EN_MASK (15 << ED_CONTROL_EN_SHIFT)
#define ED_CONTROL_D_SHIFT (11) /* Bits 11-12: Direction */
#define ED_CONTROL_D_MASK (3 << ED_CONTROL_D_SHIFT)
# define ED_CONTROL_D_TD1 (0 << ED_CONTROL_D_SHIFT) /* Get direction from TD */
# define ED_CONTROL_D_OUT (1 << ED_CONTROL_D_SHIFT) /* OUT */
# define ED_CONTROL_D_IN (2 << ED_CONTROL_D_SHIFT) /* IN */
# define ED_CONTROL_D_TD2 (3 << ED_CONTROL_D_SHIFT) /* Get direction from TD */
#define ED_CONTROL_S (1 << 13) /* Bit 13: Speed (low) */
#define ED_CONTROL_K (1 << 14) /* Bit 14: Skip */
#define ED_CONTROL_F (1 << 15) /* Bit 15: Format (isochronous) */
#define ED_CONTROL_MPS_SHIFT (16) /* Bits 16-26: Maximum packet size */
#define ED_CONTROL_MPS_MASK (0x7ff << ED_CONTROL_MPS_SHIFT)
#define ED_HEADP_ADDR_SHIFT (0)
#define ED_HEADP_ADDR_MASK 0xfffffff0
#define ED_HEADP_H (1 << 0) /* Bit 0: Halted */
#define ED_HEADP_C (1 << 1) /* Bit 1: Toggle carry */
/* General Transfer Descriptor Offsets (4.3.1) */
#define GTD_STATUS_OFFSET (0x00) /* TD status bits */
#define GTD_CBP_OFFSET (0x04) /* Current Buffer Pointer (CBP) */
#define GTD_NEXTTD_OFFSET (0x08) /* Next TD (NextTD) */
#define GTD_BE_OFFSET (0x0c) /* Buffer End (BE) */
/* General Transfer Descriptor Bit Definitions */
/* Bits 0-17: Reserved */
#define GTD_STATUS_R (1 << 18) /* Bit 18: Buffer rounding */
#define GTD_STATUS_DP_SHIFT (19) /* Bits 19-20: Direction/PID */
#define GTD_STATUS_DP_MASK (3 << GTD_STATUS_DP_SHIFT)
# define GTD_STATUS_DP_SETUP (0 << GTD_STATUS_DP_SHIFT) /* To endpoint */
# define GTD_STATUS_DP_OUT (1 << GTD_STATUS_DP_SHIFT) /* To endpoint */
# define GTD_STATUS_DP_IN (2 << GTD_STATUS_DP_SHIFT) /* From endpoint */
#define GTD_STATUS_DI_SHIFT (21) /* Bits 21-23: Delay input */
#define GTD_STATUS_DI_MASK (7 << GTD_STATUS_DI_SHIFT)
#define GTD_STATUS_T_SHIFT (24) /* Bits 24-25: Data Toggle */
#define GTD_STATUS_T_MASK (3 << GTD_STATUS_T_SHIFT)
# define GTD_STATUS_T_TOGGLE (0 << GTD_STATUS_T_SHIFT)
# define GTD_STATUS_T_DATA0 (2 << GTD_STATUS_T_SHIFT)
# define GTD_STATUS_T_DATA1 (3 << GTD_STATUS_T_SHIFT)
#define GTD_STATUS_EC_SHIFT (26) /* Bits 26-27: Error count */
#define GTD_STATUS_EC_MASK (3 << GTD_STATUS_EC_SHIFT)
#define GTD_STATUS_CC_SHIFT (28) /* Bits 28-31: Condition code */
#define GTD_STATUS_CC_MASK (15 << GTD_STATUS_CC_SHIFT)
/* Isochronous Transfer Descriptor Offsets (4.3.2) */
#define ITD_STATUS_OFFSET (0x00) /* TD status bits */
#define ITD_BP0_OFFSET (0x04) /* Buffer page 0 (BP0) */
#define ITD_NEXTTD_OFFSET (0x08) /* Next TD (NextTD) */
#define ITD_BE_OFFSET (0x0c) /* Buffer End (BE) */
#define ITD_NPSW (8)
#define ITD_PSW0_OFFSET (0x10) /* Offset0/PSW0 */
#define ITD_PSW1_OFFSET (0x12) /* Offset1/PSW1 */
#define ITD_PSW2_OFFSET (0x14) /* Offset2/PSW2 */
#define ITD_PSW3_OFFSET (0x16) /* Offset3/PSW3 */
#define ITD_PSW4_OFFSET (0x18) /* Offset4/PSW4 */
#define ITD_PSW5_OFFSET (0x1a) /* Offset5/PSW5 */
#define ITD_PSW6_OFFSET (0x1c) /* Offset6/PSW6 */
#define ITD_PSW7_OFFSET (0x1e) /* Offset7/PSW7 */
/* Condition codes (Table 4-7) */
#define TD_CC_NOERROR 0x00
#define TD_CC_CRC 0x01
#define TD_CC_BITSTUFFING 0x02
#define TD_CC_DATATOGGLEMISMATCH 0x03
#define TD_CC_STALL 0x04
#define TD_CC_DEVNOTRESPONDING 0x05
#define TD_CC_PIDCHECKFAILURE 0x06
#define TD_CC_UNEXPECTEDPID 0x07
#define TD_CC_DATAOVERRUN 0x08
#define TD_CC_DATAUNDERRUN 0x09
#define TD_CC_BUFFEROVERRUN 0x0c
#define TD_CC_BUFFERUNDERRUN 0x0d
#define TD_CC_NOTACCESSED 0x0f
#define TD_CC_USER 0x10 /* For use by OHCI drivers */
/* Host Controller Communications Area Format (4.4.1) ***********************/
/* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */
#define HCCA_INTTBL_OFFSET (0x00)
#define HCCA_INTTBL_WSIZE (32)
#define HCCA_INTTBL_BSIZE (HCCA_INTTBL_WSIZE * 4)
/* HccaFrameNumber: Current frame number */
#define HCCA_FMNO_OFFSET (0x80)
#define HCCA_FMNO_BSIZE (2)
/* HccaPad1: Zero when frame no. updated */
#define HCCA_PAD1_OFFSET (0x82)
#define HCCA_PAD1_BSIZE (2)
/* HccaDoneHead: When the HC reaches the end of a frame and its deferred
* interrupt register is 0, it writes the current value of its HcDoneHead to
* this location and generates an interrupt.
*
* The LSB of HCCADoneHead may be set to 1 to indicate that an unmasked
* HcInterruptStatus was set when HccaDoneHead was written.
*/
#define HCCA_DONEHEAD_OFFSET (0x84)
#define HCCA_DONEHEAD_BSIZE (4)
#define HCCA_DONEHEAD_MASK 0xfffffffe
#define HCCA_DONEHEAD_INTSTA (1 << 0)
/* 0x88: 116 bytes reserved */
#define HCCA_RESERVED_OFFSET (0x88)
#define HCCA_RESERVED_BSIZE (116)
/****************************************************************************
* Public Types
****************************************************************************/
struct ohci_hcor
{
volatile uint32_t hcrevision; /* 0x00 */
volatile uint32_t hccontrol; /* 0x04 */
volatile uint32_t hccmdsts; /* 0x08 */
volatile uint32_t hcintsts; /* 0x0c */
volatile uint32_t hcinten; /* 0x10 */
volatile uint32_t hcintdis; /* 0x14 */
volatile uint32_t hchcca; /* 0x18 */
volatile uint32_t hcperiodcurrented; /* 0x1c */
volatile uint32_t hccontrolheaded; /* 0x20 */
volatile uint32_t hccontrolcurrented; /* 0x24 */
volatile uint32_t hcbulkheaded; /* 0x28 */
volatile uint32_t hcbulkcurrented; /* 0x2c */
volatile uint32_t hcdonehead; /* 0x30 */
volatile uint32_t hcfminterval; /* 0x34 */
volatile uint32_t hcfmremaining; /* 0x38 */
volatile uint32_t hcfmnumber; /* 0x3c */
volatile uint32_t hcperiodicstart; /* 0x40 */
volatile uint32_t hclsthreshold; /* 0x44 */
volatile uint32_t hcrhdescriptora; /* 0x48 */
volatile uint32_t hcrhdescriptorb; /* 0x4c */
volatile uint32_t hcrhsts; /* 0x50 */
volatile uint32_t hcrhportsts[15]; /* 0x54 */
};
/* Endpoint Descriptor Offsets (4.2.1) */
struct ohci_ed_s
{
volatile uint32_t ctrl; /* ED status/control bits */
volatile uint32_t tailp; /* TD Queue Tail Pointer (TailP) */
volatile uint32_t headp; /* TD Queue Head Pointer (HeadP) */
volatile uint32_t nexted; /* Next Endpoint Descriptor (NextED) */
};
/* General Transfer Descriptor (4.3.1) */
struct ohci_gtd_s
{
volatile uint32_t ctrl; /* TD status/control bits */
volatile uint32_t cbp; /* Current Buffer Pointer (CBP) */
volatile uint32_t nexttd; /* Next TD (NextTD) */
volatile uint32_t be; /* Buffer End (BE) */
};
/* Isochronous Transfer Descriptor Offsets (4.3.2) */
struct ohci_itd_s
{
volatile uint32_t ctrl; /* TD status/control bits */
volatile uint32_t bp0; /* Buffer page 0 (BP0 */
volatile uint32_t nexttd; /* Next TD (NextTD) */
volatile uint32_t be; /* Buffer End (BE) */
volatile uint16_t psw[ITD_NPSW]; /* Offset/PSW */
};
/* Host Controller Communications Area Format (4.4.1) */
struct ohci_hcca_s
{
/* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */
volatile uint32_t inttbl[HCCA_INTTBL_WSIZE];
/* HccaFrameNumber: Current frame number and
* HccaPad1: Zero when frame no. updated
*/
volatile uint16_t fmno;
volatile uint16_t pad1;
/* HccaDoneHead: When the HC reaches the end of a frame and its deferred
* interrupt register is 0, it writes the current value of its HcDoneHead
* to this location and generates an interrupt.
*/
volatile uint32_t donehead;
volatile uint8_t reserved[HCCA_RESERVED_BSIZE];
volatile uint32_t extra;
} __attribute__((aligned(256)));
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#ifndef CONFIG_USB_OHCI_ED_NUM
#define CONFIG_USB_OHCI_ED_NUM CONFIG_USBHOST_PIPE_NUM
#endif
#ifndef CONFIG_USB_OHCI_TD_NUM
#define CONFIG_USB_OHCI_TD_NUM 3
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
struct ohci_ed_hw;
struct ohci_td_hw {
struct ohci_gtd hw;
struct usbh_urb *urb;
uint32_t buf_start;
uint32_t length;
} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
#undef EXTERN
#ifdef __cplusplus
}
#endif
struct ohci_ed_hw {
struct ohci_ed hw;
struct ohci_td_hw td_pool[CONFIG_USB_OHCI_TD_NUM];
uint32_t td_count;
uint8_t ed_type;
usb_osal_sem_t waitsem;
} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */
#endif /* __INCLUDE_NUTTX_USB_OHCI_H */
struct ohci_hcd {
bool ohci_ed_used[CONFIG_USB_OHCI_ED_NUM];
uint8_t n_ports;
};
int ohci_init(struct usbh_bus *bus);
int ohci_deinit(struct usbh_bus *bus);
uint16_t ohci_get_frame_number(struct usbh_bus *bus);
int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf);
int ohci_submit_urb(struct usbh_urb *urb);
int ohci_kill_urb(struct usbh_urb *urb);
void OHCI_IRQHandler(uint8_t busid);
#endif

View File

@@ -0,0 +1,484 @@
/****************************************************************************
* include/nuttx/usb/ohci.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_USB_OHCI_H
#define __INCLUDE_NUTTX_USB_OHCI_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Register offsets *********************************************************/
/* Control and status registers (section 7.1) */
#define OHCI_HCIREV_OFFSET 0x0000 /* HcRevision: Version of HCI specification */
#define OHCI_CTRL_OFFSET 0x0004 /* HcControl: HC control */
#define OHCI_CMDST_OFFSET 0x0008 /* HcCommandStatus: HC command status */
#define OHCI_INTST_OFFSET 0x000c /* HcInterruptStatus: HC interrupt status */
#define OHCI_INTEN_OFFSET 0x0010 /* HcInterruptEnable: HC interrupt enable */
#define OHCI_INTDIS_OFFSET 0x0014 /* HcInterruptDisable: HC interrupt disable */
/* Memory pointer registers (section 7.2) */
#define OHCI_HCCA_OFFSET 0x0018 /* HcHCCA: HC communication area */
#define OHCI_PERED_OFFSET 0x001c /* HcPeriodCurrentED: Current isoc or int endpoint desc */
#define OHCI_CTRLHEADED_OFFSET 0x0020 /* HcControlHeadED: First EP desc in the control list */
#define OHCI_CTRLED_OFFSET 0x0024 /* HcControlCurrentED: Current EP desc in the control list */
#define OHCI_BULKHEADED_OFFSET 0x0028 /* HcBulkHeadED: First EP desc in the bulk list */
#define OHCI_BULKED_OFFSET 0x002c /* HcBulkCurrentED: Current EP desc in the bulk list */
#define OHCI_DONEHEAD_OFFSET 0x0030 /* HcDoneHead: Last transfer desc added to DONE queue */
/* Frame counter registers (section 7.3) */
#define OHCI_FMINT_OFFSET 0x0034 /* HcFmInterval: Bit time interval that would not cause overrun */
#define OHCI_FMREM_OFFSET 0x0038 /* HcFmRemaining: Bit time remaining in current frame */
#define OHCI_FMNO_OFFSET 0x003c /* HcFmNumber: Frame number counter */
#define OHCI_PERSTART_OFFSET 0x0040 /* HcPeriodicStart: Time to start processing periodic list */
/* Root hub registers (section 7.4) */
#define OHCI_LSTHRES_OFFSET 0x0044 /* HcLSThreshold: Commit to transfer threshold */
#define OHCI_RHDESCA_OFFSET 0x0048 /* HcRhDescriptorA: Describes root hub (part A) */
#define OHCI_RHDESCB_OFFSET 0x004c /* HcRhDescriptorB: Describes root hub (part B) */
#define OHCI_RHSTATUS_OFFSET 0x0050 /* HcRhStatus: Root hub status */
#define OHCI_MAX_RHPORT 15 /* Maximum number of OHCI root hub ports */
#define OHCI_RHPORTST_OFFSET(n) (0x0054 + (((n) - 1) << 2))
#define OHCI_RHPORTST1_OFFSET 0x0054 /* HcRhPort1Status: Root hub port status 1 */
#define OHCI_RHPORTST2_OFFSET 0x0058 /* HcRhPort2Status: Root hub port status 2 */
#define OHCI_RHPORTST3_OFFSET 0x005c /* HcRhPort3Status: Root hub port status 3 */
#define OHCI_RHPORTST4_OFFSET 0x0060 /* HcRhPort4Status: Root hub port status 4 */
#define OHCI_RHPORTST5_OFFSET 0x0064 /* HcRhPort5Status: Root hub port status 5 */
#define OHCI_RHPORTST6_OFFSET 0x0068 /* HcRhPort6Status: Root hub port status 6 */
#define OHCI_RHPORTST7_OFFSET 0x006c /* HcRhPort7Status: Root hub port status 7 */
#define OHCI_RHPORTST8_OFFSET 0x0070 /* HcRhPort8Status: Root hub port status 8 */
#define OHCI_RHPORTST9_OFFSET 0x0074 /* HcRhPort9Status: Root hub port status 9 */
#define OHCI_RHPORTST10_OFFSET 0x0078 /* HcRhPort10Status: Root hub port status 10 */
#define OHCI_RHPORTST11_OFFSET 0x007c /* HcRhPort11Status: Root hub port status 11 */
#define OHCI_RHPORTST12_OFFSET 0x0080 /* HcRhPort12Status: Root hub port status 12 */
#define OHCI_RHPORTST13_OFFSET 0x0084 /* HcRhPort13Status: Root hub port status 13 */
#define OHCI_RHPORTST14_OFFSET 0x0088 /* HcRhPort14Status: Root hub port status 14 */
#define OHCI_RHPORTST15_OFFSET 0x008c /* HcRhPort15Status: Root hub port status 15 */
/* Register bit definitions *************************************************/
/* HcRevision: Version of HCI specification (7.1.1) */
#define OHCI_HCIREV_SHIFT (0) /* Bits 0-7: HCI spec version (BCD) */
#define OHCI_HCIREV_MASK (0xff << OHCI_HCIREV_SHIFT)
/* HcControl: HC control (7.1.2) */
#define OHCI_CTRL_CBSR (3 << 0) /* Bit 0: Control/bulk service ratio */
#define OHCI_CTRL_PLE (1 << 2) /* Bit 2: Periodic list enable */
#define OHCI_CTRL_IE (1 << 3) /* Bit 3: Isochronous enable */
#define OHCI_CTRL_CLE (1 << 4) /* Bit 4: Control list enable */
#define OHCI_CTRL_BLE (1 << 5) /* Bit 5: Bulk list enable */
#define OHCI_CTRL_HCFS_SHIFT (6) /* Bits 6-7: Host controller functional state */
#define OHCI_CTRL_HCFS_MASK (3 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_RESET (0 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_RESUME (1 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_OPER (2 << OHCI_CTRL_HCFS_SHIFT)
# define OHCI_CTRL_HCFS_SUSPEND (3 << OHCI_CTRL_HCFS_SHIFT)
#define OHCI_CTRL_IR (1 << 8) /* Bit 8: Interrupt routing */
#define OHCI_CTRL_RWC (1 << 9) /* Bit 9: Remote wakeup connected */
#define OHCI_CTRL_RWE (1 << 10) /* Bit 10: Remote wakeup enable */
/* Bits 11-31: Reserved */
/* HcCommandStatus: HC command status (7.1.3) */
#define OHCI_CMDST_HCR (1 << 0) /* Bit 0: Host controller reset */
#define OHCI_CMDST_CLF (1 << 1) /* Bit 1: Control list filled */
#define OHCI_CMDST_BLF (1 << 2) /* Bit 2: Bulk list filled */
#define OHCI_CMDST_OCR (1 << 3) /* Bit 3: Ownership change request */
/* Bits 4-15: Reserved */
#define OHCI_CMDST_SOC (3 << 16) /* Bit 16: Scheduling overrun count */
/* Bits 17-31: Reserved */
/* HcInterruptStatus: HC interrupt status (7.1.4),
* HcInterruptEnable: HC interrupt enable (7.1.5), and
* HcInterruptDisable: HC interrupt disable (7.1.6)
*/
#define OHCI_INT_SO (1 << 0) /* Bit 0: Scheduling overrun */
#define OHCI_INT_WDH (1 << 1) /* Bit 1: Writeback done head */
#define OHCI_INT_SF (1 << 2) /* Bit 2: Start of frame */
#define OHCI_INT_RD (1 << 3) /* Bit 3: Resume detected */
#define OHCI_INT_UE (1 << 4) /* Bit 4: Unrecoverable error */
#define OHCI_INT_FNO (1 << 5) /* Bit 5: Frame number overflow */
#define OHCI_INT_RHSC (1 << 6) /* Bit 6: Root hub status change */
/* Bits 7-29: Reserved */
#define OHCI_INT_OC (1 << 30) /* Bit 30: Ownership change */
#define OHCI_INT_MIE (1 << 31) /* Bit 31: Master interrupt enable
* (Enable/disable only) */
/* HcHCCA: HC communication area (7.2.1):
*
* 32-bits aligned to 256 byte boundary.
*/
/* HcPeriodCurrentED: Current isoc or int endpoint desc (7.2.2),
* HcControlHeadED: First EP desc in the control list (7.2.3),
* HcControlCurrentED: Current EP desc in the control list (7.2.4),
* HcBulkHeadED: First EP desc in the bulk list (7.2.5),
* HcBulkCurrentED: Current EP desc in the bulk list (7.2.6), and
* HcDoneHead: Last transfer desc added to DONE queue (7.2.7):
*
* All 32-bits aligned to an 8-byte boundary
*/
/* HcFmInterval: Bit time interval that would not cause overrun (7.3.1) */
#define OHCI_FMINT_FI_SHIFT (0) /* Bits 0-13: Frame interval */
#define OHCI_FMINT_FI_MASK (0x3fff << OHCI_FMINT_FI_SHIFT)
/* Bits 14-15: Reserved */
#define OHCI_FMINT_FSMPS_SHIFT (16) /* Bits 16-30: FS largest packet data */
#define OHCI_FMINT_FSMPS_MASK (0x7fff << OHCI_FMINT_FSMPS_SHIFT)
#define OHCI_FMINT_FIT (1 << 31) /* Bit 31: Frame interval toggle */
/* HcFmRemaining: Bit time remaining in current frame (7.3.2) */
#define OHCI_FMREM_FR_SHIFT (0) /* Bits 0-13: Frame remaining */
#define OHCI_FMREM_FR_MASK (0x3fff << OHCI_FMREM_FR_SHIFT)
/* Bits 16-30: Reserved */
#define OHCI_FMINT_FRT (1 << 31) /* Bit 31: Frame remaining toggle */
/* HcFmNumber: Frame number counter (7.3.3) */
#define OHCI_FMNO_FI_SHIFT (0) /* Bits 0-15: Frame number */
#define OHCI_FMNO_FI_MASK (0xffff << OHCI_FMINT_FI_SHIFT)
/* Bits 16-31: Reserved */
/* HcPeriodicStart: Time to start processing periodic list (7.3.4) */
#define OHCI_PERSTART_SHIFT (0) /* Bits 0-13: Periodic start */
#define OHCI_PERSTART_MASK (0x3fff << OHCI_PERSTART_SHIFT)
/* Bits 14-31: Reserved */
/* HcLSThreshold: Commit to transfer threshold (7.3.5) */
#define OHCI_LSTHRES_SHIFT (0) /* Bits 0-11: LS threshold */
#define OHCI_LSTHRES_MASK (0x0fff << OHCI_PERSTART_SHIFT)
/* Bits 12-31: Reserved */
/* HcRhDescriptorN: Describes root hub (part A) (7.4.1) */
#define OHCI_RHDESCA_NDP_SHIFT (0) /* Bits 0-7: Number downstream ports */
#define OHCI_RHDESCA_NDP_MASK (0xff << OHCI_RHDESCA_NDP_SHIFT)
#define OHCI_RHDESCA_PSM (1 << 8) /* Bit 8: Power switching mode */
#define OHCI_RHDESCA_NPS (1 << 9) /* Bit 9: No power switching */
#define OHCI_RHDESCA_DT (1 << 10) /* Bit 10: Device type */
#define OHCI_RHDESCA_OCPM (1 << 11) /* Bit 11: Over current protection mode */
#define OHCI_RHDESCA_NOCP (1 << 12) /* Bit 12: No over current protection */
/* Bits 13-23: Reserved */
#define OHCI_RHDESCA_POTPGT_SHIFT (24) /* Bits 24-31: Power on to power good time */
#define OHCI_RHDESCA_POTPGT_MASK (0xff << OHCI_RHDESCA_POTPGT_SHIFT)
/* HcRhDescriptorB: Describes root hub (part B) (7.4.2) */
#define OHCI_RHDESCB_DR_SHIFT (0) /* Bits 0-15: Device removable */
#define OHCI_RHDESCB_DR_MASK (0xffff << OHCI_RHDESCB_DR_SHIFT)
# define OHCI_RHDESCB_ATTACHED(n) (1 << (OHCI_RHDESCB_DR_SHIFT+(n)))
#define OHCI_RHDESCB_PPCM_SHIFT (16) /* Bits 16-31: Port power control mask */
#define OHCI_RHDESCB_PPCM_MASK (0xffff << OHCI_RHDESCB_PPCM_SHIFT)
# define OHCI_RHDESCB_POWERED(n) (1 << (OHCI_RHDESCB_DR_SHIFT+(n)))
/* HcRhStatus: Root hub status (7.4.3) */
#define OHCI_RHSTATUS_LPS (1 << 0) /* Bit 0: Local power status (read)*/
#define OHCI_RHSTATUS_CGP (1 << 0) /* Bit 0: Clear global power (write)*/
#define OHCI_RHSTATUS_OCI (1 << 1) /* Bit 1: Over current indicator */
/* Bits 2-14: Reserved */
#define OHCI_RHSTATUS_DRWE (1 << 15) /* Bit 15: Device remote wakeup enable */
#define OHCI_RHSTATUS_LPSC (1 << 16) /* Bit 16: Local power status change (read) */
#define OHCI_RHSTATUS_SGP (1 << 16) /* Bit 16: Set global power (write) */
#define OHCI_RHSTATUS_OCIC (1 << 17) /* Bit 17: Overcurrent indicator change */
/* Bits 18-30: Reserved */
#define OHCI_RHSTATUS_CRWE (1 << 31) /* Bit 31: Clear remote wakeup enable */
/* HcRhPortStatus: Root hub port status (7.4.4) */
#define OHCI_RHPORTST_CCS (1 << 0) /* Bit 0: Current connect status */
#define OHCI_RHPORTST_PES (1 << 1) /* Bit 1: Port enable status */
#define OHCI_RHPORTST_PSS (1 << 2) /* Bit 2: Port suspend status */
#define OHCI_RHPORTST_POCI (1 << 3) /* Bit 3: Port over current indicator */
#define OHCI_RHPORTST_PRS (1 << 4) /* Bit 4: Port reset status */
/* Bits 5-7: Reserved */
#define OHCI_RHPORTST_PPS (1 << 8) /* Bit 8: Port power status */
#define OHCI_RHPORTST_LSDA (1 << 9) /* Bit 9: Low speed device attached */
/* Bits 10-15: Reserved */
#define OHCI_RHPORTST_CSC (1 << 16) /* Bit 16: Connect status change */
#define OHCI_RHPORTST_PESC (1 << 17) /* Bit 17: Port enable status change */
#define OHCI_RHPORTST_PSSC (1 << 18) /* Bit 18: Port suspend status change */
#define OHCI_RHPORTST_OCIC (1 << 19) /* Bit 19: Port over current indicator change */
#define OHCI_RHPORTST_PRSC (1 << 20) /* Bit 20: Port reset status change */
/* Bits 21-31: Reserved */
/* Transfer Descriptors *****************************************************/
/* Endpoint Descriptor Offsets (4.2.1) */
#define ED_CONTROL_OFFSET (0x00) /* ED status/control bits */
#define ED_TAILP_OFFSET (0x04) /* TD Queue Tail Pointer (TailP) */
#define ED_HEADP_OFFSET (0x08) /* TD Queue Head Pointer (HeadP) */
#define ED_NEXTED_OFFSET (0x0c) /* Next Endpoint Descriptor (NextED) */
/* Endpoint Descriptor Bit Definitions (4.2.2) */
#define ED_CONTROL_FA_SHIFT (0) /* Bits 0-6: Function Address */
#define ED_CONTROL_FA_MASK (0x7f << ED_CONTROL_FA_SHIFT)
#define ED_CONTROL_EN_SHIFT (7) /* Bits 7-10: Endpoint number */
#define ED_CONTROL_EN_MASK (15 << ED_CONTROL_EN_SHIFT)
#define ED_CONTROL_D_SHIFT (11) /* Bits 11-12: Direction */
#define ED_CONTROL_D_MASK (3 << ED_CONTROL_D_SHIFT)
# define ED_CONTROL_D_TD1 (0 << ED_CONTROL_D_SHIFT) /* Get direction from TD */
# define ED_CONTROL_D_OUT (1 << ED_CONTROL_D_SHIFT) /* OUT */
# define ED_CONTROL_D_IN (2 << ED_CONTROL_D_SHIFT) /* IN */
# define ED_CONTROL_D_TD2 (3 << ED_CONTROL_D_SHIFT) /* Get direction from TD */
#define ED_CONTROL_SPPED_LOW (1 << 13) /* Bit 13: Speed (low) */
#define ED_CONTROL_SKIP (1 << 14) /* Bit 14: Skip */
#define ED_CONTROL_FORMAT_ISO (1 << 15) /* Bit 15: Format (isochronous) */
#define ED_CONTROL_MPS_SHIFT (16) /* Bits 16-26: Maximum packet size */
#define ED_CONTROL_MPS_MASK (0x7ff << ED_CONTROL_MPS_SHIFT)
#define ED_HEADP_ADDR_SHIFT (0)
#define ED_HEADP_ADDR_MASK 0xfffffff0
#define ED_HEADP_H (1 << 0) /* Bit 0: Halted */
#define ED_HEADP_C (1 << 1) /* Bit 1: Toggle carry */
/* General Transfer Descriptor Offsets (4.3.1) */
#define GTD_STATUS_OFFSET (0x00) /* TD status bits */
#define GTD_CBP_OFFSET (0x04) /* Current Buffer Pointer (CBP) */
#define GTD_NEXTTD_OFFSET (0x08) /* Next TD (NextTD) */
#define GTD_BE_OFFSET (0x0c) /* Buffer End (BE) */
/* General Transfer Descriptor Bit Definitions */
/* Bits 0-17: Reserved */
#define GTD_STATUS_R (1 << 18) /* Bit 18: Buffer rounding */
#define GTD_STATUS_DP_SHIFT (19) /* Bits 19-20: Direction/PID */
#define GTD_STATUS_DP_MASK (3 << GTD_STATUS_DP_SHIFT)
# define GTD_STATUS_DP_SETUP (0 << GTD_STATUS_DP_SHIFT) /* To endpoint */
# define GTD_STATUS_DP_OUT (1 << GTD_STATUS_DP_SHIFT) /* To endpoint */
# define GTD_STATUS_DP_IN (2 << GTD_STATUS_DP_SHIFT) /* From endpoint */
#define GTD_STATUS_DI_SHIFT (21) /* Bits 21-23: Delay input */
#define GTD_STATUS_DI_MASK (7 << GTD_STATUS_DI_SHIFT)
#define GTD_STATUS_T_SHIFT (24) /* Bits 24-25: Data Toggle */
#define GTD_STATUS_T_MASK (3 << GTD_STATUS_T_SHIFT)
# define GTD_STATUS_T_TOGGLE (0 << GTD_STATUS_T_SHIFT)
# define GTD_STATUS_T_DATA0 (2 << GTD_STATUS_T_SHIFT)
# define GTD_STATUS_T_DATA1 (3 << GTD_STATUS_T_SHIFT)
#define GTD_STATUS_EC_SHIFT (26) /* Bits 26-27: Error count */
#define GTD_STATUS_EC_MASK (3 << GTD_STATUS_EC_SHIFT)
#define GTD_STATUS_CC_SHIFT (28) /* Bits 28-31: Condition code */
#define GTD_STATUS_CC_MASK (15 << GTD_STATUS_CC_SHIFT)
/* Isochronous Transfer Descriptor Offsets (4.3.2) */
#define ITD_STATUS_OFFSET (0x00) /* TD status bits */
#define ITD_BP0_OFFSET (0x04) /* Buffer page 0 (BP0) */
#define ITD_NEXTTD_OFFSET (0x08) /* Next TD (NextTD) */
#define ITD_BE_OFFSET (0x0c) /* Buffer End (BE) */
#define ITD_NPSW (8)
#define ITD_PSW0_OFFSET (0x10) /* Offset0/PSW0 */
#define ITD_PSW1_OFFSET (0x12) /* Offset1/PSW1 */
#define ITD_PSW2_OFFSET (0x14) /* Offset2/PSW2 */
#define ITD_PSW3_OFFSET (0x16) /* Offset3/PSW3 */
#define ITD_PSW4_OFFSET (0x18) /* Offset4/PSW4 */
#define ITD_PSW5_OFFSET (0x1a) /* Offset5/PSW5 */
#define ITD_PSW6_OFFSET (0x1c) /* Offset6/PSW6 */
#define ITD_PSW7_OFFSET (0x1e) /* Offset7/PSW7 */
/* Condition codes (Table 4-7) */
#define TD_CC_NOERROR 0x00
#define TD_CC_CRC 0x01
#define TD_CC_BITSTUFFING 0x02
#define TD_CC_DATATOGGLEMISMATCH 0x03
#define TD_CC_STALL 0x04
#define TD_CC_DEVNOTRESPONDING 0x05
#define TD_CC_PIDCHECKFAILURE 0x06
#define TD_CC_UNEXPECTEDPID 0x07
#define TD_CC_DATAOVERRUN 0x08
#define TD_CC_DATAUNDERRUN 0x09
#define TD_CC_BUFFEROVERRUN 0x0c
#define TD_CC_BUFFERUNDERRUN 0x0d
#define TD_CC_NOTACCESSED 0x0f
#define TD_CC_USER 0x10 /* For use by OHCI drivers */
/* Host Controller Communications Area Format (4.4.1) ***********************/
/* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */
#define HCCA_INTTBL_OFFSET (0x00)
#define HCCA_INTTBL_WSIZE (32)
#define HCCA_INTTBL_BSIZE (HCCA_INTTBL_WSIZE * 4)
/* HccaFrameNumber: Current frame number */
#define HCCA_FMNO_OFFSET (0x80)
#define HCCA_FMNO_BSIZE (2)
/* HccaPad1: Zero when frame no. updated */
#define HCCA_PAD1_OFFSET (0x82)
#define HCCA_PAD1_BSIZE (2)
/* HccaDoneHead: When the HC reaches the end of a frame and its deferred
* interrupt register is 0, it writes the current value of its HcDoneHead to
* this location and generates an interrupt.
*
* The LSB of HCCADoneHead may be set to 1 to indicate that an unmasked
* HcInterruptStatus was set when HccaDoneHead was written.
*/
#define HCCA_DONEHEAD_OFFSET (0x84)
#define HCCA_DONEHEAD_BSIZE (4)
#define HCCA_DONEHEAD_MASK 0xfffffffe
#define HCCA_DONEHEAD_INTSTA (1 << 0)
/* 0x88: 116 bytes reserved */
#define HCCA_RESERVED_OFFSET (0x88)
#define HCCA_RESERVED_BSIZE (116)
/****************************************************************************
* Public Types
****************************************************************************/
struct ohci_hcor
{
volatile uint32_t hcrevision; /* 0x00 */
volatile uint32_t hccontrol; /* 0x04 */
volatile uint32_t hccmdsts; /* 0x08 */
volatile uint32_t hcintsts; /* 0x0c */
volatile uint32_t hcinten; /* 0x10 */
volatile uint32_t hcintdis; /* 0x14 */
volatile uint32_t hchcca; /* 0x18 */
volatile uint32_t hcperiodcurrented; /* 0x1c */
volatile uint32_t hccontrolheaded; /* 0x20 */
volatile uint32_t hccontrolcurrented; /* 0x24 */
volatile uint32_t hcbulkheaded; /* 0x28 */
volatile uint32_t hcbulkcurrented; /* 0x2c */
volatile uint32_t hcdonehead; /* 0x30 */
volatile uint32_t hcfminterval; /* 0x34 */
volatile uint32_t hcfmremaining; /* 0x38 */
volatile uint32_t hcfmnumber; /* 0x3c */
volatile uint32_t hcperiodicstart; /* 0x40 */
volatile uint32_t hclsthreshold; /* 0x44 */
volatile uint32_t hcrhdescriptora; /* 0x48 */
volatile uint32_t hcrhdescriptorb; /* 0x4c */
volatile uint32_t hcrhsts; /* 0x50 */
volatile uint32_t hcrhportsts[15]; /* 0x54 */
};
/* Endpoint Descriptor Offsets (4.2.1) */
struct ohci_ed
{
volatile uint32_t ctrl; /* ED status/control bits */
volatile uint32_t tailp; /* TD Queue Tail Pointer (TailP) */
volatile uint32_t headp; /* TD Queue Head Pointer (HeadP) */
volatile uint32_t nexted; /* Next Endpoint Descriptor (NextED) */
};
/* General Transfer Descriptor (4.3.1) */
struct ohci_gtd
{
volatile uint32_t ctrl; /* TD status/control bits */
volatile uint32_t cbp; /* Current Buffer Pointer (CBP) */
volatile uint32_t nexttd; /* Next TD (NextTD) */
volatile uint32_t be; /* Buffer End (BE) */
};
/* Isochronous Transfer Descriptor Offsets (4.3.2) */
struct ohci_itd
{
volatile uint32_t ctrl; /* TD status/control bits */
volatile uint32_t bp0; /* Buffer page 0 (BP0 */
volatile uint32_t nexttd; /* Next TD (NextTD) */
volatile uint32_t be; /* Buffer End (BE) */
volatile uint16_t psw[ITD_NPSW]; /* Offset/PSW */
};
/* Host Controller Communications Area Format (4.4.1) */
struct ohci_hcca
{
/* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */
volatile uint32_t inttbl[HCCA_INTTBL_WSIZE];
/* HccaFrameNumber: Current frame number and
* HccaPad1: Zero when frame no. updated
*/
volatile uint16_t fmno;
volatile uint16_t pad1;
/* HccaDoneHead: When the HC reaches the end of a frame and its deferred
* interrupt register is 0, it writes the current value of its HcDoneHead
* to this location and generates an interrupt.
*/
volatile uint32_t donehead;
volatile uint8_t reserved[HCCA_RESERVED_BSIZE];
volatile uint32_t extra;
} __attribute__((aligned(256)));
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_USB_OHCI_H */