| 1 | /***************************************************************************** |
| 2 | ** FILE NAME : ifxhcd.h |
| 3 | ** PROJECT : IFX USB sub-system V3 |
| 4 | ** MODULES : IFX USB sub-system Host and Device driver |
| 5 | ** SRC VERSION : 3.2 |
| 6 | ** DATE : 1/Jan/2011 |
| 7 | ** AUTHOR : Chen, Howard |
| 8 | ** DESCRIPTION : This file contains the structures, constants, and interfaces for |
| 9 | ** the Host Contoller Driver (HCD). |
| 10 | ** |
| 11 | ** The Host Controller Driver (HCD) is responsible for translating requests |
| 12 | ** from the USB Driver into the appropriate actions on the IFXUSB controller. |
| 13 | ** It isolates the USBD from the specifics of the controller by providing an |
| 14 | ** API to the USBD. |
| 15 | ** FUNCTIONS : |
| 16 | ** COMPILER : gcc |
| 17 | ** REFERENCE : Synopsys DWC-OTG Driver 2.7 |
| 18 | ** COPYRIGHT : Copyright (c) 2010 |
| 19 | ** LANTIQ DEUTSCHLAND GMBH, |
| 20 | ** Am Campeon 3, 85579 Neubiberg, Germany |
| 21 | ** |
| 22 | ** This program is free software; you can redistribute it and/or modify |
| 23 | ** it under the terms of the GNU General Public License as published by |
| 24 | ** the Free Software Foundation; either version 2 of the License, or |
| 25 | ** (at your option) any later version. |
| 26 | ** |
| 27 | ** Version Control Section ** |
| 28 | ** $Author$ |
| 29 | ** $Date$ |
| 30 | ** $Revisions$ |
| 31 | ** $Log$ Revision history |
| 32 | *****************************************************************************/ |
| 33 | |
| 34 | /* |
| 35 | * This file contains code fragments from Synopsys HS OTG Linux Software Driver. |
| 36 | * For this code the following notice is applicable: |
| 37 | * |
| 38 | * ========================================================================== |
| 39 | * |
| 40 | * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, |
| 41 | * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless |
| 42 | * otherwise expressly agreed to in writing between Synopsys and you. |
| 43 | * |
| 44 | * The Software IS NOT an item of Licensed Software or Licensed Product under |
| 45 | * any End User Software License Agreement or Agreement for Licensed Product |
| 46 | * with Synopsys or any supplement thereto. You are permitted to use and |
| 47 | * redistribute this Software in source and binary forms, with or without |
| 48 | * modification, provided that redistributions of source code must retain this |
| 49 | * notice. You may not view, use, disclose, copy or distribute this file or |
| 50 | * any information contained herein except pursuant to this license grant from |
| 51 | * Synopsys. If you do not agree with this notice, including the disclaimer |
| 52 | * below, then you are not authorized to use the Software. |
| 53 | * |
| 54 | * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS |
| 55 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 57 | * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, |
| 58 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 59 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 60 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| 61 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| 64 | * DAMAGE. |
| 65 | * ========================================================================== */ |
| 66 | |
| 67 | /*! |
| 68 | \defgroup IFXUSB_HCD HCD Interface |
| 69 | \ingroup IFXUSB_DRIVER_V3 |
| 70 | \brief The Host Controller Driver (HCD) is responsible for translating requests |
| 71 | from the USB Driver into the appropriate actions on the IFXUSB controller. |
| 72 | It isolates the USBD from the specifics of the controller by providing an |
| 73 | API to the USBD. |
| 74 | */ |
| 75 | |
| 76 | |
| 77 | /*! |
| 78 | \file ifxhcd.h |
| 79 | \ingroup IFXUSB_DRIVER_V3 |
| 80 | \brief This file contains the structures, constants, and interfaces for |
| 81 | the Host Contoller Driver (HCD). |
| 82 | */ |
| 83 | |
| 84 | #if !defined(__IFXHCD_H__) |
| 85 | #define __IFXHCD_H__ |
| 86 | |
| 87 | |
| 88 | #define __STRICT_ORDER__ |
| 89 | |
| 90 | |
| 91 | #include <linux/list.h> |
| 92 | #include <linux/usb.h> |
| 93 | |
| 94 | #include <linux/usb/hcd.h> |
| 95 | |
| 96 | #include "ifxusb_cif.h" |
| 97 | #include "ifxusb_plat.h" |
| 98 | |
| 99 | |
| 100 | #undef __INNAKSTOP__ |
| 101 | #if !defined(__INNAKSTOP__) && defined(__INNAKSTOP_CTRL__) |
| 102 | #define __INNAKSTOP__ 1 |
| 103 | #endif |
| 104 | #if !defined(__INNAKSTOP__) && defined(__INNAKSTOP_BULK__) |
| 105 | #define __INNAKSTOP__ 1 |
| 106 | #endif |
| 107 | |
| 108 | #undef __PINGSTOP__ |
| 109 | #if !defined(__PINGSTOP__) && defined(__PINGSTOP_CTRL__) |
| 110 | #define __PINGSTOP__ 1 |
| 111 | #endif |
| 112 | #if !defined(__PINGSTOP__) && defined(__PINGSTOP_BULK__) |
| 113 | #define __PINGSTOP__ 1 |
| 114 | #endif |
| 115 | |
| 116 | #undef __NAKSTOP__ |
| 117 | #if defined(__INNAKSTOP__) || defined(__PINGSTOP__) |
| 118 | #define __NAKSTOP__ 1 |
| 119 | #endif |
| 120 | |
| 121 | |
| 122 | /* Phases for control transfers.*/ |
| 123 | typedef enum ifxhcd_epqh_phase { |
| 124 | EPQH_IDLE=0, |
| 125 | EPQH_DISABLING, |
| 126 | // EPQH_COMPLETING, |
| 127 | EPQH_STDBY, |
| 128 | EPQH_READY, |
| 129 | EPQH_ACTIVE |
| 130 | } ifxhcd_epqh_phase_e; |
| 131 | |
| 132 | /* Phases for control transfers.*/ |
| 133 | typedef enum ifxhcd_urbd_phase { |
| 134 | URBD_IDLE=0, |
| 135 | URBD_ACTIVE, |
| 136 | URBD_STARTING, |
| 137 | URBD_STARTED, |
| 138 | URBD_FINISHING, //URB_Complete already scheduled |
| 139 | URBD_COMPLETING, //To URB_Complete, it's normal finish |
| 140 | URBD_DEQUEUEING, //To URB_Complete, it's abnormal finish |
| 141 | } ifxhcd_urbd_phase_e; |
| 142 | |
| 143 | /* Phases for control transfers.*/ |
| 144 | typedef enum ifxhcd_hc_phase { |
| 145 | HC_IDLE=0, |
| 146 | HC_ASSIGNED, |
| 147 | HC_WAITING, |
| 148 | HC_STARTING, |
| 149 | HC_STARTED, |
| 150 | HC_STOPPING, |
| 151 | HC_STOPPED, |
| 152 | } ifxhcd_hc_phase_e; |
| 153 | |
| 154 | /*! |
| 155 | \addtogroup IFXUSB_HCD |
| 156 | */ |
| 157 | /*@{*/ |
| 158 | |
| 159 | /*! \typedef ifxhcd_control_phase_e |
| 160 | \brief Phases for control transfers. |
| 161 | */ |
| 162 | |
| 163 | typedef enum ifxhcd_control_phase { |
| 164 | IFXHCD_CONTROL_SETUP, |
| 165 | IFXHCD_CONTROL_DATA, |
| 166 | IFXHCD_CONTROL_STATUS |
| 167 | } ifxhcd_control_phase_e; |
| 168 | |
| 169 | /*! \typedef ifxhcd_halt_status_e |
| 170 | \brief Reasons for halting a host channel. |
| 171 | */ |
| 172 | typedef enum ifxhcd_halt_status |
| 173 | { |
| 174 | HC_XFER_NO_HALT_STATUS, // Initial |
| 175 | HC_XFER_COMPLETE, // Xact complete without error, upward |
| 176 | HC_XFER_URB_COMPLETE, // Xfer complete without error, short upward |
| 177 | HC_XFER_STALL, // HC stopped abnormally, upward/downward |
| 178 | HC_XFER_XACT_ERR, // HC stopped abnormally, upward |
| 179 | HC_XFER_FRAME_OVERRUN, // HC stopped abnormally, upward |
| 180 | HC_XFER_BABBLE_ERR, // HC stopped abnormally, upward |
| 181 | HC_XFER_AHB_ERR, // HC stopped abnormally, upward |
| 182 | HC_XFER_DATA_TOGGLE_ERR, |
| 183 | HC_XFER_URB_DEQUEUE, // HC stopper manually, downward |
| 184 | HC_XFER_NO_URB, // HC stopper manually, downward |
| 185 | HC_XFER_NO_EPQH, // HC stopper manually, downward |
| 186 | #ifdef __NAKSTOP__ |
| 187 | HC_XFER_NAK, // HC stopped by nak monitor, downward |
| 188 | #endif |
| 189 | #if defined(__INTRNAKRETRY__) || defined(__INTRINCRETRY__) |
| 190 | HC_XFER_INTR_NAK_RETRY, // HC stopped by nak monitor, downward |
| 191 | #endif |
| 192 | } ifxhcd_halt_status_e; |
| 193 | |
| 194 | struct ifxhcd_urbd; |
| 195 | struct ifxhcd_hc ; |
| 196 | struct ifxhcd_epqh ; |
| 197 | struct ifxhcd_hcd; |
| 198 | |
| 199 | /*! typedef ifxhcd_urbd_t |
| 200 | \brief A URB Descriptor (URBD) holds the state of a bulk, control, |
| 201 | interrupt, or isochronous transfer. A single URBD is created for each URB |
| 202 | (of one of these types) submitted to the HCD. The transfer associated with |
| 203 | a URBD may require one or multiple transactions. |
| 204 | |
| 205 | A URBD is linked to a EP Queue Head, which is entered in either the |
| 206 | isoc, intr or non-periodic schedule for execution. When a URBD is chosen for |
| 207 | execution, some or all of its transactions may be executed. After |
| 208 | execution, the state of the URBD is updated. The URBD may be retired if all |
| 209 | its transactions are complete or if an error occurred. Otherwise, it |
| 210 | remains in the schedule so more transactions can be executed later. |
| 211 | */ |
| 212 | typedef struct ifxhcd_urbd { |
| 213 | ifxhcd_urbd_phase_e phase; |
| 214 | struct list_head ql; // Hook for EPQH->urbd_list |
| 215 | struct urb *urb; /*!< URB for this transfer */ |
| 216 | //struct urb { |
| 217 | // struct list_head urb_list; |
| 218 | // struct list_head anchor_list; |
| 219 | // struct usb_anchor * anchor; |
| 220 | // struct usb_device * dev; |
| 221 | // struct usb_host_endpoint * ep; |
| 222 | // unsigned int pipe; |
| 223 | // int status; |
| 224 | // unsigned int transfer_flags; |
| 225 | // void * transfer_buffer; |
| 226 | // dma_addr_t transfer_dma; |
| 227 | // u32 transfer_buffer_length; |
| 228 | // u32 actual_length; |
| 229 | // unsigned char * setup_packet; |
| 230 | // dma_addr_t setup_dma; |
| 231 | // int start_frame; |
| 232 | // int number_of_packets; |
| 233 | // int interval; |
| 234 | // int error_count; |
| 235 | // void * context; |
| 236 | // usb_complete_t complete; |
| 237 | // struct usb_iso_packet_descriptor iso_frame_desc[0]; |
| 238 | //}; |
| 239 | //urb_list For use by current owner of the URB. |
| 240 | //anchor_list membership in the list of an anchor |
| 241 | //anchor to anchor URBs to a common mooring |
| 242 | //dev Identifies the USB device to perform the request. |
| 243 | //ep Points to the endpoint's data structure. Will |
| 244 | // eventually replace pipe. |
| 245 | //pipe Holds endpoint number, direction, type, and more. |
| 246 | // Create these values with the eight macros available; u |
| 247 | // sb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is |
| 248 | // "ctrl", "bulk", "int" or "iso". For example |
| 249 | // usb_sndbulkpipe or usb_rcvintpipe. Endpoint numbers |
| 250 | // range from zero to fifteen. Note that "in" endpoint two |
| 251 | // is a different endpoint (and pipe) from "out" endpoint |
| 252 | // two. The current configuration controls the existence, |
| 253 | // type, and maximum packet size of any given endpoint. |
| 254 | //status This is read in non-iso completion functions to get |
| 255 | // the status of the particular request. ISO requests |
| 256 | // only use it to tell whether the URB was unlinked; |
| 257 | // detailed status for each frame is in the fields of |
| 258 | // the iso_frame-desc. |
| 259 | //transfer_flags A variety of flags may be used to affect how URB |
| 260 | // submission, unlinking, or operation are handled. |
| 261 | // Different kinds of URB can use different flags. |
| 262 | // URB_SHORT_NOT_OK |
| 263 | // URB_ISO_ASAP |
| 264 | // URB_NO_TRANSFER_DMA_MAP |
| 265 | // URB_NO_SETUP_DMA_MAP |
| 266 | // URB_NO_FSBR |
| 267 | // URB_ZERO_PACKET |
| 268 | // URB_NO_INTERRUPT |
| 269 | //transfer_buffer This identifies the buffer to (or from) which the I/O |
| 270 | // request will be performed (unless URB_NO_TRANSFER_DMA_MAP |
| 271 | // is set). This buffer must be suitable for DMA; allocate it |
| 272 | // with kmalloc or equivalent. For transfers to "in" |
| 273 | // endpoints, contents of this buffer will be modified. This |
| 274 | // buffer is used for the data stage of control transfers. |
| 275 | //transfer_dma When transfer_flags includes URB_NO_TRANSFER_DMA_MAP, the |
| 276 | // device driver is saying that it provided this DMA address, |
| 277 | // which the host controller driver should use in preference |
| 278 | // to the transfer_buffer. |
| 279 | //transfer_buffer_length How big is transfer_buffer. The transfer may be broken |
| 280 | // up into chunks according to the current maximum packet size |
| 281 | // for the endpoint, which is a function of the configuration |
| 282 | // and is encoded in the pipe. When the length is zero, neither |
| 283 | // transfer_buffer nor transfer_dma is used. |
| 284 | //actual_length This is read in non-iso completion functions, and it tells |
| 285 | // how many bytes (out of transfer_buffer_length) were transferred. |
| 286 | // It will normally be the same as requested, unless either an error |
| 287 | // was reported or a short read was performed. The URB_SHORT_NOT_OK |
| 288 | // transfer flag may be used to make such short reads be reported |
| 289 | // as errors. |
| 290 | //setup_packet Only used for control transfers, this points to eight bytes of |
| 291 | // setup data. Control transfers always start by sending this data |
| 292 | // to the device. Then transfer_buffer is read or written, if needed. |
| 293 | //setup_dma For control transfers with URB_NO_SETUP_DMA_MAP set, the device |
| 294 | // driver has provided this DMA address for the setup packet. The |
| 295 | // host controller driver should use this in preference to setup_packet. |
| 296 | //start_frame Returns the initial frame for isochronous transfers. |
| 297 | //number_of_packets Lists the number of ISO transfer buffers. |
| 298 | //interval Specifies the polling interval for interrupt or isochronous transfers. |
| 299 | // The units are frames (milliseconds) for for full and low speed devices, |
| 300 | // and microframes (1/8 millisecond) for highspeed ones. |
| 301 | //error_count Returns the number of ISO transfers that reported errors. |
| 302 | //context For use in completion functions. This normally points to request-specific |
| 303 | // driver context. |
| 304 | //complete Completion handler. This URB is passed as the parameter to the completion |
| 305 | // function. The completion function may then do what it likes with the URB, |
| 306 | // including resubmitting or freeing it. |
| 307 | //iso_frame_desc[0] Used to provide arrays of ISO transfer buffers and to collect the transfer |
| 308 | // status for each buffer. |
| 309 | |
| 310 | struct ifxhcd_epqh *epqh; |
| 311 | // Actual data portion, not SETUP or STATUS in case of CTRL XFER |
| 312 | // DMA adjusted |
| 313 | uint8_t *setup_buff; /*!< Pointer to the entire transfer buffer. (CPU accessable)*/ |
| 314 | uint8_t *xfer_buff; /*!< Pointer to the entire transfer buffer. (CPU accessable)*/ |
| 315 | uint32_t xfer_len; /*!< Total number of bytes to transfer in this xfer. */ |
| 316 | |
| 317 | #if defined(__UNALIGNED_BUF_ADJ__) |
| 318 | // uint8_t using_aligned_setup; |
| 319 | uint8_t *aligned_setup; |
| 320 | // uint8_t using_aligned_buf; |
| 321 | uint8_t *aligned_buf; |
| 322 | unsigned aligned_buf_len : 19; |
| 323 | #endif |
| 324 | #if defined(__UNALIGNED_BUF_ADJ__) || defined(__UNALIGNED_BUF_CHK__) |
| 325 | unsigned aligned_checked : 1; |
| 326 | #endif |
| 327 | unsigned is_in :1; |
| 328 | #ifndef __STRICT_ORDER__ |
| 329 | struct tasklet_struct complete_urb_sub; |
| 330 | #endif |
| 331 | |
| 332 | // For ALL XFER |
| 333 | uint8_t error_count; /*!< Holds the number of bus errors that have occurred for a transaction |
| 334 | within this transfer. |
| 335 | */ |
| 336 | // For ISOC XFER only |
| 337 | #ifdef __EN_ISOC__ |
| 338 | int isoc_frame_index; /*!< Index of the next frame descriptor for an isochronous transfer. A |
| 339 | frame descriptor describes the buffer position and length of the |
| 340 | data to be transferred in the next scheduled (micro)frame of an |
| 341 | isochronous transfer. It also holds status for that transaction. |
| 342 | The frame index starts at 0. |
| 343 | */ |
| 344 | #endif |
| 345 | int status; |
| 346 | } ifxhcd_urbd_t; |
| 347 | |
| 348 | /*! typedef ifxhcd_epqh_t |
| 349 | \brief A EP Queue Head (EPQH) holds the static characteristics of an endpoint and |
| 350 | maintains a list of transfers (URBDs) for that endpoint. A EPQH structure may |
| 351 | be entered in either the isoc, intr or non-periodic schedule. |
| 352 | */ |
| 353 | |
| 354 | typedef struct ifxhcd_epqh { |
| 355 | struct ifxhcd_hcd *ifxhcd; |
| 356 | struct usb_host_endpoint *sysep; |
| 357 | uint8_t devno; |
| 358 | |
| 359 | ifxhcd_epqh_phase_e phase; |
| 360 | struct list_head ql_all; |
| 361 | struct list_head ql; // Hook for EP Queues |
| 362 | struct list_head urbd_list; /*!< List of URBDs for this EPQH. */ |
| 363 | #ifdef __STRICT_ORDER__ |
| 364 | struct list_head release_list; |
| 365 | struct tasklet_struct complete_urb_sub; |
| 366 | #endif |
| 367 | struct ifxhcd_hc *hc; /*!< Host channel currently processing transfers for this EPQH. */ |
| 368 | struct ifxhcd_urbd *urbd; /*!< URBD currently assigned to a host channel for this EPQH. */ |
| 369 | uint8_t ep_type; /*!< Endpoint type. One of the following values: |
| 370 | - IFXUSB_EP_TYPE_CTRL |
| 371 | - IFXUSB_EP_TYPE_ISOC |
| 372 | - IFXUSB_EP_TYPE_BULK |
| 373 | - IFXUSB_EP_TYPE_INTR |
| 374 | */ |
| 375 | uint16_t mps; /*!< wMaxPacketSize Field of Endpoint Descriptor. */ |
| 376 | #ifdef __EPQD_DESTROY_TIMEOUT__ |
| 377 | struct timer_list destroy_timer; |
| 378 | #endif |
| 379 | |
| 380 | unsigned need_split : 1 ; |
| 381 | unsigned do_ping : 1 ; /*!< Set to 1 to indicate that a PING request should be issued on this |
| 382 | channel. If 0, process normally. |
| 383 | */ |
| 384 | unsigned pause : 1; |
| 385 | unsigned period_do : 1; |
| 386 | uint16_t interval; /*!< Interval between transfers in (micro)frames. (for INTR)*/ |
| 387 | uint16_t period_counter; /*!< Interval between transfers in (micro)frames. */ |
| 388 | |
| 389 | #ifdef __EN_ISOC__ |
| 390 | struct tasklet_struct tasklet_next_isoc; |
| 391 | uint8_t isoc_now; |
| 392 | uint32_t isoc_start_frame; |
| 393 | // For SPLITed ISOC XFER only |
| 394 | #ifdef __EN_ISOC_SPLIT__ |
| 395 | uint8_t isoc_split_pos; /*!< Position of the ISOC split on full/low speed */ |
| 396 | uint16_t isoc_split_offset;/*!< Position of the ISOC split in the buffer for the current frame */ |
| 397 | #endif |
| 398 | #endif |
| 399 | spinlock_t urbd_list_lock; |
| 400 | int urbd_count; |
| 401 | } ifxhcd_epqh_t; |
| 402 | |
| 403 | |
| 404 | /*! typedef ifxhcd_hc_t |
| 405 | \brief Host channel descriptor. This structure represents the state of a single |
| 406 | host channel when acting in host mode. It contains the data items needed to |
| 407 | transfer packets to an endpoint via a host channel. |
| 408 | */ |
| 409 | typedef struct ifxhcd_hc |
| 410 | { |
| 411 | struct ifxhcd_epqh *epqh ; /*!< EP Queue Head for the transfer being processed by this channel. */ |
| 412 | uint8_t hc_num ; /*!< Host channel number used for register address lookup */ |
| 413 | uint8_t *xfer_buff ; /*!< Pointer to the entire transfer buffer. */ |
| 414 | uint32_t xfer_count ; /*!< Number of bytes transferred so far. The offset of the begin of the buf */ |
| 415 | uint32_t xfer_len ; /*!< Total number of bytes to transfer in this xfer. */ |
| 416 | uint16_t start_pkt_count ; /*!< Packet count at start of transfer. Used to calculate the actual xfer size*/ |
| 417 | ifxhcd_halt_status_e halt_status; /*!< Reason for halting the host channel. */ |
| 418 | ifxhcd_hc_phase_e phase; |
| 419 | |
| 420 | unsigned dev_addr : 7; /*!< Device to access */ |
| 421 | unsigned ep_num : 4; /*!< EP to access */ |
| 422 | unsigned is_in : 1; /*!< EP direction. 0: OUT, 1: IN */ |
| 423 | unsigned speed : 2; /*!< EP speed. */ |
| 424 | unsigned ep_type : 2; /*!< Endpoint type. */ |
| 425 | unsigned mps :11; /*!< Max packet size in bytes */ |
| 426 | unsigned data_pid_start : 2; /*!< PID for initial transaction. */ |
| 427 | unsigned short_rw : 1; /*!< When Tx, means termination needed. |
| 428 | When Rx, indicate Short Read */ |
| 429 | /* Split settings for the host channel */ |
| 430 | unsigned split : 2; /*!< Split: 0-Non Split, 1-SSPLIT, 2&3 CSPLIT */ |
| 431 | |
| 432 | unsigned sof_delay :16; |
| 433 | unsigned erron : 1; |
| 434 | |
| 435 | #ifdef __NAKSTOP__ |
| 436 | unsigned stop_on : 1; |
| 437 | // unsigned wait_for_sof_quick : 1; |
| 438 | #endif |
| 439 | |
| 440 | ifxhcd_control_phase_e control_phase; /*!< Current phase for control transfers (Setup, Data, or Status). */ |
| 441 | uint32_t ssplit_out_xfer_count; /*!< How many bytes transferred during SSPLIT OUT */ |
| 442 | #ifdef __DEBUG__ |
| 443 | uint32_t start_hcchar_val; |
| 444 | #endif |
| 445 | uint32_t hcchar; |
| 446 | |
| 447 | /* Split settings for the host channel */ |
| 448 | uint8_t hub_addr; /*!< Address of high speed hub */ |
| 449 | uint8_t port_addr; /*!< Port of the low/full speed device */ |
| 450 | #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__) |
| 451 | uint8_t isoc_xact_pos; /*!< Split transaction position */ |
| 452 | #endif |
| 453 | } ifxhcd_hc_t; |
| 454 | |
| 455 | |
| 456 | /*! typedef ifxhcd_hcd_t |
| 457 | \brief This structure holds the state of the HCD, including the non-periodic and |
| 458 | periodic schedules. |
| 459 | */ |
| 460 | typedef struct ifxhcd_hcd |
| 461 | { |
| 462 | struct device *dev; |
| 463 | struct hc_driver hc_driver; |
| 464 | ifxusb_core_if_t core_if; /*!< Pointer to the core interface structure. */ |
| 465 | struct usb_hcd *syshcd; |
| 466 | |
| 467 | volatile union |
| 468 | { |
| 469 | uint32_t d32; |
| 470 | struct |
| 471 | { |
| 472 | unsigned port_connect_status_change : 1; |
| 473 | unsigned port_connect_status : 1; |
| 474 | unsigned port_reset_change : 1; |
| 475 | unsigned port_enable_change : 1; |
| 476 | unsigned port_suspend_change : 1; |
| 477 | unsigned port_over_current_change : 1; |
| 478 | unsigned reserved : 27; |
| 479 | } b; |
| 480 | } flags; /*!< Internal HCD Flags */ |
| 481 | |
| 482 | struct ifxhcd_hc ifxhc[MAX_EPS_CHANNELS]; /*!< Array of pointers to the host channel descriptors. Allows accessing |
| 483 | a host channel descriptor given the host channel number. This is |
| 484 | useful in interrupt handlers. |
| 485 | */ |
| 486 | uint8_t *status_buf; /*!< Buffer to use for any data received during the status phase of a |
| 487 | control transfer. Normally no data is transferred during the status |
| 488 | phase. This buffer is used as a bit bucket. |
| 489 | */ |
| 490 | #define IFXHCD_STATUS_BUF_SIZE 64 /*!< buffer size of status phase in CTRL xfer */ |
| 491 | |
| 492 | struct list_head epqh_list_all; |
| 493 | struct list_head epqh_list_np; |
| 494 | struct list_head epqh_list_intr; |
| 495 | #ifdef __EN_ISOC__ |
| 496 | struct list_head epqh_list_isoc; |
| 497 | #endif |
| 498 | |
| 499 | uint32_t lastframe; |
| 500 | |
| 501 | uint16_t pkt_remaining; |
| 502 | uint16_t pkt_remaining_reload; |
| 503 | uint16_t pkt_remaining_reload_hs; |
| 504 | uint16_t pkt_remaining_reload_fs; |
| 505 | uint16_t pkt_remaining_reload_ls; |
| 506 | #define PKT_REMAINING_RELOAD_HS 88 |
| 507 | #define PKT_REMAINING_RELOAD_FS 10 |
| 508 | #define PKT_REMAINING_RELOAD_LS 20 |
| 509 | #ifdef __EN_ISOC__ |
| 510 | uint8_t isoc_ep_count; |
| 511 | #endif |
| 512 | |
| 513 | spinlock_t epqh_list_lock; |
| 514 | spinlock_t epqh_list_all_lock; |
| 515 | |
| 516 | struct timer_list host_probe_timer; |
| 517 | struct timer_list autoprobe_timer; |
| 518 | |
| 519 | unsigned power_status; |
| 520 | int probe_sec; |
| 521 | int autoprobe_sec; |
| 522 | #ifdef __DYN_SOF_INTR__ |
| 523 | uint32_t dyn_sof_count; |
| 524 | #define DYN_SOF_COUNT_DEF 40000 |
| 525 | #endif |
| 526 | struct tasklet_struct tasklet_select_eps; /*!< Tasket to do a reset */ |
| 527 | struct tasklet_struct tasklet_free_epqh_list ; /*!< Tasket to do a reset */ |
| 528 | unsigned disconnecting : 1 ; |
| 529 | |
| 530 | uint8_t pkt_count_limit_bo; |
| 531 | uint8_t pkt_count_limit_bi; |
| 532 | } ifxhcd_hcd_t; |
| 533 | |
| 534 | /* Gets the ifxhcd_hcd from a struct usb_hcd */ |
| 535 | static inline ifxhcd_hcd_t *syshcd_to_ifxhcd(struct usb_hcd *syshcd) |
| 536 | { |
| 537 | return (ifxhcd_hcd_t *)(syshcd->hcd_priv[0]); |
| 538 | } |
| 539 | |
| 540 | /* Gets the struct usb_hcd that contains a ifxhcd_hcd_t. */ |
| 541 | static inline struct usb_hcd *ifxhcd_to_syshcd(ifxhcd_hcd_t *ifxhcd) |
| 542 | { |
| 543 | return (struct usb_hcd *)(ifxhcd->syshcd); |
| 544 | } |
| 545 | |
| 546 | |
| 547 | extern ifxhcd_epqh_t * sysep_to_epqh(ifxhcd_hcd_t *_ifxhcd, struct usb_host_endpoint *_sysep); |
| 548 | |
| 549 | /* HCD Create/Destroy Functions */ |
| 550 | extern int ifxhcd_init (ifxhcd_hcd_t *_ifxhcd); |
| 551 | extern void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd); |
| 552 | |
| 553 | /*Linux HC Driver API Functions */ |
| 554 | |
| 555 | extern int ifxhcd_start(struct usb_hcd *hcd); |
| 556 | extern void ifxhcd_stop (struct usb_hcd *hcd); |
| 557 | extern int ifxhcd_get_frame_number(struct usb_hcd *hcd); |
| 558 | |
| 559 | |
| 560 | /*! |
| 561 | \brief This function does the setup for a data transfer for a host channel and |
| 562 | starts the transfer. May be called in either Slave mode or DMA mode. In |
| 563 | Slave mode, the caller must ensure that there is sufficient space in the |
| 564 | request queue and Tx Data FIFO. |
| 565 | |
| 566 | For an OUT transfer in Slave mode, it loads a data packet into the |
| 567 | appropriate FIFO. If necessary, additional data packets will be loaded in |
| 568 | the Host ISR. |
| 569 | |
| 570 | For an IN transfer in Slave mode, a data packet is requested. The data |
| 571 | packets are unloaded from the Rx FIFO in the Host ISR. If necessary, |
| 572 | additional data packets are requested in the Host ISR. |
| 573 | |
| 574 | For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ |
| 575 | register along with a packet count of 1 and the channel is enabled. This |
| 576 | causes a single PING transaction to occur. Other fields in HCTSIZ are |
| 577 | simply set to 0 since no data transfer occurs in this case. |
| 578 | |
| 579 | For a PING transfer in DMA mode, the HCTSIZ register is initialized with |
| 580 | all the information required to perform the subsequent data transfer. In |
| 581 | addition, the Do Ping bit is set in the HCTSIZ register. In this case, the |
| 582 | controller performs the entire PING protocol, then starts the data |
| 583 | transfer. |
| 584 | |
| 585 | @param _ifxhc Information needed to initialize the host channel. The xfer_len |
| 586 | value may be reduced to accommodate the max widths of the XferSize and |
| 587 | PktCnt fields in the HCTSIZn register. The multi_count value may be changed |
| 588 | to reflect the final xfer_len value. |
| 589 | */ |
| 590 | extern void ifxhcd_hc_start(ifxhcd_hcd_t *_ifxhcd, ifxhcd_hc_t *_ifxhc); |
| 591 | |
| 592 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) |
| 593 | extern int ifxhcd_urb_enqueue(struct usb_hcd *_syshcd, struct usb_host_endpoint *_sysep, struct urb *_urb, gfp_t mem_flags); |
| 594 | extern int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb); |
| 595 | #else |
| 596 | extern int ifxhcd_urb_enqueue(struct usb_hcd *_syshcd, struct urb *_urb, gfp_t mem_flags); |
| 597 | extern int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb, int status); |
| 598 | #endif |
| 599 | extern irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd); |
| 600 | |
| 601 | extern void ifxhcd_endpoint_disable(struct usb_hcd *_syshcd, struct usb_host_endpoint *_sysep); |
| 602 | |
| 603 | extern int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf); |
| 604 | extern int ifxhcd_hub_control( struct usb_hcd *_syshcd, |
| 605 | u16 _typeReq, |
| 606 | u16 _wValue, |
| 607 | u16 _wIndex, |
| 608 | char *_buf, |
| 609 | u16 _wLength); |
| 610 | |
| 611 | /*@}*/ |
| 612 | |
| 613 | /*! \brief Transaction Execution Functions */ |
| 614 | /*@{*/ |
| 615 | extern void ifxhcd_complete_urb (ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status); |
| 616 | |
| 617 | /*! |
| 618 | \brief Clears the transfer state for a host channel. This function is normally |
| 619 | called after a transfer is done and the host channel is being released. |
| 620 | */ |
| 621 | extern void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc); |
| 622 | |
| 623 | /*! |
| 624 | \brief Attempts to halt a host channel. This function should only be called in |
| 625 | Slave mode or to abort a transfer in either Slave mode or DMA mode. Under |
| 626 | normal circumstances in DMA mode, the controller halts the channel when the |
| 627 | transfer is complete or a condition occurs that requires application |
| 628 | intervention. |
| 629 | |
| 630 | In DMA mode, always sets the Channel Enable and Channel Disable bits of the |
| 631 | HCCHARn register. The controller ensures there is space in the request |
| 632 | queue before submitting the halt request. |
| 633 | |
| 634 | Some time may elapse before the core flushes any posted requests for this |
| 635 | host channel and halts. The Channel Halted interrupt handler completes the |
| 636 | deactivation of the host channel. |
| 637 | */ |
| 638 | extern int ifxhcd_hc_halt(ifxusb_core_if_t *_core_if, |
| 639 | ifxhcd_hc_t *_ifxhc, |
| 640 | ifxhcd_halt_status_e _halt_status); |
| 641 | |
| 642 | /*! |
| 643 | \brief Prepares a host channel for transferring packets to/from a specific |
| 644 | endpoint. The HCCHARn register is set up with the characteristics specified |
| 645 | in _ifxhc. Host channel interrupts that may need to be serviced while this |
| 646 | transfer is in progress are enabled. |
| 647 | */ |
| 648 | extern void ifxhcd_hc_init(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc); |
| 649 | |
| 650 | /*! |
| 651 | \brief This function is called to handle the disconnection of host port. |
| 652 | */ |
| 653 | int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd); |
| 654 | /*@}*/ |
| 655 | |
| 656 | /*! \brief Interrupt Handler Functions */ |
| 657 | /*@{*/ |
| 658 | extern irqreturn_t ifxhcd_oc_irq(int _irq, void *_dev); |
| 659 | |
| 660 | extern int32_t ifxhcd_handle_oc_intr(ifxhcd_hcd_t *_ifxhcd); |
| 661 | extern int32_t ifxhcd_handle_intr (ifxhcd_hcd_t *_ifxhcd); |
| 662 | /*@}*/ |
| 663 | |
| 664 | |
| 665 | /*! \brief Schedule Queue Functions */ |
| 666 | /*@{*/ |
| 667 | extern void ifxhcd_epqh_free (ifxhcd_epqh_t *_epqh); |
| 668 | extern void select_eps (ifxhcd_hcd_t *_ifxhcd); |
| 669 | extern void ifxhcd_epqh_idle(ifxhcd_epqh_t *_epqh); |
| 670 | extern void ifxhcd_epqh_idle_periodic(ifxhcd_epqh_t *_epqh); |
| 671 | extern ifxhcd_epqh_t *ifxhcd_urbd_create (ifxhcd_hcd_t *_ifxhcd,struct urb *_urb); |
| 672 | /*@}*/ |
| 673 | |
| 674 | /*! \brief Gets the usb_host_endpoint associated with an URB. */ |
| 675 | static inline struct usb_host_endpoint *ifxhcd_urb_to_endpoint(struct urb *_urb) |
| 676 | { |
| 677 | struct usb_device *dev = _urb->dev; |
| 678 | int ep_num = usb_pipeendpoint(_urb->pipe); |
| 679 | |
| 680 | return (usb_pipein(_urb->pipe))?(dev->ep_in[ep_num]):(dev->ep_out[ep_num]); |
| 681 | } |
| 682 | |
| 683 | /*! |
| 684 | * \brief Gets the endpoint number from a _bEndpointAddress argument. The endpoint is |
| 685 | * qualified with its direction (possible 32 endpoints per device). |
| 686 | */ |
| 687 | #define ifxhcd_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ |
| 688 | ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) |
| 689 | |
| 690 | |
| 691 | |
| 692 | /*! Internal debug function */ |
| 693 | void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd); |
| 694 | |
| 695 | /*@}*//*IFXUSB_HCD*/ |
| 696 | |
| 697 | extern struct usb_device *usb_alloc_dev (struct usb_device *parent, struct usb_bus *, unsigned port); |
| 698 | extern int usb_add_hcd (struct usb_hcd *syshcd, unsigned int irqnum, unsigned long irqflags); |
| 699 | extern void usb_remove_hcd (struct usb_hcd *syshcd); |
| 700 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) |
| 701 | extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, struct device *dev, char *bus_name); |
| 702 | #else |
| 703 | extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, struct device *dev, const char *bus_name); |
| 704 | #endif |
| 705 | |
| 706 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) |
| 707 | extern void usb_hcd_giveback_urb (struct usb_hcd *syshcd, struct urb *urb); |
| 708 | #else |
| 709 | extern void usb_hcd_giveback_urb (struct usb_hcd *syshcd, struct urb *urb,int status); |
| 710 | #endif |
| 711 | |
| 712 | extern void usb_put_hcd (struct usb_hcd *syshcd); |
| 713 | extern long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount); |
| 714 | extern char *syserr(int errno); |
| 715 | |
| 716 | |
| 717 | |
| 718 | static inline void INIT_EPQH_LIST_ALL(ifxhcd_hcd_t *_ifxhcd) |
| 719 | { |
| 720 | spin_lock_init(&_ifxhcd->epqh_list_all_lock); |
| 721 | } |
| 722 | static inline void LOCK_EPQH_LIST_ALL(ifxhcd_hcd_t *_ifxhcd) |
| 723 | { |
| 724 | spin_lock(&_ifxhcd->epqh_list_all_lock); |
| 725 | } |
| 726 | static inline void UNLOCK_EPQH_LIST_ALL(ifxhcd_hcd_t *_ifxhcd) |
| 727 | { |
| 728 | spin_unlock(&_ifxhcd->epqh_list_all_lock); |
| 729 | } |
| 730 | |
| 731 | static inline void INIT_EPQH_LIST(ifxhcd_hcd_t *_ifxhcd) |
| 732 | { |
| 733 | spin_lock_init(&_ifxhcd->epqh_list_lock); |
| 734 | } |
| 735 | static inline void LOCK_EPQH_LIST(ifxhcd_hcd_t *_ifxhcd) |
| 736 | { |
| 737 | spin_lock(&_ifxhcd->epqh_list_lock); |
| 738 | } |
| 739 | static inline void UNLOCK_EPQH_LIST(ifxhcd_hcd_t *_ifxhcd) |
| 740 | { |
| 741 | spin_unlock(&_ifxhcd->epqh_list_lock); |
| 742 | } |
| 743 | |
| 744 | static inline void INIT_URBD_LIST(ifxhcd_epqh_t *_epqh) |
| 745 | { |
| 746 | spin_lock_init(&_epqh->urbd_list_lock); |
| 747 | } |
| 748 | static inline void LOCK_URBD_LIST(ifxhcd_epqh_t *_epqh) |
| 749 | { |
| 750 | spin_lock(&_epqh->urbd_list_lock); |
| 751 | } |
| 752 | static inline void UNLOCK_URBD_LIST(ifxhcd_epqh_t *_epqh) |
| 753 | { |
| 754 | spin_unlock(&_epqh->urbd_list_lock); |
| 755 | } |
| 756 | |
| 757 | #endif // __IFXHCD_H__ |
| 758 | |
| 759 | |