Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

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: #58 $
00004  * $Date: 2011/09/15 $
00005  * $Change: 1846647 $
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 "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         /* Tasket to do a reset */
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 /* Implemented in dwc_otg_hcd_queue.c */
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 /* DWC_DEVICE_ONLY */

Generated on Thu Oct 27 03:56:37 2011 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.3.9.1