From 30c8f68930880903fe6210fc8247d9350c630d95 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Dec 2013 12:26:37 +0700 Subject: able to get connect status change interrupt occured --- tinyusb/host/ohci/ohci.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) (limited to 'tinyusb/host/ohci') 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 -- cgit v1.3.1