Branch data Line data Source code
1 : : /* ========================================================================== 2 : : * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ 3 : : * $Revision: #58 $ 4 : : * $Date: 2011/09/15 $ 5 : : * $Change: 1846647 $ 6 : : * 7 : : * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, 8 : : * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless 9 : : * otherwise expressly agreed to in writing between Synopsys and you. 10 : : * 11 : : * The Software IS NOT an item of Licensed Software or Licensed Product under 12 : : * any End User Software License Agreement or Agreement for Licensed Product 13 : : * with Synopsys or any supplement thereto. You are permitted to use and 14 : : * redistribute this Software in source and binary forms, with or without 15 : : * modification, provided that redistributions of source code must retain this 16 : : * notice. You may not view, use, disclose, copy or distribute this file or 17 : : * any information contained herein except pursuant to this license grant from 18 : : * Synopsys. If you do not agree with this notice, including the disclaimer 19 : : * below, then you are not authorized to use the Software. 20 : : * 21 : : * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS 22 : : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 : : * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, 25 : : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 : : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 : : * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 : : * DAMAGE. 32 : : * ========================================================================== */ 33 : : #ifndef DWC_DEVICE_ONLY 34 : : #ifndef __DWC_HCD_H__ 35 : : #define __DWC_HCD_H__ 36 : : 37 : : #include "dwc_otg_os_dep.h" 38 : : #include "usb.h" 39 : : #include "dwc_otg_hcd_if.h" 40 : : #include "dwc_otg_core_if.h" 41 : : #include "dwc_list.h" 42 : : #include "dwc_otg_cil.h" 43 : : #include "dwc_otg_fiq_fsm.h" 44 : : #include "dwc_otg_driver.h" 45 : : 46 : : 47 : : /** 48 : : * @file 49 : : * 50 : : * This file contains the structures, constants, and interfaces for 51 : : * the Host Contoller Driver (HCD). 52 : : * 53 : : * The Host Controller Driver (HCD) is responsible for translating requests 54 : : * from the USB Driver into the appropriate actions on the DWC_otg controller. 55 : : * It isolates the USBD from the specifics of the controller by providing an 56 : : * API to the USBD. 57 : : */ 58 : : 59 : : struct dwc_otg_hcd_pipe_info { 60 : : uint8_t dev_addr; 61 : : uint8_t ep_num; 62 : : uint8_t pipe_type; 63 : : uint8_t pipe_dir; 64 : : uint16_t mps; 65 : : }; 66 : : 67 : : struct dwc_otg_hcd_iso_packet_desc { 68 : : uint32_t offset; 69 : : uint32_t length; 70 : : uint32_t actual_length; 71 : : uint32_t status; 72 : : }; 73 : : 74 : : struct dwc_otg_qtd; 75 : : 76 : : struct dwc_otg_hcd_urb { 77 : : void *priv; 78 : : struct dwc_otg_qtd *qtd; 79 : : void *buf; 80 : : dwc_dma_t dma; 81 : : void *setup_packet; 82 : : dwc_dma_t setup_dma; 83 : : uint32_t length; 84 : : uint32_t actual_length; 85 : : uint32_t status; 86 : : uint32_t error_count; 87 : : uint32_t packet_count; 88 : : uint32_t flags; 89 : : uint16_t interval; 90 : : struct dwc_otg_hcd_pipe_info pipe_info; 91 : : struct dwc_otg_hcd_iso_packet_desc iso_descs[0]; 92 : : }; 93 : : 94 : : static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe) 95 : : { 96 : 3 : return pipe->ep_num; 97 : : } 98 : : 99 : : static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info 100 : : *pipe) 101 : : { 102 : 3 : return pipe->pipe_type; 103 : : } 104 : : 105 : : static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe) 106 : : { 107 : 3 : return pipe->mps; 108 : : } 109 : : 110 : : static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info 111 : : *pipe) 112 : : { 113 : 3 : return pipe->dev_addr; 114 : : } 115 : : 116 : : static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info 117 : : *pipe) 118 : : { 119 : : return (pipe->pipe_type == UE_ISOCHRONOUS); 120 : : } 121 : : 122 : : static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info 123 : : *pipe) 124 : : { 125 : : return (pipe->pipe_type == UE_INTERRUPT); 126 : : } 127 : : 128 : : static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info 129 : : *pipe) 130 : : { 131 : : return (pipe->pipe_type == UE_BULK); 132 : : } 133 : : 134 : : static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info 135 : : *pipe) 136 : : { 137 : : return (pipe->pipe_type == UE_CONTROL); 138 : : } 139 : : 140 : : static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe) 141 : : { 142 : 3 : return (pipe->pipe_dir == UE_DIR_IN); 143 : : } 144 : : 145 : : static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info 146 : : *pipe) 147 : : { 148 : 3 : return (!dwc_otg_hcd_is_pipe_in(pipe)); 149 : : } 150 : : 151 : : static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, 152 : : uint8_t devaddr, uint8_t ep_num, 153 : : uint8_t pipe_type, uint8_t pipe_dir, 154 : : uint16_t mps) 155 : : { 156 : 3 : pipe->dev_addr = devaddr; 157 : 3 : pipe->ep_num = ep_num; 158 : 3 : pipe->pipe_type = pipe_type; 159 : 3 : pipe->pipe_dir = pipe_dir; 160 : 3 : pipe->mps = mps; 161 : : } 162 : : 163 : : /** 164 : : * Phases for control transfers. 165 : : */ 166 : : typedef enum dwc_otg_control_phase { 167 : : DWC_OTG_CONTROL_SETUP, 168 : : DWC_OTG_CONTROL_DATA, 169 : : DWC_OTG_CONTROL_STATUS 170 : : } dwc_otg_control_phase_e; 171 : : 172 : : /** Transaction types. */ 173 : : typedef enum dwc_otg_transaction_type { 174 : : DWC_OTG_TRANSACTION_NONE = 0, 175 : : DWC_OTG_TRANSACTION_PERIODIC = 1, 176 : : DWC_OTG_TRANSACTION_NON_PERIODIC = 2, 177 : : DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC 178 : : } dwc_otg_transaction_type_e; 179 : : 180 : : struct dwc_otg_qh; 181 : : 182 : : /** 183 : : * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, 184 : : * interrupt, or isochronous transfer. A single QTD is created for each URB 185 : : * (of one of these types) submitted to the HCD. The transfer associated with 186 : : * a QTD may require one or multiple transactions. 187 : : * 188 : : * A QTD is linked to a Queue Head, which is entered in either the 189 : : * non-periodic or periodic schedule for execution. When a QTD is chosen for 190 : : * execution, some or all of its transactions may be executed. After 191 : : * execution, the state of the QTD is updated. The QTD may be retired if all 192 : : * its transactions are complete or if an error occurred. Otherwise, it 193 : : * remains in the schedule so more transactions can be executed later. 194 : : */ 195 : : typedef struct dwc_otg_qtd { 196 : : /** 197 : : * Determines the PID of the next data packet for the data phase of 198 : : * control transfers. Ignored for other transfer types.<br> 199 : : * One of the following values: 200 : : * - DWC_OTG_HC_PID_DATA0 201 : : * - DWC_OTG_HC_PID_DATA1 202 : : */ 203 : : uint8_t data_toggle; 204 : : 205 : : /** Current phase for control transfers (Setup, Data, or Status). */ 206 : : dwc_otg_control_phase_e control_phase; 207 : : 208 : : /** Keep track of the current split type 209 : : * for FS/LS endpoints on a HS Hub */ 210 : : uint8_t complete_split; 211 : : 212 : : /** How many bytes transferred during SSPLIT OUT */ 213 : : uint32_t ssplit_out_xfer_count; 214 : : 215 : : /** 216 : : * Holds the number of bus errors that have occurred for a transaction 217 : : * within this transfer. 218 : : */ 219 : : uint8_t error_count; 220 : : 221 : : /** 222 : : * Index of the next frame descriptor for an isochronous transfer. A 223 : : * frame descriptor describes the buffer position and length of the 224 : : * data to be transferred in the next scheduled (micro)frame of an 225 : : * isochronous transfer. It also holds status for that transaction. 226 : : * The frame index starts at 0. 227 : : */ 228 : : uint16_t isoc_frame_index; 229 : : 230 : : /** Position of the ISOC split on full/low speed */ 231 : : uint8_t isoc_split_pos; 232 : : 233 : : /** Position of the ISOC split in the buffer for the current frame */ 234 : : uint16_t isoc_split_offset; 235 : : 236 : : /** URB for this transfer */ 237 : : struct dwc_otg_hcd_urb *urb; 238 : : 239 : : struct dwc_otg_qh *qh; 240 : : 241 : : /** This list of QTDs */ 242 : : DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; 243 : : 244 : : /** Indicates if this QTD is currently processed by HW. */ 245 : : uint8_t in_process; 246 : : 247 : : /** Number of DMA descriptors for this QTD */ 248 : : uint8_t n_desc; 249 : : 250 : : /** 251 : : * Last activated frame(packet) index. 252 : : * Used in Descriptor DMA mode only. 253 : : */ 254 : : uint16_t isoc_frame_index_last; 255 : : 256 : : } dwc_otg_qtd_t; 257 : : 258 : : DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); 259 : : 260 : : /** 261 : : * A Queue Head (QH) holds the static characteristics of an endpoint and 262 : : * maintains a list of transfers (QTDs) for that endpoint. A QH structure may 263 : : * be entered in either the non-periodic or periodic schedule. 264 : : */ 265 : : typedef struct dwc_otg_qh { 266 : : /** 267 : : * Endpoint type. 268 : : * One of the following values: 269 : : * - UE_CONTROL 270 : : * - UE_BULK 271 : : * - UE_INTERRUPT 272 : : * - UE_ISOCHRONOUS 273 : : */ 274 : : uint8_t ep_type; 275 : : uint8_t ep_is_in; 276 : : 277 : : /** wMaxPacketSize Field of Endpoint Descriptor. */ 278 : : uint16_t maxp; 279 : : 280 : : /** 281 : : * Device speed. 282 : : * One of the following values: 283 : : * - DWC_OTG_EP_SPEED_LOW 284 : : * - DWC_OTG_EP_SPEED_FULL 285 : : * - DWC_OTG_EP_SPEED_HIGH 286 : : */ 287 : : uint8_t dev_speed; 288 : : 289 : : /** 290 : : * Determines the PID of the next data packet for non-control 291 : : * transfers. Ignored for control transfers.<br> 292 : : * One of the following values: 293 : : * - DWC_OTG_HC_PID_DATA0 294 : : * - DWC_OTG_HC_PID_DATA1 295 : : */ 296 : : uint8_t data_toggle; 297 : : 298 : : /** Ping state if 1. */ 299 : : uint8_t ping_state; 300 : : 301 : : /** 302 : : * List of QTDs for this QH. 303 : : */ 304 : : struct dwc_otg_qtd_list qtd_list; 305 : : 306 : : /** Host channel currently processing transfers for this QH. */ 307 : : struct dwc_hc *channel; 308 : : 309 : : /** Full/low speed endpoint on high-speed hub requires split. */ 310 : : uint8_t do_split; 311 : : 312 : : /** @name Periodic schedule information */ 313 : : /** @{ */ 314 : : 315 : : /** Bandwidth in microseconds per (micro)frame. */ 316 : : uint16_t usecs; 317 : : 318 : : /** Interval between transfers in (micro)frames. */ 319 : : uint16_t interval; 320 : : 321 : : /** 322 : : * (micro)frame to initialize a periodic transfer. The transfer 323 : : * executes in the following (micro)frame. 324 : : */ 325 : : uint16_t sched_frame; 326 : : 327 : : /* 328 : : ** Frame a NAK was received on this queue head, used to minimise NAK retransmission 329 : : */ 330 : : uint16_t nak_frame; 331 : : 332 : : /** (micro)frame at which last start split was initialized. */ 333 : : uint16_t start_split_frame; 334 : : 335 : : /** @} */ 336 : : 337 : : /** 338 : : * Used instead of original buffer if 339 : : * it(physical address) is not dword-aligned. 340 : : */ 341 : : uint8_t *dw_align_buf; 342 : : dwc_dma_t dw_align_buf_dma; 343 : : 344 : : /** Entry for QH in either the periodic or non-periodic schedule. */ 345 : : dwc_list_link_t qh_list_entry; 346 : : 347 : : /** @name Descriptor DMA support */ 348 : : /** @{ */ 349 : : 350 : : /** Descriptor List. */ 351 : : dwc_otg_host_dma_desc_t *desc_list; 352 : : 353 : : /** Descriptor List physical address. */ 354 : : dwc_dma_t desc_list_dma; 355 : : 356 : : /** 357 : : * Xfer Bytes array. 358 : : * Each element corresponds to a descriptor and indicates 359 : : * original XferSize size value for the descriptor. 360 : : */ 361 : : uint32_t *n_bytes; 362 : : 363 : : /** Actual number of transfer descriptors in a list. */ 364 : : uint16_t ntd; 365 : : 366 : : /** First activated isochronous transfer descriptor index. */ 367 : : uint8_t td_first; 368 : : /** Last activated isochronous transfer descriptor index. */ 369 : : uint8_t td_last; 370 : : 371 : : /** @} */ 372 : : 373 : : 374 : : uint16_t speed; 375 : : uint16_t frame_usecs[8]; 376 : : 377 : : uint32_t skip_count; 378 : : } dwc_otg_qh_t; 379 : : 380 : : DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); 381 : : 382 : : typedef struct urb_tq_entry { 383 : : struct urb *urb; 384 : : DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries; 385 : : } urb_tq_entry_t; 386 : : 387 : : DWC_TAILQ_HEAD(urb_list, urb_tq_entry); 388 : : 389 : : /** 390 : : * This structure holds the state of the HCD, including the non-periodic and 391 : : * periodic schedules. 392 : : */ 393 : : struct dwc_otg_hcd { 394 : : /** The DWC otg device pointer */ 395 : : struct dwc_otg_device *otg_dev; 396 : : /** DWC OTG Core Interface Layer */ 397 : : dwc_otg_core_if_t *core_if; 398 : : 399 : : /** Function HCD driver callbacks */ 400 : : struct dwc_otg_hcd_function_ops *fops; 401 : : 402 : : /** Internal DWC HCD Flags */ 403 : : volatile union dwc_otg_hcd_internal_flags { 404 : : uint32_t d32; 405 : : struct { 406 : : unsigned port_connect_status_change:1; 407 : : unsigned port_connect_status:1; 408 : : unsigned port_reset_change:1; 409 : : unsigned port_enable_change:1; 410 : : unsigned port_suspend_change:1; 411 : : unsigned port_over_current_change:1; 412 : : unsigned port_l1_change:1; 413 : : unsigned port_speed:2; 414 : : unsigned reserved:24; 415 : : } b; 416 : : } flags; 417 : : 418 : : /** 419 : : * Inactive items in the non-periodic schedule. This is a list of 420 : : * Queue Heads. Transfers associated with these Queue Heads are not 421 : : * currently assigned to a host channel. 422 : : */ 423 : : dwc_list_link_t non_periodic_sched_inactive; 424 : : 425 : : /** 426 : : * Active items in the non-periodic schedule. This is a list of 427 : : * Queue Heads. Transfers associated with these Queue Heads are 428 : : * currently assigned to a host channel. 429 : : */ 430 : : dwc_list_link_t non_periodic_sched_active; 431 : : 432 : : /** 433 : : * Pointer to the next Queue Head to process in the active 434 : : * non-periodic schedule. 435 : : */ 436 : : dwc_list_link_t *non_periodic_qh_ptr; 437 : : 438 : : /** 439 : : * Inactive items in the periodic schedule. This is a list of QHs for 440 : : * periodic transfers that are _not_ scheduled for the next frame. 441 : : * Each QH in the list has an interval counter that determines when it 442 : : * needs to be scheduled for execution. This scheduling mechanism 443 : : * allows only a simple calculation for periodic bandwidth used (i.e. 444 : : * must assume that all periodic transfers may need to execute in the 445 : : * same frame). However, it greatly simplifies scheduling and should 446 : : * be sufficient for the vast majority of OTG hosts, which need to 447 : : * connect to a small number of peripherals at one time. 448 : : * 449 : : * Items move from this list to periodic_sched_ready when the QH 450 : : * interval counter is 0 at SOF. 451 : : */ 452 : : dwc_list_link_t periodic_sched_inactive; 453 : : 454 : : /** 455 : : * List of periodic QHs that are ready for execution in the next 456 : : * frame, but have not yet been assigned to host channels. 457 : : * 458 : : * Items move from this list to periodic_sched_assigned as host 459 : : * channels become available during the current frame. 460 : : */ 461 : : dwc_list_link_t periodic_sched_ready; 462 : : 463 : : /** 464 : : * List of periodic QHs to be executed in the next frame that are 465 : : * assigned to host channels. 466 : : * 467 : : * Items move from this list to periodic_sched_queued as the 468 : : * transactions for the QH are queued to the DWC_otg controller. 469 : : */ 470 : : dwc_list_link_t periodic_sched_assigned; 471 : : 472 : : /** 473 : : * List of periodic QHs that have been queued for execution. 474 : : * 475 : : * Items move from this list to either periodic_sched_inactive or 476 : : * periodic_sched_ready when the channel associated with the transfer 477 : : * is released. If the interval for the QH is 1, the item moves to 478 : : * periodic_sched_ready because it must be rescheduled for the next 479 : : * frame. Otherwise, the item moves to periodic_sched_inactive. 480 : : */ 481 : : dwc_list_link_t periodic_sched_queued; 482 : : 483 : : /** 484 : : * Total bandwidth claimed so far for periodic transfers. This value 485 : : * is in microseconds per (micro)frame. The assumption is that all 486 : : * periodic transfers may occur in the same (micro)frame. 487 : : */ 488 : : uint16_t periodic_usecs; 489 : : 490 : : /** 491 : : * Total bandwidth claimed so far for all periodic transfers 492 : : * in a frame. 493 : : * This will include a mixture of HS and FS transfers. 494 : : * Units are microseconds per (micro)frame. 495 : : * We have a budget per frame and have to schedule 496 : : * transactions accordingly. 497 : : * Watch out for the fact that things are actually scheduled for the 498 : : * "next frame". 499 : : */ 500 : : uint16_t frame_usecs[8]; 501 : : 502 : : 503 : : /** 504 : : * Frame number read from the core at SOF. The value ranges from 0 to 505 : : * DWC_HFNUM_MAX_FRNUM. 506 : : */ 507 : : uint16_t frame_number; 508 : : 509 : : /** 510 : : * Count of periodic QHs, if using several eps. For SOF enable/disable. 511 : : */ 512 : : uint16_t periodic_qh_count; 513 : : 514 : : /** 515 : : * Free host channels in the controller. This is a list of 516 : : * dwc_hc_t items. 517 : : */ 518 : : struct hc_list free_hc_list; 519 : : /** 520 : : * Number of host channels assigned to periodic transfers. Currently 521 : : * assuming that there is a dedicated host channel for each periodic 522 : : * transaction and at least one host channel available for 523 : : * non-periodic transactions. 524 : : */ 525 : : int periodic_channels; /* microframe_schedule==0 */ 526 : : 527 : : /** 528 : : * Number of host channels assigned to non-periodic transfers. 529 : : */ 530 : : int non_periodic_channels; /* microframe_schedule==0 */ 531 : : 532 : : /** 533 : : * Number of host channels assigned to non-periodic transfers. 534 : : */ 535 : : int available_host_channels; 536 : : 537 : : /** 538 : : * Array of pointers to the host channel descriptors. Allows accessing 539 : : * a host channel descriptor given the host channel number. This is 540 : : * useful in interrupt handlers. 541 : : */ 542 : : struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; 543 : : 544 : : /** 545 : : * Buffer to use for any data received during the status phase of a 546 : : * control transfer. Normally no data is transferred during the status 547 : : * phase. This buffer is used as a bit bucket. 548 : : */ 549 : : uint8_t *status_buf; 550 : : 551 : : /** 552 : : * DMA address for status_buf. 553 : : */ 554 : : dma_addr_t status_buf_dma; 555 : : #define DWC_OTG_HCD_STATUS_BUF_SIZE 64 556 : : 557 : : /** 558 : : * Connection timer. An OTG host must display a message if the device 559 : : * does not connect. Started when the VBus power is turned on via 560 : : * sysfs attribute "buspower". 561 : : */ 562 : : dwc_timer_t *conn_timer; 563 : : 564 : : /* Tasket to do a reset */ 565 : : dwc_tasklet_t *reset_tasklet; 566 : : 567 : : dwc_tasklet_t *completion_tasklet; 568 : : struct urb_list completed_urb_list; 569 : : 570 : : /* */ 571 : : dwc_spinlock_t *lock; 572 : : /** 573 : : * Private data that could be used by OS wrapper. 574 : : */ 575 : : void *priv; 576 : : 577 : : uint8_t otg_port; 578 : : 579 : : /** Frame List */ 580 : : uint32_t *frame_list; 581 : : 582 : : /** Hub - Port assignment */ 583 : : int hub_port[128]; 584 : : #ifdef FIQ_DEBUG 585 : : int hub_port_alloc[2048]; 586 : : #endif 587 : : 588 : : /** Frame List DMA address */ 589 : : dma_addr_t frame_list_dma; 590 : : 591 : : struct fiq_stack *fiq_stack; 592 : : struct fiq_state *fiq_state; 593 : : 594 : : /** Virtual address for split transaction DMA bounce buffers */ 595 : : struct fiq_dma_blob *fiq_dmab; 596 : : 597 : : #ifdef DEBUG 598 : : uint32_t frrem_samples; 599 : : uint64_t frrem_accum; 600 : : 601 : : uint32_t hfnum_7_samples_a; 602 : : uint64_t hfnum_7_frrem_accum_a; 603 : : uint32_t hfnum_0_samples_a; 604 : : uint64_t hfnum_0_frrem_accum_a; 605 : : uint32_t hfnum_other_samples_a; 606 : : uint64_t hfnum_other_frrem_accum_a; 607 : : 608 : : uint32_t hfnum_7_samples_b; 609 : : uint64_t hfnum_7_frrem_accum_b; 610 : : uint32_t hfnum_0_samples_b; 611 : : uint64_t hfnum_0_frrem_accum_b; 612 : : uint32_t hfnum_other_samples_b; 613 : : uint64_t hfnum_other_frrem_accum_b; 614 : : #endif 615 : : }; 616 : : 617 : : static inline struct device *dwc_otg_hcd_to_dev(struct dwc_otg_hcd *hcd) 618 : : { 619 : 3 : return &hcd->otg_dev->os_dep.platformdev->dev; 620 : : } 621 : : 622 : : /** @name Transaction Execution Functions */ 623 : : /** @{ */ 624 : : extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t 625 : : * hcd); 626 : : extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, 627 : : dwc_otg_transaction_type_e tr_type); 628 : : 629 : : int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh); 630 : : void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh); 631 : : 632 : : extern int fiq_fsm_queue_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh); 633 : : extern int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh); 634 : : extern void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num); 635 : : 636 : : /** @} */ 637 : : 638 : : /** @name Interrupt Handler Functions */ 639 : : /** @{ */ 640 : : extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); 641 : : extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); 642 : : extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * 643 : : dwc_otg_hcd); 644 : : extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * 645 : : dwc_otg_hcd); 646 : : extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * 647 : : dwc_otg_hcd); 648 : : extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t * 649 : : dwc_otg_hcd); 650 : : extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd); 651 : : extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t * 652 : : dwc_otg_hcd); 653 : : extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd); 654 : : extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd); 655 : : extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, 656 : : uint32_t num); 657 : : extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd); 658 : : extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t * 659 : : dwc_otg_hcd); 660 : : /** @} */ 661 : : 662 : : /** @name Schedule Queue Functions */ 663 : : /** @{ */ 664 : : 665 : : /* Implemented in dwc_otg_hcd_queue.c */ 666 : : extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, 667 : : dwc_otg_hcd_urb_t * urb, int atomic_alloc); 668 : : extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); 669 : : extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); 670 : : extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); 671 : : extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, 672 : : int sched_csplit); 673 : : 674 : : /** Remove and free a QH */ 675 : 0 : static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, 676 : : dwc_otg_qh_t * qh) 677 : : { 678 : : dwc_irqflags_t flags; 679 : 0 : DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); 680 : 0 : dwc_otg_hcd_qh_remove(hcd, qh); 681 : 0 : DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); 682 : 0 : dwc_otg_hcd_qh_free(hcd, qh); 683 : 0 : } 684 : : 685 : : /** Allocates memory for a QH structure. 686 : : * @return Returns the memory allocate or NULL on error. */ 687 : 3 : static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc) 688 : : { 689 : 3 : if (atomic_alloc) 690 : 3 : return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t)); 691 : : else 692 : 0 : return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t)); 693 : : } 694 : : 695 : : extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, 696 : : int atomic_alloc); 697 : : extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); 698 : : extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, 699 : : dwc_otg_qh_t ** qh, int atomic_alloc); 700 : : 701 : : /** Allocates memory for a QTD structure. 702 : : * @return Returns the memory allocate or NULL on error. */ 703 : 3 : static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc) 704 : : { 705 : 3 : if (atomic_alloc) 706 : 3 : return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t)); 707 : : else 708 : 0 : return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t)); 709 : : } 710 : : 711 : : /** Frees the memory for a QTD structure. QTD should already be removed from 712 : : * list. 713 : : * @param qtd QTD to free.*/ 714 : : static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) 715 : : { 716 : 3 : DWC_FREE(qtd); 717 : : } 718 : : 719 : : /** Removes a QTD from list. 720 : : * @param hcd HCD instance. 721 : : * @param qtd QTD to remove from list. 722 : : * @param qh QTD belongs to. 723 : : */ 724 : : static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd, 725 : : dwc_otg_qtd_t * qtd, 726 : : dwc_otg_qh_t * qh) 727 : : { 728 : 3 : DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); 729 : : } 730 : : 731 : : /** Remove and free a QTD 732 : : * Need to disable IRQ and hold hcd lock while calling this function out of 733 : : * interrupt servicing chain */ 734 : 3 : static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, 735 : : dwc_otg_qtd_t * qtd, 736 : : dwc_otg_qh_t * qh) 737 : : { 738 : : dwc_otg_hcd_qtd_remove(hcd, qtd, qh); 739 : : dwc_otg_hcd_qtd_free(qtd); 740 : 3 : } 741 : : 742 : : /** @} */ 743 : : 744 : : /** @name Descriptor DMA Supporting Functions */ 745 : : /** @{ */ 746 : : 747 : : extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); 748 : : extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, 749 : : dwc_hc_t * hc, 750 : : dwc_otg_hc_regs_t * hc_regs, 751 : : dwc_otg_halt_status_e halt_status); 752 : : 753 : : extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); 754 : : extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); 755 : : 756 : : /** @} */ 757 : : 758 : : /** @name Internal Functions */ 759 : : /** @{ */ 760 : : dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); 761 : : /** @} */ 762 : : 763 : : #ifdef CONFIG_USB_DWC_OTG_LPM 764 : : extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, 765 : : uint8_t devaddr); 766 : : extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd); 767 : : #endif 768 : : 769 : : /** Gets the QH that contains the list_head */ 770 : : #define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry) 771 : : 772 : : /** Gets the QTD that contains the list_head */ 773 : : #define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry) 774 : : 775 : : /** Check if QH is non-periodic */ 776 : : #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \ 777 : : (_qh_ptr_->ep_type == UE_CONTROL)) 778 : : 779 : : /** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ 780 : : #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) 781 : : 782 : : /** Packet size for any kind of endpoint descriptor */ 783 : : #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) 784 : : 785 : : /** 786 : : * Returns true if _frame1 is less than or equal to _frame2. The comparison is 787 : : * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the 788 : : * frame number when the max frame number is reached. 789 : : */ 790 : : static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) 791 : : { 792 : 3 : return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= 793 : : (DWC_HFNUM_MAX_FRNUM >> 1); 794 : : } 795 : : 796 : : /** 797 : : * Returns true if _frame1 is greater than _frame2. The comparison is done 798 : : * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame 799 : : * number when the max frame number is reached. 800 : : */ 801 : : static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) 802 : : { 803 : 1 : return (frame1 != frame2) && 804 : 1 : (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < 805 : : (DWC_HFNUM_MAX_FRNUM >> 1)); 806 : : } 807 : : 808 : : /** 809 : : * Increments _frame by the amount specified by _inc. The addition is done 810 : : * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. 811 : : */ 812 : : static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) 813 : : { 814 : 3 : return (frame + inc) & DWC_HFNUM_MAX_FRNUM; 815 : : } 816 : : 817 : : static inline uint16_t dwc_full_frame_num(uint16_t frame) 818 : : { 819 : 0 : return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; 820 : : } 821 : : 822 : : static inline uint16_t dwc_micro_frame_num(uint16_t frame) 823 : : { 824 : 0 : return frame & 0x7; 825 : : } 826 : : 827 : : extern void init_hcd_usecs(dwc_otg_hcd_t *_hcd); 828 : : 829 : : void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, 830 : : dwc_otg_hc_regs_t * hc_regs, 831 : : dwc_otg_qtd_t * qtd); 832 : : 833 : : #ifdef DEBUG 834 : : /** 835 : : * Macro to sample the remaining PHY clocks left in the current frame. This 836 : : * may be used during debugging to determine the average time it takes to 837 : : * execute sections of code. There are two possible sample points, "a" and 838 : : * "b", so the _letter argument must be one of these values. 839 : : * 840 : : * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For 841 : : * example, "cat /sys/devices/lm0/hcd_frrem". 842 : : */ 843 : : #define dwc_sample_frrem(_hcd, _qh, _letter) \ 844 : : { \ 845 : : hfnum_data_t hfnum; \ 846 : : dwc_otg_qtd_t *qtd; \ 847 : : qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ 848 : : if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ 849 : : hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ 850 : : switch (hfnum.b.frnum & 0x7) { \ 851 : : case 7: \ 852 : : _hcd->hfnum_7_samples_##_letter++; \ 853 : : _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ 854 : : break; \ 855 : : case 0: \ 856 : : _hcd->hfnum_0_samples_##_letter++; \ 857 : : _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ 858 : : break; \ 859 : : default: \ 860 : : _hcd->hfnum_other_samples_##_letter++; \ 861 : : _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \ 862 : : break; \ 863 : : } \ 864 : : } \ 865 : : } 866 : : #else 867 : : #define dwc_sample_frrem(_hcd, _qh, _letter) 868 : : #endif 869 : : #endif 870 : : #endif /* DWC_DEVICE_ONLY */