LCOV - code coverage report
Current view: top level - drivers/usb/host/dwc_otg - dwc_otg_hcd.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 610 1407 43.4 %
Date: 2020-09-30 20:25:40 Functions: 31 59 52.5 %
Branches: 308 719 42.8 %

           Branch data     Line data    Source code
       1                 :            : 
       2                 :            : /* ==========================================================================
       3                 :            :  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
       4                 :            :  * $Revision: #104 $
       5                 :            :  * $Date: 2011/10/24 $
       6                 :            :  * $Change: 1871159 $
       7                 :            :  *
       8                 :            :  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
       9                 :            :  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
      10                 :            :  * otherwise expressly agreed to in writing between Synopsys and you.
      11                 :            :  *
      12                 :            :  * The Software IS NOT an item of Licensed Software or Licensed Product under
      13                 :            :  * any End User Software License Agreement or Agreement for Licensed Product
      14                 :            :  * with Synopsys or any supplement thereto. You are permitted to use and
      15                 :            :  * redistribute this Software in source and binary forms, with or without
      16                 :            :  * modification, provided that redistributions of source code must retain this
      17                 :            :  * notice. You may not view, use, disclose, copy or distribute this file or
      18                 :            :  * any information contained herein except pursuant to this license grant from
      19                 :            :  * Synopsys. If you do not agree with this notice, including the disclaimer
      20                 :            :  * below, then you are not authorized to use the Software.
      21                 :            :  *
      22                 :            :  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
      23                 :            :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      24                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      25                 :            :  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
      26                 :            :  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      27                 :            :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      28                 :            :  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
      29                 :            :  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      30                 :            :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      31                 :            :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
      32                 :            :  * DAMAGE.
      33                 :            :  * ========================================================================== */
      34                 :            : #ifndef DWC_DEVICE_ONLY
      35                 :            : 
      36                 :            : /** @file
      37                 :            :  * This file implements HCD Core. All code in this file is portable and doesn't
      38                 :            :  * use any OS specific functions.
      39                 :            :  * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
      40                 :            :  * header file.
      41                 :            :  */
      42                 :            : 
      43                 :            : #include <linux/usb.h>
      44                 :            : #include <linux/usb/hcd.h>
      45                 :            : 
      46                 :            : #include "dwc_otg_hcd.h"
      47                 :            : #include "dwc_otg_regs.h"
      48                 :            : #include "dwc_otg_fiq_fsm.h"
      49                 :            : 
      50                 :            : extern bool microframe_schedule;
      51                 :            : extern uint16_t fiq_fsm_mask, nak_holdoff;
      52                 :            : 
      53                 :            : //#define DEBUG_HOST_CHANNELS
      54                 :            : #ifdef DEBUG_HOST_CHANNELS
      55                 :            : static int last_sel_trans_num_per_scheduled = 0;
      56                 :            : static int last_sel_trans_num_nonper_scheduled = 0;
      57                 :            : static int last_sel_trans_num_avail_hc_at_start = 0;
      58                 :            : static int last_sel_trans_num_avail_hc_at_end = 0;
      59                 :            : #endif /* DEBUG_HOST_CHANNELS */
      60                 :            : 
      61                 :            : 
      62                 :        207 : dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
      63                 :            : {
      64                 :        207 :         return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
      65                 :            : }
      66                 :            : 
      67                 :            : /**
      68                 :            :  * Connection timeout function.  An OTG host is required to display a
      69                 :            :  * message if the device does not connect within 10 seconds.
      70                 :            :  */
      71                 :          0 : void dwc_otg_hcd_connect_timeout(void *ptr)
      72                 :            : {
      73                 :            :         DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
      74                 :          0 :         DWC_PRINTF("Connect Timeout\n");
      75                 :          0 :         __DWC_ERROR("Device Not Connected/Responding\n");
      76                 :          0 : }
      77                 :            : 
      78                 :            : #if defined(DEBUG)
      79                 :            : static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
      80                 :            : {
      81                 :            :         if (qh->channel != NULL) {
      82                 :            :                 dwc_hc_t *hc = qh->channel;
      83                 :            :                 dwc_list_link_t *item;
      84                 :            :                 dwc_otg_qh_t *qh_item;
      85                 :            :                 int num_channels = hcd->core_if->core_params->host_channels;
      86                 :            :                 int i;
      87                 :            : 
      88                 :            :                 dwc_otg_hc_regs_t *hc_regs;
      89                 :            :                 hcchar_data_t hcchar;
      90                 :            :                 hcsplt_data_t hcsplt;
      91                 :            :                 hctsiz_data_t hctsiz;
      92                 :            :                 uint32_t hcdma;
      93                 :            : 
      94                 :            :                 hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
      95                 :            :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
      96                 :            :                 hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
      97                 :            :                 hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
      98                 :            :                 hcdma = DWC_READ_REG32(&hc_regs->hcdma);
      99                 :            : 
     100                 :            :                 DWC_PRINTF("  Assigned to channel %p:\n", hc);
     101                 :            :                 DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
     102                 :            :                            hcsplt.d32);
     103                 :            :                 DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
     104                 :            :                            hcdma);
     105                 :            :                 DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
     106                 :            :                            hc->dev_addr, hc->ep_num, hc->ep_is_in);
     107                 :            :                 DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
     108                 :            :                 DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
     109                 :            :                 DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
     110                 :            :                 DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
     111                 :            :                 DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
     112                 :            :                 DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
     113                 :            :                 DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
     114                 :            :                 DWC_PRINTF("    qh: %p\n", hc->qh);
     115                 :            :                 DWC_PRINTF("  NP inactive sched:\n");
     116                 :            :                 DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
     117                 :            :                         qh_item =
     118                 :            :                             DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
     119                 :            :                         DWC_PRINTF("    %p\n", qh_item);
     120                 :            :                 }
     121                 :            :                 DWC_PRINTF("  NP active sched:\n");
     122                 :            :                 DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
     123                 :            :                         qh_item =
     124                 :            :                             DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
     125                 :            :                         DWC_PRINTF("    %p\n", qh_item);
     126                 :            :                 }
     127                 :            :                 DWC_PRINTF("  Channels: \n");
     128                 :            :                 for (i = 0; i < num_channels; i++) {
     129                 :            :                         dwc_hc_t *hc = hcd->hc_ptr_array[i];
     130                 :            :                         DWC_PRINTF("    %2d: %p\n", i, hc);
     131                 :            :                 }
     132                 :            :         }
     133                 :            : }
     134                 :            : #else
     135                 :            : #define dump_channel_info(hcd, qh)
     136                 :            : #endif /* DEBUG */
     137                 :            : 
     138                 :            : /**
     139                 :            :  * Work queue function for starting the HCD when A-Cable is connected.
     140                 :            :  * The hcd_start() must be called in a process context.
     141                 :            :  */
     142                 :          0 : static void hcd_start_func(void *_vp)
     143                 :            : {
     144                 :            :         dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
     145                 :            : 
     146                 :            :         DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
     147         [ #  # ]:          0 :         if (hcd) {
     148                 :          0 :                 hcd->fops->start(hcd);
     149                 :            :         }
     150                 :          0 : }
     151                 :            : 
     152                 :            : static void del_xfer_timers(dwc_otg_hcd_t * hcd)
     153                 :            : {
     154                 :            : #ifdef DEBUG
     155                 :            :         int i;
     156                 :            :         int num_channels = hcd->core_if->core_params->host_channels;
     157                 :            :         for (i = 0; i < num_channels; i++) {
     158                 :            :                 DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
     159                 :            :         }
     160                 :            : #endif
     161                 :            : }
     162                 :            : 
     163                 :            : static void del_timers(dwc_otg_hcd_t * hcd)
     164                 :            : {
     165                 :            :         del_xfer_timers(hcd);
     166                 :          0 :         DWC_TIMER_CANCEL(hcd->conn_timer);
     167                 :            : }
     168                 :            : 
     169                 :            : /**
     170                 :            :  * Processes all the URBs in a single list of QHs. Completes them with
     171                 :            :  * -ESHUTDOWN and frees the QTD.
     172                 :            :  */
     173                 :          0 : static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
     174                 :            : {
     175                 :            :         dwc_list_link_t *qh_item, *qh_tmp;
     176                 :            :         dwc_otg_qh_t *qh;
     177                 :            :         dwc_otg_qtd_t *qtd, *qtd_tmp;
     178                 :            :         int quiesced = 0;
     179                 :            : 
     180         [ #  # ]:          0 :         DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {
     181                 :          0 :                 qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
     182         [ #  # ]:          0 :                 DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
     183                 :            :                                          &qh->qtd_list, qtd_list_entry) {
     184                 :          0 :                         qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
     185         [ #  # ]:          0 :                         if (qtd->urb != NULL) {
     186                 :          0 :                                 hcd->fops->complete(hcd, qtd->urb->priv,
     187                 :            :                                                     qtd->urb, -DWC_E_SHUTDOWN);
     188                 :          0 :                                 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
     189                 :            :                         }
     190                 :            : 
     191                 :            :                 }
     192         [ #  # ]:          0 :                 if(qh->channel) {
     193                 :          0 :                         int n = qh->channel->hc_num;
     194                 :            :                         /* Using hcchar.chen == 1 is not a reliable test.
     195                 :            :                          * It is possible that the channel has already halted
     196                 :            :                          * but not yet been through the IRQ handler.
     197                 :            :                          */
     198   [ #  #  #  # ]:          0 :                         if (fiq_fsm_enable && (hcd->fiq_state->channel[qh->channel->hc_num].fsm != FIQ_PASSTHROUGH)) {
     199                 :          0 :                                 qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
     200                 :          0 :                                 qh->channel->halt_pending = 1;
     201         [ #  # ]:          0 :                                 if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
     202                 :            :                                     hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
     203                 :          0 :                                         hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
     204                 :            :                                 /* We're called from disconnect callback or in the middle of freeing the HCD here,
     205                 :            :                                  * so FIQ is disabled, top-level interrupts masked and we're holding the spinlock.
     206                 :            :                                  * No further URBs will be submitted, but wait 1 microframe for any previously
     207                 :            :                                  * submitted periodic DMA to finish.
     208                 :            :                                  */
     209         [ #  # ]:          0 :                                 if (!quiesced) {
     210                 :          0 :                                         udelay(125);
     211                 :            :                                         quiesced = 1;
     212                 :            :                                 }
     213                 :            :                         } else {
     214                 :          0 :                                 dwc_otg_hc_halt(hcd->core_if, qh->channel,
     215                 :            :                                                 DWC_OTG_HC_XFER_URB_DEQUEUE);
     216                 :            :                         }
     217                 :          0 :                         qh->channel = NULL;
     218                 :            :                 }
     219                 :          0 :                 dwc_otg_hcd_qh_remove(hcd, qh);
     220                 :            :         }
     221                 :          0 : }
     222                 :            : 
     223                 :            : /**
     224                 :            :  * Responds with an error status of ESHUTDOWN to all URBs in the non-periodic
     225                 :            :  * and periodic schedules. The QTD associated with each URB is removed from
     226                 :            :  * the schedule and freed. This function may be called when a disconnect is
     227                 :            :  * detected or when the HCD is being stopped.
     228                 :            :  */
     229                 :          0 : static void kill_all_urbs(dwc_otg_hcd_t * hcd)
     230                 :            : {
     231                 :          0 :         kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
     232                 :          0 :         kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
     233                 :          0 :         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
     234                 :          0 :         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
     235                 :          0 :         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
     236                 :          0 :         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
     237                 :          0 : }
     238                 :            : 
     239                 :            : /**
     240                 :            :  * Start the connection timer.  An OTG host is required to display a
     241                 :            :  * message if the device does not connect within 10 seconds.  The
     242                 :            :  * timer is deleted if a port connect interrupt occurs before the
     243                 :            :  * timer expires.
     244                 :            :  */
     245                 :            : static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
     246                 :            : {
     247                 :          0 :         DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
     248                 :            : }
     249                 :            : 
     250                 :            : /**
     251                 :            :  * HCD Callback function for disconnect of the HCD.
     252                 :            :  *
     253                 :            :  * @param p void pointer to the <code>struct usb_hcd</code>
     254                 :            :  */
     255                 :          0 : static int32_t dwc_otg_hcd_session_start_cb(void *p)
     256                 :            : {
     257                 :            :         dwc_otg_hcd_t *dwc_otg_hcd;
     258                 :            :         DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
     259                 :            :         dwc_otg_hcd = p;
     260                 :            :         dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
     261                 :          0 :         return 1;
     262                 :            : }
     263                 :            : 
     264                 :            : /**
     265                 :            :  * HCD Callback function for starting the HCD when A-Cable is
     266                 :            :  * connected.
     267                 :            :  *
     268                 :            :  * @param p void pointer to the <code>struct usb_hcd</code>
     269                 :            :  */
     270                 :          0 : static int32_t dwc_otg_hcd_start_cb(void *p)
     271                 :            : {
     272                 :            :         dwc_otg_hcd_t *dwc_otg_hcd = p;
     273                 :            :         dwc_otg_core_if_t *core_if;
     274                 :            :         hprt0_data_t hprt0;
     275                 :            : 
     276                 :          0 :         core_if = dwc_otg_hcd->core_if;
     277                 :            : 
     278         [ #  # ]:          0 :         if (core_if->op_state == B_HOST) {
     279                 :            :                 /*
     280                 :            :                  * Reset the port.  During a HNP mode switch the reset
     281                 :            :                  * needs to occur within 1ms and have a duration of at
     282                 :            :                  * least 50ms.
     283                 :            :                  */
     284                 :          0 :                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
     285                 :          0 :                 hprt0.b.prtrst = 1;
     286                 :          0 :                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
     287                 :            :         }
     288                 :          0 :         DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
     289                 :            :                                    hcd_start_func, dwc_otg_hcd, 50,
     290                 :            :                                    "start hcd");
     291                 :            : 
     292                 :          0 :         return 1;
     293                 :            : }
     294                 :            : 
     295                 :            : /**
     296                 :            :  * HCD Callback function for disconnect of the HCD.
     297                 :            :  *
     298                 :            :  * @param p void pointer to the <code>struct usb_hcd</code>
     299                 :            :  */
     300                 :          0 : static int32_t dwc_otg_hcd_disconnect_cb(void *p)
     301                 :            : {
     302                 :            :         gintsts_data_t intr;
     303                 :            :         dwc_otg_hcd_t *dwc_otg_hcd = p;
     304                 :            : 
     305                 :          0 :         DWC_SPINLOCK(dwc_otg_hcd->lock);
     306                 :            :         /*
     307                 :            :          * Set status flags for the hub driver.
     308                 :            :          */
     309                 :          0 :         dwc_otg_hcd->flags.b.port_connect_status_change = 1;
     310                 :          0 :         dwc_otg_hcd->flags.b.port_connect_status = 0;
     311         [ #  # ]:          0 :         if(fiq_enable) {
     312                 :          0 :                 local_fiq_disable();
     313                 :          0 :                 fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
     314                 :            :         }
     315                 :            :         /*
     316                 :            :          * Shutdown any transfers in process by clearing the Tx FIFO Empty
     317                 :            :          * interrupt mask and status bits and disabling subsequent host
     318                 :            :          * channel interrupts.
     319                 :            :          */
     320                 :          0 :         intr.d32 = 0;
     321                 :          0 :         intr.b.nptxfempty = 1;
     322                 :          0 :         intr.b.ptxfempty = 1;
     323                 :          0 :         intr.b.hcintr = 1;
     324                 :          0 :         DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
     325                 :            :                          intr.d32, 0);
     326                 :          0 :         DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
     327                 :            :                          intr.d32, 0);
     328                 :            : 
     329                 :            :         del_timers(dwc_otg_hcd);
     330                 :            : 
     331                 :            :         /*
     332                 :            :          * Turn off the vbus power only if the core has transitioned to device
     333                 :            :          * mode. If still in host mode, need to keep power on to detect a
     334                 :            :          * reconnection.
     335                 :            :          */
     336         [ #  # ]:          0 :         if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
     337         [ #  # ]:          0 :                 if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
     338                 :          0 :                         hprt0_data_t hprt0 = {.d32 = 0 };
     339                 :          0 :                         DWC_PRINTF("Disconnect: PortPower off\n");
     340                 :          0 :                         hprt0.b.prtpwr = 0;
     341                 :          0 :                         DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
     342                 :            :                                         hprt0.d32);
     343                 :            :                 }
     344                 :            : 
     345                 :          0 :                 dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
     346                 :            :         }
     347                 :            : 
     348                 :            :         /* Respond with an error status to all URBs in the schedule. */
     349                 :          0 :         kill_all_urbs(dwc_otg_hcd);
     350                 :            : 
     351         [ #  # ]:          0 :         if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
     352                 :            :                 /* Clean up any host channels that were in use. */
     353                 :            :                 int num_channels;
     354                 :            :                 int i;
     355                 :            :                 dwc_hc_t *channel;
     356                 :            :                 dwc_otg_hc_regs_t *hc_regs;
     357                 :            :                 hcchar_data_t hcchar;
     358                 :            : 
     359                 :          0 :                 num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
     360                 :            : 
     361         [ #  # ]:          0 :                 if (!dwc_otg_hcd->core_if->dma_enable) {
     362                 :            :                         /* Flush out any channel requests in slave mode. */
     363         [ #  # ]:          0 :                         for (i = 0; i < num_channels; i++) {
     364                 :          0 :                                 channel = dwc_otg_hcd->hc_ptr_array[i];
     365   [ #  #  #  # ]:          0 :                                 if (DWC_CIRCLEQ_EMPTY_ENTRY
     366                 :            :                                     (channel, hc_list_entry)) {
     367                 :          0 :                                         hc_regs =
     368                 :          0 :                                             dwc_otg_hcd->core_if->
     369                 :            :                                             host_if->hc_regs[i];
     370                 :          0 :                                         hcchar.d32 =
     371                 :          0 :                                             DWC_READ_REG32(&hc_regs->hcchar);
     372         [ #  # ]:          0 :                                         if (hcchar.b.chen) {
     373                 :          0 :                                                 hcchar.b.chen = 0;
     374                 :          0 :                                                 hcchar.b.chdis = 1;
     375                 :          0 :                                                 hcchar.b.epdir = 0;
     376                 :          0 :                                                 DWC_WRITE_REG32
     377                 :            :                                                     (&hc_regs->hcchar,
     378                 :            :                                                      hcchar.d32);
     379                 :            :                                         }
     380                 :            :                                 }
     381                 :            :                         }
     382                 :            :                 }
     383                 :            : 
     384         [ #  # ]:          0 :                 if(fiq_fsm_enable) {
     385         [ #  # ]:          0 :                         for(i=0; i < 128; i++) {
     386                 :          0 :                                 dwc_otg_hcd->hub_port[i] = 0;
     387                 :            :                         }
     388                 :            :                 }
     389                 :            :         }
     390                 :            : 
     391         [ #  # ]:          0 :         if(fiq_enable) {
     392                 :          0 :                 fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
     393                 :          0 :                 local_fiq_enable();
     394                 :            :         }
     395                 :            : 
     396         [ #  # ]:          0 :         if (dwc_otg_hcd->fops->disconnect) {
     397                 :          0 :                 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
     398                 :            :         }
     399                 :            : 
     400                 :          0 :         DWC_SPINUNLOCK(dwc_otg_hcd->lock);
     401                 :          0 :         return 1;
     402                 :            : }
     403                 :            : 
     404                 :            : /**
     405                 :            :  * HCD Callback function for stopping the HCD.
     406                 :            :  *
     407                 :            :  * @param p void pointer to the <code>struct usb_hcd</code>
     408                 :            :  */
     409                 :          0 : static int32_t dwc_otg_hcd_stop_cb(void *p)
     410                 :            : {
     411                 :            :         dwc_otg_hcd_t *dwc_otg_hcd = p;
     412                 :            : 
     413                 :            :         DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
     414                 :          0 :         dwc_otg_hcd_stop(dwc_otg_hcd);
     415                 :          0 :         return 1;
     416                 :            : }
     417                 :            : 
     418                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
     419                 :            : /**
     420                 :            :  * HCD Callback function for sleep of HCD.
     421                 :            :  *
     422                 :            :  * @param p void pointer to the <code>struct usb_hcd</code>
     423                 :            :  */
     424                 :            : static int dwc_otg_hcd_sleep_cb(void *p)
     425                 :            : {
     426                 :            :         dwc_otg_hcd_t *hcd = p;
     427                 :            : 
     428                 :            :         dwc_otg_hcd_free_hc_from_lpm(hcd);
     429                 :            : 
     430                 :            :         return 0;
     431                 :            : }
     432                 :            : #endif
     433                 :            : 
     434                 :            : 
     435                 :            : /**
     436                 :            :  * HCD Callback function for Remote Wakeup.
     437                 :            :  *
     438                 :            :  * @param p void pointer to the <code>struct usb_hcd</code>
     439                 :            :  */
     440                 :          0 : static int dwc_otg_hcd_rem_wakeup_cb(void *p)
     441                 :            : {
     442                 :            :         dwc_otg_hcd_t *hcd = p;
     443                 :            : 
     444         [ #  # ]:          0 :         if (hcd->core_if->lx_state == DWC_OTG_L2) {
     445                 :          0 :                 hcd->flags.b.port_suspend_change = 1;
     446                 :            :         }
     447                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
     448                 :            :         else {
     449                 :            :                 hcd->flags.b.port_l1_change = 1;
     450                 :            :         }
     451                 :            : #endif
     452                 :          0 :         return 0;
     453                 :            : }
     454                 :            : 
     455                 :            : /**
     456                 :            :  * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
     457                 :            :  * stopped.
     458                 :            :  */
     459                 :          0 : void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
     460                 :            : {
     461                 :          0 :         hprt0_data_t hprt0 = {.d32 = 0 };
     462                 :            : 
     463                 :            :         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
     464                 :            : 
     465                 :            :         /*
     466                 :            :          * The root hub should be disconnected before this function is called.
     467                 :            :          * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
     468                 :            :          * and the QH lists (via ..._hcd_endpoint_disable).
     469                 :            :          */
     470                 :            : 
     471                 :            :         /* Turn off all host-specific interrupts. */
     472                 :          0 :         dwc_otg_disable_host_interrupts(hcd->core_if);
     473                 :            : 
     474                 :            :         /* Turn off the vbus power */
     475                 :          0 :         DWC_PRINTF("PortPower off\n");
     476                 :          0 :         hprt0.b.prtpwr = 0;
     477                 :          0 :         DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
     478                 :          0 :         dwc_mdelay(1);
     479                 :          0 : }
     480                 :            : 
     481                 :     134698 : int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
     482                 :            :                             dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
     483                 :            :                             int atomic_alloc)
     484                 :            : {
     485                 :            :         int retval = 0;
     486                 :            :         uint8_t needs_scheduling = 0;
     487                 :            :         dwc_otg_transaction_type_e tr_type;
     488                 :            :         dwc_otg_qtd_t *qtd;
     489                 :            :         gintmsk_data_t intr_mask = {.d32 = 0 };
     490                 :            :         hprt0_data_t hprt0 = { .d32 = 0 };
     491                 :            : 
     492                 :            : #ifdef DEBUG /* integrity checks (Broadcom) */
     493                 :            :         if (NULL == hcd->core_if) {
     494                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
     495                 :            :                 /* No longer connected. */
     496                 :            :                 return -DWC_E_INVALID;
     497                 :            :         }
     498                 :            : #endif
     499         [ -  + ]:     134698 :         if (!hcd->flags.b.port_connect_status) {
     500                 :            :                 /* No longer connected. */
     501                 :          0 :                 DWC_ERROR("Not connected\n");
     502                 :          0 :                 return -DWC_E_NO_DEVICE;
     503                 :            :         }
     504                 :            : 
     505                 :            :         /* Some core configurations cannot support LS traffic on a FS root port */
     506         [ +  + ]:     134698 :         if ((hcd->fops->speed(hcd, dwc_otg_urb->priv) == USB_SPEED_LOW) &&
     507         [ +  - ]:       6419 :                 (hcd->core_if->hwcfg2.b.fs_phy_type == 1) &&
     508                 :            :                 (hcd->core_if->hwcfg2.b.hs_phy_type == 1)) {
     509                 :       6419 :                         hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
     510         [ +  - ]:       6419 :                         if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED) {
     511                 :            :                                 return -DWC_E_NO_DEVICE;
     512                 :            :                         }
     513                 :            :         }
     514                 :            : 
     515                 :     134698 :         qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
     516         [ -  + ]:     134698 :         if (qtd == NULL) {
     517                 :          0 :                 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
     518                 :          0 :                 return -DWC_E_NO_MEMORY;
     519                 :            :         }
     520                 :            : #ifdef DEBUG /* integrity checks (Broadcom) */
     521                 :            :         if (qtd->urb == NULL) {
     522                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
     523                 :            :                 return -DWC_E_NO_MEMORY;
     524                 :            :         }
     525                 :            :         if (qtd->urb->priv == NULL) {
     526                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
     527                 :            :                 return -DWC_E_NO_MEMORY;
     528                 :            :         }
     529                 :            : #endif
     530                 :     134698 :         intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
     531   [ +  -  +  - ]:     134698 :         if(!intr_mask.b.sofintr || fiq_enable) needs_scheduling = 1;
     532   [ -  +  #  # ]:     134698 :         if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))
     533                 :            :                 /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
     534                 :            :                 needs_scheduling = 0;
     535                 :            : 
     536                 :     134698 :         retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
     537                 :            :             // creates a new queue in ep_handle if it doesn't exist already
     538         [ -  + ]:     134698 :         if (retval < 0) {
     539                 :          0 :                 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
     540                 :            :                           "Error status %d\n", retval);
     541                 :            :                 dwc_otg_hcd_qtd_free(qtd);
     542                 :          0 :                 return retval;
     543                 :            :         }
     544                 :            : 
     545         [ +  - ]:     134698 :         if(needs_scheduling) {
     546                 :     134698 :                 tr_type = dwc_otg_hcd_select_transactions(hcd);
     547         [ +  + ]:     134698 :                 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
     548                 :     133446 :                         dwc_otg_hcd_queue_transactions(hcd, tr_type);
     549                 :            :                 }
     550                 :            :         }
     551                 :     134698 :         return retval;
     552                 :            : }
     553                 :            : 
     554                 :       7245 : int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
     555                 :            :                             dwc_otg_hcd_urb_t * dwc_otg_urb)
     556                 :            : {
     557                 :            :         dwc_otg_qh_t *qh;
     558                 :            :         dwc_otg_qtd_t *urb_qtd;
     559         [ -  + ]:       7245 :         BUG_ON(!hcd);
     560         [ -  + ]:       7245 :         BUG_ON(!dwc_otg_urb);
     561                 :            : 
     562                 :            : #ifdef DEBUG /* integrity checks (Broadcom) */
     563                 :            : 
     564                 :            :         if (hcd == NULL) {
     565                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
     566                 :            :                 return -DWC_E_INVALID;
     567                 :            :         }
     568                 :            :         if (dwc_otg_urb == NULL) {
     569                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
     570                 :            :                 return -DWC_E_INVALID;
     571                 :            :         }
     572                 :            :         if (dwc_otg_urb->qtd == NULL) {
     573                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
     574                 :            :                 return -DWC_E_INVALID;
     575                 :            :         }
     576                 :            :         urb_qtd = dwc_otg_urb->qtd;
     577                 :            :         BUG_ON(!urb_qtd);
     578                 :            :         if (urb_qtd->qh == NULL) {
     579                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
     580                 :            :                 return -DWC_E_INVALID;
     581                 :            :         }
     582                 :            : #else
     583                 :       7245 :         urb_qtd = dwc_otg_urb->qtd;
     584         [ -  + ]:       7245 :         BUG_ON(!urb_qtd);
     585                 :            : #endif
     586                 :       7245 :         qh = urb_qtd->qh;
     587         [ -  + ]:       7245 :         BUG_ON(!qh);
     588                 :            :         if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
     589                 :            :                 if (urb_qtd->in_process) {
     590                 :            :                         dump_channel_info(hcd, qh);
     591                 :            :                 }
     592                 :            :         }
     593                 :            : #ifdef DEBUG /* integrity checks (Broadcom) */
     594                 :            :         if (hcd->core_if == NULL) {
     595                 :            :                 DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
     596                 :            :                 return -DWC_E_INVALID;
     597                 :            :         }
     598                 :            : #endif
     599   [ +  +  +  - ]:       7245 :         if (urb_qtd->in_process && qh->channel) {
     600                 :            :                 /* The QTD is in process (it has been assigned to a channel). */
     601         [ +  - ]:       6516 :                 if (hcd->flags.b.port_connect_status) {
     602                 :       6516 :                         int n = qh->channel->hc_num;
     603                 :            :                         /*
     604                 :            :                          * If still connected (i.e. in host mode), halt the
     605                 :            :                          * channel so it can be used for other transfers. If
     606                 :            :                          * no longer connected, the host registers can't be
     607                 :            :                          * written to halt the channel since the core is in
     608                 :            :                          * device mode.
     609                 :            :                          */
     610                 :            :                         /* In FIQ FSM mode, we need to shut down carefully.
     611                 :            :                          * The FIQ may attempt to restart a disabled channel */
     612   [ +  -  -  + ]:       6516 :                         if (fiq_fsm_enable && (hcd->fiq_state->channel[n].fsm != FIQ_PASSTHROUGH)) {
     613                 :            :                                 int retries = 3;
     614                 :            :                                 int running = 0;
     615                 :            :                                 enum fiq_fsm_state state;
     616                 :            : 
     617                 :          0 :                                 local_fiq_disable();
     618                 :          0 :                                 fiq_fsm_spin_lock(&hcd->fiq_state->lock);
     619                 :          0 :                                 qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
     620                 :          0 :                                 qh->channel->halt_pending = 1;
     621         [ #  # ]:          0 :                                 if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
     622                 :            :                                     hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
     623                 :          0 :                                         hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
     624                 :          0 :                                 fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
     625                 :          0 :                                 local_fiq_enable();
     626                 :            : 
     627         [ #  # ]:          0 :                                 if (dwc_qh_is_non_per(qh)) {
     628                 :            :                                         do {
     629                 :          0 :                                                 state = READ_ONCE(hcd->fiq_state->channel[n].fsm);
     630                 :            :                                                 running = (state != FIQ_NP_SPLIT_DONE) &&
     631                 :          0 :                                                           (state != FIQ_NP_SPLIT_LS_ABORTED) &&
     632                 :            :                                                           (state != FIQ_NP_SPLIT_HS_ABORTED);
     633         [ #  # ]:          0 :                                                 if (!running)
     634                 :            :                                                         break;
     635                 :          0 :                                                 udelay(125);
     636         [ #  # ]:          0 :                                         } while(--retries);
     637         [ #  # ]:          0 :                                         if (!retries)
     638                 :          0 :                                                 DWC_WARN("Timed out waiting for FSM NP transfer to complete on %d",
     639                 :            :                                                          qh->channel->hc_num);
     640                 :            :                                 }
     641                 :            :                         } else {
     642                 :       6516 :                                 dwc_otg_hc_halt(hcd->core_if, qh->channel,
     643                 :            :                                                 DWC_OTG_HC_XFER_URB_DEQUEUE);
     644                 :            :                         }
     645                 :            :                 }
     646                 :            :         }
     647                 :            : 
     648                 :            :         /*
     649                 :            :          * Free the QTD and clean up the associated QH. Leave the QH in the
     650                 :            :          * schedule if it has any remaining QTDs.
     651                 :            :          */
     652                 :            : 
     653                 :            :         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
     654                 :            :                     "delete %sQueue handler\n",
     655                 :            :                     hcd->core_if->dma_desc_enable?"DMA ":"");
     656         [ +  - ]:       7245 :         if (!hcd->core_if->dma_desc_enable) {
     657                 :       7245 :                 uint8_t b = urb_qtd->in_process;
     658   [ +  -  -  +  :       7245 :                 if (nak_holdoff && qh->do_split && dwc_qh_is_non_per(qh))
                   #  # ]
     659                 :          0 :                         qh->nak_frame = 0xFFFF;
     660                 :       7245 :                 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
     661         [ +  + ]:       7245 :                 if (b) {
     662                 :       6516 :                         dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
     663                 :       6516 :                         qh->channel = NULL;
     664         [ +  + ]:        729 :                 } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
     665                 :         17 :                         dwc_otg_hcd_qh_remove(hcd, qh);
     666                 :            :                 }
     667                 :            :         } else {
     668                 :          0 :                 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
     669                 :            :         }
     670                 :       7245 :         return 0;
     671                 :            : }
     672                 :            : 
     673                 :       2484 : int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
     674                 :            :                                  int retry)
     675                 :            : {
     676                 :            :         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
     677                 :            :         int retval = 0;
     678                 :            :         dwc_irqflags_t flags;
     679                 :            : 
     680         [ +  - ]:       2484 :         if (retry < 0) {
     681                 :            :                 retval = -DWC_E_INVALID;
     682                 :            :                 goto done;
     683                 :            :         }
     684                 :            : 
     685         [ +  + ]:       2484 :         if (!qh) {
     686                 :            :                 retval = -DWC_E_INVALID;
     687                 :            :                 goto done;
     688                 :            :         }
     689                 :            : 
     690                 :        828 :         DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
     691                 :            : 
     692   [ -  +  #  # ]:       1656 :         while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
     693                 :          0 :                 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
     694                 :          0 :                 retry--;
     695                 :          0 :                 dwc_msleep(5);
     696                 :          0 :                 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
     697                 :            :         }
     698                 :            : 
     699                 :        828 :         dwc_otg_hcd_qh_remove(hcd, qh);
     700                 :            : 
     701                 :        828 :         DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
     702                 :            :         /*
     703                 :            :          * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
     704                 :            :          * and qh_free to prevent stack dump on DWC_DMA_FREE() with
     705                 :            :          * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
     706                 :            :          * and dwc_otg_hcd_frame_list_alloc().
     707                 :            :          */
     708                 :        828 :         dwc_otg_hcd_qh_free(hcd, qh);
     709                 :            : 
     710                 :            : done:
     711                 :       2484 :         return retval;
     712                 :            : }
     713                 :            : 
     714                 :            : #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
     715                 :          0 : int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
     716                 :            : {
     717                 :            :         int retval = 0;
     718                 :            :         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
     719         [ #  # ]:          0 :         if (!qh)
     720                 :            :                 return -DWC_E_INVALID;
     721                 :            : 
     722                 :          0 :         qh->data_toggle = DWC_OTG_HC_PID_DATA0;
     723                 :          0 :         return retval;
     724                 :            : }
     725                 :            : #endif
     726                 :            : 
     727                 :            : /**
     728                 :            :  * HCD Callback structure for handling mode switching.
     729                 :            :  */
     730                 :            : static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
     731                 :            :         .start = dwc_otg_hcd_start_cb,
     732                 :            :         .stop = dwc_otg_hcd_stop_cb,
     733                 :            :         .disconnect = dwc_otg_hcd_disconnect_cb,
     734                 :            :         .session_start = dwc_otg_hcd_session_start_cb,
     735                 :            :         .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
     736                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
     737                 :            :         .sleep = dwc_otg_hcd_sleep_cb,
     738                 :            : #endif
     739                 :            :         .p = 0,
     740                 :            : };
     741                 :            : 
     742                 :            : /**
     743                 :            :  * Reset tasklet function
     744                 :            :  */
     745                 :          0 : static void reset_tasklet_func(void *data)
     746                 :            : {
     747                 :            :         dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
     748                 :          0 :         dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
     749                 :            :         hprt0_data_t hprt0;
     750                 :            : 
     751                 :            :         DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
     752                 :            : 
     753                 :          0 :         hprt0.d32 = dwc_otg_read_hprt0(core_if);
     754                 :          0 :         hprt0.b.prtrst = 1;
     755                 :          0 :         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
     756                 :          0 :         dwc_mdelay(60);
     757                 :            : 
     758                 :          0 :         hprt0.b.prtrst = 0;
     759                 :          0 :         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
     760                 :          0 :         dwc_otg_hcd->flags.b.port_reset_change = 1;
     761                 :          0 : }
     762                 :            : 
     763                 :     115051 : static void completion_tasklet_func(void *ptr)
     764                 :            : {
     765                 :            :         dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;
     766                 :            :         struct urb *urb;
     767                 :            :         urb_tq_entry_t *item;
     768                 :            :         dwc_irqflags_t flags;
     769                 :            : 
     770                 :            :         /* This could just be spin_lock_irq */
     771                 :     115051 :         DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
     772         [ +  + ]:     349275 :         while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
     773                 :            :                 item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
     774                 :     119173 :                 urb = item->urb;
     775         [ +  + ]:     119173 :                 DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,
     776                 :            :                                 urb_tq_entries);
     777                 :     119173 :                 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
     778                 :     119173 :                 DWC_FREE(item);
     779                 :            : 
     780                 :     119173 :                 usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
     781                 :            : 
     782                 :            : 
     783                 :     119173 :                 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
     784                 :            :         }
     785                 :     115051 :         DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
     786                 :     115051 :         return;
     787                 :            : }
     788                 :            : 
     789                 :          0 : static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
     790                 :            : {
     791                 :            :         dwc_list_link_t *item;
     792                 :            :         dwc_otg_qh_t *qh;
     793                 :            :         dwc_irqflags_t flags;
     794                 :            : 
     795         [ #  # ]:          0 :         if (!qh_list->next) {
     796                 :            :                 /* The list hasn't been initialized yet. */
     797                 :          0 :                 return;
     798                 :            :         }
     799                 :            :         /*
     800                 :            :          * Hold spinlock here. Not needed in that case if bellow
     801                 :            :          * function is being called from ISR
     802                 :            :          */
     803                 :          0 :         DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
     804                 :            :         /* Ensure there are no QTDs or URBs left. */
     805                 :          0 :         kill_urbs_in_qh_list(hcd, qh_list);
     806                 :          0 :         DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
     807                 :            : 
     808         [ #  # ]:          0 :         DWC_LIST_FOREACH(item, qh_list) {
     809                 :          0 :                 qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
     810                 :          0 :                 dwc_otg_hcd_qh_remove_and_free(hcd, qh);
     811                 :            :         }
     812                 :            : }
     813                 :            : 
     814                 :            : /**
     815                 :            :  * Exit from Hibernation if Host did not detect SRP from connected SRP capable
     816                 :            :  * Device during SRP time by host power up.
     817                 :            :  */
     818                 :          0 : void dwc_otg_hcd_power_up(void *ptr)
     819                 :            : {
     820                 :          0 :         gpwrdn_data_t gpwrdn = {.d32 = 0 };
     821                 :            :         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
     822                 :            : 
     823                 :          0 :         DWC_PRINTF("%s called\n", __FUNCTION__);
     824                 :            : 
     825         [ #  # ]:          0 :         if (!core_if->hibernation_suspend) {
     826                 :          0 :                 DWC_PRINTF("Already exited from Hibernation\n");
     827                 :          0 :                 return;
     828                 :            :         }
     829                 :            : 
     830                 :            :         /* Switch on the voltage to the core */
     831                 :          0 :         gpwrdn.b.pwrdnswtch = 1;
     832                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
     833                 :          0 :         dwc_udelay(10);
     834                 :            : 
     835                 :            :         /* Reset the core */
     836                 :          0 :         gpwrdn.d32 = 0;
     837                 :          0 :         gpwrdn.b.pwrdnrstn = 1;
     838                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
     839                 :          0 :         dwc_udelay(10);
     840                 :            : 
     841                 :            :         /* Disable power clamps */
     842                 :          0 :         gpwrdn.d32 = 0;
     843                 :          0 :         gpwrdn.b.pwrdnclmp = 1;
     844                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
     845                 :            : 
     846                 :            :         /* Remove reset the core signal */
     847                 :          0 :         gpwrdn.d32 = 0;
     848                 :          0 :         gpwrdn.b.pwrdnrstn = 1;
     849                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
     850                 :          0 :         dwc_udelay(10);
     851                 :            : 
     852                 :            :         /* Disable PMU interrupt */
     853                 :          0 :         gpwrdn.d32 = 0;
     854                 :          0 :         gpwrdn.b.pmuintsel = 1;
     855                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
     856                 :            : 
     857                 :          0 :         core_if->hibernation_suspend = 0;
     858                 :            : 
     859                 :            :         /* Disable PMU */
     860                 :          0 :         gpwrdn.d32 = 0;
     861                 :          0 :         gpwrdn.b.pmuactv = 1;
     862                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
     863                 :          0 :         dwc_udelay(10);
     864                 :            : 
     865                 :            :         /* Enable VBUS */
     866                 :          0 :         gpwrdn.d32 = 0;
     867                 :          0 :         gpwrdn.b.dis_vbus = 1;
     868                 :          0 :         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
     869                 :            : 
     870                 :          0 :         core_if->op_state = A_HOST;
     871                 :          0 :         dwc_otg_core_init(core_if);
     872                 :          0 :         dwc_otg_enable_global_interrupts(core_if);
     873                 :            :         cil_hcd_start(core_if);
     874                 :            : }
     875                 :            : 
     876                 :    4331631 : void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num)
     877                 :            : {
     878                 :    4331631 :         struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
     879                 :    4331631 :         struct fiq_dma_blob *blob = hcd->fiq_dmab;
     880                 :            :         int i;
     881                 :            : 
     882                 :    4331631 :         st->fsm = FIQ_PASSTHROUGH;
     883                 :    4331631 :         st->hcchar_copy.d32 = 0;
     884                 :    4331631 :         st->hcsplt_copy.d32 = 0;
     885                 :    4331631 :         st->hcint_copy.d32 = 0;
     886                 :    4331631 :         st->hcintmsk_copy.d32 = 0;
     887                 :    4331631 :         st->hctsiz_copy.d32 = 0;
     888                 :    4331631 :         st->hcdma_copy.d32 = 0;
     889                 :    4331631 :         st->nr_errors = 0;
     890                 :    4331631 :         st->hub_addr = 0;
     891                 :    4331631 :         st->port_addr = 0;
     892                 :    4331631 :         st->expected_uframe = 0;
     893                 :    4331631 :         st->nrpackets = 0;
     894                 :    4331631 :         st->dma_info.index = 0;
     895         [ +  + ]:   30321417 :         for (i = 0; i < 6; i++)
     896                 :   25989786 :                 st->dma_info.slot_len[i] = 255;
     897                 :    4331631 :         st->hs_isoc_info.index = 0;
     898                 :    4331631 :         st->hs_isoc_info.iso_desc = NULL;
     899                 :    4331631 :         st->hs_isoc_info.nrframes = 0;
     900                 :            : 
     901                 :    4331631 :         DWC_MEMSET(&blob->channel[num].index[0], 0x6b, 1128);
     902                 :    4331631 : }
     903                 :            : 
     904                 :            : /**
     905                 :            :  * Frees secondary storage associated with the dwc_otg_hcd structure contained
     906                 :            :  * in the struct usb_hcd field.
     907                 :            :  */
     908                 :          0 : static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
     909                 :            : {
     910                 :            :         struct device *dev = dwc_otg_hcd_to_dev(dwc_otg_hcd);
     911                 :            :         int i;
     912                 :            : 
     913                 :            :         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
     914                 :            : 
     915                 :            :         del_timers(dwc_otg_hcd);
     916                 :            : 
     917                 :            :         /* Free memory for QH/QTD lists */
     918                 :          0 :         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
     919                 :          0 :         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
     920                 :          0 :         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
     921                 :          0 :         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
     922                 :          0 :         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
     923                 :          0 :         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
     924                 :            : 
     925                 :            :         /* Free memory for the host channels. */
     926         [ #  # ]:          0 :         for (i = 0; i < MAX_EPS_CHANNELS; i++) {
     927                 :          0 :                 dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
     928                 :            : 
     929                 :            : #ifdef DEBUG
     930                 :            :                 if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
     931                 :            :                         DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
     932                 :            :                 }
     933                 :            : #endif
     934         [ #  # ]:          0 :                 if (hc != NULL) {
     935                 :            :                         DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
     936                 :            :                                     i, hc);
     937                 :          0 :                         DWC_FREE(hc);
     938                 :            :                 }
     939                 :            :         }
     940                 :            : 
     941         [ #  # ]:          0 :         if (dwc_otg_hcd->core_if->dma_enable) {
     942         [ #  # ]:          0 :                 if (dwc_otg_hcd->status_buf_dma) {
     943                 :          0 :                         DWC_DMA_FREE(dev, DWC_OTG_HCD_STATUS_BUF_SIZE,
     944                 :            :                                      dwc_otg_hcd->status_buf,
     945                 :            :                                      dwc_otg_hcd->status_buf_dma);
     946                 :            :                 }
     947         [ #  # ]:          0 :         } else if (dwc_otg_hcd->status_buf != NULL) {
     948                 :          0 :                 DWC_FREE(dwc_otg_hcd->status_buf);
     949                 :            :         }
     950                 :          0 :         DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
     951                 :            :         /* Set core_if's lock pointer to NULL */
     952                 :          0 :         dwc_otg_hcd->core_if->lock = NULL;
     953                 :            : 
     954                 :          0 :         DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
     955                 :          0 :         DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
     956                 :          0 :         DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
     957                 :          0 :         DWC_DMA_FREE(dev, 16, dwc_otg_hcd->fiq_state->dummy_send,
     958                 :            :                      dwc_otg_hcd->fiq_state->dummy_send_dma);
     959                 :          0 :         DWC_FREE(dwc_otg_hcd->fiq_state);
     960                 :            : 
     961                 :            : #ifdef DWC_DEV_SRPCAP
     962                 :            :         if (dwc_otg_hcd->core_if->power_down == 2 &&
     963                 :            :             dwc_otg_hcd->core_if->pwron_timer) {
     964                 :            :                 DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
     965                 :            :         }
     966                 :            : #endif
     967                 :          0 :         DWC_FREE(dwc_otg_hcd);
     968                 :          0 : }
     969                 :            : 
     970                 :        207 : int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
     971                 :            : {
     972                 :            :         struct device *dev = dwc_otg_hcd_to_dev(hcd);
     973                 :            :         int retval = 0;
     974                 :            :         int num_channels;
     975                 :            :         int i;
     976                 :            :         dwc_hc_t *channel;
     977                 :            : 
     978                 :            : #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
     979                 :            :         DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->lock);
     980                 :            : #else
     981                 :        207 :         hcd->lock = DWC_SPINLOCK_ALLOC();
     982                 :            : #endif
     983                 :            :         DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
     984                 :            :                     hcd, core_if);
     985         [ -  + ]:        207 :         if (!hcd->lock) {
     986                 :          0 :                 DWC_ERROR("Could not allocate lock for pcd");
     987                 :          0 :                 DWC_FREE(hcd);
     988                 :            :                 retval = -DWC_E_NO_MEMORY;
     989                 :          0 :                 goto out;
     990                 :            :         }
     991                 :        207 :         hcd->core_if = core_if;
     992                 :            : 
     993                 :            :         /* Register the HCD CIL Callbacks */
     994                 :        207 :         dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
     995                 :            :                                            &hcd_cil_callbacks, hcd);
     996                 :            : 
     997                 :            :         /* Initialize the non-periodic schedule. */
     998                 :        207 :         DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
     999                 :        207 :         DWC_LIST_INIT(&hcd->non_periodic_sched_active);
    1000                 :            : 
    1001                 :            :         /* Initialize the periodic schedule. */
    1002                 :        207 :         DWC_LIST_INIT(&hcd->periodic_sched_inactive);
    1003                 :        207 :         DWC_LIST_INIT(&hcd->periodic_sched_ready);
    1004                 :        207 :         DWC_LIST_INIT(&hcd->periodic_sched_assigned);
    1005                 :        207 :         DWC_LIST_INIT(&hcd->periodic_sched_queued);
    1006                 :        207 :         DWC_TAILQ_INIT(&hcd->completed_urb_list);
    1007                 :            :         /*
    1008                 :            :          * Create a host channel descriptor for each host channel implemented
    1009                 :            :          * in the controller. Initialize the channel descriptor array.
    1010                 :            :          */
    1011                 :        207 :         DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
    1012                 :        207 :         num_channels = hcd->core_if->core_params->host_channels;
    1013                 :        207 :         DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
    1014         [ +  + ]:       1863 :         for (i = 0; i < num_channels; i++) {
    1015                 :       1656 :                 channel = DWC_ALLOC(sizeof(dwc_hc_t));
    1016         [ -  + ]:       1656 :                 if (channel == NULL) {
    1017                 :            :                         retval = -DWC_E_NO_MEMORY;
    1018                 :          0 :                         DWC_ERROR("%s: host channel allocation failed\n",
    1019                 :            :                                   __func__);
    1020                 :          0 :                         dwc_otg_hcd_free(hcd);
    1021                 :          0 :                         goto out;
    1022                 :            :                 }
    1023                 :       1656 :                 channel->hc_num = i;
    1024                 :       1656 :                 hcd->hc_ptr_array[i] = channel;
    1025                 :            : #ifdef DEBUG
    1026                 :            :                 hcd->core_if->hc_xfer_timer[i] =
    1027                 :            :                     DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
    1028                 :            :                                     &hcd->core_if->hc_xfer_info[i]);
    1029                 :            : #endif
    1030                 :            :                 DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
    1031                 :            :                             channel);
    1032                 :            :         }
    1033                 :            : 
    1034         [ +  - ]:        207 :         if (fiq_enable) {
    1035                 :        207 :                 hcd->fiq_state = DWC_ALLOC(sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels));
    1036         [ -  + ]:        207 :                 if (!hcd->fiq_state) {
    1037                 :            :                         retval = -DWC_E_NO_MEMORY;
    1038                 :          0 :                         DWC_ERROR("%s: cannot allocate fiq_state structure\n", __func__);
    1039                 :          0 :                         dwc_otg_hcd_free(hcd);
    1040                 :          0 :                         goto out;
    1041                 :            :                 }
    1042                 :        207 :                 DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels)));
    1043                 :            : 
    1044                 :            : #ifdef CONFIG_ARM64
    1045                 :            :                 spin_lock_init(&hcd->fiq_state->lock);
    1046                 :            : #endif
    1047                 :            : 
    1048         [ +  + ]:       1863 :                 for (i = 0; i < num_channels; i++) {
    1049                 :       1656 :                         hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
    1050                 :            :                 }
    1051                 :        207 :                 hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
    1052                 :            :                                                          &hcd->fiq_state->dummy_send_dma);
    1053                 :            : 
    1054                 :        207 :                 hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack));
    1055         [ -  + ]:        207 :                 if (!hcd->fiq_stack) {
    1056                 :            :                         retval = -DWC_E_NO_MEMORY;
    1057                 :          0 :                         DWC_ERROR("%s: cannot allocate fiq_stack structure\n", __func__);
    1058                 :          0 :                         dwc_otg_hcd_free(hcd);
    1059                 :          0 :                         goto out;
    1060                 :            :                 }
    1061                 :        207 :                 hcd->fiq_stack->magic1 = 0xDEADBEEF;
    1062                 :        207 :                 hcd->fiq_stack->magic2 = 0xD00DFEED;
    1063                 :        207 :                 hcd->fiq_state->gintmsk_saved.d32 = ~0;
    1064                 :        207 :                 hcd->fiq_state->haintmsk_saved.b2.chint = ~0;
    1065                 :            : 
    1066                 :            :                 /* This bit is terrible and uses no API, but necessary. The FIQ has no concept of DMA pools
    1067                 :            :                  * (and if it did, would be a lot slower). This allocates a chunk of memory (~9kiB for 8 host channels)
    1068                 :            :                  * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some
    1069                 :            :                  * moderately readable array casts.
    1070                 :            :                  */
    1071                 :        207 :                 hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base);
    1072                 :        207 :                 DWC_WARN("FIQ DMA bounce buffers: virt = %px dma = %pad len=%zu",
    1073                 :            :                                 hcd->fiq_dmab, &hcd->fiq_state->dma_base,
    1074                 :            :                                 sizeof(struct fiq_dma_channel) * num_channels);
    1075                 :            : 
    1076                 :        207 :                 DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024);
    1077                 :            : 
    1078                 :            :                 /* pointer for debug in fiq_print */
    1079                 :        207 :                 hcd->fiq_state->fiq_dmab = hcd->fiq_dmab;
    1080         [ +  - ]:        207 :                 if (fiq_fsm_enable) {
    1081                 :            :                         int i;
    1082         [ +  + ]:       1656 :                         for (i=0; i < hcd->core_if->core_params->host_channels; i++) {
    1083                 :       1656 :                                 dwc_otg_cleanup_fiq_channel(hcd, i);
    1084                 :            :                         }
    1085   [ -  +  -  +  :        828 :                         DWC_PRINTF("FIQ FSM acceleration enabled for :\n%s%s%s%s",
             -  +  -  + ]
    1086                 :        207 :                                 (fiq_fsm_mask & 0x1) ? "Non-periodic Split Transactions\n" : "",
    1087                 :        207 :                                 (fiq_fsm_mask & 0x2) ? "Periodic Split Transactions\n" : "",
    1088                 :        207 :                                 (fiq_fsm_mask & 0x4) ? "High-Speed Isochronous Endpoints\n" : "",
    1089                 :        207 :                                 (fiq_fsm_mask & 0x8) ? "Interrupt/Control Split Transaction hack enabled\n" : "");
    1090                 :            :                 }
    1091                 :            :         }
    1092                 :            : 
    1093                 :            :         /* Initialize the Connection timeout timer. */
    1094                 :        207 :         hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
    1095                 :            :                                           dwc_otg_hcd_connect_timeout, 0);
    1096                 :            : 
    1097         [ -  + ]:        207 :         printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
    1098         [ +  - ]:        207 :         if (microframe_schedule)
    1099                 :        207 :                 init_hcd_usecs(hcd);
    1100                 :            : 
    1101                 :            :         /* Initialize reset tasklet. */
    1102                 :        207 :         hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
    1103                 :            : 
    1104                 :        207 :         hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",
    1105                 :            :                                                 completion_tasklet_func, hcd);
    1106                 :            : #ifdef DWC_DEV_SRPCAP
    1107                 :            :         if (hcd->core_if->power_down == 2) {
    1108                 :            :                 /* Initialize Power on timer for Host power up in case hibernation */
    1109                 :            :                 hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
    1110                 :            :                                                                         dwc_otg_hcd_power_up, core_if);
    1111                 :            :         }
    1112                 :            : #endif
    1113                 :            : 
    1114                 :            :         /*
    1115                 :            :          * Allocate space for storing data on status transactions. Normally no
    1116                 :            :          * data is sent, but this space acts as a bit bucket. This must be
    1117                 :            :          * done after usb_add_hcd since that function allocates the DMA buffer
    1118                 :            :          * pool.
    1119                 :            :          */
    1120         [ +  - ]:        207 :         if (hcd->core_if->dma_enable) {
    1121                 :        207 :                 hcd->status_buf =
    1122                 :        207 :                     DWC_DMA_ALLOC(dev, DWC_OTG_HCD_STATUS_BUF_SIZE,
    1123                 :            :                                   &hcd->status_buf_dma);
    1124                 :            :         } else {
    1125                 :          0 :                 hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
    1126                 :            :         }
    1127         [ -  + ]:        207 :         if (!hcd->status_buf) {
    1128                 :            :                 retval = -DWC_E_NO_MEMORY;
    1129                 :          0 :                 DWC_ERROR("%s: status_buf allocation failed\n", __func__);
    1130                 :          0 :                 dwc_otg_hcd_free(hcd);
    1131                 :          0 :                 goto out;
    1132                 :            :         }
    1133                 :            : 
    1134                 :        207 :         hcd->otg_port = 1;
    1135                 :        207 :         hcd->frame_list = NULL;
    1136                 :        207 :         hcd->frame_list_dma = 0;
    1137                 :        207 :         hcd->periodic_qh_count = 0;
    1138                 :            : 
    1139                 :        207 :         DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port));
    1140                 :            : #ifdef FIQ_DEBUG
    1141                 :            :         DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc));
    1142                 :            : #endif
    1143                 :            : 
    1144                 :            : out:
    1145                 :        207 :         return retval;
    1146                 :            : }
    1147                 :            : 
    1148                 :          0 : void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
    1149                 :            : {
    1150                 :            :         /* Turn off all host-specific interrupts. */
    1151                 :          0 :         dwc_otg_disable_host_interrupts(hcd->core_if);
    1152                 :            : 
    1153                 :          0 :         dwc_otg_hcd_free(hcd);
    1154                 :          0 : }
    1155                 :            : 
    1156                 :            : /**
    1157                 :            :  * Initializes dynamic portions of the DWC_otg HCD state.
    1158                 :            :  */
    1159                 :        207 : static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
    1160                 :            : {
    1161                 :            :         int num_channels;
    1162                 :            :         int i;
    1163                 :            :         dwc_hc_t *channel;
    1164                 :            :         dwc_hc_t *channel_tmp;
    1165                 :            : 
    1166                 :        207 :         hcd->flags.d32 = 0;
    1167                 :            : 
    1168                 :        207 :         hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
    1169         [ -  + ]:        207 :         if (!microframe_schedule) {
    1170                 :          0 :                 hcd->non_periodic_channels = 0;
    1171                 :          0 :                 hcd->periodic_channels = 0;
    1172                 :            :         } else {
    1173                 :        207 :                 hcd->available_host_channels = hcd->core_if->core_params->host_channels;
    1174                 :            :         }
    1175                 :            :         /*
    1176                 :            :          * Put all channels in the free channel list and clean up channel
    1177                 :            :          * states.
    1178                 :            :          */
    1179         [ -  + ]:        207 :         DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
    1180                 :            :                                  &hcd->free_hc_list, hc_list_entry) {
    1181   [ #  #  #  # ]:          0 :                 DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
    1182                 :            :         }
    1183                 :            : 
    1184                 :        207 :         num_channels = hcd->core_if->core_params->host_channels;
    1185         [ +  + ]:       1863 :         for (i = 0; i < num_channels; i++) {
    1186                 :       1656 :                 channel = hcd->hc_ptr_array[i];
    1187         [ +  + ]:       1656 :                 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
    1188                 :            :                                         hc_list_entry);
    1189                 :       1656 :                 dwc_otg_hc_cleanup(hcd->core_if, channel);
    1190                 :            :         }
    1191                 :            : 
    1192                 :            :         /* Initialize the DWC core for host mode operation. */
    1193                 :        207 :         dwc_otg_core_host_init(hcd->core_if);
    1194                 :            : 
    1195                 :            :         /* Set core_if's lock pointer to the hcd->lock */
    1196                 :        207 :         hcd->core_if->lock = hcd->lock;
    1197                 :        207 : }
    1198                 :            : 
    1199                 :            : /**
    1200                 :            :  * Assigns transactions from a QTD to a free host channel and initializes the
    1201                 :            :  * host channel to perform the transactions. The host channel is removed from
    1202                 :            :  * the free list.
    1203                 :            :  *
    1204                 :            :  * @param hcd The HCD state structure.
    1205                 :            :  * @param qh Transactions from the first QTD for this QH are selected and
    1206                 :            :  * assigned to a free host channel.
    1207                 :            :  */
    1208                 :    7077032 : static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
    1209                 :            : {
    1210                 :            :         dwc_hc_t *hc;
    1211                 :            :         dwc_otg_qtd_t *qtd;
    1212                 :            :         dwc_otg_hcd_urb_t *urb;
    1213                 :            :         void* ptr = NULL;
    1214                 :            :         uint16_t wLength;
    1215                 :            :         uint32_t intr_enable;
    1216                 :            :         unsigned long flags;
    1217                 :    7077032 :         gintmsk_data_t gintmsk = { .d32 = 0, };
    1218                 :            :         struct device *dev = dwc_otg_hcd_to_dev(hcd);
    1219                 :            : 
    1220                 :    7077032 :         qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
    1221                 :            : 
    1222                 :    7077032 :         urb = qtd->urb;
    1223                 :            : 
    1224                 :            :         DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
    1225                 :            : 
    1226   [ -  +  #  # ]:    7077032 :         if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
    1227                 :          0 :                 urb->actual_length = urb->length;
    1228                 :            : 
    1229                 :            : 
    1230                 :    7077032 :         hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
    1231                 :            : 
    1232                 :            :         /* Remove the host channel from the free list. */
    1233   [ -  +  +  - ]:    7077032 :         DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
    1234                 :            : 
    1235                 :    7077032 :         qh->channel = hc;
    1236                 :            : 
    1237                 :    7077032 :         qtd->in_process = 1;
    1238                 :            : 
    1239                 :            :         /*
    1240                 :            :          * Use usb_pipedevice to determine device address. This address is
    1241                 :            :          * 0 before the SET_ADDRESS command and the correct address afterward.
    1242                 :            :          */
    1243                 :    7077032 :         hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
    1244                 :    7077032 :         hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
    1245                 :    7077032 :         hc->speed = qh->dev_speed;
    1246                 :    7077032 :         hc->max_packet = dwc_max_packet(qh->maxp);
    1247                 :            : 
    1248                 :    7077032 :         hc->xfer_started = 0;
    1249                 :    7077032 :         hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
    1250                 :    7077032 :         hc->error_state = (qtd->error_count > 0);
    1251                 :    7077032 :         hc->halt_on_queue = 0;
    1252                 :    7077032 :         hc->halt_pending = 0;
    1253                 :    7077032 :         hc->requests = 0;
    1254                 :            : 
    1255                 :            :         /*
    1256                 :            :          * The following values may be modified in the transfer type section
    1257                 :            :          * below. The xfer_len value may be reduced when the transfer is
    1258                 :            :          * started to accommodate the max widths of the XferSize and PktCnt
    1259                 :            :          * fields in the HCTSIZn register.
    1260                 :            :          */
    1261                 :            : 
    1262                 :    7077032 :         hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
    1263         [ +  + ]:    7077032 :         if (hc->ep_is_in) {
    1264                 :    6953735 :                 hc->do_ping = 0;
    1265                 :            :         } else {
    1266                 :     123297 :                 hc->do_ping = qh->ping_state;
    1267                 :            :         }
    1268                 :            : 
    1269                 :    7077032 :         hc->data_pid_start = qh->data_toggle;
    1270                 :    7077032 :         hc->multi_count = 1;
    1271                 :            : 
    1272         [ +  - ]:    7077032 :         if (hcd->core_if->dma_enable) {
    1273                 :    7077032 :                 hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
    1274                 :            : 
    1275                 :            :                 /* For non-dword aligned case */
    1276         [ +  + ]:    7077032 :                 if (((unsigned long)hc->xfer_buff & 0x3)
    1277         [ +  - ]:      15517 :                     && !hcd->core_if->dma_desc_enable) {
    1278                 :      15517 :                         ptr = (uint8_t *) urb->buf + urb->actual_length;
    1279                 :            :                 }
    1280                 :            :         } else {
    1281                 :          0 :                 hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
    1282                 :            :         }
    1283                 :    7077032 :         hc->xfer_len = urb->length - urb->actual_length;
    1284                 :    7077032 :         hc->xfer_count = 0;
    1285                 :            : 
    1286                 :            :         /*
    1287                 :            :          * Set the split attributes
    1288                 :            :          */
    1289                 :    7077032 :         hc->do_split = 0;
    1290         [ +  + ]:    7077032 :         if (qh->do_split) {
    1291                 :            :                 uint32_t hub_addr, port_addr;
    1292                 :    4329979 :                 hc->do_split = 1;
    1293                 :    4329979 :                 hc->start_pkt_count = 1;
    1294                 :    4329979 :                 hc->xact_pos = qtd->isoc_split_pos;
    1295                 :            :                 /* We don't need to do complete splits anymore */
    1296                 :            : //              if(fiq_fsm_enable)
    1297                 :            :                 if (0)
    1298                 :            :                         hc->complete_split = qtd->complete_split = 0;
    1299                 :            :                 else
    1300                 :    4329979 :                         hc->complete_split = qtd->complete_split;
    1301                 :            : 
    1302                 :    4329979 :                 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
    1303                 :    4329979 :                 hc->hub_addr = (uint8_t) hub_addr;
    1304                 :    4329979 :                 hc->port_addr = (uint8_t) port_addr;
    1305                 :            :         }
    1306                 :            : 
    1307   [ +  +  +  -  :    7077032 :         switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
                      - ]
    1308                 :            :         case UE_CONTROL:
    1309                 :     313142 :                 hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
    1310   [ +  +  +  - ]:     313142 :                 switch (qtd->control_phase) {
    1311                 :            :                 case DWC_OTG_CONTROL_SETUP:
    1312                 :            :                         DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
    1313                 :     101290 :                         hc->do_ping = 0;
    1314                 :     101290 :                         hc->ep_is_in = 0;
    1315                 :     101290 :                         hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
    1316         [ +  - ]:     101290 :                         if (hcd->core_if->dma_enable) {
    1317                 :     101290 :                                 hc->xfer_buff = (uint8_t *) urb->setup_dma;
    1318                 :            :                         } else {
    1319                 :          0 :                                 hc->xfer_buff = (uint8_t *) urb->setup_packet;
    1320                 :            :                         }
    1321                 :     101290 :                         hc->xfer_len = 8;
    1322                 :            :                         ptr = NULL;
    1323                 :     101290 :                         break;
    1324                 :            :                 case DWC_OTG_CONTROL_DATA:
    1325                 :            :                         DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
    1326                 :            :                         /*
    1327                 :            :                          * Hardware bug: small IN packets with length < 4
    1328                 :            :                          * cause a 4-byte write to memory. We can only catch
    1329                 :            :                          * the case where we know a short packet is going to be
    1330                 :            :                          * returned in a control transfer, as the length is
    1331                 :            :                          * specified in the setup packet. This is only an issue
    1332                 :            :                          * for drivers that insist on packing a device's various
    1333                 :            :                          * properties into a struct and querying them one at a
    1334                 :            :                          * time (uvcvideo).
    1335                 :            :                          * Force the use of align_buf so that the subsequent
    1336                 :            :                          * memcpy puts the right number of bytes in the URB's
    1337                 :            :                          * buffer.
    1338                 :            :                          */
    1339                 :     110309 :                         wLength = ((uint16_t *)urb->setup_packet)[3];
    1340   [ +  +  +  + ]:     110309 :                         if (hc->ep_is_in && wLength < 4)
    1341                 :        207 :                                 ptr = hc->xfer_buff;
    1342                 :            : 
    1343                 :     110309 :                         hc->data_pid_start = qtd->data_toggle;
    1344                 :     110309 :                         break;
    1345                 :            :                 case DWC_OTG_CONTROL_STATUS:
    1346                 :            :                         /*
    1347                 :            :                          * Direction is opposite of data direction or IN if no
    1348                 :            :                          * data.
    1349                 :            :                          */
    1350                 :            :                         DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
    1351         [ +  + ]:     101543 :                         if (urb->length == 0) {
    1352                 :       7256 :                                 hc->ep_is_in = 1;
    1353                 :            :                         } else {
    1354                 :      94287 :                                 hc->ep_is_in =
    1355                 :            :                                     dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
    1356                 :            :                         }
    1357         [ +  + ]:     101543 :                         if (hc->ep_is_in) {
    1358                 :      40373 :                                 hc->do_ping = 0;
    1359                 :            :                         }
    1360                 :            : 
    1361                 :     101543 :                         hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
    1362                 :            : 
    1363                 :     101543 :                         hc->xfer_len = 0;
    1364         [ +  - ]:     101543 :                         if (hcd->core_if->dma_enable) {
    1365                 :     101543 :                                 hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
    1366                 :            :                         } else {
    1367                 :          0 :                                 hc->xfer_buff = (uint8_t *) hcd->status_buf;
    1368                 :            :                         }
    1369                 :            :                         ptr = NULL;
    1370                 :            :                         break;
    1371                 :            :                 }
    1372                 :            :                 break;
    1373                 :            :         case UE_BULK:
    1374                 :      24385 :                 hc->ep_type = DWC_OTG_EP_TYPE_BULK;
    1375                 :      24385 :                 break;
    1376                 :            :         case UE_INTERRUPT:
    1377                 :    6739505 :                 hc->ep_type = DWC_OTG_EP_TYPE_INTR;
    1378                 :    6739505 :                 break;
    1379                 :            :         case UE_ISOCHRONOUS:
    1380                 :            :                 {
    1381                 :            :                         struct dwc_otg_hcd_iso_packet_desc *frame_desc;
    1382                 :            : 
    1383                 :          0 :                         hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
    1384                 :            : 
    1385         [ #  # ]:          0 :                         if (hcd->core_if->dma_desc_enable)
    1386                 :            :                                 break;
    1387                 :            : 
    1388                 :          0 :                         frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
    1389                 :            : 
    1390                 :          0 :                         frame_desc->status = 0;
    1391                 :            : 
    1392         [ #  # ]:          0 :                         if (hcd->core_if->dma_enable) {
    1393                 :          0 :                                 hc->xfer_buff = (uint8_t *) urb->dma;
    1394                 :            :                         } else {
    1395                 :          0 :                                 hc->xfer_buff = (uint8_t *) urb->buf;
    1396                 :            :                         }
    1397                 :          0 :                         hc->xfer_buff +=
    1398                 :          0 :                             frame_desc->offset + qtd->isoc_split_offset;
    1399                 :          0 :                         hc->xfer_len =
    1400                 :          0 :                             frame_desc->length - qtd->isoc_split_offset;
    1401                 :            : 
    1402                 :            :                         /* For non-dword aligned buffers */
    1403         [ #  # ]:          0 :                         if (((unsigned long)hc->xfer_buff & 0x3)
    1404         [ #  # ]:          0 :                             && hcd->core_if->dma_enable) {
    1405                 :          0 :                                 ptr =
    1406                 :          0 :                                     (uint8_t *) urb->buf + frame_desc->offset +
    1407                 :          0 :                                     qtd->isoc_split_offset;
    1408                 :            :                         } else
    1409                 :            :                                 ptr = NULL;
    1410                 :            : 
    1411         [ #  # ]:          0 :                         if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
    1412         [ #  # ]:          0 :                                 if (hc->xfer_len <= 188) {
    1413                 :          0 :                                         hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
    1414                 :            :                                 } else {
    1415                 :          0 :                                         hc->xact_pos =
    1416                 :            :                                             DWC_HCSPLIT_XACTPOS_BEGIN;
    1417                 :            :                                 }
    1418                 :            :                         }
    1419                 :            :                 }
    1420                 :            :                 break;
    1421                 :            :         }
    1422                 :            :         /* non DWORD-aligned buffer case */
    1423         [ +  + ]:    7077032 :         if (ptr) {
    1424                 :            :                 uint32_t buf_size;
    1425         [ +  - ]:      10100 :                 if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
    1426                 :      10100 :                         buf_size = hcd->core_if->core_params->max_transfer_size;
    1427                 :            :                 } else {
    1428                 :            :                         buf_size = 4096;
    1429                 :            :                 }
    1430         [ +  + ]:      10100 :                 if (!qh->dw_align_buf) {
    1431                 :        414 :                         qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(dev, buf_size,
    1432                 :            :                                                          &qh->dw_align_buf_dma);
    1433         [ -  + ]:        414 :                         if (!qh->dw_align_buf) {
    1434                 :          0 :                                 DWC_ERROR
    1435                 :            :                                     ("%s: Failed to allocate memory to handle "
    1436                 :            :                                      "non-dword aligned buffer case\n",
    1437                 :            :                                      __func__);
    1438                 :    7077032 :                                 return;
    1439                 :            :                         }
    1440                 :            :                 }
    1441         [ +  + ]:      10100 :                 if (!hc->ep_is_in) {
    1442                 :       9893 :                         dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
    1443                 :            :                 }
    1444                 :      10100 :                 hc->align_buff = qh->dw_align_buf_dma;
    1445                 :            :         } else {
    1446                 :    7066932 :                 hc->align_buff = 0;
    1447                 :            :         }
    1448                 :            : 
    1449         [ +  + ]:    7077032 :         if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
    1450                 :            :             hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
    1451                 :            :                 /*
    1452                 :            :                  * This value may be modified when the transfer is started to
    1453                 :            :                  * reflect the actual transfer length.
    1454                 :            :                  */
    1455                 :    6739505 :                 hc->multi_count = dwc_hb_mult(qh->maxp);
    1456                 :            :         }
    1457                 :            : 
    1458         [ -  + ]:    7077032 :         if (hcd->core_if->dma_desc_enable)
    1459                 :          0 :                 hc->desc_list_addr = qh->desc_list_dma;
    1460                 :            : 
    1461                 :    7077032 :         dwc_otg_hc_init(hcd->core_if, hc);
    1462                 :            : 
    1463                 :    7077032 :         local_irq_save(flags);
    1464                 :            : 
    1465         [ +  - ]:    7077032 :         if (fiq_enable) {
    1466                 :    7077032 :                 local_fiq_disable();
    1467                 :    7077032 :                 fiq_fsm_spin_lock(&hcd->fiq_state->lock);
    1468                 :            :         }
    1469                 :            : 
    1470                 :            :         /* Enable the top level host channel interrupt. */
    1471                 :    7077032 :         intr_enable = (1 << hc->hc_num);
    1472                 :    7077032 :         DWC_MODIFY_REG32(&hcd->core_if->host_if->host_global_regs->haintmsk, 0, intr_enable);
    1473                 :            : 
    1474                 :            :         /* Make sure host channel interrupts are enabled. */
    1475                 :    7077032 :         gintmsk.b.hcintr = 1;
    1476                 :    7077032 :         DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
    1477                 :            : 
    1478         [ +  - ]:    7077032 :         if (fiq_enable) {
    1479                 :    7077032 :                 fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
    1480                 :    7077032 :                 local_fiq_enable();
    1481                 :            :         }
    1482                 :            : 
    1483         [ +  - ]:   14154064 :         local_irq_restore(flags);
    1484                 :    7077032 :         hc->qh = qh;
    1485                 :            : }
    1486                 :            : 
    1487                 :            : 
    1488                 :            : /**
    1489                 :            :  * fiq_fsm_transaction_suitable() - Test a QH for compatibility with the FIQ
    1490                 :            :  * @hcd:        Pointer to the dwc_otg_hcd struct
    1491                 :            :  * @qh: pointer to the endpoint's queue head
    1492                 :            :  *
    1493                 :            :  * Transaction start/end control flow is grafted onto the existing dwc_otg
    1494                 :            :  * mechanisms, to avoid spaghettifying the functions more than they already are.
    1495                 :            :  * This function's eligibility check is altered by debug parameter.
    1496                 :            :  *
    1497                 :            :  * Returns: 0 for unsuitable, 1 implies the FIQ can be enabled for this transaction.
    1498                 :            :  */
    1499                 :            : 
    1500                 :   24925078 : int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
    1501                 :            : {
    1502         [ +  + ]:   24925078 :         if (qh->do_split) {
    1503      [ +  +  - ]:    4363029 :                 switch (qh->ep_type) {
    1504                 :            :                 case UE_CONTROL:
    1505                 :            :                 case UE_BULK:
    1506         [ -  + ]:      65299 :                         if (fiq_fsm_mask & (1 << 0))
    1507                 :            :                                 return 1;
    1508                 :            :                         break;
    1509                 :            :                 case UE_INTERRUPT:
    1510                 :            :                 case UE_ISOCHRONOUS:
    1511         [ -  + ]:    4297730 :                         if (fiq_fsm_mask & (1 << 1))
    1512                 :            :                                 return 1;
    1513                 :            :                         break;
    1514                 :            :                 default:
    1515                 :            :                         break;
    1516                 :            :                 }
    1517         [ -  + ]:   20562049 :         } else if (qh->ep_type == UE_ISOCHRONOUS) {
    1518         [ #  # ]:          0 :                 if (fiq_fsm_mask & (1 << 2)) {
    1519                 :            :                         /* ISOCH support. We test for compatibility:
    1520                 :            :                          * - DWORD aligned buffers
    1521                 :            :                          * - Must be at least 2 transfers (otherwise pointless to use the FIQ)
    1522                 :            :                          * If yes, then the fsm enqueue function will handle the state machine setup.
    1523                 :            :                          */
    1524                 :          0 :                         dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
    1525                 :          0 :                         dwc_otg_hcd_urb_t *urb = qtd->urb;
    1526                 :            :                         dwc_dma_t ptr;
    1527                 :            :                         int i;
    1528                 :            : 
    1529         [ #  # ]:          0 :                         if (urb->packet_count < 2)
    1530                 :            :                                 return 0;
    1531         [ #  # ]:          0 :                         for (i = 0; i < urb->packet_count; i++) {
    1532                 :          0 :                                 ptr = urb->dma + urb->iso_descs[i].offset;
    1533         [ #  # ]:          0 :                                 if (ptr & 0x3)
    1534                 :            :                                         return 0;
    1535                 :            :                         }
    1536                 :            :                         return 1;
    1537                 :            :                 }
    1538                 :            :         }
    1539                 :   20562049 :         return 0;
    1540                 :            : }
    1541                 :            : 
    1542                 :            : /**
    1543                 :            :  * fiq_fsm_setup_periodic_dma() - Set up DMA bounce buffers
    1544                 :            :  * @hcd: Pointer to the dwc_otg_hcd struct
    1545                 :            :  * @qh: Pointer to the endpoint's queue head
    1546                 :            :  *
    1547                 :            :  * Periodic split transactions are transmitted modulo 188 bytes.
    1548                 :            :  * This necessitates slicing data up into buckets for isochronous out
    1549                 :            :  * and fixing up the DMA address for all IN transfers.
    1550                 :            :  *
    1551                 :            :  * Returns 1 if the DMA bounce buffers have been used, 0 if the default
    1552                 :            :  * HC buffer has been used.
    1553                 :            :  */
    1554                 :    4297729 : int fiq_fsm_setup_periodic_dma(dwc_otg_hcd_t *hcd, struct fiq_channel_state *st, dwc_otg_qh_t *qh)
    1555                 :            :  {
    1556                 :            :         int frame_length, i = 0;
    1557                 :            :         uint8_t *ptr = NULL;
    1558                 :    4297729 :         dwc_hc_t *hc = qh->channel;
    1559                 :            :         struct fiq_dma_blob *blob;
    1560                 :            :         struct dwc_otg_hcd_iso_packet_desc *frame_desc;
    1561                 :            : 
    1562         [ +  + ]:   30084103 :         for (i = 0; i < 6; i++) {
    1563                 :   25786374 :                 st->dma_info.slot_len[i] = 255;
    1564                 :            :         }
    1565                 :    4297729 :         st->dma_info.index = 0;
    1566                 :            :         i = 0;
    1567         [ +  - ]:    4297729 :         if (hc->ep_is_in) {
    1568                 :            :                 /*
    1569                 :            :                  * Set dma_regs to bounce buffer. FIQ will update the
    1570                 :            :                  * state depending on transaction progress.
    1571                 :            :                  * Pointer arithmetic on hcd->fiq_state->dma_base (a dma_addr_t)
    1572                 :            :                  * to point it to the correct offset in the allocated buffers.
    1573                 :            :                  */
    1574                 :    4297729 :                 blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
    1575                 :    4297729 :                 st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
    1576                 :            : 
    1577                 :            :                 /* Calculate the max number of CSPLITS such that the FIQ can time out
    1578                 :            :                  * a transaction if it fails.
    1579                 :            :                  */
    1580                 :    4297729 :                 frame_length = st->hcchar_copy.b.mps;
    1581                 :            :                 do {
    1582                 :    4297729 :                         i++;
    1583                 :    4297729 :                         frame_length -= 188;
    1584         [ -  + ]:    4297729 :                 } while (frame_length >= 0);
    1585                 :    4297729 :                 st->nrpackets = i;
    1586                 :    4297729 :                 return 1;
    1587                 :            :         } else {
    1588         [ #  # ]:          0 :                 if (qh->ep_type == UE_ISOCHRONOUS) {
    1589                 :            : 
    1590                 :          0 :                         dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
    1591                 :            : 
    1592                 :          0 :                         frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
    1593                 :          0 :                         frame_length = frame_desc->length;
    1594                 :            : 
    1595                 :            :                         /* Virtual address for bounce buffers */
    1596                 :          0 :                         blob = hcd->fiq_dmab;
    1597                 :            : 
    1598                 :          0 :                         ptr = qtd->urb->buf + frame_desc->offset;
    1599         [ #  # ]:          0 :                         if (frame_length == 0) {
    1600                 :            :                                 /*
    1601                 :            :                                  * for isochronous transactions, we must still transmit a packet
    1602                 :            :                                  * even if the length is zero.
    1603                 :            :                                  */
    1604                 :          0 :                                 st->dma_info.slot_len[0] = 0;
    1605                 :          0 :                                 st->nrpackets = 1;
    1606                 :            :                         } else {
    1607                 :            :                                 do {
    1608         [ #  # ]:          0 :                                         if (frame_length <= 188) {
    1609                 :          0 :                                                 dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, frame_length);
    1610                 :          0 :                                                 st->dma_info.slot_len[i] = frame_length;
    1611                 :          0 :                                                 ptr += frame_length;
    1612                 :            :                                         } else {
    1613                 :          0 :                                                 dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, 188);
    1614                 :          0 :                                                 st->dma_info.slot_len[i] = 188;
    1615                 :          0 :                                                 ptr += 188;
    1616                 :            :                                         }
    1617                 :          0 :                                         i++;
    1618                 :          0 :                                         frame_length -= 188;
    1619         [ #  # ]:          0 :                                 } while (frame_length > 0);
    1620                 :          0 :                                 st->nrpackets = i;
    1621                 :            :                         }
    1622                 :            :                         ptr = qtd->urb->buf + frame_desc->offset;
    1623                 :            :                         /*
    1624                 :            :                          * Point the HC at the DMA address of the bounce buffers
    1625                 :            :                          *
    1626                 :            :                          * Pointer arithmetic on hcd->fiq_state->dma_base (a
    1627                 :            :                          * dma_addr_t) to point it to the correct offset in the
    1628                 :            :                          * allocated buffers.
    1629                 :            :                          */
    1630                 :          0 :                         blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
    1631                 :          0 :                         st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
    1632                 :            : 
    1633                 :            :                         /* fixup xfersize to the actual packet size */
    1634                 :          0 :                         st->hctsiz_copy.b.pid = 0;
    1635                 :          0 :                         st->hctsiz_copy.b.xfersize = st->dma_info.slot_len[0];
    1636                 :          0 :                         return 1;
    1637                 :            :                 } else {
    1638                 :            :                         /* For interrupt, single OUT packet required, goes in the SSPLIT from hc_buff. */
    1639                 :            :                         return 0;
    1640                 :            :                 }
    1641                 :            :         }
    1642                 :            : }
    1643                 :            : 
    1644                 :            : /**
    1645                 :            :  * fiq_fsm_np_tt_contended() - Avoid performing contended non-periodic transfers
    1646                 :            :  * @hcd: Pointer to the dwc_otg_hcd struct
    1647                 :            :  * @qh: Pointer to the endpoint's queue head
    1648                 :            :  *
    1649                 :            :  * Certain hub chips don't differentiate between IN and OUT non-periodic pipes
    1650                 :            :  * with the same endpoint number. If transfers get completed out of order
    1651                 :            :  * (disregarding the direction token) then the hub can lock up
    1652                 :            :  * or return erroneous responses.
    1653                 :            :  *
    1654                 :            :  * Returns 1 if initiating the transfer would cause contention, 0 otherwise.
    1655                 :            :  */
    1656                 :    4329977 : int fiq_fsm_np_tt_contended(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
    1657                 :            : {
    1658                 :            :         int i;
    1659                 :            :         struct fiq_channel_state *st;
    1660                 :    4329977 :         int dev_addr = qh->channel->dev_addr;
    1661                 :    4329977 :         int ep_num = qh->channel->ep_num;
    1662         [ +  + ]:   38969793 :         for (i = 0; i < hcd->core_if->core_params->host_channels; i++) {
    1663         [ +  + ]:   34639816 :                 if (i == qh->channel->hc_num)
    1664                 :    4329977 :                         continue;
    1665                 :   30309839 :                 st = &hcd->fiq_state->channel[i];
    1666         [ +  + ]:   30309839 :                 switch (st->fsm) {
    1667                 :            :                 case FIQ_NP_SSPLIT_STARTED:
    1668                 :            :                 case FIQ_NP_SSPLIT_RETRY:
    1669                 :            :                 case FIQ_NP_SSPLIT_PENDING:
    1670                 :            :                 case FIQ_NP_OUT_CSPLIT_RETRY:
    1671                 :            :                 case FIQ_NP_IN_CSPLIT_RETRY:
    1672   [ +  +  +  - ]:     226763 :                         if (st->hcchar_copy.b.devaddr == dev_addr &&
    1673                 :       4265 :                                 st->hcchar_copy.b.epnum == ep_num)
    1674                 :            :                                 return 1;
    1675                 :            :                         break;
    1676                 :            :                 default:
    1677                 :            :                         break;
    1678                 :            :                 }
    1679                 :            :         }
    1680                 :            :         return 0;
    1681                 :            : }
    1682                 :            : 
    1683                 :            : /*
    1684                 :            :  * Pushing a periodic request into the queue near the EOF1 point
    1685                 :            :  * in a microframe causes erroneous behaviour (frmovrun) interrupt.
    1686                 :            :  * Usually, the request goes out on the bus causing a transfer but
    1687                 :            :  * the core does not transfer the data to memory.
    1688                 :            :  * This guard interval (in number of 60MHz clocks) is required which
    1689                 :            :  * must cater for CPU latency between reading the value and enabling
    1690                 :            :  * the channel.
    1691                 :            :  */
    1692                 :            : #define PERIODIC_FRREM_BACKOFF 1000
    1693                 :            : 
    1694                 :          0 : int fiq_fsm_queue_isoc_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
    1695                 :            : {
    1696                 :          0 :         dwc_hc_t *hc = qh->channel;
    1697                 :          0 :         dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
    1698                 :          0 :         dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
    1699                 :            :         int frame;
    1700                 :          0 :         struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num];
    1701                 :            :         int xfer_len, nrpackets;
    1702                 :            :         hcdma_data_t hcdma;
    1703                 :            :         hfnum_data_t hfnum;
    1704                 :            : 
    1705         [ #  # ]:          0 :         if (st->fsm != FIQ_PASSTHROUGH)
    1706                 :            :                 return 0;
    1707                 :            : 
    1708                 :          0 :         st->nr_errors = 0;
    1709                 :            : 
    1710                 :          0 :         st->hcchar_copy.d32 = 0;
    1711                 :          0 :         st->hcchar_copy.b.mps = hc->max_packet;
    1712                 :          0 :         st->hcchar_copy.b.epdir = hc->ep_is_in;
    1713                 :          0 :         st->hcchar_copy.b.devaddr = hc->dev_addr;
    1714                 :          0 :         st->hcchar_copy.b.epnum = hc->ep_num;
    1715                 :          0 :         st->hcchar_copy.b.eptype = hc->ep_type;
    1716                 :            : 
    1717                 :          0 :         st->hcintmsk_copy.b.chhltd = 1;
    1718                 :            : 
    1719                 :            :         frame = dwc_otg_hcd_get_frame_number(hcd);
    1720                 :          0 :         st->hcchar_copy.b.oddfrm = (frame & 0x1) ? 0 : 1;
    1721                 :            : 
    1722                 :          0 :         st->hcchar_copy.b.lspddev = 0;
    1723                 :            :         /* Enable the channel later as a final register write. */
    1724                 :            : 
    1725                 :          0 :         st->hcsplt_copy.d32 = 0;
    1726                 :            : 
    1727                 :          0 :         st->hs_isoc_info.iso_desc = (struct dwc_otg_hcd_iso_packet_desc *) &qtd->urb->iso_descs;
    1728                 :          0 :         st->hs_isoc_info.nrframes = qtd->urb->packet_count;
    1729                 :            :         /* grab the next DMA address offset from the array */
    1730                 :          0 :         st->hcdma_copy.d32 = qtd->urb->dma;
    1731                 :          0 :         hcdma.d32 = st->hcdma_copy.d32 + st->hs_isoc_info.iso_desc[0].offset;
    1732                 :            : 
    1733                 :            :         /* We need to set multi_count. This is a bit tricky - has to be set per-transaction as
    1734                 :            :          * the core needs to be told to send the correct number. Caution: for IN transfers,
    1735                 :            :          * this is always set to the maximum size of the endpoint. */
    1736                 :          0 :         xfer_len = st->hs_isoc_info.iso_desc[0].length;
    1737                 :          0 :         nrpackets = (xfer_len + st->hcchar_copy.b.mps - 1) / st->hcchar_copy.b.mps;
    1738         [ #  # ]:          0 :         if (nrpackets == 0)
    1739                 :            :                 nrpackets = 1;
    1740                 :          0 :         st->hcchar_copy.b.multicnt = nrpackets;
    1741                 :          0 :         st->hctsiz_copy.b.pktcnt = nrpackets;
    1742                 :            : 
    1743                 :            :         /* Initial PID also needs to be set */
    1744         [ #  # ]:          0 :         if (st->hcchar_copy.b.epdir == 0) {
    1745                 :          0 :                 st->hctsiz_copy.b.xfersize = xfer_len;
    1746      [ #  #  # ]:          0 :                 switch (st->hcchar_copy.b.multicnt) {
    1747                 :            :                 case 1:
    1748                 :          0 :                         st->hctsiz_copy.b.pid = DWC_PID_DATA0;
    1749                 :          0 :                         break;
    1750                 :            :                 case 2:
    1751                 :            :                 case 3:
    1752                 :          0 :                         st->hctsiz_copy.b.pid = DWC_PID_MDATA;
    1753                 :          0 :                         break;
    1754                 :            :                 }
    1755                 :            : 
    1756                 :            :         } else {
    1757                 :          0 :                 st->hctsiz_copy.b.xfersize = nrpackets * st->hcchar_copy.b.mps;
    1758   [ #  #  #  # ]:          0 :                 switch (st->hcchar_copy.b.multicnt) {
    1759                 :            :                 case 1:
    1760                 :          0 :                         st->hctsiz_copy.b.pid = DWC_PID_DATA0;
    1761                 :          0 :                         break;
    1762                 :            :                 case 2:
    1763                 :          0 :                         st->hctsiz_copy.b.pid = DWC_PID_DATA1;
    1764                 :          0 :                         break;
    1765                 :            :                 case 3:
    1766                 :          0 :                         st->hctsiz_copy.b.pid = DWC_PID_DATA2;
    1767                 :          0 :                         break;
    1768                 :            :                 }
    1769                 :            :         }
    1770                 :            : 
    1771                 :          0 :         st->hs_isoc_info.stride = qh->interval;
    1772                 :          0 :         st->uframe_sleeps = 0;
    1773                 :            : 
    1774                 :            :         fiq_print(FIQDBG_INT, hcd->fiq_state, "FSMQ  %01d ", hc->hc_num);
    1775                 :            :         fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcchar_copy.d32);
    1776                 :            :         fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32);
    1777                 :            :         fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32);
    1778                 :          0 :         hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
    1779                 :          0 :         local_fiq_disable();
    1780                 :          0 :         fiq_fsm_spin_lock(&hcd->fiq_state->lock);
    1781                 :          0 :         DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32);
    1782                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32);
    1783                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32);
    1784                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
    1785                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32);
    1786         [ #  # ]:          0 :         if (hfnum.b.frrem < PERIODIC_FRREM_BACKOFF) {
    1787                 :            :                 /* Prevent queueing near EOF1. Bad things happen if a periodic
    1788                 :            :                  * split transaction is queued very close to EOF. SOF interrupt handler
    1789                 :            :                  * will wake this channel at the next interrupt.
    1790                 :            :                  */
    1791                 :          0 :                 st->fsm = FIQ_HS_ISOC_SLEEPING;
    1792                 :          0 :                 st->uframe_sleeps = 1;
    1793                 :            :         } else {
    1794                 :          0 :                 st->fsm = FIQ_HS_ISOC_TURBO;
    1795                 :          0 :                 st->hcchar_copy.b.chen = 1;
    1796                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
    1797                 :            :         }
    1798                 :          0 :         mb();
    1799                 :          0 :         st->hcchar_copy.b.chen = 0;
    1800                 :          0 :         fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
    1801                 :          0 :         local_fiq_enable();
    1802                 :          0 :         return 0;
    1803                 :            : }
    1804                 :            : 
    1805                 :            : 
    1806                 :            : /**
    1807                 :            :  * fiq_fsm_queue_split_transaction() - Set up a host channel and FIQ state
    1808                 :            :  * @hcd: Pointer to the dwc_otg_hcd struct
    1809                 :            :  * @qh: Pointer to the endpoint's queue head
    1810                 :            :  *
    1811                 :            :  * This overrides the dwc_otg driver's normal method of queueing a transaction.
    1812                 :            :  * Called from dwc_otg_hcd_queue_transactions(), this performs specific setup
    1813                 :            :  * for the nominated host channel.
    1814                 :            :  *
    1815                 :            :  * For periodic transfers, it also peeks at the FIQ state to see if an immediate
    1816                 :            :  * start is possible. If not, then the FIQ is left to start the transfer.
    1817                 :            :  */
    1818                 :    4363027 : int fiq_fsm_queue_split_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
    1819                 :            : {
    1820                 :            :         int start_immediate = 1, i;
    1821                 :            :         hfnum_data_t hfnum;
    1822                 :    4363027 :         dwc_hc_t *hc = qh->channel;
    1823                 :    4363027 :         dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
    1824                 :            :         /* Program HC registers, setup FIQ_state, examine FIQ if periodic, start transfer (not if uframe 5) */
    1825                 :            :         int hub_addr, port_addr, frame, uframe;
    1826                 :    4363027 :         struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num];
    1827                 :            : 
    1828                 :            :         /*
    1829                 :            :          * Non-periodic channel assignments stay in the non_periodic_active queue.
    1830                 :            :          * Therefore we get repeatedly called until the FIQ's done processing this channel.
    1831                 :            :          */
    1832         [ +  + ]:    4363027 :         if (qh->channel->xfer_started == 1)
    1833                 :            :                 return 0;
    1834                 :            : 
    1835         [ -  + ]:    4329977 :         if (st->fsm != FIQ_PASSTHROUGH) {
    1836         [ #  # ]:          0 :                 pr_warn_ratelimited("%s:%d: Queue called for an active channel\n", __func__, __LINE__);
    1837                 :            :                 return 0;
    1838                 :            :         }
    1839                 :            : 
    1840                 :    4329977 :         qh->channel->xfer_started = 1;
    1841                 :            : 
    1842                 :    4329977 :         st->nr_errors = 0;
    1843                 :            : 
    1844                 :    4329977 :         st->hcchar_copy.d32 = 0;
    1845                 :    4329977 :         st->hcchar_copy.b.mps = min_t(uint32_t, hc->xfer_len, hc->max_packet);
    1846                 :    4329977 :         st->hcchar_copy.b.epdir = hc->ep_is_in;
    1847                 :    4329977 :         st->hcchar_copy.b.devaddr = hc->dev_addr;
    1848                 :    4329977 :         st->hcchar_copy.b.epnum = hc->ep_num;
    1849                 :    4329977 :         st->hcchar_copy.b.eptype = hc->ep_type;
    1850         [ +  + ]:    4329977 :         if (hc->ep_type & 0x1) {
    1851         [ +  - ]:    4297728 :                 if (hc->ep_is_in)
    1852                 :    4297728 :                         st->hcchar_copy.b.multicnt = 3;
    1853                 :            :                 else
    1854                 :            :                         /* Docs say set this to 1, but driver sets to 0! */
    1855                 :          0 :                         st->hcchar_copy.b.multicnt = 0;
    1856                 :            :         } else {
    1857                 :      32249 :                 st->hcchar_copy.b.multicnt = 1;
    1858                 :      32249 :                 st->hcchar_copy.b.oddfrm = 0;
    1859                 :            :         }
    1860                 :    4329977 :         st->hcchar_copy.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW) ? 1 : 0;
    1861                 :            :         /* Enable the channel later as a final register write. */
    1862                 :            : 
    1863                 :    4329977 :         st->hcsplt_copy.d32 = 0;
    1864         [ +  - ]:    4329977 :         if(qh->do_split) {
    1865                 :    4329977 :                 hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
    1866                 :    4329977 :                 st->hcsplt_copy.b.compsplt = 0;
    1867                 :    4329977 :                 st->hcsplt_copy.b.spltena = 1;
    1868                 :            :                 // XACTPOS is for isoc-out only but needs initialising anyway.
    1869                 :    4329977 :                 st->hcsplt_copy.b.xactpos = ISOC_XACTPOS_ALL;
    1870         [ -  + ]:    4329977 :                 if((qh->ep_type == DWC_OTG_EP_TYPE_ISOC) && (!qh->ep_is_in)) {
    1871                 :            :                         /* For packetsize 0 < L < 188, ISOC_XACTPOS_ALL.
    1872                 :            :                          * for longer than this, ISOC_XACTPOS_BEGIN and the FIQ
    1873                 :            :                          * will update as necessary.
    1874                 :            :                          */
    1875         [ #  # ]:          0 :                         if (hc->xfer_len > 188) {
    1876                 :          0 :                                 st->hcsplt_copy.b.xactpos = ISOC_XACTPOS_BEGIN;
    1877                 :            :                         }
    1878                 :            :                 }
    1879                 :    4329977 :                 st->hcsplt_copy.b.hubaddr = (uint8_t) hub_addr;
    1880                 :    4329977 :                 st->hcsplt_copy.b.prtaddr = (uint8_t) port_addr;
    1881                 :    4329977 :                 st->hub_addr = hub_addr;
    1882                 :    4329977 :                 st->port_addr = port_addr;
    1883                 :            :         }
    1884                 :            : 
    1885                 :    4329977 :         st->hctsiz_copy.d32 = 0;
    1886                 :    4329977 :         st->hctsiz_copy.b.dopng = 0;
    1887                 :    4329977 :         st->hctsiz_copy.b.pid = hc->data_pid_start;
    1888                 :            : 
    1889   [ +  +  -  + ]:    4329977 :         if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
    1890                 :    4319798 :                 hc->xfer_len = min_t(uint32_t, hc->xfer_len, hc->max_packet);
    1891   [ +  -  -  + ]:      10179 :         } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
    1892                 :          0 :                 hc->xfer_len = 188;
    1893                 :            :         }
    1894                 :    4329977 :         st->hctsiz_copy.b.xfersize = hc->xfer_len;
    1895                 :            : 
    1896                 :    4329977 :         st->hctsiz_copy.b.pktcnt = 1;
    1897                 :            : 
    1898         [ +  + ]:    4329977 :         if (hc->ep_type & 0x1) {
    1899                 :            :                 /*
    1900                 :            :                  * For potentially multi-packet transfers, must use the DMA bounce buffers. For IN transfers,
    1901                 :            :                  * the DMA address is the address of the first 188byte slot buffer in the bounce buffer array.
    1902                 :            :                  * For multi-packet OUT transfers, we need to copy the data into the bounce buffer array so the FIQ can punt
    1903                 :            :                  * the right address out as necessary. hc->xfer_buff and hc->xfer_len have already been set
    1904                 :            :                  * in assign_and_init_hc(), but this is for the eventual transaction completion only. The FIQ
    1905                 :            :                  * must not touch internal driver state.
    1906                 :            :                  */
    1907         [ -  + ]:    4297728 :                 if(!fiq_fsm_setup_periodic_dma(hcd, st, qh)) {
    1908         [ #  # ]:          0 :                         if (hc->align_buff) {
    1909                 :          0 :                                 st->hcdma_copy.d32 = hc->align_buff;
    1910                 :            :                         } else {
    1911                 :          0 :                                 st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
    1912                 :            :                         }
    1913                 :            :                 }
    1914                 :            :         } else {
    1915         [ -  + ]:      32249 :                 if (hc->align_buff) {
    1916                 :          0 :                         st->hcdma_copy.d32 = hc->align_buff;
    1917                 :            :                 } else {
    1918                 :      32249 :                         st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
    1919                 :            :                 }
    1920                 :            :         }
    1921                 :            :         /* The FIQ depends upon no other interrupts being enabled except channel halt.
    1922                 :            :          * Fixup channel interrupt mask. */
    1923                 :    4329977 :         st->hcintmsk_copy.d32 = 0;
    1924                 :    4329977 :         st->hcintmsk_copy.b.chhltd = 1;
    1925                 :    4329977 :         st->hcintmsk_copy.b.ahberr = 1;
    1926                 :            : 
    1927                 :            :         /* Hack courtesy of FreeBSD: apparently forcing Interrupt Split transactions
    1928                 :            :          * as Control puts the transfer into the non-periodic request queue and the
    1929                 :            :          * non-periodic handler in the hub. Makes things lots easier.
    1930                 :            :          */
    1931   [ +  -  +  + ]:    4329977 :         if ((fiq_fsm_mask & 0x8) && hc->ep_type == UE_INTERRUPT) {
    1932                 :    4297728 :                 st->hcchar_copy.b.multicnt = 0;
    1933                 :    4297728 :                 st->hcchar_copy.b.oddfrm = 0;
    1934                 :    4297728 :                 st->hcchar_copy.b.eptype = UE_CONTROL;
    1935         [ -  + ]:    4297728 :                 if (hc->align_buff) {
    1936                 :          0 :                         st->hcdma_copy.d32 = hc->align_buff;
    1937                 :            :                 } else {
    1938                 :    4297728 :                         st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
    1939                 :            :                 }
    1940                 :            :         }
    1941                 :    4329977 :         DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32);
    1942                 :    4329977 :         DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32);
    1943                 :    4329977 :         DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32);
    1944                 :    4329977 :         DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
    1945                 :    4329977 :         DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32);
    1946                 :            : 
    1947                 :    4329977 :         local_fiq_disable();
    1948                 :    4329977 :         fiq_fsm_spin_lock(&hcd->fiq_state->lock);
    1949                 :            : 
    1950         [ +  + ]:    4329977 :         if (hc->ep_type & 0x1) {
    1951                 :    4297728 :                 hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
    1952                 :            :                 frame = (hfnum.b.frnum & ~0x7) >> 3;
    1953                 :    4297728 :                 uframe = hfnum.b.frnum & 0x7;
    1954         [ +  + ]:    4297728 :                 if (hfnum.b.frrem < PERIODIC_FRREM_BACKOFF) {
    1955                 :            :                         /* Prevent queueing near EOF1. Bad things happen if a periodic
    1956                 :            :                          * split transaction is queued very close to EOF.
    1957                 :            :                          */
    1958                 :            :                         start_immediate = 0;
    1959         [ +  + ]:    4110236 :                 } else if (uframe == 5) {
    1960                 :            :                         start_immediate = 0;
    1961         [ +  - ]:    4110193 :                 } else if (hc->ep_type == UE_ISOCHRONOUS && !hc->ep_is_in) {
    1962                 :            :                         start_immediate = 0;
    1963   [ +  -  +  + ]:    4110193 :                 } else if (hc->ep_is_in && fiq_fsm_too_late(hcd->fiq_state, hc->hc_num)) {
    1964                 :            :                         start_immediate = 0;
    1965                 :            :                 } else {
    1966                 :            :                         /* Search through all host channels to determine if a transaction
    1967                 :            :                          * is currently in progress */
    1968         [ +  + ]:   36991728 :                         for (i = 0; i < hcd->core_if->core_params->host_channels; i++) {
    1969   [ +  +  +  + ]:   32881536 :                                 if (i == hc->hc_num || hcd->fiq_state->channel[i].fsm == FIQ_PASSTHROUGH)
    1970                 :   32678992 :                                         continue;
    1971         [ -  + ]:     202544 :                                 switch (hcd->fiq_state->channel[i].fsm) {
    1972                 :            :                                 /* TT is reserved for channels that are in the middle of a periodic
    1973                 :            :                                  * split transaction.
    1974                 :            :                                  */
    1975                 :            :                                 case FIQ_PER_SSPLIT_STARTED:
    1976                 :            :                                 case FIQ_PER_CSPLIT_WAIT:
    1977                 :            :                                 case FIQ_PER_CSPLIT_NYET1:
    1978                 :            :                                 case FIQ_PER_CSPLIT_POLL:
    1979                 :            :                                 case FIQ_PER_ISO_OUT_ACTIVE:
    1980                 :            :                                 case FIQ_PER_ISO_OUT_LAST:
    1981   [ #  #  #  # ]:          0 :                                         if (hcd->fiq_state->channel[i].hub_addr == hub_addr &&
    1982                 :          0 :                                                         hcd->fiq_state->channel[i].port_addr == port_addr) {
    1983                 :            :                                                 start_immediate = 0;
    1984                 :            :                                         }
    1985                 :            :                                         break;
    1986                 :            :                                 default:
    1987                 :            :                                         break;
    1988                 :            :                                 }
    1989         [ +  - ]:     202544 :                                 if (!start_immediate)
    1990                 :            :                                         break;
    1991                 :            :                         }
    1992                 :            :                 }
    1993                 :            :         }
    1994   [ +  +  +  + ]:    4329977 :         if ((fiq_fsm_mask & 0x8) && hc->ep_type == UE_INTERRUPT)
    1995                 :            :                 start_immediate = 1;
    1996                 :            : 
    1997                 :            :         fiq_print(FIQDBG_INT, hcd->fiq_state, "FSMQ %01d %01d", hc->hc_num, start_immediate);
    1998                 :            :         fiq_print(FIQDBG_INT, hcd->fiq_state, "%08d", hfnum.b.frrem);
    1999                 :            :         //fiq_print(FIQDBG_INT, hcd->fiq_state, "H:%02dP:%02d", hub_addr, port_addr);
    2000                 :            :         //fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32);
    2001                 :            :         //fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32);
    2002   [ +  -  +  + ]:    4329977 :         switch (hc->ep_type) {
    2003                 :            :                 case UE_CONTROL:
    2004                 :            :                 case UE_BULK:
    2005         [ -  + ]:      32249 :                         if (fiq_fsm_np_tt_contended(hcd, qh)) {
    2006                 :          0 :                                 st->fsm = FIQ_NP_SSPLIT_PENDING;
    2007                 :            :                                 start_immediate = 0;
    2008                 :            :                         } else {
    2009                 :      32249 :                                 st->fsm = FIQ_NP_SSPLIT_STARTED;
    2010                 :            :                         }
    2011                 :            :                         break;
    2012                 :            :                 case UE_ISOCHRONOUS:
    2013         [ #  # ]:          0 :                         if (hc->ep_is_in) {
    2014         [ #  # ]:          0 :                                 if (start_immediate) {
    2015                 :          0 :                                         st->fsm = FIQ_PER_SSPLIT_STARTED;
    2016                 :            :                                 } else {
    2017                 :          0 :                                         st->fsm = FIQ_PER_SSPLIT_QUEUED;
    2018                 :            :                                 }
    2019                 :            :                         } else {
    2020         [ #  # ]:          0 :                                 if (start_immediate) {
    2021                 :            :                                         /* Single-isoc OUT packets don't require FIQ involvement */
    2022         [ #  # ]:          0 :                                         if (st->nrpackets == 1) {
    2023                 :          0 :                                                 st->fsm = FIQ_PER_ISO_OUT_LAST;
    2024                 :            :                                         } else {
    2025                 :          0 :                                                 st->fsm = FIQ_PER_ISO_OUT_ACTIVE;
    2026                 :            :                                         }
    2027                 :            :                                 } else {
    2028                 :          0 :                                         st->fsm = FIQ_PER_ISO_OUT_PENDING;
    2029                 :            :                                 }
    2030                 :            :                         }
    2031                 :            :                         break;
    2032                 :            :                 case UE_INTERRUPT:
    2033         [ +  - ]:    4297727 :                         if (fiq_fsm_mask & 0x8) {
    2034         [ -  + ]:    4297727 :                                 if (fiq_fsm_np_tt_contended(hcd, qh)) {
    2035                 :          0 :                                         st->fsm = FIQ_NP_SSPLIT_PENDING;
    2036                 :            :                                         start_immediate = 0;
    2037                 :            :                                 } else {
    2038                 :    4297727 :                                         st->fsm = FIQ_NP_SSPLIT_STARTED;
    2039                 :            :                                 }
    2040         [ #  # ]:          0 :                         } else if (start_immediate) {
    2041                 :          0 :                                         st->fsm = FIQ_PER_SSPLIT_STARTED;
    2042                 :            :                         } else {
    2043                 :          0 :                                 st->fsm = FIQ_PER_SSPLIT_QUEUED;
    2044                 :            :                         }
    2045                 :            :                 default:
    2046                 :            :                         break;
    2047                 :            :         }
    2048         [ +  + ]:    4329977 :         if (start_immediate) {
    2049                 :            :                 /* Set the oddfrm bit as close as possible to actual queueing */
    2050                 :            :                 frame = dwc_otg_hcd_get_frame_number(hcd);
    2051                 :    4329976 :                 st->expected_uframe = (frame + 1) & 0x3FFF;
    2052                 :    4329976 :                 st->hcchar_copy.b.oddfrm = (frame & 0x1) ? 0 : 1;
    2053                 :    4329976 :                 st->hcchar_copy.b.chen = 1;
    2054                 :    4329976 :                 DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
    2055                 :            :         }
    2056                 :    4329977 :         mb();
    2057                 :    4329976 :         fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
    2058                 :    4329976 :         local_fiq_enable();
    2059                 :    4329976 :         return 0;
    2060                 :            : }
    2061                 :            : 
    2062                 :            : 
    2063                 :            : /**
    2064                 :            :  * This function selects transactions from the HCD transfer schedule and
    2065                 :            :  * assigns them to available host channels. It is called from HCD interrupt
    2066                 :            :  * handler functions.
    2067                 :            :  *
    2068                 :            :  * @param hcd The HCD state structure.
    2069                 :            :  *
    2070                 :            :  * @return The types of new transactions that were assigned to host channels.
    2071                 :            :  */
    2072                 :   21003372 : dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
    2073                 :            : {
    2074                 :            :         dwc_list_link_t *qh_ptr;
    2075                 :            :         dwc_otg_qh_t *qh;
    2076                 :            :         int num_channels;
    2077                 :            :         dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
    2078                 :            : 
    2079                 :            : #ifdef DEBUG_HOST_CHANNELS
    2080                 :            :         last_sel_trans_num_per_scheduled = 0;
    2081                 :            :         last_sel_trans_num_nonper_scheduled = 0;
    2082                 :            :         last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
    2083                 :            : #endif /* DEBUG_HOST_CHANNELS */
    2084                 :            : 
    2085                 :            :         /* Process entries in the periodic ready list. */
    2086                 :   21003372 :         qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
    2087                 :            : 
    2088   [ +  +  +  - ]:   55485746 :         while (qh_ptr != &hcd->periodic_sched_ready &&
    2089                 :    6739501 :                !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
    2090                 :            : 
    2091                 :            :                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
    2092                 :            : 
    2093         [ +  - ]:    6739501 :                 if (microframe_schedule) {
    2094                 :            :                         // Make sure we leave one channel for non periodic transactions.
    2095         [ +  - ]:    6739501 :                         if (hcd->available_host_channels <= 1) {
    2096                 :            :                                 break;
    2097                 :            :                         }
    2098                 :    6739501 :                         hcd->available_host_channels--;
    2099                 :            : #ifdef DEBUG_HOST_CHANNELS
    2100                 :            :                         last_sel_trans_num_per_scheduled++;
    2101                 :            : #endif /* DEBUG_HOST_CHANNELS */
    2102                 :            :                 }
    2103                 :    6739501 :                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
    2104                 :    6739501 :                 assign_and_init_hc(hcd, qh);
    2105                 :            : 
    2106                 :            :                 /*
    2107                 :            :                  * Move the QH from the periodic ready schedule to the
    2108                 :            :                  * periodic assigned schedule.
    2109                 :            :                  */
    2110                 :    6739501 :                 qh_ptr = DWC_LIST_NEXT(qh_ptr);
    2111                 :    6739501 :                 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
    2112                 :            :                                    &qh->qh_list_entry);
    2113                 :            :         }
    2114                 :            : 
    2115                 :            :         /*
    2116                 :            :          * Process entries in the inactive portion of the non-periodic
    2117                 :            :          * schedule. Some free host channels may not be used if they are
    2118                 :            :          * reserved for periodic transfers.
    2119                 :            :          */
    2120                 :   21003372 :         qh_ptr = hcd->non_periodic_sched_inactive.next;
    2121                 :   21003372 :         num_channels = hcd->core_if->core_params->host_channels;
    2122   [ +  +  -  + ]:   42702994 :         while (qh_ptr != &hcd->non_periodic_sched_inactive &&
    2123         [ #  # ]:     348125 :                (microframe_schedule || hcd->non_periodic_channels <
    2124         [ +  - ]:     348125 :                 num_channels - hcd->periodic_channels) &&
    2125                 :     348125 :                !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
    2126                 :            : 
    2127                 :     348125 :                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
    2128                 :            :                 /*
    2129                 :            :                  * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
    2130                 :            :                  * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
    2131                 :            :                  * cheeky devices that just hold off using NAKs
    2132                 :            :                  */
    2133   [ +  -  +  -  :     348125 :                 if (fiq_enable && nak_holdoff && qh->do_split) {
                   +  + ]
    2134         [ +  + ]:      42847 :                         if (qh->nak_frame != 0xffff) {
    2135         [ -  + ]:      15316 :                                 uint16_t next_frame = dwc_frame_num_inc(qh->nak_frame, (qh->ep_type == UE_BULK) ? nak_holdoff : 8);
    2136                 :            :                                 uint16_t frame = dwc_otg_hcd_get_frame_number(hcd);
    2137         [ +  + ]:      15316 :                                 if (dwc_frame_num_le(frame, next_frame)) {
    2138         [ +  + ]:      21196 :                                         if(dwc_frame_num_le(next_frame, hcd->fiq_state->next_sched_frame)) {
    2139                 :      10259 :                                                 hcd->fiq_state->next_sched_frame = next_frame;
    2140                 :            :                                         }
    2141                 :      10598 :                                         qh_ptr = DWC_LIST_NEXT(qh_ptr);
    2142                 :      10598 :                                         continue;
    2143                 :            :                                 } else {
    2144                 :       4718 :                                         qh->nak_frame = 0xFFFF;
    2145                 :            :                                 }
    2146                 :            :                         }
    2147                 :            :                 }
    2148                 :            : 
    2149         [ +  - ]:     337527 :                 if (microframe_schedule) {
    2150         [ +  - ]:     337527 :                                 if (hcd->available_host_channels < 1) {
    2151                 :            :                                         break;
    2152                 :            :                                 }
    2153                 :     337527 :                                 hcd->available_host_channels--;
    2154                 :            : #ifdef DEBUG_HOST_CHANNELS
    2155                 :            :                                 last_sel_trans_num_nonper_scheduled++;
    2156                 :            : #endif /* DEBUG_HOST_CHANNELS */
    2157                 :            :                 }
    2158                 :            : 
    2159                 :     337527 :                 assign_and_init_hc(hcd, qh);
    2160                 :            : 
    2161                 :            :                 /*
    2162                 :            :                  * Move the QH from the non-periodic inactive schedule to the
    2163                 :            :                  * non-periodic active schedule.
    2164                 :            :                  */
    2165                 :     337527 :                 qh_ptr = DWC_LIST_NEXT(qh_ptr);
    2166                 :     337527 :                 DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
    2167                 :            :                                    &qh->qh_list_entry);
    2168                 :            : 
    2169         [ -  + ]:     337527 :                 if (!microframe_schedule)
    2170                 :          0 :                         hcd->non_periodic_channels++;
    2171                 :            :         }
    2172                 :            :         /* we moved a non-periodic QH to the active schedule. If the inactive queue is empty,
    2173                 :            :          * stop the FIQ from kicking us. We could potentially still have elements here if we
    2174                 :            :          * ran out of host channels.
    2175                 :            :          */
    2176         [ +  - ]:   21003372 :         if (fiq_enable) {
    2177         [ +  + ]:   21003372 :                 if (DWC_LIST_EMPTY(&hcd->non_periodic_sched_inactive)) {
    2178                 :   20992774 :                         hcd->fiq_state->kick_np_queues = 0;
    2179                 :            :                 } else {
    2180                 :            :                         /* For each entry remaining in the NP inactive queue,
    2181                 :            :                         * if this a NAK'd retransmit then don't set the kick flag.
    2182                 :            :                         */
    2183         [ +  - ]:      10598 :                         if(nak_holdoff) {
    2184         [ +  + ]:      10598 :                                 DWC_LIST_FOREACH(qh_ptr, &hcd->non_periodic_sched_inactive) {
    2185                 :            :                                         qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
    2186         [ -  + ]:      10598 :                                         if (qh->nak_frame == 0xFFFF) {
    2187                 :          0 :                                                 hcd->fiq_state->kick_np_queues = 1;
    2188                 :            :                                         }
    2189                 :            :                                 }
    2190                 :            :                         }
    2191                 :            :                 }
    2192                 :            :         }
    2193         [ +  + ]:   21003372 :         if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))
    2194                 :            :                 ret_val |= DWC_OTG_TRANSACTION_PERIODIC;
    2195                 :            : 
    2196         [ +  + ]:   21003372 :         if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active))
    2197                 :   17918313 :                 ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC;
    2198                 :            : 
    2199                 :            : 
    2200                 :            : #ifdef DEBUG_HOST_CHANNELS
    2201                 :            :         last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
    2202                 :            : #endif /* DEBUG_HOST_CHANNELS */
    2203                 :   21003372 :         return ret_val;
    2204                 :            : }
    2205                 :            : 
    2206                 :            : /**
    2207                 :            :  * Attempts to queue a single transaction request for a host channel
    2208                 :            :  * associated with either a periodic or non-periodic transfer. This function
    2209                 :            :  * assumes that there is space available in the appropriate request queue. For
    2210                 :            :  * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
    2211                 :            :  * is available in the appropriate Tx FIFO.
    2212                 :            :  *
    2213                 :            :  * @param hcd The HCD state structure.
    2214                 :            :  * @param hc Host channel descriptor associated with either a periodic or
    2215                 :            :  * non-periodic transfer.
    2216                 :            :  * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
    2217                 :            :  * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
    2218                 :            :  * transfers.
    2219                 :            :  *
    2220                 :            :  * @return 1 if a request is queued and more requests may be needed to
    2221                 :            :  * complete the transfer, 0 if no more requests are required for this
    2222                 :            :  * transfer, -1 if there is insufficient space in the Tx FIFO.
    2223                 :            :  */
    2224                 :   20562028 : static int queue_transaction(dwc_otg_hcd_t * hcd,
    2225                 :            :                              dwc_hc_t * hc, uint16_t fifo_dwords_avail)
    2226                 :            : {
    2227                 :            :         int retval;
    2228                 :            : 
    2229         [ +  - ]:   20562028 :         if (hcd->core_if->dma_enable) {
    2230         [ -  + ]:   20562028 :                 if (hcd->core_if->dma_desc_enable) {
    2231         [ #  # ]:          0 :                         if (!hc->xfer_started
    2232         [ #  # ]:          0 :                             || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
    2233                 :          0 :                                 dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
    2234                 :          0 :                                 hc->qh->ping_state = 0;
    2235                 :            :                         }
    2236         [ +  + ]:   20562028 :                 } else if (!hc->xfer_started) {
    2237   [ +  -  -  + ]:    2747052 :                         if (fiq_fsm_enable && hc->error_state) {
    2238                 :          0 :                                 hcd->fiq_state->channel[hc->hc_num].nr_errors =
    2239                 :          0 :                                         DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list)->error_count;
    2240                 :          0 :                                 hcd->fiq_state->channel[hc->hc_num].fsm =
    2241                 :            :                                         FIQ_PASSTHROUGH_ERRORSTATE;
    2242                 :            :                         }
    2243                 :    2747052 :                         dwc_otg_hc_start_transfer(hcd->core_if, hc);
    2244                 :    2747051 :                         hc->qh->ping_state = 0;
    2245                 :            :                 }
    2246                 :            :                 retval = 0;
    2247         [ #  # ]:          0 :         } else if (hc->halt_pending) {
    2248                 :            :                 /* Don't queue a request if the channel has been halted. */
    2249                 :            :                 retval = 0;
    2250         [ #  # ]:          0 :         } else if (hc->halt_on_queue) {
    2251                 :          0 :                 dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
    2252                 :            :                 retval = 0;
    2253         [ #  # ]:          0 :         } else if (hc->do_ping) {
    2254         [ #  # ]:          0 :                 if (!hc->xfer_started) {
    2255                 :          0 :                         dwc_otg_hc_start_transfer(hcd->core_if, hc);
    2256                 :            :                 }
    2257                 :            :                 retval = 0;
    2258   [ #  #  #  # ]:          0 :         } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
    2259         [ #  # ]:          0 :                 if ((fifo_dwords_avail * 4) >= hc->max_packet) {
    2260         [ #  # ]:          0 :                         if (!hc->xfer_started) {
    2261                 :          0 :                                 dwc_otg_hc_start_transfer(hcd->core_if, hc);
    2262                 :            :                                 retval = 1;
    2263                 :            :                         } else {
    2264                 :          0 :                                 retval =
    2265                 :            :                                     dwc_otg_hc_continue_transfer(hcd->core_if,
    2266                 :            :                                                                  hc);
    2267                 :            :                         }
    2268                 :            :                 } else {
    2269                 :            :                         retval = -1;
    2270                 :            :                 }
    2271                 :            :         } else {
    2272         [ #  # ]:          0 :                 if (!hc->xfer_started) {
    2273                 :          0 :                         dwc_otg_hc_start_transfer(hcd->core_if, hc);
    2274                 :            :                         retval = 1;
    2275                 :            :                 } else {
    2276                 :          0 :                         retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
    2277                 :            :                 }
    2278                 :            :         }
    2279                 :            : 
    2280                 :   20562027 :         return retval;
    2281                 :            : }
    2282                 :            : 
    2283                 :            : /**
    2284                 :            :  * Processes periodic channels for the next frame and queues transactions for
    2285                 :            :  * these channels to the DWC_otg controller. After queueing transactions, the
    2286                 :            :  * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
    2287                 :            :  * to queue as Periodic Tx FIFO or request queue space becomes available.
    2288                 :            :  * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
    2289                 :            :  */
    2290                 :    6073756 : static void process_periodic_channels(dwc_otg_hcd_t * hcd)
    2291                 :            : {
    2292                 :            :         hptxsts_data_t tx_status;
    2293                 :            :         dwc_list_link_t *qh_ptr;
    2294                 :            :         dwc_otg_qh_t *qh;
    2295                 :            :         int status = 0;
    2296                 :            :         int no_queue_space = 0;
    2297                 :            :         int no_fifo_space = 0;
    2298                 :            : 
    2299                 :            :         dwc_otg_host_global_regs_t *host_regs;
    2300                 :    6073756 :         host_regs = hcd->core_if->host_if->host_global_regs;
    2301                 :            : 
    2302                 :            :         DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
    2303                 :            : #ifdef DEBUG
    2304                 :            :         tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
    2305                 :            :         DWC_DEBUGPL(DBG_HCDV,
    2306                 :            :                     "  P Tx Req Queue Space Avail (before queue): %d\n",
    2307                 :            :                     tx_status.b.ptxqspcavail);
    2308                 :            :         DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
    2309                 :            :                     tx_status.b.ptxfspcavail);
    2310                 :            : #endif
    2311                 :            : 
    2312                 :    6073756 :         qh_ptr = hcd->periodic_sched_assigned.next;
    2313         [ +  + ]:   18887050 :         while (qh_ptr != &hcd->periodic_sched_assigned) {
    2314                 :    6739538 :                 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
    2315         [ +  - ]:    6739538 :                 if (tx_status.b.ptxqspcavail == 0) {
    2316                 :            :                         no_queue_space = 1;
    2317                 :            :                         break;
    2318                 :            :                 }
    2319                 :            : 
    2320                 :    6739538 :                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
    2321                 :            : 
    2322                 :            :                 // Do not send a split start transaction any later than frame .6
    2323                 :            :                 // Note, we have to schedule a periodic in .5 to make it go in .6
    2324   [ +  -  +  +  :   11037303 :                 if(fiq_fsm_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
                   +  + ]
    2325                 :            :                 {
    2326                 :         39 :                         qh_ptr = qh_ptr->next;
    2327                 :         78 :                         hcd->fiq_state->next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
    2328                 :         39 :                         continue;
    2329                 :            :                 }
    2330                 :            : 
    2331   [ +  -  +  + ]:    6739499 :                 if (fiq_fsm_enable && fiq_fsm_transaction_suitable(hcd, qh)) {
    2332         [ +  - ]:    4297726 :                         if (qh->do_split)
    2333                 :    4297726 :                                 fiq_fsm_queue_split_transaction(hcd, qh);
    2334                 :            :                         else
    2335                 :          0 :                                 fiq_fsm_queue_isoc_transaction(hcd, qh);
    2336                 :            :                 } else {
    2337                 :            : 
    2338                 :            :                         /*
    2339                 :            :                          * Set a flag if we're queueing high-bandwidth in slave mode.
    2340                 :            :                          * The flag prevents any halts to get into the request queue in
    2341                 :            :                          * the middle of multiple high-bandwidth packets getting queued.
    2342                 :            :                          */
    2343   [ -  +  #  # ]:    2441773 :                         if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
    2344                 :          0 :                                 hcd->core_if->queuing_high_bandwidth = 1;
    2345                 :            :                         }
    2346                 :    2441773 :                         status = queue_transaction(hcd, qh->channel,
    2347                 :            :                                                         tx_status.b.ptxfspcavail);
    2348         [ +  - ]:    2441773 :                         if (status < 0) {
    2349                 :            :                                 no_fifo_space = 1;
    2350                 :            :                                 break;
    2351                 :            :                         }
    2352                 :            :                 }
    2353                 :            : 
    2354                 :            :                 /*
    2355                 :            :                  * In Slave mode, stay on the current transfer until there is
    2356                 :            :                  * nothing more to do or the high-bandwidth request count is
    2357                 :            :                  * reached. In DMA mode, only need to queue one request. The
    2358                 :            :                  * controller automatically handles multiple packets for
    2359                 :            :                  * high-bandwidth transfers.
    2360                 :            :                  */
    2361   [ -  +  #  #  :    6739499 :                 if (hcd->core_if->dma_enable || status == 0 ||
                   #  # ]
    2362                 :          0 :                     qh->channel->requests == qh->channel->multi_count) {
    2363                 :    6739499 :                         qh_ptr = qh_ptr->next;
    2364                 :            :                         /*
    2365                 :            :                          * Move the QH from the periodic assigned schedule to
    2366                 :            :                          * the periodic queued schedule.
    2367                 :            :                          */
    2368                 :    6739499 :                         DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
    2369                 :            :                                            &qh->qh_list_entry);
    2370                 :            : 
    2371                 :            :                         /* done queuing high bandwidth */
    2372                 :    6739499 :                         hcd->core_if->queuing_high_bandwidth = 0;
    2373                 :            :                 }
    2374                 :            :         }
    2375                 :            : 
    2376         [ -  + ]:    6073756 :         if (!hcd->core_if->dma_enable) {
    2377                 :            :                 dwc_otg_core_global_regs_t *global_regs;
    2378                 :          0 :                 gintmsk_data_t intr_mask = {.d32 = 0 };
    2379                 :            : 
    2380                 :          0 :                 global_regs = hcd->core_if->core_global_regs;
    2381                 :          0 :                 intr_mask.b.ptxfempty = 1;
    2382                 :            : #ifdef DEBUG
    2383                 :            :                 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
    2384                 :            :                 DWC_DEBUGPL(DBG_HCDV,
    2385                 :            :                             "  P Tx Req Queue Space Avail (after queue): %d\n",
    2386                 :            :                             tx_status.b.ptxqspcavail);
    2387                 :            :                 DWC_DEBUGPL(DBG_HCDV,
    2388                 :            :                             "  P Tx FIFO Space Avail (after queue): %d\n",
    2389                 :            :                             tx_status.b.ptxfspcavail);
    2390                 :            : #endif
    2391         [ #  # ]:          0 :                 if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
    2392         [ #  # ]:          0 :                     no_queue_space || no_fifo_space) {
    2393                 :            :                         /*
    2394                 :            :                          * May need to queue more transactions as the request
    2395                 :            :                          * queue or Tx FIFO empties. Enable the periodic Tx
    2396                 :            :                          * FIFO empty interrupt. (Always use the half-empty
    2397                 :            :                          * level to ensure that new requests are loaded as
    2398                 :            :                          * soon as possible.)
    2399                 :            :                          */
    2400                 :          0 :                         DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
    2401                 :            :                                          intr_mask.d32);
    2402                 :            :                 } else {
    2403                 :            :                         /*
    2404                 :            :                          * Disable the Tx FIFO empty interrupt since there are
    2405                 :            :                          * no more transactions that need to be queued right
    2406                 :            :                          * now. This function is called from interrupt
    2407                 :            :                          * handlers to queue more transactions as transfer
    2408                 :            :                          * states change.
    2409                 :            :                          */
    2410                 :          0 :                         DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
    2411                 :            :                                          0);
    2412                 :            :                 }
    2413                 :            :         }
    2414                 :    6073756 : }
    2415                 :            : 
    2416                 :            : /**
    2417                 :            :  * Processes active non-periodic channels and queues transactions for these
    2418                 :            :  * channels to the DWC_otg controller. After queueing transactions, the NP Tx
    2419                 :            :  * FIFO Empty interrupt is enabled if there are more transactions to queue as
    2420                 :            :  * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
    2421                 :            :  * FIFO Empty interrupt is disabled.
    2422                 :            :  */
    2423                 :   17918306 : static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
    2424                 :            : {
    2425                 :            :         gnptxsts_data_t tx_status;
    2426                 :            :         dwc_list_link_t *orig_qh_ptr;
    2427                 :            :         dwc_otg_qh_t *qh;
    2428                 :            :         int status;
    2429                 :            :         int no_queue_space = 0;
    2430                 :            :         int no_fifo_space = 0;
    2431                 :            :         int more_to_do = 0;
    2432                 :            : 
    2433                 :   17918306 :         dwc_otg_core_global_regs_t *global_regs =
    2434                 :   17918306 :             hcd->core_if->core_global_regs;
    2435                 :            : 
    2436                 :            :         DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
    2437                 :            : #ifdef DEBUG
    2438                 :            :         tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
    2439                 :            :         DWC_DEBUGPL(DBG_HCDV,
    2440                 :            :                     "  NP Tx Req Queue Space Avail (before queue): %d\n",
    2441                 :            :                     tx_status.b.nptxqspcavail);
    2442                 :            :         DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
    2443                 :            :                     tx_status.b.nptxfspcavail);
    2444                 :            : #endif
    2445                 :            :         /*
    2446                 :            :          * Keep track of the starting point. Skip over the start-of-list
    2447                 :            :          * entry.
    2448                 :            :          */
    2449         [ +  + ]:   17918306 :         if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
    2450                 :     207345 :                 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
    2451                 :            :         }
    2452                 :   17918306 :         orig_qh_ptr = hcd->non_periodic_qh_ptr;
    2453                 :            : 
    2454                 :            :         /*
    2455                 :            :          * Process once through the active list or until no more space is
    2456                 :            :          * available in the request queue or the Tx FIFO.
    2457                 :            :          */
    2458                 :            :         do {
    2459                 :   18185551 :                 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
    2460   [ -  +  #  # ]:   18185551 :                 if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
    2461                 :            :                         no_queue_space = 1;
    2462                 :            :                         break;
    2463                 :            :                 }
    2464                 :            : 
    2465                 :   18185551 :                 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
    2466                 :            :                                     qh_list_entry);
    2467                 :            : 
    2468   [ +  -  +  + ]:   18185551 :                 if(fiq_fsm_enable && fiq_fsm_transaction_suitable(hcd, qh)) {
    2469                 :      65299 :                         fiq_fsm_queue_split_transaction(hcd, qh);
    2470                 :            :                 } else {
    2471                 :   18120252 :                         status = queue_transaction(hcd, qh->channel,
    2472                 :            :                                                 tx_status.b.nptxfspcavail);
    2473                 :            : 
    2474         [ +  - ]:   18120252 :                         if (status > 0) {
    2475                 :            :                                 more_to_do = 1;
    2476         [ +  - ]:   18120252 :                         } else if (status < 0) {
    2477                 :            :                                 no_fifo_space = 1;
    2478                 :            :                                 break;
    2479                 :            :                         }
    2480                 :            :                 }
    2481                 :            :                 /* Advance to next QH, skipping start-of-list entry. */
    2482                 :   18185551 :                 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
    2483         [ +  + ]:   18185551 :                 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
    2484                 :   17918306 :                         hcd->non_periodic_qh_ptr =
    2485                 :   17918306 :                             hcd->non_periodic_qh_ptr->next;
    2486                 :            :                 }
    2487                 :            : 
    2488         [ +  + ]:   18185551 :         } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
    2489                 :            : 
    2490         [ -  + ]:   17918306 :         if (!hcd->core_if->dma_enable) {
    2491                 :          0 :                 gintmsk_data_t intr_mask = {.d32 = 0 };
    2492                 :          0 :                 intr_mask.b.nptxfempty = 1;
    2493                 :            : 
    2494                 :            : #ifdef DEBUG
    2495                 :            :                 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
    2496                 :            :                 DWC_DEBUGPL(DBG_HCDV,
    2497                 :            :                             "  NP Tx Req Queue Space Avail (after queue): %d\n",
    2498                 :            :                             tx_status.b.nptxqspcavail);
    2499                 :            :                 DWC_DEBUGPL(DBG_HCDV,
    2500                 :            :                             "  NP Tx FIFO Space Avail (after queue): %d\n",
    2501                 :            :                             tx_status.b.nptxfspcavail);
    2502                 :            : #endif
    2503         [ #  # ]:          0 :                 if (more_to_do || no_queue_space || no_fifo_space) {
    2504                 :            :                         /*
    2505                 :            :                          * May need to queue more transactions as the request
    2506                 :            :                          * queue or Tx FIFO empties. Enable the non-periodic
    2507                 :            :                          * Tx FIFO empty interrupt. (Always use the half-empty
    2508                 :            :                          * level to ensure that new requests are loaded as
    2509                 :            :                          * soon as possible.)
    2510                 :            :                          */
    2511                 :          0 :                         DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
    2512                 :            :                                          intr_mask.d32);
    2513                 :            :                 } else {
    2514                 :            :                         /*
    2515                 :            :                          * Disable the Tx FIFO empty interrupt since there are
    2516                 :            :                          * no more transactions that need to be queued right
    2517                 :            :                          * now. This function is called from interrupt
    2518                 :            :                          * handlers to queue more transactions as transfer
    2519                 :            :                          * states change.
    2520                 :            :                          */
    2521                 :          0 :                         DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
    2522                 :            :                                          0);
    2523                 :            :                 }
    2524                 :            :         }
    2525                 :   17918306 : }
    2526                 :            : 
    2527                 :            : /**
    2528                 :            :  * This function processes the currently active host channels and queues
    2529                 :            :  * transactions for these channels to the DWC_otg controller. It is called
    2530                 :            :  * from HCD interrupt handler functions.
    2531                 :            :  *
    2532                 :            :  * @param hcd The HCD state structure.
    2533                 :            :  * @param tr_type The type(s) of transactions to queue (non-periodic,
    2534                 :            :  * periodic, or both).
    2535                 :            :  */
    2536                 :   18604736 : void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
    2537                 :            :                                     dwc_otg_transaction_type_e tr_type)
    2538                 :            : {
    2539                 :            : #ifdef DEBUG_SOF
    2540                 :            :         DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
    2541                 :            : #endif
    2542                 :            :         /* Process host channels associated with periodic transfers. */
    2543         [ +  + ]:   37209472 :         if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
    2544         [ +  - ]:   24678491 :              tr_type == DWC_OTG_TRANSACTION_ALL) &&
    2545                 :    6073755 :             !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
    2546                 :            : 
    2547                 :    6073755 :                 process_periodic_channels(hcd);
    2548                 :            :         }
    2549                 :            : 
    2550                 :            :         /* Process host channels associated with non-periodic transfers. */
    2551         [ +  + ]:   18604735 :         if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
    2552                 :            :             tr_type == DWC_OTG_TRANSACTION_ALL) {
    2553         [ +  - ]:   17918303 :                 if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
    2554                 :   17918303 :                         process_non_periodic_channels(hcd);
    2555                 :            :                 } else {
    2556                 :            :                         /*
    2557                 :            :                          * Ensure NP Tx FIFO empty interrupt is disabled when
    2558                 :            :                          * there are no non-periodic transfers to process.
    2559                 :            :                          */
    2560                 :          0 :                         gintmsk_data_t gintmsk = {.d32 = 0 };
    2561                 :          0 :                         gintmsk.b.nptxfempty = 1;
    2562                 :            : 
    2563         [ #  # ]:          0 :                         if (fiq_enable) {
    2564                 :          0 :                                 local_fiq_disable();
    2565                 :          0 :                                 fiq_fsm_spin_lock(&hcd->fiq_state->lock);
    2566                 :          0 :                                 DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
    2567                 :          0 :                                 fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
    2568                 :          0 :                                 local_fiq_enable();
    2569                 :            :                         } else {
    2570                 :          0 :                                 DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
    2571                 :            :                         }
    2572                 :            :                 }
    2573                 :            :         }
    2574                 :   18604735 : }
    2575                 :            : 
    2576                 :            : #ifdef DWC_HS_ELECT_TST
    2577                 :            : /*
    2578                 :            :  * Quick and dirty hack to implement the HS Electrical Test
    2579                 :            :  * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
    2580                 :            :  *
    2581                 :            :  * This code was copied from our userspace app "hset". It sends a
    2582                 :            :  * Get Device Descriptor control sequence in two parts, first the
    2583                 :            :  * Setup packet by itself, followed some time later by the In and
    2584                 :            :  * Ack packets. Rather than trying to figure out how to add this
    2585                 :            :  * functionality to the normal driver code, we just hijack the
    2586                 :            :  * hardware, using these two function to drive the hardware
    2587                 :            :  * directly.
    2588                 :            :  */
    2589                 :            : 
    2590                 :            : static dwc_otg_core_global_regs_t *global_regs;
    2591                 :            : static dwc_otg_host_global_regs_t *hc_global_regs;
    2592                 :            : static dwc_otg_hc_regs_t *hc_regs;
    2593                 :            : static uint32_t *data_fifo;
    2594                 :            : 
    2595                 :          0 : static void do_setup(void)
    2596                 :            : {
    2597                 :            :         gintsts_data_t gintsts;
    2598                 :            :         hctsiz_data_t hctsiz;
    2599                 :            :         hcchar_data_t hcchar;
    2600                 :            :         haint_data_t haint;
    2601                 :            :         hcint_data_t hcint;
    2602                 :            : 
    2603                 :            :         /* Enable HAINTs */
    2604                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
    2605                 :            : 
    2606                 :            :         /* Enable HCINTs */
    2607                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
    2608                 :            : 
    2609                 :            :         /* Read GINTSTS */
    2610                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2611                 :            : 
    2612                 :            :         /* Read HAINT */
    2613                 :          0 :         haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2614                 :            : 
    2615                 :            :         /* Read HCINT */
    2616                 :          0 :         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2617                 :            : 
    2618                 :            :         /* Read HCCHAR */
    2619                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2620                 :            : 
    2621                 :            :         /* Clear HCINT */
    2622                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2623                 :            : 
    2624                 :            :         /* Clear HAINT */
    2625                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2626                 :            : 
    2627                 :            :         /* Clear GINTSTS */
    2628                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2629                 :            : 
    2630                 :            :         /* Read GINTSTS */
    2631                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2632                 :            : 
    2633                 :            :         /*
    2634                 :            :          * Send Setup packet (Get Device Descriptor)
    2635                 :            :          */
    2636                 :            : 
    2637                 :            :         /* Make sure channel is disabled */
    2638                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2639         [ #  # ]:          0 :         if (hcchar.b.chen) {
    2640                 :          0 :                 hcchar.b.chdis = 1;
    2641                 :            : //              hcchar.b.chen = 1;
    2642                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
    2643                 :            :                 //sleep(1);
    2644                 :          0 :                 dwc_mdelay(1000);
    2645                 :            : 
    2646                 :            :                 /* Read GINTSTS */
    2647                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2648                 :            : 
    2649                 :            :                 /* Read HAINT */
    2650                 :          0 :                 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2651                 :            : 
    2652                 :            :                 /* Read HCINT */
    2653                 :          0 :                 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2654                 :            : 
    2655                 :            :                 /* Read HCCHAR */
    2656                 :          0 :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2657                 :            : 
    2658                 :            :                 /* Clear HCINT */
    2659                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2660                 :            : 
    2661                 :            :                 /* Clear HAINT */
    2662                 :          0 :                 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2663                 :            : 
    2664                 :            :                 /* Clear GINTSTS */
    2665                 :          0 :                 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2666                 :            : 
    2667                 :          0 :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2668                 :            :         }
    2669                 :            : 
    2670                 :            :         /* Set HCTSIZ */
    2671                 :          0 :         hctsiz.d32 = 0;
    2672                 :          0 :         hctsiz.b.xfersize = 8;
    2673                 :          0 :         hctsiz.b.pktcnt = 1;
    2674                 :          0 :         hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
    2675                 :          0 :         DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
    2676                 :            : 
    2677                 :            :         /* Set HCCHAR */
    2678                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2679                 :          0 :         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
    2680                 :          0 :         hcchar.b.epdir = 0;
    2681                 :          0 :         hcchar.b.epnum = 0;
    2682                 :          0 :         hcchar.b.mps = 8;
    2683                 :          0 :         hcchar.b.chen = 1;
    2684                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
    2685                 :            : 
    2686                 :            :         /* Fill FIFO with Setup data for Get Device Descriptor */
    2687                 :          0 :         data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
    2688                 :          0 :         DWC_WRITE_REG32(data_fifo++, 0x01000680);
    2689                 :          0 :         DWC_WRITE_REG32(data_fifo++, 0x00080000);
    2690                 :            : 
    2691                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2692                 :            : 
    2693                 :            :         /* Wait for host channel interrupt */
    2694                 :            :         do {
    2695                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2696         [ #  # ]:          0 :         } while (gintsts.b.hcintr == 0);
    2697                 :            : 
    2698                 :            :         /* Disable HCINTs */
    2699                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
    2700                 :            : 
    2701                 :            :         /* Disable HAINTs */
    2702                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
    2703                 :            : 
    2704                 :            :         /* Read HAINT */
    2705                 :          0 :         haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2706                 :            : 
    2707                 :            :         /* Read HCINT */
    2708                 :          0 :         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2709                 :            : 
    2710                 :            :         /* Read HCCHAR */
    2711                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2712                 :            : 
    2713                 :            :         /* Clear HCINT */
    2714                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2715                 :            : 
    2716                 :            :         /* Clear HAINT */
    2717                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2718                 :            : 
    2719                 :            :         /* Clear GINTSTS */
    2720                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2721                 :            : 
    2722                 :            :         /* Read GINTSTS */
    2723                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2724                 :          0 : }
    2725                 :            : 
    2726                 :          0 : static void do_in_ack(void)
    2727                 :            : {
    2728                 :            :         gintsts_data_t gintsts;
    2729                 :            :         hctsiz_data_t hctsiz;
    2730                 :            :         hcchar_data_t hcchar;
    2731                 :            :         haint_data_t haint;
    2732                 :            :         hcint_data_t hcint;
    2733                 :            :         host_grxsts_data_t grxsts;
    2734                 :            : 
    2735                 :            :         /* Enable HAINTs */
    2736                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
    2737                 :            : 
    2738                 :            :         /* Enable HCINTs */
    2739                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
    2740                 :            : 
    2741                 :            :         /* Read GINTSTS */
    2742                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2743                 :            : 
    2744                 :            :         /* Read HAINT */
    2745                 :          0 :         haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2746                 :            : 
    2747                 :            :         /* Read HCINT */
    2748                 :          0 :         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2749                 :            : 
    2750                 :            :         /* Read HCCHAR */
    2751                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2752                 :            : 
    2753                 :            :         /* Clear HCINT */
    2754                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2755                 :            : 
    2756                 :            :         /* Clear HAINT */
    2757                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2758                 :            : 
    2759                 :            :         /* Clear GINTSTS */
    2760                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2761                 :            : 
    2762                 :            :         /* Read GINTSTS */
    2763                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2764                 :            : 
    2765                 :            :         /*
    2766                 :            :          * Receive Control In packet
    2767                 :            :          */
    2768                 :            : 
    2769                 :            :         /* Make sure channel is disabled */
    2770                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2771         [ #  # ]:          0 :         if (hcchar.b.chen) {
    2772                 :          0 :                 hcchar.b.chdis = 1;
    2773                 :          0 :                 hcchar.b.chen = 1;
    2774                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
    2775                 :            :                 //sleep(1);
    2776                 :          0 :                 dwc_mdelay(1000);
    2777                 :            : 
    2778                 :            :                 /* Read GINTSTS */
    2779                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2780                 :            : 
    2781                 :            :                 /* Read HAINT */
    2782                 :          0 :                 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2783                 :            : 
    2784                 :            :                 /* Read HCINT */
    2785                 :          0 :                 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2786                 :            : 
    2787                 :            :                 /* Read HCCHAR */
    2788                 :          0 :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2789                 :            : 
    2790                 :            :                 /* Clear HCINT */
    2791                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2792                 :            : 
    2793                 :            :                 /* Clear HAINT */
    2794                 :          0 :                 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2795                 :            : 
    2796                 :            :                 /* Clear GINTSTS */
    2797                 :          0 :                 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2798                 :            : 
    2799                 :          0 :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2800                 :            :         }
    2801                 :            : 
    2802                 :            :         /* Set HCTSIZ */
    2803                 :          0 :         hctsiz.d32 = 0;
    2804                 :          0 :         hctsiz.b.xfersize = 8;
    2805                 :          0 :         hctsiz.b.pktcnt = 1;
    2806                 :          0 :         hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
    2807                 :          0 :         DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
    2808                 :            : 
    2809                 :            :         /* Set HCCHAR */
    2810                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2811                 :          0 :         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
    2812                 :          0 :         hcchar.b.epdir = 1;
    2813                 :          0 :         hcchar.b.epnum = 0;
    2814                 :          0 :         hcchar.b.mps = 8;
    2815                 :          0 :         hcchar.b.chen = 1;
    2816                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
    2817                 :            : 
    2818                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2819                 :            : 
    2820                 :            :         /* Wait for receive status queue interrupt */
    2821                 :            :         do {
    2822                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2823         [ #  # ]:          0 :         } while (gintsts.b.rxstsqlvl == 0);
    2824                 :            : 
    2825                 :            :         /* Read RXSTS */
    2826                 :          0 :         grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
    2827                 :            : 
    2828                 :            :         /* Clear RXSTSQLVL in GINTSTS */
    2829                 :          0 :         gintsts.d32 = 0;
    2830                 :          0 :         gintsts.b.rxstsqlvl = 1;
    2831                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2832                 :            : 
    2833         [ #  # ]:          0 :         switch (grxsts.b.pktsts) {
    2834                 :            :         case DWC_GRXSTS_PKTSTS_IN:
    2835                 :            :                 /* Read the data into the host buffer */
    2836         [ #  # ]:          0 :                 if (grxsts.b.bcnt > 0) {
    2837                 :            :                         int i;
    2838                 :          0 :                         int word_count = (grxsts.b.bcnt + 3) / 4;
    2839                 :            : 
    2840                 :          0 :                         data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
    2841                 :            : 
    2842         [ #  # ]:          0 :                         for (i = 0; i < word_count; i++) {
    2843                 :          0 :                                 (void)DWC_READ_REG32(data_fifo++);
    2844                 :            :                         }
    2845                 :            :                 }
    2846                 :            :                 break;
    2847                 :            : 
    2848                 :            :         default:
    2849                 :            :                 break;
    2850                 :            :         }
    2851                 :            : 
    2852                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2853                 :            : 
    2854                 :            :         /* Wait for receive status queue interrupt */
    2855                 :            :         do {
    2856                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2857         [ #  # ]:          0 :         } while (gintsts.b.rxstsqlvl == 0);
    2858                 :            : 
    2859                 :            :         /* Read RXSTS */
    2860                 :          0 :         grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
    2861                 :            : 
    2862                 :            :         /* Clear RXSTSQLVL in GINTSTS */
    2863                 :          0 :         gintsts.d32 = 0;
    2864                 :          0 :         gintsts.b.rxstsqlvl = 1;
    2865                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2866                 :            : 
    2867                 :            :         switch (grxsts.b.pktsts) {
    2868                 :            :         case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
    2869                 :            :                 break;
    2870                 :            : 
    2871                 :            :         default:
    2872                 :            :                 break;
    2873                 :            :         }
    2874                 :            : 
    2875                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2876                 :            : 
    2877                 :            :         /* Wait for host channel interrupt */
    2878                 :            :         do {
    2879                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2880         [ #  # ]:          0 :         } while (gintsts.b.hcintr == 0);
    2881                 :            : 
    2882                 :            :         /* Read HAINT */
    2883                 :          0 :         haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2884                 :            : 
    2885                 :            :         /* Read HCINT */
    2886                 :          0 :         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2887                 :            : 
    2888                 :            :         /* Read HCCHAR */
    2889                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2890                 :            : 
    2891                 :            :         /* Clear HCINT */
    2892                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2893                 :            : 
    2894                 :            :         /* Clear HAINT */
    2895                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2896                 :            : 
    2897                 :            :         /* Clear GINTSTS */
    2898                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2899                 :            : 
    2900                 :            :         /* Read GINTSTS */
    2901                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2902                 :            : 
    2903                 :            : //      usleep(100000);
    2904                 :            : //      mdelay(100);
    2905                 :          0 :         dwc_mdelay(1);
    2906                 :            : 
    2907                 :            :         /*
    2908                 :            :          * Send handshake packet
    2909                 :            :          */
    2910                 :            : 
    2911                 :            :         /* Read HAINT */
    2912                 :          0 :         haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2913                 :            : 
    2914                 :            :         /* Read HCINT */
    2915                 :          0 :         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2916                 :            : 
    2917                 :            :         /* Read HCCHAR */
    2918                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2919                 :            : 
    2920                 :            :         /* Clear HCINT */
    2921                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2922                 :            : 
    2923                 :            :         /* Clear HAINT */
    2924                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2925                 :            : 
    2926                 :            :         /* Clear GINTSTS */
    2927                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2928                 :            : 
    2929                 :            :         /* Read GINTSTS */
    2930                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2931                 :            : 
    2932                 :            :         /* Make sure channel is disabled */
    2933                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2934         [ #  # ]:          0 :         if (hcchar.b.chen) {
    2935                 :          0 :                 hcchar.b.chdis = 1;
    2936                 :          0 :                 hcchar.b.chen = 1;
    2937                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
    2938                 :            :                 //sleep(1);
    2939                 :          0 :                 dwc_mdelay(1000);
    2940                 :            : 
    2941                 :            :                 /* Read GINTSTS */
    2942                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2943                 :            : 
    2944                 :            :                 /* Read HAINT */
    2945                 :          0 :                 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2946                 :            : 
    2947                 :            :                 /* Read HCINT */
    2948                 :          0 :                 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2949                 :            : 
    2950                 :            :                 /* Read HCCHAR */
    2951                 :          0 :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2952                 :            : 
    2953                 :            :                 /* Clear HCINT */
    2954                 :          0 :                 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    2955                 :            : 
    2956                 :            :                 /* Clear HAINT */
    2957                 :          0 :                 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    2958                 :            : 
    2959                 :            :                 /* Clear GINTSTS */
    2960                 :          0 :                 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    2961                 :            : 
    2962                 :          0 :                 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2963                 :            :         }
    2964                 :            : 
    2965                 :            :         /* Set HCTSIZ */
    2966                 :          0 :         hctsiz.d32 = 0;
    2967                 :          0 :         hctsiz.b.xfersize = 0;
    2968                 :          0 :         hctsiz.b.pktcnt = 1;
    2969                 :          0 :         hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
    2970                 :          0 :         DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
    2971                 :            : 
    2972                 :            :         /* Set HCCHAR */
    2973                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    2974                 :          0 :         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
    2975                 :          0 :         hcchar.b.epdir = 0;
    2976                 :          0 :         hcchar.b.epnum = 0;
    2977                 :          0 :         hcchar.b.mps = 8;
    2978                 :          0 :         hcchar.b.chen = 1;
    2979                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
    2980                 :            : 
    2981                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2982                 :            : 
    2983                 :            :         /* Wait for host channel interrupt */
    2984                 :            :         do {
    2985                 :          0 :                 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    2986         [ #  # ]:          0 :         } while (gintsts.b.hcintr == 0);
    2987                 :            : 
    2988                 :            :         /* Disable HCINTs */
    2989                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
    2990                 :            : 
    2991                 :            :         /* Disable HAINTs */
    2992                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
    2993                 :            : 
    2994                 :            :         /* Read HAINT */
    2995                 :          0 :         haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
    2996                 :            : 
    2997                 :            :         /* Read HCINT */
    2998                 :          0 :         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
    2999                 :            : 
    3000                 :            :         /* Read HCCHAR */
    3001                 :          0 :         hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
    3002                 :            : 
    3003                 :            :         /* Clear HCINT */
    3004                 :          0 :         DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
    3005                 :            : 
    3006                 :            :         /* Clear HAINT */
    3007                 :          0 :         DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
    3008                 :            : 
    3009                 :            :         /* Clear GINTSTS */
    3010                 :          0 :         DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
    3011                 :            : 
    3012                 :            :         /* Read GINTSTS */
    3013                 :          0 :         gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
    3014                 :          0 : }
    3015                 :            : #endif
    3016                 :            : 
    3017                 :            : /** Handles hub class-specific requests. */
    3018                 :       2898 : int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
    3019                 :            :                             uint16_t typeReq,
    3020                 :            :                             uint16_t wValue,
    3021                 :            :                             uint16_t wIndex, uint8_t * buf, uint16_t wLength)
    3022                 :            : {
    3023                 :            :         int retval = 0;
    3024                 :            : 
    3025                 :       2898 :         dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
    3026                 :            :         usb_hub_descriptor_t *hub_desc;
    3027                 :            :         hprt0_data_t hprt0 = {.d32 = 0 };
    3028                 :            : 
    3029                 :            :         uint32_t port_status;
    3030                 :            : 
    3031   [ -  +  +  +  :       2898 :         switch (typeReq) {
             +  +  -  - ]
    3032                 :            :         case UCR_CLEAR_HUB_FEATURE:
    3033                 :            :                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3034                 :            :                             "ClearHubFeature 0x%x\n", wValue);
    3035         [ #  # ]:          0 :                 switch (wValue) {
    3036                 :            :                 case UHF_C_HUB_LOCAL_POWER:
    3037                 :            :                 case UHF_C_HUB_OVER_CURRENT:
    3038                 :            :                         /* Nothing required here */
    3039                 :            :                         break;
    3040                 :            :                 default:
    3041                 :            :                         retval = -DWC_E_INVALID;
    3042                 :          0 :                         DWC_ERROR("DWC OTG HCD - "
    3043                 :            :                                   "ClearHubFeature request %xh unknown\n",
    3044                 :            :                                   wValue);
    3045                 :            :                 }
    3046                 :            :                 break;
    3047                 :            :         case UCR_CLEAR_PORT_FEATURE:
    3048                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
    3049                 :            :                 if (wValue != UHF_PORT_L1)
    3050                 :            : #endif
    3051         [ +  - ]:        828 :                         if (!wIndex || wIndex > 1)
    3052                 :            :                                 goto error;
    3053                 :            : 
    3054   [ -  -  -  +  :        828 :                 switch (wValue) {
          +  +  -  -  -  
                      - ]
    3055                 :            :                 case UHF_PORT_ENABLE:
    3056                 :            :                         DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
    3057                 :            :                                     "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
    3058                 :          0 :                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3059                 :          0 :                         hprt0.b.prtena = 1;
    3060                 :          0 :                         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3061                 :          0 :                         break;
    3062                 :            :                 case UHF_PORT_SUSPEND:
    3063                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3064                 :            :                                     "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
    3065                 :            : 
    3066         [ #  # ]:          0 :                         if (core_if->power_down == 2) {
    3067                 :          0 :                                 dwc_otg_host_hibernation_restore(core_if, 0, 0);
    3068                 :            :                         } else {
    3069                 :          0 :                                 DWC_WRITE_REG32(core_if->pcgcctl, 0);
    3070                 :          0 :                                 dwc_mdelay(5);
    3071                 :            : 
    3072                 :          0 :                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3073                 :          0 :                                 hprt0.b.prtres = 1;
    3074                 :          0 :                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3075                 :          0 :                                 hprt0.b.prtsusp = 0;
    3076                 :            :                                 /* Clear Resume bit */
    3077                 :          0 :                                 dwc_mdelay(100);
    3078                 :          0 :                                 hprt0.b.prtres = 0;
    3079                 :          0 :                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3080                 :            :                         }
    3081                 :            :                         break;
    3082                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
    3083                 :            :                 case UHF_PORT_L1:
    3084                 :            :                         {
    3085                 :            :                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
    3086                 :            :                                 glpmcfg_data_t lpmcfg = {.d32 = 0 };
    3087                 :            : 
    3088                 :            :                                 lpmcfg.d32 =
    3089                 :            :                                     DWC_READ_REG32(&core_if->
    3090                 :            :                                                    core_global_regs->glpmcfg);
    3091                 :            :                                 lpmcfg.b.en_utmi_sleep = 0;
    3092                 :            :                                 lpmcfg.b.hird_thres &= (~(1 << 4));
    3093                 :            :                                 lpmcfg.b.prt_sleep_sts = 1;
    3094                 :            :                                 DWC_WRITE_REG32(&core_if->
    3095                 :            :                                                 core_global_regs->glpmcfg,
    3096                 :            :                                                 lpmcfg.d32);
    3097                 :            : 
    3098                 :            :                                 /* Clear Enbl_L1Gating bit. */
    3099                 :            :                                 pcgcctl.b.enbl_sleep_gating = 1;
    3100                 :            :                                 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
    3101                 :            :                                                  0);
    3102                 :            : 
    3103                 :            :                                 dwc_mdelay(5);
    3104                 :            : 
    3105                 :            :                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3106                 :            :                                 hprt0.b.prtres = 1;
    3107                 :            :                                 DWC_WRITE_REG32(core_if->host_if->hprt0,
    3108                 :            :                                                 hprt0.d32);
    3109                 :            :                                 /* This bit will be cleared in wakeup interrupt handle */
    3110                 :            :                                 break;
    3111                 :            :                         }
    3112                 :            : #endif
    3113                 :            :                 case UHF_PORT_POWER:
    3114                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3115                 :            :                                     "ClearPortFeature USB_PORT_FEAT_POWER\n");
    3116                 :          0 :                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3117                 :          0 :                         hprt0.b.prtpwr = 0;
    3118                 :          0 :                         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3119                 :          0 :                         break;
    3120                 :            :                 case UHF_PORT_INDICATOR:
    3121                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3122                 :            :                                     "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
    3123                 :            :                         /* Port inidicator not supported */
    3124                 :            :                         break;
    3125                 :            :                 case UHF_C_PORT_CONNECTION:
    3126                 :            :                         /* Clears drivers internal connect status change
    3127                 :            :                          * flag */
    3128                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3129                 :            :                                     "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
    3130                 :        207 :                         dwc_otg_hcd->flags.b.port_connect_status_change = 0;
    3131                 :        207 :                         break;
    3132                 :            :                 case UHF_C_PORT_RESET:
    3133                 :            :                         /* Clears the driver's internal Port Reset Change
    3134                 :            :                          * flag */
    3135                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3136                 :            :                                     "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
    3137                 :        414 :                         dwc_otg_hcd->flags.b.port_reset_change = 0;
    3138                 :        414 :                         break;
    3139                 :            :                 case UHF_C_PORT_ENABLE:
    3140                 :            :                         /* Clears the driver's internal Port
    3141                 :            :                          * Enable/Disable Change flag */
    3142                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3143                 :            :                                     "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
    3144                 :        207 :                         dwc_otg_hcd->flags.b.port_enable_change = 0;
    3145                 :        207 :                         break;
    3146                 :            :                 case UHF_C_PORT_SUSPEND:
    3147                 :            :                         /* Clears the driver's internal Port Suspend
    3148                 :            :                          * Change flag, which is set when resume signaling on
    3149                 :            :                          * the host port is complete */
    3150                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3151                 :            :                                     "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
    3152                 :          0 :                         dwc_otg_hcd->flags.b.port_suspend_change = 0;
    3153                 :          0 :                         break;
    3154                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
    3155                 :            :                 case UHF_C_PORT_L1:
    3156                 :            :                         dwc_otg_hcd->flags.b.port_l1_change = 0;
    3157                 :            :                         break;
    3158                 :            : #endif
    3159                 :            :                 case UHF_C_PORT_OVER_CURRENT:
    3160                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3161                 :            :                                     "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
    3162                 :          0 :                         dwc_otg_hcd->flags.b.port_over_current_change = 0;
    3163                 :          0 :                         break;
    3164                 :            :                 default:
    3165                 :            :                         retval = -DWC_E_INVALID;
    3166                 :          0 :                         DWC_ERROR("DWC OTG HCD - "
    3167                 :            :                                   "ClearPortFeature request %xh "
    3168                 :            :                                   "unknown or unsupported\n", wValue);
    3169                 :            :                 }
    3170                 :            :                 break;
    3171                 :            :         case UCR_GET_HUB_DESCRIPTOR:
    3172                 :            :                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3173                 :            :                             "GetHubDescriptor\n");
    3174                 :            :                 hub_desc = (usb_hub_descriptor_t *) buf;
    3175                 :        207 :                 hub_desc->bDescLength = 9;
    3176                 :        207 :                 hub_desc->bDescriptorType = 0x29;
    3177                 :        207 :                 hub_desc->bNbrPorts = 1;
    3178                 :        207 :                 USETW(hub_desc->wHubCharacteristics, 0x08);
    3179                 :        207 :                 hub_desc->bPwrOn2PwrGood = 1;
    3180                 :        207 :                 hub_desc->bHubContrCurrent = 0;
    3181                 :        207 :                 hub_desc->DeviceRemovable[0] = 0;
    3182                 :        207 :                 hub_desc->DeviceRemovable[1] = 0xff;
    3183                 :        207 :                 break;
    3184                 :            :         case UCR_GET_HUB_STATUS:
    3185                 :            :                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3186                 :            :                             "GetHubStatus\n");
    3187                 :        207 :                 DWC_MEMSET(buf, 0, 4);
    3188                 :        207 :                 break;
    3189                 :            :         case UCR_GET_PORT_STATUS:
    3190                 :            :                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3191                 :            :                             "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
    3192                 :            :                             wIndex, dwc_otg_hcd->flags.d32);
    3193         [ +  - ]:       1035 :                 if (!wIndex || wIndex > 1)
    3194                 :            :                         goto error;
    3195                 :            : 
    3196                 :       1035 :                 port_status = 0;
    3197                 :            : 
    3198         [ +  + ]:       1035 :                 if (dwc_otg_hcd->flags.b.port_connect_status_change)
    3199                 :        207 :                         port_status |= (1 << UHF_C_PORT_CONNECTION);
    3200                 :            : 
    3201         [ +  + ]:       1035 :                 if (dwc_otg_hcd->flags.b.port_enable_change)
    3202                 :        414 :                         port_status |= (1 << UHF_C_PORT_ENABLE);
    3203                 :            : 
    3204         [ -  + ]:       1035 :                 if (dwc_otg_hcd->flags.b.port_suspend_change)
    3205                 :          0 :                         port_status |= (1 << UHF_C_PORT_SUSPEND);
    3206                 :            : 
    3207         [ -  + ]:       1035 :                 if (dwc_otg_hcd->flags.b.port_l1_change)
    3208                 :          0 :                         port_status |= (1 << UHF_C_PORT_L1);
    3209                 :            : 
    3210         [ +  + ]:       1035 :                 if (dwc_otg_hcd->flags.b.port_reset_change) {
    3211                 :        414 :                         port_status |= (1 << UHF_C_PORT_RESET);
    3212                 :            :                 }
    3213                 :            : 
    3214         [ -  + ]:       1035 :                 if (dwc_otg_hcd->flags.b.port_over_current_change) {
    3215                 :          0 :                         DWC_WARN("Overcurrent change detected\n");
    3216                 :          0 :                         port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
    3217                 :            :                 }
    3218                 :            : 
    3219         [ -  + ]:       1035 :                 if (!dwc_otg_hcd->flags.b.port_connect_status) {
    3220                 :            :                         /*
    3221                 :            :                          * The port is disconnected, which means the core is
    3222                 :            :                          * either in device mode or it soon will be. Just
    3223                 :            :                          * return 0's for the remainder of the port status
    3224                 :            :                          * since the port register can't be read if the core
    3225                 :            :                          * is in device mode.
    3226                 :            :                          */
    3227                 :          0 :                         *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
    3228                 :          0 :                         break;
    3229                 :            :                 }
    3230                 :            : 
    3231                 :       1035 :                 hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
    3232                 :            :                 DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
    3233                 :            : 
    3234         [ +  - ]:       1035 :                 if (hprt0.b.prtconnsts)
    3235                 :       1035 :                         port_status |= (1 << UHF_PORT_CONNECTION);
    3236                 :            : 
    3237         [ +  + ]:       1035 :                 if (hprt0.b.prtena)
    3238                 :        621 :                         port_status |= (1 << UHF_PORT_ENABLE);
    3239                 :            : 
    3240         [ -  + ]:       1035 :                 if (hprt0.b.prtsusp)
    3241                 :          0 :                         port_status |= (1 << UHF_PORT_SUSPEND);
    3242                 :            : 
    3243         [ -  + ]:       1035 :                 if (hprt0.b.prtovrcurract)
    3244                 :          0 :                         port_status |= (1 << UHF_PORT_OVER_CURRENT);
    3245                 :            : 
    3246         [ -  + ]:       1035 :                 if (hprt0.b.prtrst)
    3247                 :          0 :                         port_status |= (1 << UHF_PORT_RESET);
    3248                 :            : 
    3249         [ +  - ]:       1035 :                 if (hprt0.b.prtpwr)
    3250                 :       1035 :                         port_status |= (1 << UHF_PORT_POWER);
    3251                 :            : 
    3252         [ +  + ]:       1035 :                 if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
    3253                 :        621 :                         port_status |= (1 << UHF_PORT_HIGH_SPEED);
    3254         [ -  + ]:        414 :                 else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
    3255                 :          0 :                         port_status |= (1 << UHF_PORT_LOW_SPEED);
    3256                 :            : 
    3257         [ -  + ]:       1035 :                 if (hprt0.b.prttstctl)
    3258                 :          0 :                         port_status |= (1 << UHF_PORT_TEST);
    3259         [ -  + ]:       1035 :                 if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
    3260                 :          0 :                         port_status |= (1 << UHF_PORT_L1);
    3261                 :            :                 }
    3262                 :            :                 /*
    3263                 :            :                    For Synopsys HW emulation of Power down wkup_control asserts the
    3264                 :            :                    hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
    3265                 :            :                    We intentionally tell the software that port is in L2Suspend state.
    3266                 :            :                    Only for STE.
    3267                 :            :                 */
    3268         [ -  + ]:       1035 :                 if ((core_if->power_down == 2)
    3269         [ #  # ]:          0 :                     && (core_if->hibernation_suspend == 1)) {
    3270                 :          0 :                         port_status |= (1 << UHF_PORT_SUSPEND);
    3271                 :            :                 }
    3272                 :            :                 /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
    3273                 :            : 
    3274                 :       1035 :                 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
    3275                 :            : 
    3276                 :       1035 :                 break;
    3277                 :            :         case UCR_SET_HUB_FEATURE:
    3278                 :            :                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3279                 :            :                             "SetHubFeature\n");
    3280                 :            :                 /* No HUB features supported */
    3281                 :            :                 break;
    3282                 :            :         case UCR_SET_PORT_FEATURE:
    3283         [ +  - ]:        621 :                 if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
    3284                 :            :                         goto error;
    3285                 :            : 
    3286         [ +  + ]:        621 :                 if (!dwc_otg_hcd->flags.b.port_connect_status) {
    3287                 :            :                         /*
    3288                 :            :                          * The port is disconnected, which means the core is
    3289                 :            :                          * either in device mode or it soon will be. Just
    3290                 :            :                          * return without doing anything since the port
    3291                 :            :                          * register can't be written if the core is in device
    3292                 :            :                          * mode.
    3293                 :            :                          */
    3294                 :            :                         break;
    3295                 :            :                 }
    3296                 :            : 
    3297   [ -  -  +  -  :        414 :                 switch (wValue) {
                   -  - ]
    3298                 :            :                 case UHF_PORT_SUSPEND:
    3299                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3300                 :            :                                     "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
    3301         [ #  # ]:          0 :                         if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
    3302                 :            :                                 goto error;
    3303                 :            :                         }
    3304         [ #  # ]:          0 :                         if (core_if->power_down == 2) {
    3305                 :            :                                 int timeout = 300;
    3306                 :            :                                 dwc_irqflags_t flags;
    3307                 :          0 :                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
    3308                 :          0 :                                 gpwrdn_data_t gpwrdn = {.d32 = 0 };
    3309                 :            :                                 gusbcfg_data_t gusbcfg = {.d32 = 0 };
    3310                 :            : #ifdef DWC_DEV_SRPCAP
    3311                 :            :                                 int32_t otg_cap_param = core_if->core_params->otg_cap;
    3312                 :            : #endif
    3313                 :          0 :                                 DWC_PRINTF("Preparing for complete power-off\n");
    3314                 :            : 
    3315                 :            :                                 /* Save registers before hibernation */
    3316                 :          0 :                                 dwc_otg_save_global_regs(core_if);
    3317                 :          0 :                                 dwc_otg_save_host_regs(core_if);
    3318                 :            : 
    3319                 :          0 :                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3320                 :          0 :                                 hprt0.b.prtsusp = 1;
    3321                 :          0 :                                 hprt0.b.prtena = 0;
    3322                 :          0 :                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3323                 :            :                                 /* Spin hprt0.b.prtsusp to became 1 */
    3324                 :            :                                 do {
    3325                 :          0 :                                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3326         [ #  # ]:          0 :                                         if (hprt0.b.prtsusp) {
    3327                 :            :                                                 break;
    3328                 :            :                                         }
    3329                 :          0 :                                         dwc_mdelay(1);
    3330         [ #  # ]:          0 :                                 } while (--timeout);
    3331         [ #  # ]:          0 :                                 if (!timeout) {
    3332                 :          0 :                                         DWC_WARN("Suspend wasn't genereted\n");
    3333                 :            :                                 }
    3334                 :          0 :                                 dwc_udelay(10);
    3335                 :            : 
    3336                 :            :                                 /*
    3337                 :            :                                  * We need to disable interrupts to prevent servicing of any IRQ
    3338                 :            :                                  * during going to hibernation
    3339                 :            :                                  */
    3340                 :          0 :                                 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
    3341                 :          0 :                                 core_if->lx_state = DWC_OTG_L2;
    3342                 :            : #ifdef DWC_DEV_SRPCAP
    3343                 :            :                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3344                 :            :                                 hprt0.b.prtpwr = 0;
    3345                 :            :                                 hprt0.b.prtena = 0;
    3346                 :            :                                 DWC_WRITE_REG32(core_if->host_if->hprt0,
    3347                 :            :                                                 hprt0.d32);
    3348                 :            : #endif
    3349                 :            :                                 gusbcfg.d32 =
    3350                 :          0 :                                     DWC_READ_REG32(&core_if->core_global_regs->
    3351                 :            :                                                    gusbcfg);
    3352         [ #  # ]:          0 :                                 if (gusbcfg.b.ulpi_utmi_sel == 1) {
    3353                 :            :                                         /* ULPI interface */
    3354                 :            :                                         /* Suspend the Phy Clock */
    3355                 :            :                                         pcgcctl.d32 = 0;
    3356                 :          0 :                                         pcgcctl.b.stoppclk = 1;
    3357                 :          0 :                                         DWC_MODIFY_REG32(core_if->pcgcctl, 0,
    3358                 :            :                                                          pcgcctl.d32);
    3359                 :          0 :                                         dwc_udelay(10);
    3360                 :          0 :                                         gpwrdn.b.pmuactv = 1;
    3361                 :          0 :                                         DWC_MODIFY_REG32(&core_if->
    3362                 :            :                                                          core_global_regs->
    3363                 :            :                                                          gpwrdn, 0, gpwrdn.d32);
    3364                 :            :                                 } else {
    3365                 :            :                                         /* UTMI+ Interface */
    3366                 :          0 :                                         gpwrdn.b.pmuactv = 1;
    3367                 :          0 :                                         DWC_MODIFY_REG32(&core_if->
    3368                 :            :                                                          core_global_regs->
    3369                 :            :                                                          gpwrdn, 0, gpwrdn.d32);
    3370                 :          0 :                                         dwc_udelay(10);
    3371                 :          0 :                                         pcgcctl.b.stoppclk = 1;
    3372                 :          0 :                                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
    3373                 :          0 :                                         dwc_udelay(10);
    3374                 :            :                                 }
    3375                 :            : #ifdef DWC_DEV_SRPCAP
    3376                 :            :                                 gpwrdn.d32 = 0;
    3377                 :            :                                 gpwrdn.b.dis_vbus = 1;
    3378                 :            :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3379                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3380                 :            : #endif
    3381                 :          0 :                                 gpwrdn.d32 = 0;
    3382                 :          0 :                                 gpwrdn.b.pmuintsel = 1;
    3383                 :          0 :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3384                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3385                 :          0 :                                 dwc_udelay(10);
    3386                 :            : 
    3387                 :          0 :                                 gpwrdn.d32 = 0;
    3388                 :            : #ifdef DWC_DEV_SRPCAP
    3389                 :            :                                 gpwrdn.b.srp_det_msk = 1;
    3390                 :            : #endif
    3391                 :          0 :                                 gpwrdn.b.disconn_det_msk = 1;
    3392                 :          0 :                                 gpwrdn.b.lnstchng_msk = 1;
    3393                 :          0 :                                 gpwrdn.b.sts_chngint_msk = 1;
    3394                 :          0 :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3395                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3396                 :          0 :                                 dwc_udelay(10);
    3397                 :            : 
    3398                 :            :                                 /* Enable Power Down Clamp and all interrupts in GPWRDN */
    3399                 :          0 :                                 gpwrdn.d32 = 0;
    3400                 :          0 :                                 gpwrdn.b.pwrdnclmp = 1;
    3401                 :          0 :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3402                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3403                 :          0 :                                 dwc_udelay(10);
    3404                 :            : 
    3405                 :            :                                 /* Switch off VDD */
    3406                 :          0 :                                 gpwrdn.d32 = 0;
    3407                 :          0 :                                 gpwrdn.b.pwrdnswtch = 1;
    3408                 :          0 :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3409                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3410                 :            : 
    3411                 :            : #ifdef DWC_DEV_SRPCAP
    3412                 :            :                                 if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
    3413                 :            :                                 {
    3414                 :            :                                         core_if->pwron_timer_started = 1;
    3415                 :            :                                         DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
    3416                 :            :                                 }
    3417                 :            : #endif
    3418                 :            :                                 /* Save gpwrdn register for further usage if stschng interrupt */
    3419                 :          0 :                                 core_if->gr_backup->gpwrdn_local =
    3420                 :          0 :                                                 DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
    3421                 :            : 
    3422                 :            :                                 /* Set flag to indicate that we are in hibernation */
    3423                 :          0 :                                 core_if->hibernation_suspend = 1;
    3424                 :          0 :                                 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
    3425                 :            : 
    3426                 :          0 :                                 DWC_PRINTF("Host hibernation completed\n");
    3427                 :            :                                 // Exit from case statement
    3428                 :            :                                 break;
    3429                 :            : 
    3430                 :            :                         }
    3431   [ #  #  #  # ]:          0 :                         if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
    3432                 :          0 :                             dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
    3433                 :          0 :                                 gotgctl_data_t gotgctl = {.d32 = 0 };
    3434                 :          0 :                                 gotgctl.b.hstsethnpen = 1;
    3435                 :          0 :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3436                 :            :                                                  gotgctl, 0, gotgctl.d32);
    3437                 :          0 :                                 core_if->op_state = A_SUSPEND;
    3438                 :            :                         }
    3439                 :          0 :                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3440                 :          0 :                         hprt0.b.prtsusp = 1;
    3441                 :          0 :                         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3442                 :            :                         {
    3443                 :            :                                 dwc_irqflags_t flags;
    3444                 :            :                                 /* Update lx_state */
    3445                 :          0 :                                 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
    3446                 :          0 :                                 core_if->lx_state = DWC_OTG_L2;
    3447                 :          0 :                                 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
    3448                 :            :                         }
    3449                 :            :                         /* Suspend the Phy Clock */
    3450                 :            :                         {
    3451                 :          0 :                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
    3452                 :          0 :                                 pcgcctl.b.stoppclk = 1;
    3453                 :          0 :                                 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
    3454                 :            :                                                  pcgcctl.d32);
    3455                 :          0 :                                 dwc_udelay(10);
    3456                 :            :                         }
    3457                 :            : 
    3458                 :            :                         /* For HNP the bus must be suspended for at least 200ms. */
    3459         [ #  # ]:          0 :                         if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
    3460                 :          0 :                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
    3461                 :          0 :                                 pcgcctl.b.stoppclk = 1;
    3462                 :          0 :                 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
    3463                 :          0 :                                 dwc_mdelay(200);
    3464                 :            :                         }
    3465                 :            : 
    3466                 :            :                         /** @todo - check how sw can wait for 1 sec to check asesvld??? */
    3467                 :            : #if 0 //vahrama !!!!!!!!!!!!!!!!!!
    3468                 :            :                         if (core_if->adp_enable) {
    3469                 :            :                                 gotgctl_data_t gotgctl = {.d32 = 0 };
    3470                 :            :                                 gpwrdn_data_t gpwrdn;
    3471                 :            : 
    3472                 :            :                                 while (gotgctl.b.asesvld == 1) {
    3473                 :            :                                         gotgctl.d32 =
    3474                 :            :                                             DWC_READ_REG32(&core_if->
    3475                 :            :                                                            core_global_regs->
    3476                 :            :                                                            gotgctl);
    3477                 :            :                                         dwc_mdelay(100);
    3478                 :            :                                 }
    3479                 :            : 
    3480                 :            :                                 /* Enable Power Down Logic */
    3481                 :            :                                 gpwrdn.d32 = 0;
    3482                 :            :                                 gpwrdn.b.pmuactv = 1;
    3483                 :            :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3484                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3485                 :            : 
    3486                 :            :                                 /* Unmask SRP detected interrupt from Power Down Logic */
    3487                 :            :                                 gpwrdn.d32 = 0;
    3488                 :            :                                 gpwrdn.b.srp_det_msk = 1;
    3489                 :            :                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
    3490                 :            :                                                  gpwrdn, 0, gpwrdn.d32);
    3491                 :            : 
    3492                 :            :                                 dwc_otg_adp_probe_start(core_if);
    3493                 :            :                         }
    3494                 :            : #endif
    3495                 :            :                         break;
    3496                 :            :                 case UHF_PORT_POWER:
    3497                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3498                 :            :                                     "SetPortFeature - USB_PORT_FEAT_POWER\n");
    3499                 :          0 :                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3500                 :          0 :                         hprt0.b.prtpwr = 1;
    3501                 :          0 :                         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3502                 :          0 :                         break;
    3503                 :            :                 case UHF_PORT_RESET:
    3504         [ -  + ]:        414 :                         if ((core_if->power_down == 2)
    3505         [ #  # ]:          0 :                             && (core_if->hibernation_suspend == 1)) {
    3506                 :            :                                 /* If we are going to exit from Hibernated
    3507                 :            :                                  * state via USB RESET.
    3508                 :            :                                  */
    3509                 :          0 :                                 dwc_otg_host_hibernation_restore(core_if, 0, 1);
    3510                 :            :                         } else {
    3511                 :        414 :                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3512                 :            : 
    3513                 :            :                                 DWC_DEBUGPL(DBG_HCD,
    3514                 :            :                                             "DWC OTG HCD HUB CONTROL - "
    3515                 :            :                                             "SetPortFeature - USB_PORT_FEAT_RESET\n");
    3516                 :            :                                 {
    3517                 :        414 :                                         pcgcctl_data_t pcgcctl = {.d32 = 0 };
    3518                 :        414 :                                         pcgcctl.b.enbl_sleep_gating = 1;
    3519                 :        414 :                                         pcgcctl.b.stoppclk = 1;
    3520                 :        414 :                                         DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
    3521                 :        414 :                                         DWC_WRITE_REG32(core_if->pcgcctl, 0);
    3522                 :            :                                 }
    3523                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
    3524                 :            :                                 {
    3525                 :            :                                         glpmcfg_data_t lpmcfg;
    3526                 :            :                                         lpmcfg.d32 =
    3527                 :            :                                                 DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
    3528                 :            :                                         if (lpmcfg.b.prt_sleep_sts) {
    3529                 :            :                                                 lpmcfg.b.en_utmi_sleep = 0;
    3530                 :            :                                                 lpmcfg.b.hird_thres &= (~(1 << 4));
    3531                 :            :                                                 DWC_WRITE_REG32
    3532                 :            :                                                     (&core_if->core_global_regs->glpmcfg,
    3533                 :            :                                                      lpmcfg.d32);
    3534                 :            :                                                 dwc_mdelay(1);
    3535                 :            :                                         }
    3536                 :            :                                 }
    3537                 :            : #endif
    3538                 :        414 :                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3539                 :            :                                 /* Clear suspend bit if resetting from suspended state. */
    3540                 :        414 :                                 hprt0.b.prtsusp = 0;
    3541                 :            :                                 /* When B-Host the Port reset bit is set in
    3542                 :            :                                  * the Start HCD Callback function, so that
    3543                 :            :                                  * the reset is started within 1ms of the HNP
    3544                 :            :                                  * success interrupt. */
    3545         [ +  - ]:        414 :                                 if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
    3546                 :        414 :                                         hprt0.b.prtpwr = 1;
    3547                 :        414 :                                         hprt0.b.prtrst = 1;
    3548                 :        414 :                                         DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
    3549                 :        414 :                                         DWC_WRITE_REG32(core_if->host_if->hprt0,
    3550                 :            :                                                         hprt0.d32);
    3551                 :            :                                 }
    3552                 :            :                                 /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
    3553                 :        414 :                                 dwc_mdelay(60);
    3554                 :        414 :                                 hprt0.b.prtrst = 0;
    3555                 :        414 :                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3556                 :        414 :                                 core_if->lx_state = DWC_OTG_L0;      /* Now back to the on state */
    3557                 :            :                         }
    3558                 :            :                         break;
    3559                 :            : #ifdef DWC_HS_ELECT_TST
    3560                 :            :                 case UHF_PORT_TEST:
    3561                 :            :                         {
    3562                 :            :                                 uint32_t t;
    3563                 :            :                                 gintmsk_data_t gintmsk;
    3564                 :            : 
    3565                 :          0 :                                 t = (wIndex >> 8);        /* MSB wIndex USB */
    3566                 :            :                                 DWC_DEBUGPL(DBG_HCD,
    3567                 :            :                                             "DWC OTG HCD HUB CONTROL - "
    3568                 :            :                                             "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
    3569                 :            :                                             t);
    3570                 :          0 :                                 DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
    3571         [ #  # ]:          0 :                                 if (t < 6) {
    3572                 :          0 :                                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
    3573                 :          0 :                                         hprt0.b.prttstctl = t;
    3574                 :          0 :                                         DWC_WRITE_REG32(core_if->host_if->hprt0,
    3575                 :            :                                                         hprt0.d32);
    3576                 :            :                                 } else {
    3577                 :            :                                         /* Setup global vars with reg addresses (quick and
    3578                 :            :                                          * dirty hack, should be cleaned up)
    3579                 :            :                                          */
    3580                 :          0 :                                         global_regs = core_if->core_global_regs;
    3581                 :          0 :                                         hc_global_regs =
    3582                 :          0 :                                             core_if->host_if->host_global_regs;
    3583                 :          0 :                                         hc_regs =
    3584                 :          0 :                                             (dwc_otg_hc_regs_t *) ((char *)
    3585                 :            :                                                                    global_regs +
    3586                 :            :                                                                    0x500);
    3587                 :          0 :                                         data_fifo =
    3588                 :          0 :                                             (uint32_t *) ((char *)global_regs +
    3589                 :            :                                                           0x1000);
    3590                 :            : 
    3591         [ #  # ]:          0 :                                         if (t == 6) {   /* HS_HOST_PORT_SUSPEND_RESUME */
    3592                 :            :                                                 /* Save current interrupt mask */
    3593                 :            :                                                 gintmsk.d32 =
    3594                 :          0 :                                                     DWC_READ_REG32
    3595                 :            :                                                     (&global_regs->gintmsk);
    3596                 :            : 
    3597                 :            :                                                 /* Disable all interrupts while we muck with
    3598                 :            :                                                  * the hardware directly
    3599                 :            :                                                  */
    3600                 :          0 :                                                 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
    3601                 :            : 
    3602                 :            :                                                 /* 15 second delay per the test spec */
    3603                 :          0 :                                                 dwc_mdelay(15000);
    3604                 :            : 
    3605                 :            :                                                 /* Drive suspend on the root port */
    3606                 :          0 :                                                 hprt0.d32 =
    3607                 :          0 :                                                     dwc_otg_read_hprt0(core_if);
    3608                 :          0 :                                                 hprt0.b.prtsusp = 1;
    3609                 :          0 :                                                 hprt0.b.prtres = 0;
    3610                 :          0 :                                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3611                 :            : 
    3612                 :            :                                                 /* 15 second delay per the test spec */
    3613                 :          0 :                                                 dwc_mdelay(15000);
    3614                 :            : 
    3615                 :            :                                                 /* Drive resume on the root port */
    3616                 :          0 :                                                 hprt0.d32 =
    3617                 :          0 :                                                     dwc_otg_read_hprt0(core_if);
    3618                 :          0 :                                                 hprt0.b.prtsusp = 0;
    3619                 :          0 :                                                 hprt0.b.prtres = 1;
    3620                 :          0 :                                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3621                 :          0 :                                                 dwc_mdelay(100);
    3622                 :            : 
    3623                 :            :                                                 /* Clear the resume bit */
    3624                 :          0 :                                                 hprt0.b.prtres = 0;
    3625                 :          0 :                                                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
    3626                 :            : 
    3627                 :            :                                                 /* Restore interrupts */
    3628                 :          0 :                                                 DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
    3629         [ #  # ]:          0 :                                         } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
    3630                 :            :                                                 /* Save current interrupt mask */
    3631                 :            :                                                 gintmsk.d32 =
    3632                 :          0 :                                                     DWC_READ_REG32
    3633                 :            :                                                     (&global_regs->gintmsk);
    3634                 :            : 
    3635                 :            :                                                 /* Disable all interrupts while we muck with
    3636                 :            :                                                  * the hardware directly
    3637                 :            :                                                  */
    3638                 :          0 :                                                 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
    3639                 :            : 
    3640                 :            :                                                 /* 15 second delay per the test spec */
    3641                 :          0 :                                                 dwc_mdelay(15000);
    3642                 :            : 
    3643                 :            :                                                 /* Send the Setup packet */
    3644                 :          0 :                                                 do_setup();
    3645                 :            : 
    3646                 :            :                                                 /* 15 second delay so nothing else happens for awhile */
    3647                 :          0 :                                                 dwc_mdelay(15000);
    3648                 :            : 
    3649                 :            :                                                 /* Restore interrupts */
    3650                 :          0 :                                                 DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
    3651         [ #  # ]:          0 :                                         } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
    3652                 :            :                                                 /* Save current interrupt mask */
    3653                 :            :                                                 gintmsk.d32 =
    3654                 :          0 :                                                     DWC_READ_REG32
    3655                 :            :                                                     (&global_regs->gintmsk);
    3656                 :            : 
    3657                 :            :                                                 /* Disable all interrupts while we muck with
    3658                 :            :                                                  * the hardware directly
    3659                 :            :                                                  */
    3660                 :          0 :                                                 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
    3661                 :            : 
    3662                 :            :                                                 /* Send the Setup packet */
    3663                 :          0 :                                                 do_setup();
    3664                 :            : 
    3665                 :            :                                                 /* 15 second delay so nothing else happens for awhile */
    3666                 :          0 :                                                 dwc_mdelay(15000);
    3667                 :            : 
    3668                 :            :                                                 /* Send the In and Ack packets */
    3669                 :          0 :                                                 do_in_ack();
    3670                 :            : 
    3671                 :            :                                                 /* 15 second delay so nothing else happens for awhile */
    3672                 :          0 :                                                 dwc_mdelay(15000);
    3673                 :            : 
    3674                 :            :                                                 /* Restore interrupts */
    3675                 :          0 :                                                 DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
    3676                 :            :                                         }
    3677                 :            :                                 }
    3678                 :            :                                 break;
    3679                 :            :                         }
    3680                 :            : #endif /* DWC_HS_ELECT_TST */
    3681                 :            : 
    3682                 :            :                 case UHF_PORT_INDICATOR:
    3683                 :            :                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
    3684                 :            :                                     "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
    3685                 :            :                         /* Not supported */
    3686                 :            :                         break;
    3687                 :            :                 default:
    3688                 :            :                         retval = -DWC_E_INVALID;
    3689                 :          0 :                         DWC_ERROR("DWC OTG HCD - "
    3690                 :            :                                   "SetPortFeature request %xh "
    3691                 :            :                                   "unknown or unsupported\n", wValue);
    3692                 :          0 :                         break;
    3693                 :            :                 }
    3694                 :            :                 break;
    3695                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
    3696                 :            :         case UCR_SET_AND_TEST_PORT_FEATURE:
    3697                 :            :                 if (wValue != UHF_PORT_L1) {
    3698                 :            :                         goto error;
    3699                 :            :                 }
    3700                 :            :                 {
    3701                 :            :                         int portnum, hird, devaddr, remwake;
    3702                 :            :                         glpmcfg_data_t lpmcfg;
    3703                 :            :                         uint32_t time_usecs;
    3704                 :            :                         gintsts_data_t gintsts;
    3705                 :            :                         gintmsk_data_t gintmsk;
    3706                 :            : 
    3707                 :            :                         if (!dwc_otg_get_param_lpm_enable(core_if)) {
    3708                 :            :                                 goto error;
    3709                 :            :                         }
    3710                 :            :                         if (wValue != UHF_PORT_L1 || wLength != 1) {
    3711                 :            :                                 goto error;
    3712                 :            :                         }
    3713                 :            :                         /* Check if the port currently is in SLEEP state */
    3714                 :            :                         lpmcfg.d32 =
    3715                 :            :                             DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
    3716                 :            :                         if (lpmcfg.b.prt_sleep_sts) {
    3717                 :            :                                 DWC_INFO("Port is already in sleep mode\n");
    3718                 :            :                                 buf[0] = 0;     /* Return success */
    3719                 :            :                                 break;
    3720                 :            :                         }
    3721                 :            : 
    3722                 :            :                         portnum = wIndex & 0xf;
    3723                 :            :                         hird = (wIndex >> 4) & 0xf;
    3724                 :            :                         devaddr = (wIndex >> 8) & 0x7f;
    3725                 :            :                         remwake = (wIndex >> 15);
    3726                 :            : 
    3727                 :            :                         if (portnum != 1) {
    3728                 :            :                                 retval = -DWC_E_INVALID;
    3729                 :            :                                 DWC_WARN
    3730                 :            :                                     ("Wrong port number(%d) in SetandTestPortFeature request\n",
    3731                 :            :                                      portnum);
    3732                 :            :                                 break;
    3733                 :            :                         }
    3734                 :            : 
    3735                 :            :                         DWC_PRINTF
    3736                 :            :                             ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
    3737                 :            :                              portnum, hird, devaddr, remwake);
    3738                 :            :                         /* Disable LPM interrupt */
    3739                 :            :                         gintmsk.d32 = 0;
    3740                 :            :                         gintmsk.b.lpmtranrcvd = 1;
    3741                 :            :                         DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
    3742                 :            :                                          gintmsk.d32, 0);
    3743                 :            : 
    3744                 :            :                         if (dwc_otg_hcd_send_lpm
    3745                 :            :                             (dwc_otg_hcd, devaddr, hird, remwake)) {
    3746                 :            :                                 retval = -DWC_E_INVALID;
    3747                 :            :                                 break;
    3748                 :            :                         }
    3749                 :            : 
    3750                 :            :                         time_usecs = 10 * (lpmcfg.b.retry_count + 1);
    3751                 :            :                         /* We will consider timeout if time_usecs microseconds pass,
    3752                 :            :                          * and we don't receive LPM transaction status.
    3753                 :            :                          * After receiving non-error responce(ACK/NYET/STALL) from device,
    3754                 :            :                          *  core will set lpmtranrcvd bit.
    3755                 :            :                          */
    3756                 :            :                         do {
    3757                 :            :                                 gintsts.d32 =
    3758                 :            :                                     DWC_READ_REG32(&core_if->core_global_regs->gintsts);
    3759                 :            :                                 if (gintsts.b.lpmtranrcvd) {
    3760                 :            :                                         break;
    3761                 :            :                                 }
    3762                 :            :                                 dwc_udelay(1);
    3763                 :            :                         } while (--time_usecs);
    3764                 :            :                         /* lpm_int bit will be cleared in LPM interrupt handler */
    3765                 :            : 
    3766                 :            :                         /* Now fill status
    3767                 :            :                          * 0x00 - Success
    3768                 :            :                          * 0x10 - NYET
    3769                 :            :                          * 0x11 - Timeout
    3770                 :            :                          */
    3771                 :            :                         if (!gintsts.b.lpmtranrcvd) {
    3772                 :            :                                 buf[0] = 0x3;   /* Completion code is Timeout */
    3773                 :            :                                 dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
    3774                 :            :                         } else {
    3775                 :            :                                 lpmcfg.d32 =
    3776                 :            :                                     DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
    3777                 :            :                                 if (lpmcfg.b.lpm_resp == 0x3) {
    3778                 :            :                                         /* ACK responce from the device */
    3779                 :            :                                         buf[0] = 0x00;  /* Success */
    3780                 :            :                                 } else if (lpmcfg.b.lpm_resp == 0x2) {
    3781                 :            :                                         /* NYET responce from the device */
    3782                 :            :                                         buf[0] = 0x2;
    3783                 :            :                                 } else {
    3784                 :            :                                         /* Otherwise responce with Timeout */
    3785                 :            :                                         buf[0] = 0x3;
    3786                 :            :                                 }
    3787                 :            :                         }
    3788                 :            :                         DWC_PRINTF("Device responce to LPM trans is %x\n",
    3789                 :            :                                    lpmcfg.b.lpm_resp);
    3790                 :            :                         DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
    3791                 :            :                                          gintmsk.d32);
    3792                 :            : 
    3793                 :            :                         break;
    3794                 :            :                 }
    3795                 :            : #endif /* CONFIG_USB_DWC_OTG_LPM */
    3796                 :            :         default:
    3797                 :            : error:
    3798                 :            :                 retval = -DWC_E_INVALID;
    3799                 :          0 :                 DWC_WARN("DWC OTG HCD - "
    3800                 :            :                          "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
    3801                 :            :                          typeReq, wIndex, wValue);
    3802                 :          0 :                 break;
    3803                 :            :         }
    3804                 :            : 
    3805                 :       2898 :         return retval;
    3806                 :            : }
    3807                 :            : 
    3808                 :            : #ifdef CONFIG_USB_DWC_OTG_LPM
    3809                 :            : /** Returns index of host channel to perform LPM transaction. */
    3810                 :            : int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
    3811                 :            : {
    3812                 :            :         dwc_otg_core_if_t *core_if = hcd->core_if;
    3813                 :            :         dwc_hc_t *hc;
    3814                 :            :         hcchar_data_t hcchar;
    3815                 :            :         gintmsk_data_t gintmsk = {.d32 = 0 };
    3816                 :            : 
    3817                 :            :         if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
    3818                 :            :                 DWC_PRINTF("No free channel to select for LPM transaction\n");
    3819                 :            :                 return -1;
    3820                 :            :         }
    3821                 :            : 
    3822                 :            :         hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
    3823                 :            : 
    3824                 :            :         /* Mask host channel interrupts. */
    3825                 :            :         gintmsk.b.hcintr = 1;
    3826                 :            :         DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
    3827                 :            : 
    3828                 :            :         /* Fill fields that core needs for LPM transaction */
    3829                 :            :         hcchar.b.devaddr = devaddr;
    3830                 :            :         hcchar.b.epnum = 0;
    3831                 :            :         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
    3832                 :            :         hcchar.b.mps = 64;
    3833                 :            :         hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
    3834                 :            :         hcchar.b.epdir = 0;     /* OUT */
    3835                 :            :         DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
    3836                 :            :                         hcchar.d32);
    3837                 :            : 
    3838                 :            :         /* Remove the host channel from the free list. */
    3839                 :            :         DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
    3840                 :            : 
    3841                 :            :         DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
    3842                 :            : 
    3843                 :            :         return hc->hc_num;
    3844                 :            : }
    3845                 :            : 
    3846                 :            : /** Release hc after performing LPM transaction */
    3847                 :            : void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
    3848                 :            : {
    3849                 :            :         dwc_hc_t *hc;
    3850                 :            :         glpmcfg_data_t lpmcfg;
    3851                 :            :         uint8_t hc_num;
    3852                 :            : 
    3853                 :            :         lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
    3854                 :            :         hc_num = lpmcfg.b.lpm_chan_index;
    3855                 :            : 
    3856                 :            :         hc = hcd->hc_ptr_array[hc_num];
    3857                 :            : 
    3858                 :            :         DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
    3859                 :            :         /* Return host channel to free list */
    3860                 :            :         DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
    3861                 :            : }
    3862                 :            : 
    3863                 :            : int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
    3864                 :            :                          uint8_t bRemoteWake)
    3865                 :            : {
    3866                 :            :         glpmcfg_data_t lpmcfg;
    3867                 :            :         pcgcctl_data_t pcgcctl = {.d32 = 0 };
    3868                 :            :         int channel;
    3869                 :            : 
    3870                 :            :         channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
    3871                 :            :         if (channel < 0) {
    3872                 :            :                 return channel;
    3873                 :            :         }
    3874                 :            : 
    3875                 :            :         pcgcctl.b.enbl_sleep_gating = 1;
    3876                 :            :         DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
    3877                 :            : 
    3878                 :            :         /* Read LPM config register */
    3879                 :            :         lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
    3880                 :            : 
    3881                 :            :         /* Program LPM transaction fields */
    3882                 :            :         lpmcfg.b.rem_wkup_en = bRemoteWake;
    3883                 :            :         lpmcfg.b.hird = hird;
    3884                 :            :         lpmcfg.b.hird_thres = 0x1c;
    3885                 :            :         lpmcfg.b.lpm_chan_index = channel;
    3886                 :            :         lpmcfg.b.en_utmi_sleep = 1;
    3887                 :            :         /* Program LPM config register */
    3888                 :            :         DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
    3889                 :            : 
    3890                 :            :         /* Send LPM transaction */
    3891                 :            :         lpmcfg.b.send_lpm = 1;
    3892                 :            :         DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
    3893                 :            : 
    3894                 :            :         return 0;
    3895                 :            : }
    3896                 :            : 
    3897                 :            : #endif /* CONFIG_USB_DWC_OTG_LPM */
    3898                 :            : 
    3899                 :      89149 : int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
    3900                 :            : {
    3901                 :            :         int retval;
    3902                 :            : 
    3903         [ +  - ]:      89149 :         if (port != 1) {
    3904                 :            :                 return -DWC_E_INVALID;
    3905                 :            :         }
    3906                 :            : 
    3907         [ +  - ]:     178298 :         retval = (hcd->flags.b.port_connect_status_change ||
    3908         [ +  + ]:     178298 :                   hcd->flags.b.port_reset_change ||
    3909         [ +  - ]:     178091 :                   hcd->flags.b.port_enable_change ||
    3910   [ +  -  +  - ]:     267033 :                   hcd->flags.b.port_suspend_change ||
    3911                 :      88942 :                   hcd->flags.b.port_over_current_change);
    3912                 :            : #ifdef DEBUG
    3913                 :            :         if (retval) {
    3914                 :            :                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
    3915                 :            :                             " Root port status changed\n");
    3916                 :            :                 DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
    3917                 :            :                             hcd->flags.b.port_connect_status_change);
    3918                 :            :                 DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
    3919                 :            :                             hcd->flags.b.port_reset_change);
    3920                 :            :                 DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
    3921                 :            :                             hcd->flags.b.port_enable_change);
    3922                 :            :                 DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
    3923                 :            :                             hcd->flags.b.port_suspend_change);
    3924                 :            :                 DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
    3925                 :            :                             hcd->flags.b.port_over_current_change);
    3926                 :            :         }
    3927                 :            : #endif
    3928                 :      89149 :         return retval;
    3929                 :            : }
    3930                 :            : 
    3931                 :    6744205 : int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
    3932                 :            : {
    3933                 :            :         hfnum_data_t hfnum;
    3934                 :   15387301 :         hfnum.d32 =
    3935                 :   15387301 :             DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
    3936                 :            :                            hfnum);
    3937                 :            : 
    3938                 :            : #ifdef DEBUG_SOF
    3939                 :            :         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
    3940                 :            :                     hfnum.b.frnum);
    3941                 :            : #endif
    3942                 :   15387301 :         return hfnum.b.frnum;
    3943                 :            : }
    3944                 :            : 
    3945                 :        207 : int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
    3946                 :            :                       struct dwc_otg_hcd_function_ops *fops)
    3947                 :            : {
    3948                 :            :         int retval = 0;
    3949                 :            : 
    3950                 :        207 :         hcd->fops = fops;
    3951   [ +  -  -  + ]:        414 :         if (!dwc_otg_is_device_mode(hcd->core_if) &&
    3952         [ #  # ]:        207 :                 (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
    3953                 :        207 :                 dwc_otg_hcd_reinit(hcd);
    3954                 :            :         } else {
    3955                 :            :                 retval = -DWC_E_NO_DEVICE;
    3956                 :            :         }
    3957                 :            : 
    3958                 :        207 :         return retval;
    3959                 :            : }
    3960                 :            : 
    3961                 :    8899958 : void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
    3962                 :            : {
    3963                 :    8899958 :         return hcd->priv;
    3964                 :            : }
    3965                 :            : 
    3966                 :        207 : void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
    3967                 :            : {
    3968                 :        207 :         hcd->priv = priv_data;
    3969                 :        207 : }
    3970                 :            : 
    3971                 :        207 : uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
    3972                 :            : {
    3973                 :        207 :         return hcd->otg_port;
    3974                 :            : }
    3975                 :            : 
    3976                 :          0 : uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
    3977                 :            : {
    3978                 :            :         uint32_t is_b_host;
    3979   [ #  #  +  - ]:        414 :         if (hcd->core_if->op_state == B_HOST) {
    3980                 :            :                 is_b_host = 1;
    3981                 :            :         } else {
    3982                 :            :                 is_b_host = 0;
    3983                 :            :         }
    3984                 :            : 
    3985                 :          0 :         return is_b_host;
    3986                 :            : }
    3987                 :            : 
    3988                 :     134698 : dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
    3989                 :            :                                          int iso_desc_count, int atomic_alloc)
    3990                 :            : {
    3991                 :            :         dwc_otg_hcd_urb_t *dwc_otg_urb;
    3992                 :            :         uint32_t size;
    3993                 :            : 
    3994                 :     134698 :         size =
    3995                 :            :             sizeof(*dwc_otg_urb) +
    3996                 :     134698 :             iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
    3997         [ +  + ]:     134698 :         if (atomic_alloc)
    3998                 :      40032 :                 dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
    3999                 :            :         else
    4000                 :      94666 :                 dwc_otg_urb = DWC_ALLOC(size);
    4001                 :            : 
    4002         [ +  - ]:     134698 :         if (dwc_otg_urb)
    4003                 :     134698 :                 dwc_otg_urb->packet_count = iso_desc_count;
    4004                 :            :         else {
    4005         [ #  # ]:          0 :                 DWC_ERROR("**** DWC OTG HCD URB alloc - "
    4006                 :            :                         "%salloc of %db failed\n",
    4007                 :            :                         atomic_alloc?"atomic ":"", size);
    4008                 :            :         }
    4009                 :     134698 :         return dwc_otg_urb;
    4010                 :            : }
    4011                 :            : 
    4012                 :     134695 : void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
    4013                 :            :                                   uint8_t dev_addr, uint8_t ep_num,
    4014                 :            :                                   uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
    4015                 :            : {
    4016                 :            :         dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
    4017                 :            :                               ep_type, ep_dir, mps);
    4018                 :            : #if 0
    4019                 :            :         DWC_PRINTF
    4020                 :            :             ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
    4021                 :            :              dev_addr, ep_num, ep_dir, ep_type, mps);
    4022                 :            : #endif
    4023                 :     134695 : }
    4024                 :            : 
    4025                 :     134695 : void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
    4026                 :            :                                 void *urb_handle, void *buf, dwc_dma_t dma,
    4027                 :            :                                 uint32_t buflen, void *setup_packet,
    4028                 :            :                                 dwc_dma_t setup_dma, uint32_t flags,
    4029                 :            :                                 uint16_t interval)
    4030                 :            : {
    4031                 :     134695 :         dwc_otg_urb->priv = urb_handle;
    4032                 :     134695 :         dwc_otg_urb->buf = buf;
    4033                 :     134695 :         dwc_otg_urb->dma = dma;
    4034                 :     134695 :         dwc_otg_urb->length = buflen;
    4035                 :     134695 :         dwc_otg_urb->setup_packet = setup_packet;
    4036                 :     134695 :         dwc_otg_urb->setup_dma = setup_dma;
    4037                 :     134695 :         dwc_otg_urb->flags = flags;
    4038                 :     134695 :         dwc_otg_urb->interval = interval;
    4039                 :     134695 :         dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
    4040                 :     134695 : }
    4041                 :            : 
    4042                 :          0 : uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
    4043                 :            : {
    4044                 :          0 :         return dwc_otg_urb->status;
    4045                 :            : }
    4046                 :            : 
    4047                 :     119173 : uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
    4048                 :            : {
    4049                 :     119173 :         return dwc_otg_urb->actual_length;
    4050                 :            : }
    4051                 :            : 
    4052                 :          0 : uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
    4053                 :            : {
    4054                 :          0 :         return dwc_otg_urb->error_count;
    4055                 :            : }
    4056                 :            : 
    4057                 :          0 : void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
    4058                 :            :                                          int desc_num, uint32_t offset,
    4059                 :            :                                          uint32_t length)
    4060                 :            : {
    4061                 :          0 :         dwc_otg_urb->iso_descs[desc_num].offset = offset;
    4062                 :          0 :         dwc_otg_urb->iso_descs[desc_num].length = length;
    4063                 :          0 : }
    4064                 :            : 
    4065                 :          0 : uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
    4066                 :            :                                              int desc_num)
    4067                 :            : {
    4068                 :          0 :         return dwc_otg_urb->iso_descs[desc_num].status;
    4069                 :            : }
    4070                 :            : 
    4071                 :          0 : uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
    4072                 :            :                                                     dwc_otg_urb, int desc_num)
    4073                 :            : {
    4074                 :          0 :         return dwc_otg_urb->iso_descs[desc_num].actual_length;
    4075                 :            : }
    4076                 :            : 
    4077                 :       1256 : int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
    4078                 :            : {
    4079                 :            :         int allocated = 0;
    4080                 :            :         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
    4081                 :            : 
    4082         [ +  - ]:       1256 :         if (qh) {
    4083         [ +  + ]:       1256 :                 if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
    4084                 :            :                         allocated = 1;
    4085                 :            :                 }
    4086                 :            :         }
    4087                 :       1256 :         return allocated;
    4088                 :            : }
    4089                 :            : 
    4090                 :          0 : int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
    4091                 :            : {
    4092                 :            :         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
    4093                 :            :         int freed = 0;
    4094                 :            :         DWC_ASSERT(qh, "qh is not allocated\n");
    4095                 :            : 
    4096         [ #  # ]:          0 :         if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
    4097                 :            :                 freed = 1;
    4098                 :            :         }
    4099                 :            : 
    4100                 :          0 :         return freed;
    4101                 :            : }
    4102                 :            : 
    4103                 :        223 : uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
    4104                 :            : {
    4105                 :            :         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
    4106                 :            :         DWC_ASSERT(qh, "qh is not allocated\n");
    4107                 :        223 :         return qh->usecs;
    4108                 :            : }
    4109                 :            : 
    4110                 :          0 : void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
    4111                 :            : {
    4112                 :            : #ifdef DEBUG
    4113                 :            :         int num_channels;
    4114                 :            :         int i;
    4115                 :            :         gnptxsts_data_t np_tx_status;
    4116                 :            :         hptxsts_data_t p_tx_status;
    4117                 :            : 
    4118                 :            :         num_channels = hcd->core_if->core_params->host_channels;
    4119                 :            :         DWC_PRINTF("\n");
    4120                 :            :         DWC_PRINTF
    4121                 :            :             ("************************************************************\n");
    4122                 :            :         DWC_PRINTF("HCD State:\n");
    4123                 :            :         DWC_PRINTF("  Num channels: %d\n", num_channels);
    4124                 :            :         for (i = 0; i < num_channels; i++) {
    4125                 :            :                 dwc_hc_t *hc = hcd->hc_ptr_array[i];
    4126                 :            :                 DWC_PRINTF("  Channel %d:\n", i);
    4127                 :            :                 DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
    4128                 :            :                            hc->dev_addr, hc->ep_num, hc->ep_is_in);
    4129                 :            :                 DWC_PRINTF("    speed: %d\n", hc->speed);
    4130                 :            :                 DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
    4131                 :            :                 DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
    4132                 :            :                 DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
    4133                 :            :                 DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
    4134                 :            :                 DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
    4135                 :            :                 DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
    4136                 :            :                 DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
    4137                 :            :                 DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
    4138                 :            :                 DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
    4139                 :            :                 DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
    4140                 :            :                 DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
    4141                 :            :                 DWC_PRINTF("    do_split: %d\n", hc->do_split);
    4142                 :            :                 DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
    4143                 :            :                 DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
    4144                 :            :                 DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
    4145                 :            :                 DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
    4146                 :            :                 DWC_PRINTF("    requests: %d\n", hc->requests);
    4147                 :            :                 DWC_PRINTF("    qh: %p\n", hc->qh);
    4148                 :            :                 if (hc->xfer_started) {
    4149                 :            :                         hfnum_data_t hfnum;
    4150                 :            :                         hcchar_data_t hcchar;
    4151                 :            :                         hctsiz_data_t hctsiz;
    4152                 :            :                         hcint_data_t hcint;
    4153                 :            :                         hcintmsk_data_t hcintmsk;
    4154                 :            :                         hfnum.d32 =
    4155                 :            :                             DWC_READ_REG32(&hcd->core_if->
    4156                 :            :                                            host_if->host_global_regs->hfnum);
    4157                 :            :                         hcchar.d32 =
    4158                 :            :                             DWC_READ_REG32(&hcd->core_if->host_if->
    4159                 :            :                                            hc_regs[i]->hcchar);
    4160                 :            :                         hctsiz.d32 =
    4161                 :            :                             DWC_READ_REG32(&hcd->core_if->host_if->
    4162                 :            :                                            hc_regs[i]->hctsiz);
    4163                 :            :                         hcint.d32 =
    4164                 :            :                             DWC_READ_REG32(&hcd->core_if->host_if->
    4165                 :            :                                            hc_regs[i]->hcint);
    4166                 :            :                         hcintmsk.d32 =
    4167                 :            :                             DWC_READ_REG32(&hcd->core_if->host_if->
    4168                 :            :                                            hc_regs[i]->hcintmsk);
    4169                 :            :                         DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
    4170                 :            :                         DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
    4171                 :            :                         DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
    4172                 :            :                         DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
    4173                 :            :                         DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
    4174                 :            :                 }
    4175                 :            :                 if (hc->xfer_started && hc->qh) {
    4176                 :            :                         dwc_otg_qtd_t *qtd;
    4177                 :            :                         dwc_otg_hcd_urb_t *urb;
    4178                 :            : 
    4179                 :            :                         DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
    4180                 :            :                                 if (!qtd->in_process)
    4181                 :            :                                         break;
    4182                 :            : 
    4183                 :            :                                 urb = qtd->urb;
    4184                 :            :                         DWC_PRINTF("    URB Info:\n");
    4185                 :            :                         DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
    4186                 :            :                         if (urb) {
    4187                 :            :                                 DWC_PRINTF("      Dev: %d, EP: %d %s\n",
    4188                 :            :                                            dwc_otg_hcd_get_dev_addr(&urb->
    4189                 :            :                                                                     pipe_info),
    4190                 :            :                                            dwc_otg_hcd_get_ep_num(&urb->
    4191                 :            :                                                                   pipe_info),
    4192                 :            :                                            dwc_otg_hcd_is_pipe_in(&urb->
    4193                 :            :                                                                   pipe_info) ?
    4194                 :            :                                            "IN" : "OUT");
    4195                 :            :                                 DWC_PRINTF("      Max packet size: %d\n",
    4196                 :            :                                            dwc_otg_hcd_get_mps(&urb->
    4197                 :            :                                                                pipe_info));
    4198                 :            :                                 DWC_PRINTF("      transfer_buffer: %p\n",
    4199                 :            :                                            urb->buf);
    4200                 :            :                                 DWC_PRINTF("      transfer_dma: %p\n",
    4201                 :            :                                            (void *)urb->dma);
    4202                 :            :                                 DWC_PRINTF("      transfer_buffer_length: %d\n",
    4203                 :            :                                            urb->length);
    4204                 :            :                                         DWC_PRINTF("      actual_length: %d\n",
    4205                 :            :                                                    urb->actual_length);
    4206                 :            :                                 }
    4207                 :            :                         }
    4208                 :            :                 }
    4209                 :            :         }
    4210                 :            :         DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
    4211                 :            :         DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
    4212                 :            :         DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
    4213                 :            :         np_tx_status.d32 =
    4214                 :            :             DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
    4215                 :            :         DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
    4216                 :            :                    np_tx_status.b.nptxqspcavail);
    4217                 :            :         DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
    4218                 :            :                    np_tx_status.b.nptxfspcavail);
    4219                 :            :         p_tx_status.d32 =
    4220                 :            :             DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
    4221                 :            :         DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
    4222                 :            :                    p_tx_status.b.ptxqspcavail);
    4223                 :            :         DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
    4224                 :            :         dwc_otg_hcd_dump_frrem(hcd);
    4225                 :            :         dwc_otg_dump_global_registers(hcd->core_if);
    4226                 :            :         dwc_otg_dump_host_registers(hcd->core_if);
    4227                 :            :         DWC_PRINTF
    4228                 :            :             ("************************************************************\n");
    4229                 :            :         DWC_PRINTF("\n");
    4230                 :            : #endif
    4231                 :          0 : }
    4232                 :            : 
    4233                 :            : #ifdef DEBUG
    4234                 :            : void dwc_print_setup_data(uint8_t * setup)
    4235                 :            : {
    4236                 :            :         int i;
    4237                 :            :         if (CHK_DEBUG_LEVEL(DBG_HCD)) {
    4238                 :            :                 DWC_PRINTF("Setup Data = MSB ");
    4239                 :            :                 for (i = 7; i >= 0; i--)
    4240                 :            :                         DWC_PRINTF("%02x ", setup[i]);
    4241                 :            :                 DWC_PRINTF("\n");
    4242                 :            :                 DWC_PRINTF("  bmRequestType Tranfer = %s\n",
    4243                 :            :                            (setup[0] & 0x80) ? "Device-to-Host" :
    4244                 :            :                            "Host-to-Device");
    4245                 :            :                 DWC_PRINTF("  bmRequestType Type = ");
    4246                 :            :                 switch ((setup[0] & 0x60) >> 5) {
    4247                 :            :                 case 0:
    4248                 :            :                         DWC_PRINTF("Standard\n");
    4249                 :            :                         break;
    4250                 :            :                 case 1:
    4251                 :            :                         DWC_PRINTF("Class\n");
    4252                 :            :                         break;
    4253                 :            :                 case 2:
    4254                 :            :                         DWC_PRINTF("Vendor\n");
    4255                 :            :                         break;
    4256                 :            :                 case 3:
    4257                 :            :                         DWC_PRINTF("Reserved\n");
    4258                 :            :                         break;
    4259                 :            :                 }
    4260                 :            :                 DWC_PRINTF("  bmRequestType Recipient = ");
    4261                 :            :                 switch (setup[0] & 0x1f) {
    4262                 :            :                 case 0:
    4263                 :            :                         DWC_PRINTF("Device\n");
    4264                 :            :                         break;
    4265                 :            :                 case 1:
    4266                 :            :                         DWC_PRINTF("Interface\n");
    4267                 :            :                         break;
    4268                 :            :                 case 2:
    4269                 :            :                         DWC_PRINTF("Endpoint\n");
    4270                 :            :                         break;
    4271                 :            :                 case 3:
    4272                 :            :                         DWC_PRINTF("Other\n");
    4273                 :            :                         break;
    4274                 :            :                 default:
    4275                 :            :                         DWC_PRINTF("Reserved\n");
    4276                 :            :                         break;
    4277                 :            :                 }
    4278                 :            :                 DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
    4279                 :            :                 DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
    4280                 :            :                 DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
    4281                 :            :                 DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
    4282                 :            :         }
    4283                 :            : }
    4284                 :            : #endif
    4285                 :            : 
    4286                 :          0 : void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
    4287                 :            : {
    4288                 :            : #if 0
    4289                 :            :         DWC_PRINTF("Frame remaining at SOF:\n");
    4290                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4291                 :            :                    hcd->frrem_samples, hcd->frrem_accum,
    4292                 :            :                    (hcd->frrem_samples > 0) ?
    4293                 :            :                    hcd->frrem_accum / hcd->frrem_samples : 0);
    4294                 :            : 
    4295                 :            :         DWC_PRINTF("\n");
    4296                 :            :         DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
    4297                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4298                 :            :                    hcd->core_if->hfnum_7_samples,
    4299                 :            :                    hcd->core_if->hfnum_7_frrem_accum,
    4300                 :            :                    (hcd->core_if->hfnum_7_samples >
    4301                 :            :                     0) ? hcd->core_if->hfnum_7_frrem_accum /
    4302                 :            :                    hcd->core_if->hfnum_7_samples : 0);
    4303                 :            :         DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
    4304                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4305                 :            :                    hcd->core_if->hfnum_0_samples,
    4306                 :            :                    hcd->core_if->hfnum_0_frrem_accum,
    4307                 :            :                    (hcd->core_if->hfnum_0_samples >
    4308                 :            :                     0) ? hcd->core_if->hfnum_0_frrem_accum /
    4309                 :            :                    hcd->core_if->hfnum_0_samples : 0);
    4310                 :            :         DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
    4311                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4312                 :            :                    hcd->core_if->hfnum_other_samples,
    4313                 :            :                    hcd->core_if->hfnum_other_frrem_accum,
    4314                 :            :                    (hcd->core_if->hfnum_other_samples >
    4315                 :            :                     0) ? hcd->core_if->hfnum_other_frrem_accum /
    4316                 :            :                    hcd->core_if->hfnum_other_samples : 0);
    4317                 :            : 
    4318                 :            :         DWC_PRINTF("\n");
    4319                 :            :         DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
    4320                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4321                 :            :                    hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
    4322                 :            :                    (hcd->hfnum_7_samples_a > 0) ?
    4323                 :            :                    hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
    4324                 :            :         DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
    4325                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4326                 :            :                    hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
    4327                 :            :                    (hcd->hfnum_0_samples_a > 0) ?
    4328                 :            :                    hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
    4329                 :            :         DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
    4330                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4331                 :            :                    hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
    4332                 :            :                    (hcd->hfnum_other_samples_a > 0) ?
    4333                 :            :                    hcd->hfnum_other_frrem_accum_a /
    4334                 :            :                    hcd->hfnum_other_samples_a : 0);
    4335                 :            : 
    4336                 :            :         DWC_PRINTF("\n");
    4337                 :            :         DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
    4338                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4339                 :            :                    hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
    4340                 :            :                    (hcd->hfnum_7_samples_b > 0) ?
    4341                 :            :                    hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
    4342                 :            :         DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
    4343                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4344                 :            :                    hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
    4345                 :            :                    (hcd->hfnum_0_samples_b > 0) ?
    4346                 :            :                    hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
    4347                 :            :         DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
    4348                 :            :         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
    4349                 :            :                    hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
    4350                 :            :                    (hcd->hfnum_other_samples_b > 0) ?
    4351                 :            :                    hcd->hfnum_other_frrem_accum_b /
    4352                 :            :                    hcd->hfnum_other_samples_b : 0);
    4353                 :            : #endif
    4354                 :          0 : }
    4355                 :            : 
    4356                 :            : #endif /* DWC_DEVICE_ONLY */

Generated by: LCOV version 1.14