00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef DWC_DEVICE_ONLY
00034 #ifndef __DWC_HCD_H__
00035 #define __DWC_HCD_H__
00036
00037 #include <usb.h>
00038 #include "dwc_otg_hcd_if.h"
00039 #include "dwc_otg_core_if.h"
00040 #include "dwc_list.h"
00041 #include "dwc_otg_cil.h"
00042
00055 struct dwc_otg_hcd_pipe_info {
00056 uint8_t dev_addr;
00057 uint8_t ep_num;
00058 uint8_t pipe_type;
00059 uint8_t pipe_dir;
00060 uint16_t mps;
00061 };
00062
00063 struct dwc_otg_hcd_iso_packet_desc {
00064 uint32_t offset;
00065 uint32_t length;
00066 uint32_t actual_length;
00067 uint32_t status;
00068 };
00069
00070 struct dwc_otg_qtd;
00071
00072 struct dwc_otg_hcd_urb {
00073 void *priv;
00074 struct dwc_otg_qtd *qtd;
00075 void *buf;
00076 dwc_dma_t dma;
00077 void *setup_packet;
00078 dwc_dma_t setup_dma;
00079 uint32_t length;
00080 uint32_t actual_length;
00081 uint32_t status;
00082 uint32_t error_count;
00083 uint32_t packet_count;
00084 uint32_t flags;
00085 uint16_t interval;
00086 struct dwc_otg_hcd_pipe_info pipe_info;
00087 struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
00088 };
00089
00090 static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
00091 {
00092 return pipe->ep_num;
00093 }
00094
00095 static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
00096 *pipe)
00097 {
00098 return pipe->pipe_type;
00099 }
00100
00101 static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
00102 {
00103 return pipe->mps;
00104 }
00105
00106 static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
00107 *pipe)
00108 {
00109 return pipe->dev_addr;
00110 }
00111
00112 static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
00113 *pipe)
00114 {
00115 return (pipe->pipe_type == UE_ISOCHRONOUS);
00116 }
00117
00118 static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
00119 *pipe)
00120 {
00121 return (pipe->pipe_type == UE_INTERRUPT);
00122 }
00123
00124 static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
00125 *pipe)
00126 {
00127 return (pipe->pipe_type == UE_BULK);
00128 }
00129
00130 static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
00131 *pipe)
00132 {
00133 return (pipe->pipe_type == UE_CONTROL);
00134 }
00135
00136 static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
00137 {
00138 return (pipe->pipe_dir == UE_DIR_IN);
00139 }
00140
00141 static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
00142 *pipe)
00143 {
00144 return (!dwc_otg_hcd_is_pipe_in(pipe));
00145 }
00146
00147 static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
00148 uint8_t devaddr, uint8_t ep_num,
00149 uint8_t pipe_type, uint8_t pipe_dir,
00150 uint16_t mps)
00151 {
00152 pipe->dev_addr = devaddr;
00153 pipe->ep_num = ep_num;
00154 pipe->pipe_type = pipe_type;
00155 pipe->pipe_dir = pipe_dir;
00156 pipe->mps = mps;
00157 }
00158
00162 typedef enum dwc_otg_control_phase {
00163 DWC_OTG_CONTROL_SETUP,
00164 DWC_OTG_CONTROL_DATA,
00165 DWC_OTG_CONTROL_STATUS
00166 } dwc_otg_control_phase_e;
00167
00169 typedef enum dwc_otg_transaction_type {
00170 DWC_OTG_TRANSACTION_NONE,
00171 DWC_OTG_TRANSACTION_PERIODIC,
00172 DWC_OTG_TRANSACTION_NON_PERIODIC,
00173 DWC_OTG_TRANSACTION_ALL
00174 } dwc_otg_transaction_type_e;
00175
00176 struct dwc_otg_qh;
00177
00191 typedef struct dwc_otg_qtd {
00199 uint8_t data_toggle;
00200
00202 dwc_otg_control_phase_e control_phase;
00203
00206 uint8_t complete_split;
00207
00209 uint32_t ssplit_out_xfer_count;
00210
00215 uint8_t error_count;
00216
00224 uint16_t isoc_frame_index;
00225
00227 uint8_t isoc_split_pos;
00228
00230 uint16_t isoc_split_offset;
00231
00233 struct dwc_otg_hcd_urb *urb;
00234
00235 struct dwc_otg_qh *qh;
00236
00238 DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
00239
00241 uint8_t in_process;
00242
00244 uint8_t n_desc;
00245
00250 uint16_t isoc_frame_index_last;
00251
00252 } dwc_otg_qtd_t;
00253
00254 DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
00255
00261 typedef struct dwc_otg_qh {
00270 uint8_t ep_type;
00271 uint8_t ep_is_in;
00272
00274 uint16_t maxp;
00275
00283 uint8_t dev_speed;
00284
00292 uint8_t data_toggle;
00293
00295 uint8_t ping_state;
00296
00300 struct dwc_otg_qtd_list qtd_list;
00301
00303 struct dwc_hc *channel;
00304
00306 uint8_t do_split;
00307
00312 uint16_t usecs;
00313
00315 uint16_t interval;
00316
00321 uint16_t sched_frame;
00322
00324 uint16_t start_split_frame;
00325
00332 uint8_t *dw_align_buf;
00333 dwc_dma_t dw_align_buf_dma;
00334
00336 dwc_list_link_t qh_list_entry;
00337
00342 dwc_otg_host_dma_desc_t *desc_list;
00343
00345 dwc_dma_t desc_list_dma;
00346
00352 uint32_t *n_bytes;
00353
00355 uint16_t ntd;
00356
00358 uint8_t td_first;
00360 uint8_t td_last;
00361
00364 } dwc_otg_qh_t;
00365
00366 DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
00367
00372 struct dwc_otg_hcd {
00374 dwc_otg_core_if_t *core_if;
00375
00377 struct dwc_otg_hcd_function_ops *fops;
00378
00380 volatile union dwc_otg_hcd_internal_flags {
00381 uint32_t d32;
00382 struct {
00383 unsigned port_connect_status_change:1;
00384 unsigned port_connect_status:1;
00385 unsigned port_reset_change:1;
00386 unsigned port_enable_change:1;
00387 unsigned port_suspend_change:1;
00388 unsigned port_over_current_change:1;
00389 unsigned port_l1_change:1;
00390 unsigned reserved:26;
00391 } b;
00392 } flags;
00393
00399 dwc_list_link_t non_periodic_sched_inactive;
00400
00406 dwc_list_link_t non_periodic_sched_active;
00407
00412 dwc_list_link_t *non_periodic_qh_ptr;
00413
00428 dwc_list_link_t periodic_sched_inactive;
00429
00437 dwc_list_link_t periodic_sched_ready;
00438
00446 dwc_list_link_t periodic_sched_assigned;
00447
00457 dwc_list_link_t periodic_sched_queued;
00458
00464 uint16_t periodic_usecs;
00465
00470 uint16_t frame_number;
00471
00476 struct hc_list free_hc_list;
00483 int periodic_channels;
00484
00488 int non_periodic_channels;
00489
00495 struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
00496
00502 uint8_t *status_buf;
00503
00507 dma_addr_t status_buf_dma;
00508 #define DWC_OTG_HCD_STATUS_BUF_SIZE 64
00509
00515 dwc_timer_t *conn_timer;
00516
00517
00518 dwc_tasklet_t *reset_tasklet;
00519
00520
00521 dwc_spinlock_t *lock;
00522
00526 void *priv;
00527
00528 uint8_t otg_port;
00529
00531 uint32_t *frame_list;
00532
00534 dma_addr_t frame_list_dma;
00535
00536 #ifdef DEBUG
00537 uint32_t frrem_samples;
00538 uint64_t frrem_accum;
00539
00540 uint32_t hfnum_7_samples_a;
00541 uint64_t hfnum_7_frrem_accum_a;
00542 uint32_t hfnum_0_samples_a;
00543 uint64_t hfnum_0_frrem_accum_a;
00544 uint32_t hfnum_other_samples_a;
00545 uint64_t hfnum_other_frrem_accum_a;
00546
00547 uint32_t hfnum_7_samples_b;
00548 uint64_t hfnum_7_frrem_accum_b;
00549 uint32_t hfnum_0_samples_b;
00550 uint64_t hfnum_0_frrem_accum_b;
00551 uint32_t hfnum_other_samples_b;
00552 uint64_t hfnum_other_frrem_accum_b;
00553 #endif
00554 };
00555
00558 extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
00559 * hcd);
00560 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
00561 dwc_otg_transaction_type_e tr_type);
00562
00567 extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00568 extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00569 extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
00570 dwc_otg_hcd);
00571 extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
00572 dwc_otg_hcd);
00573 extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
00574 dwc_otg_hcd);
00575 extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
00576 dwc_otg_hcd);
00577 extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00578 extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
00579 dwc_otg_hcd);
00580 extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00581 extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00582 extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
00583 uint32_t num);
00584 extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00585 extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
00586 dwc_otg_hcd);
00592
00593 extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
00594 dwc_otg_hcd_urb_t * urb);
00595 extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00596 extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00597 extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00598 extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
00599 int sched_csplit);
00600
00602 static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
00603 dwc_otg_qh_t * qh)
00604 {
00605 dwc_otg_hcd_qh_remove(hcd, qh);
00606 dwc_otg_hcd_qh_free(hcd, qh);
00607 }
00608
00611 static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void)
00612 {
00613 return (dwc_otg_qh_t *) dwc_alloc(sizeof(dwc_otg_qh_t));
00614 }
00615
00616 extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb);
00617 extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
00618 extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
00619 dwc_otg_qh_t ** qh);
00620
00623 static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void)
00624 {
00625 return (dwc_otg_qtd_t *) dwc_alloc(sizeof(dwc_otg_qtd_t));
00626 }
00627
00631 static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
00632 {
00633 dwc_free(qtd);
00634 }
00635
00641 static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
00642 dwc_otg_qtd_t * qtd,
00643 dwc_otg_qh_t * qh)
00644 {
00645 uint64_t flags;
00646 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
00647 DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
00648 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
00649 }
00650
00652 static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
00653 dwc_otg_qtd_t * qtd,
00654 dwc_otg_qh_t * qh)
00655 {
00656 dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
00657 dwc_otg_hcd_qtd_free(qtd);
00658 }
00659
00665 extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00666 extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
00667 dwc_hc_t * hc,
00668 dwc_otg_hc_regs_t * hc_regs,
00669 dwc_otg_halt_status_e halt_status);
00670
00671 extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00672 extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00673
00678 dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
00681 #ifdef CONFIG_USB_DWC_OTG_LPM
00682 extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
00683 uint8_t devaddr);
00684 extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
00685 #endif
00686
00688 #define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
00689
00691 #define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
00692
00694 #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
00695 (_qh_ptr_->ep_type == UE_CONTROL))
00696
00698 #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
00699
00701 #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
00702
00708 static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
00709 {
00710 return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
00711 (DWC_HFNUM_MAX_FRNUM >> 1);
00712 }
00713
00719 static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
00720 {
00721 return (frame1 != frame2) &&
00722 (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
00723 (DWC_HFNUM_MAX_FRNUM >> 1));
00724 }
00725
00730 static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
00731 {
00732 return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
00733 }
00734
00735 static inline uint16_t dwc_full_frame_num(uint16_t frame)
00736 {
00737 return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
00738 }
00739
00740 static inline uint16_t dwc_micro_frame_num(uint16_t frame)
00741 {
00742 return frame & 0x7;
00743 }
00744
00745 void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
00746 dwc_otg_hc_regs_t * hc_regs,
00747 dwc_otg_qtd_t * qtd);
00748
00749 #ifdef DEBUG
00750
00759 #define dwc_sample_frrem(_hcd, _qh, _letter) \
00760 { \
00761 hfnum_data_t hfnum; \
00762 dwc_otg_qtd_t *qtd; \
00763 qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
00764 if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
00765 hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
00766 switch (hfnum.b.frnum & 0x7) { \
00767 case 7: \
00768 _hcd->hfnum_7_samples_##_letter++; \
00769 _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
00770 break; \
00771 case 0: \
00772 _hcd->hfnum_0_samples_##_letter++; \
00773 _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
00774 break; \
00775 default: \
00776 _hcd->hfnum_other_samples_##_letter++; \
00777 _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
00778 break; \
00779 } \
00780 } \
00781 }
00782 #else
00783 #define dwc_sample_frrem(_hcd, _qh, _letter)
00784 #endif
00785 #endif
00786 #endif