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 "dwc_otg_os_dep.h"
00038 #include "usb.h"
00039 #include "dwc_otg_hcd_if.h"
00040 #include "dwc_otg_core_if.h"
00041 #include "dwc_list.h"
00042 #include "dwc_otg_cil.h"
00043
00056 struct dwc_otg_hcd_pipe_info {
00057 uint8_t dev_addr;
00058 uint8_t ep_num;
00059 uint8_t pipe_type;
00060 uint8_t pipe_dir;
00061 uint16_t mps;
00062 };
00063
00064 struct dwc_otg_hcd_iso_packet_desc {
00065 uint32_t offset;
00066 uint32_t length;
00067 uint32_t actual_length;
00068 uint32_t status;
00069 };
00070
00071 struct dwc_otg_qtd;
00072
00073 struct dwc_otg_hcd_urb {
00074 void *priv;
00075 struct dwc_otg_qtd *qtd;
00076 void *buf;
00077 dwc_dma_t dma;
00078 void *setup_packet;
00079 dwc_dma_t setup_dma;
00080 uint32_t length;
00081 uint32_t actual_length;
00082 uint32_t status;
00083 uint32_t error_count;
00084 uint32_t packet_count;
00085 uint32_t flags;
00086 uint16_t interval;
00087 struct dwc_otg_hcd_pipe_info pipe_info;
00088 struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
00089 };
00090
00091 static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
00092 {
00093 return pipe->ep_num;
00094 }
00095
00096 static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
00097 *pipe)
00098 {
00099 return pipe->pipe_type;
00100 }
00101
00102 static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
00103 {
00104 return pipe->mps;
00105 }
00106
00107 static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
00108 *pipe)
00109 {
00110 return pipe->dev_addr;
00111 }
00112
00113 static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
00114 *pipe)
00115 {
00116 return (pipe->pipe_type == UE_ISOCHRONOUS);
00117 }
00118
00119 static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
00120 *pipe)
00121 {
00122 return (pipe->pipe_type == UE_INTERRUPT);
00123 }
00124
00125 static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
00126 *pipe)
00127 {
00128 return (pipe->pipe_type == UE_BULK);
00129 }
00130
00131 static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
00132 *pipe)
00133 {
00134 return (pipe->pipe_type == UE_CONTROL);
00135 }
00136
00137 static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
00138 {
00139 return (pipe->pipe_dir == UE_DIR_IN);
00140 }
00141
00142 static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
00143 *pipe)
00144 {
00145 return (!dwc_otg_hcd_is_pipe_in(pipe));
00146 }
00147
00148 static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
00149 uint8_t devaddr, uint8_t ep_num,
00150 uint8_t pipe_type, uint8_t pipe_dir,
00151 uint16_t mps)
00152 {
00153 pipe->dev_addr = devaddr;
00154 pipe->ep_num = ep_num;
00155 pipe->pipe_type = pipe_type;
00156 pipe->pipe_dir = pipe_dir;
00157 pipe->mps = mps;
00158 }
00159
00163 typedef enum dwc_otg_control_phase {
00164 DWC_OTG_CONTROL_SETUP,
00165 DWC_OTG_CONTROL_DATA,
00166 DWC_OTG_CONTROL_STATUS
00167 } dwc_otg_control_phase_e;
00168
00170 typedef enum dwc_otg_transaction_type {
00171 DWC_OTG_TRANSACTION_NONE,
00172 DWC_OTG_TRANSACTION_PERIODIC,
00173 DWC_OTG_TRANSACTION_NON_PERIODIC,
00174 DWC_OTG_TRANSACTION_ALL
00175 } dwc_otg_transaction_type_e;
00176
00177 struct dwc_otg_qh;
00178
00192 typedef struct dwc_otg_qtd {
00200 uint8_t data_toggle;
00201
00203 dwc_otg_control_phase_e control_phase;
00204
00207 uint8_t complete_split;
00208
00210 uint32_t ssplit_out_xfer_count;
00211
00216 uint8_t error_count;
00217
00225 uint16_t isoc_frame_index;
00226
00228 uint8_t isoc_split_pos;
00229
00231 uint16_t isoc_split_offset;
00232
00234 struct dwc_otg_hcd_urb *urb;
00235
00236 struct dwc_otg_qh *qh;
00237
00239 DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
00240
00242 uint8_t in_process;
00243
00245 uint8_t n_desc;
00246
00251 uint16_t isoc_frame_index_last;
00252
00253 } dwc_otg_qtd_t;
00254
00255 DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
00256
00262 typedef struct dwc_otg_qh {
00271 uint8_t ep_type;
00272 uint8_t ep_is_in;
00273
00275 uint16_t maxp;
00276
00284 uint8_t dev_speed;
00285
00293 uint8_t data_toggle;
00294
00296 uint8_t ping_state;
00297
00301 struct dwc_otg_qtd_list qtd_list;
00302
00304 struct dwc_hc *channel;
00305
00307 uint8_t do_split;
00308
00313 uint16_t usecs;
00314
00316 uint16_t interval;
00317
00322 uint16_t sched_frame;
00323
00325 uint16_t start_split_frame;
00326
00333 uint8_t *dw_align_buf;
00334 dwc_dma_t dw_align_buf_dma;
00335
00337 dwc_list_link_t qh_list_entry;
00338
00343 dwc_otg_host_dma_desc_t *desc_list;
00344
00346 dwc_dma_t desc_list_dma;
00347
00353 uint32_t *n_bytes;
00354
00356 uint16_t ntd;
00357
00359 uint8_t td_first;
00361 uint8_t td_last;
00362
00365 } dwc_otg_qh_t;
00366
00367 DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
00368
00373 struct dwc_otg_hcd {
00375 struct dwc_otg_device *otg_dev;
00377 dwc_otg_core_if_t *core_if;
00378
00380 struct dwc_otg_hcd_function_ops *fops;
00381
00383 volatile union dwc_otg_hcd_internal_flags {
00384 uint32_t d32;
00385 struct {
00386 unsigned port_connect_status_change:1;
00387 unsigned port_connect_status:1;
00388 unsigned port_reset_change:1;
00389 unsigned port_enable_change:1;
00390 unsigned port_suspend_change:1;
00391 unsigned port_over_current_change:1;
00392 unsigned port_l1_change:1;
00393 unsigned reserved:26;
00394 } b;
00395 } flags;
00396
00402 dwc_list_link_t non_periodic_sched_inactive;
00403
00409 dwc_list_link_t non_periodic_sched_active;
00410
00415 dwc_list_link_t *non_periodic_qh_ptr;
00416
00431 dwc_list_link_t periodic_sched_inactive;
00432
00440 dwc_list_link_t periodic_sched_ready;
00441
00449 dwc_list_link_t periodic_sched_assigned;
00450
00460 dwc_list_link_t periodic_sched_queued;
00461
00467 uint16_t periodic_usecs;
00468
00473 uint16_t frame_number;
00474
00478 uint16_t periodic_qh_count;
00479
00484 struct hc_list free_hc_list;
00491 int periodic_channels;
00492
00496 int non_periodic_channels;
00497
00503 struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
00504
00510 uint8_t *status_buf;
00511
00515 dma_addr_t status_buf_dma;
00516 #define DWC_OTG_HCD_STATUS_BUF_SIZE 64
00517
00523 dwc_timer_t *conn_timer;
00524
00525
00526 dwc_tasklet_t *reset_tasklet;
00527
00528
00529 dwc_spinlock_t *lock;
00530
00534 void *priv;
00535
00536 uint8_t otg_port;
00537
00539 uint32_t *frame_list;
00540
00542 dma_addr_t frame_list_dma;
00543
00544 #ifdef DEBUG
00545 uint32_t frrem_samples;
00546 uint64_t frrem_accum;
00547
00548 uint32_t hfnum_7_samples_a;
00549 uint64_t hfnum_7_frrem_accum_a;
00550 uint32_t hfnum_0_samples_a;
00551 uint64_t hfnum_0_frrem_accum_a;
00552 uint32_t hfnum_other_samples_a;
00553 uint64_t hfnum_other_frrem_accum_a;
00554
00555 uint32_t hfnum_7_samples_b;
00556 uint64_t hfnum_7_frrem_accum_b;
00557 uint32_t hfnum_0_samples_b;
00558 uint64_t hfnum_0_frrem_accum_b;
00559 uint32_t hfnum_other_samples_b;
00560 uint64_t hfnum_other_frrem_accum_b;
00561 #endif
00562 };
00563
00566 extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
00567 * hcd);
00568 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
00569 dwc_otg_transaction_type_e tr_type);
00570
00575 extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00576 extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00577 extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
00578 dwc_otg_hcd);
00579 extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
00580 dwc_otg_hcd);
00581 extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
00582 dwc_otg_hcd);
00583 extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
00584 dwc_otg_hcd);
00585 extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00586 extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
00587 dwc_otg_hcd);
00588 extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00589 extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00590 extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
00591 uint32_t num);
00592 extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
00593 extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
00594 dwc_otg_hcd);
00600
00601 extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
00602 dwc_otg_hcd_urb_t * urb, int atomic_alloc);
00603 extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00604 extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00605 extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00606 extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
00607 int sched_csplit);
00608
00610 static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
00611 dwc_otg_qh_t * qh)
00612 {
00613 dwc_irqflags_t flags;
00614 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
00615 dwc_otg_hcd_qh_remove(hcd, qh);
00616 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
00617 dwc_otg_hcd_qh_free(hcd, qh);
00618 }
00619
00622 static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
00623 {
00624 if (atomic_alloc)
00625 return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
00626 else
00627 return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
00628 }
00629
00630 extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
00631 int atomic_alloc);
00632 extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
00633 extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
00634 dwc_otg_qh_t ** qh, int atomic_alloc);
00635
00638 static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
00639 {
00640 if (atomic_alloc)
00641 return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
00642 else
00643 return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
00644 }
00645
00649 static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
00650 {
00651 DWC_FREE(qtd);
00652 }
00653
00659 static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
00660 dwc_otg_qtd_t * qtd,
00661 dwc_otg_qh_t * qh)
00662 {
00663 DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
00664 }
00665
00669 static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
00670 dwc_otg_qtd_t * qtd,
00671 dwc_otg_qh_t * qh)
00672 {
00673 dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
00674 dwc_otg_hcd_qtd_free(qtd);
00675 }
00676
00682 extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00683 extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
00684 dwc_hc_t * hc,
00685 dwc_otg_hc_regs_t * hc_regs,
00686 dwc_otg_halt_status_e halt_status);
00687
00688 extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00689 extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
00690
00695 dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
00698 #ifdef CONFIG_USB_DWC_OTG_LPM
00699 extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
00700 uint8_t devaddr);
00701 extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
00702 #endif
00703
00705 #define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
00706
00708 #define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
00709
00711 #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
00712 (_qh_ptr_->ep_type == UE_CONTROL))
00713
00715 #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
00716
00718 #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
00719
00725 static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
00726 {
00727 return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
00728 (DWC_HFNUM_MAX_FRNUM >> 1);
00729 }
00730
00736 static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
00737 {
00738 return (frame1 != frame2) &&
00739 (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
00740 (DWC_HFNUM_MAX_FRNUM >> 1));
00741 }
00742
00747 static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
00748 {
00749 return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
00750 }
00751
00752 static inline uint16_t dwc_full_frame_num(uint16_t frame)
00753 {
00754 return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
00755 }
00756
00757 static inline uint16_t dwc_micro_frame_num(uint16_t frame)
00758 {
00759 return frame & 0x7;
00760 }
00761
00762 void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
00763 dwc_otg_hc_regs_t * hc_regs,
00764 dwc_otg_qtd_t * qtd);
00765
00766 #ifdef DEBUG
00767
00776 #define dwc_sample_frrem(_hcd, _qh, _letter) \
00777 { \
00778 hfnum_data_t hfnum; \
00779 dwc_otg_qtd_t *qtd; \
00780 qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
00781 if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
00782 hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
00783 switch (hfnum.b.frnum & 0x7) { \
00784 case 7: \
00785 _hcd->hfnum_7_samples_##_letter++; \
00786 _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
00787 break; \
00788 case 0: \
00789 _hcd->hfnum_0_samples_##_letter++; \
00790 _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
00791 break; \
00792 default: \
00793 _hcd->hfnum_other_samples_##_letter++; \
00794 _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
00795 break; \
00796 } \
00797 } \
00798 }
00799 #else
00800 #define dwc_sample_frrem(_hcd, _qh, _letter)
00801 #endif
00802 #endif
00803 #endif