summaryrefslogtreecommitdiff
path: root/tinyusb/host
diff options
context:
space:
mode:
authorhathach <[email protected]>2013-12-13 12:26:37 +0700
committerhathach <[email protected]>2013-12-13 12:26:37 +0700
commit30c8f68930880903fe6210fc8247d9350c630d95 (patch)
tree25338f4d69cd6ddb5403947f39829ae2fc2e5cee /tinyusb/host
parent51b6c6ff41e17560ae054298e68762298d0f5d7c (diff)
able to get connect status change interrupt occured
Diffstat (limited to 'tinyusb/host')
-rw-r--r--tinyusb/host/ohci/ohci.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/tinyusb/host/ohci/ohci.c b/tinyusb/host/ohci/ohci.c
index 61cc9e737..d0257a7ce 100644
--- a/tinyusb/host/ohci/ohci.c
+++ b/tinyusb/host/ohci/ohci.c
@@ -55,6 +55,47 @@
//--------------------------------------------------------------------+
#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE)
+enum {
+ OHCI_CONTROL_FUNCSTATE_RESET = 0,
+ OHCI_CONTROL_FUNCSTATE_RESUME,
+ OHCI_CONTROL_FUNCSTATE_OPERATIONAL,
+ OHCI_CONTROL_FUNCSTATE_SUSPEND
+};
+
+enum {
+ OHCI_CONTROL_CONTROL_BULK_RATIO = 3,
+ OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK = BIT_(2),
+ OHCI_CONTROL_LIST_ISOCHRONOUS_ENABLE_MASK = BIT_(3),
+ OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK = BIT_(4),
+ OHCI_CONTROL_LIST_BULK_ENABLE_MASK = BIT_(5),
+};
+
+enum {
+ OHCI_FMINTERVAL_FI = 0x2EDF, // 7.3.1 nominal (reset) value
+ OHCI_FMINTERVAL_FSMPS = (6*(OHCI_FMINTERVAL_FI-210)) / 7, // 5.4 calculated based on maximum overhead + bit stuffing
+};
+
+enum {
+ OHCI_PERIODIC_START = 0x3E67
+};
+
+enum {
+ OHCI_INT_SCHEDULING_OVERUN_MASK = BIT_(0),
+ OHCI_INT_WRITEBACK_DONEHEAD_MASK = BIT_(1),
+ OHCI_INT_SOF_MASK = BIT_(2),
+ OHCI_INT_RESUME_DETECTED_MASK = BIT_(3),
+ OHCI_INT_UNRECOVERABLE_ERROR_MASK = BIT_(4),
+ OHCI_INT_FRAME_OVERFLOW_MASK = BIT_(5),
+ OHCI_INT_RHPORT_STATUS_CHANGE_MASK = BIT_(6),
+
+ OHCI_INT_OWNERSHIP_CHANGE_MASK = BIT_(30),
+ OHCI_INT_MASTER_ENABLE_MASK = BIT_(31),
+
+ OHCI_INT_ALL_MASK = OHCI_INT_SCHEDULING_OVERUN_MASK | OHCI_INT_WRITEBACK_DONEHEAD_MASK | OHCI_INT_SOF_MASK |
+ OHCI_INT_RESUME_DETECTED_MASK | OHCI_INT_UNRECOVERABLE_ERROR_MASK | OHCI_INT_FRAME_OVERFLOW_MASK |
+ OHCI_INT_RHPORT_STATUS_CHANGE_MASK | OHCI_INT_OWNERSHIP_CHANGE_MASK | OHCI_INT_MASTER_ENABLE_MASK
+};
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
@@ -63,12 +104,39 @@ ohci_data_t ohci_data TUSB_CFG_ATTR_USBRAM;
//--------------------------------------------------------------------+
// USBH-HCD API
//--------------------------------------------------------------------+
+// Initialization according to 5.1.1.4
tusb_error_t hcd_init(void)
{
//------------- Data Structure init -------------//
memclr_(&ohci_data, sizeof(ohci_data_t));
+ ohci_data.control[0].ed.skip = 1;
+ // reset controller
+ OHCI_REG->command_status_bit.controller_reset = 1;
+ while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us
+ // TODO peridoic list build
+ // TODO assign control, bulk head
+
+ //------------- init ohci registers -------------//
+ OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_OPERATIONAL; // move HC to operational state TODO use this to suspend (save power)
+
+ OHCI_REG->frame_interval = (OHCI_FMINTERVAL_FSMPS << 16) | OHCI_FMINTERVAL_FI;
+ OHCI_REG->periodic_start = (OHCI_FMINTERVAL_FI * 9) / 10; // Periodic start is 90% of frame interval
+
+ OHCI_REG->control_head_ed = (uint32_t) &ohci_data.control[0].ed;
+ OHCI_REG->hcca = (uint32_t) &ohci_data.hcca;
+
+ OHCI_REG->control |= OHCI_CONTROL_CONTROL_BULK_RATIO | OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK |
+ 0 /*OHCI_CONTROL_LIST_BULK_ENABLE_MASK*/; // TODO periodic enable
+
+ OHCI_REG->rh_status_bit.local_power_status_change = 1; // set global power for ports
+
+ OHCI_REG->interrupt_disable = OHCI_INT_ALL_MASK;
+ OHCI_REG->interrupt_status = OHCI_REG->interrupt_status; // clear current set bits
+ OHCI_REG->interrupt_enable = OHCI_INT_WRITEBACK_DONEHEAD_MASK | OHCI_INT_RESUME_DETECTED_MASK |
+ OHCI_INT_UNRECOVERABLE_ERROR_MASK | OHCI_INT_FRAME_OVERFLOW_MASK | OHCI_INT_RHPORT_STATUS_CHANGE_MASK |
+ OHCI_INT_MASTER_ENABLE_MASK;
return TUSB_ERROR_NONE;
}
@@ -174,7 +242,25 @@ tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl)
//--------------------------------------------------------------------+
void hcd_isr(uint8_t hostid)
{
+ uint32_t int_status = OHCI_REG->interrupt_status & OHCI_REG->interrupt_enable;
+ OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt
+
+ if (int_status == 0) return;
+ if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK )
+ {
+ // TODO dual port is not yet supported
+ if ( OHCI_REG->rhport_status_bit[0].connect_status_change )
+ {
+ if ( OHCI_REG->rhport_status_bit[0].current_connect_status )
+ {
+ usbh_hcd_rhport_plugged_isr(0);
+ }else
+ {
+ usbh_hcd_rhport_unplugged_isr(0);
+ }
+ }
+ }
}
//--------------------------------------------------------------------+
// HELPER