dwc_otg_hcd.h

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
00003  * $Revision: #52 $
00004  * $Date: 2009/04/21 $
00005  * $Change: 1237472 $
00006  *
00007  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
00008  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
00009  * otherwise expressly agreed to in writing between Synopsys and you.
00010  *
00011  * The Software IS NOT an item of Licensed Software or Licensed Product under
00012  * any End User Software License Agreement or Agreement for Licensed Product
00013  * with Synopsys or any supplement thereto. You are permitted to use and
00014  * redistribute this Software in source and binary forms, with or without
00015  * modification, provided that redistributions of source code must retain this
00016  * notice. You may not view, use, disclose, copy or distribute this file or
00017  * any information contained herein except pursuant to this license grant from
00018  * Synopsys. If you do not agree with this notice, including the disclaimer
00019  * below, then you are not authorized to use the Software.
00020  *
00021  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
00022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
00025  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00027  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00031  * DAMAGE.
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         /* Tasket to do a reset */
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 /* Implemented in dwc_otg_hcd_queue.c */
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                          /* DWC_DEVICE_ONLY */

Generated on Tue May 5 02:22:48 2009 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.4.7