linux/drivers/staging/bcm/InterfaceIdleMode.c
<<
>>
Prefs
   1#include "headers.h"
   2
   3/*
   4Function:                               InterfaceIdleModeWakeup
   5
   6Description:                    This is the hardware specific Function for waking up HW device from Idle mode.
   7                                                A software abort pattern is written to the device to wake it and necessary power state
   8                                                transitions from host are performed here.
   9
  10Input parameters:               IN struct bcm_mini_adapter *Adapter   - Miniport Adapter Context
  11
  12
  13Return:                         BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful.
  14                                                Other           - If an error occurred.
  15*/
  16
  17
  18/*
  19Function:                               InterfaceIdleModeRespond
  20
  21Description:                    This is the hardware specific Function for responding to Idle mode request from target.
  22                                                Necessary power state transitions from host for idle mode or other device specific
  23                                                initializations are performed here.
  24
  25Input parameters:               IN struct bcm_mini_adapter * Adapter   - Miniport Adapter Context
  26
  27
  28Return:                         BCM_STATUS_SUCCESS - If Idle mode response related HW configuration was successful.
  29                                                Other           - If an error occurred.
  30*/
  31
  32/*
  33"dmem bfc02f00  100" tells how many time device went in Idle mode.
  34this value will be at address bfc02fa4.just before value d0ea1dle.
  35
  36Set time value by writing at bfc02f98 7d0
  37
  38checking the Ack timer expire on kannon by running command
  39d qcslog .. if it shows e means host has not send response to f/w with in 200 ms. Response should be
  40send to f/w with in 200 ms after the Idle/Shutdown req issued
  41
  42*/
  43
  44
  45int InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int* puiBuffer)
  46{
  47        int     status = STATUS_SUCCESS;
  48        unsigned int    uiRegRead = 0;
  49        int bytes;
  50
  51        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer));
  52
  53        if(ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD)
  54        {
  55                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL," Got GO_TO_IDLE_MODE_PAYLOAD(210) Msg Subtype");
  56                if(ntohl(*(puiBuffer+1)) == 0 )
  57                {
  58                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Got IDLE MODE WAKE UP Response From F/W");
  59
  60                        status = wrmalt (Adapter,SW_ABORT_IDLEMODE_LOC, &uiRegRead, sizeof(uiRegRead));
  61                        if(status)
  62                        {
  63                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");
  64                                return status;
  65                        }
  66
  67                        if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
  68                        {
  69                                uiRegRead = 0x00000000 ;
  70                                status = wrmalt (Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegRead, sizeof(uiRegRead));
  71                                if(status)
  72                                {
  73                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode     Reg");
  74                                        return status;
  75                                }
  76                        }
  77                        //Below Register should not br read in case of Manual and Protocol Idle mode.
  78                        else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
  79                        {
  80                                //clear on read Register
  81                                bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
  82                                if (bytes < 0) {
  83                                        status = bytes;
  84                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");
  85                                        return status;
  86                                }
  87                                //clear on read Register
  88                                bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
  89                                if (bytes < 0) {
  90                                        status = bytes;
  91                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort     Reg1");
  92                                        return status;
  93                                }
  94                        }
  95                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode");
  96
  97                        // Set Idle Mode Flag to False and Clear IdleMode reg.
  98                        Adapter->IdleMode = FALSE;
  99                        Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
 100
 101                        wake_up(&Adapter->lowpower_mode_wait_queue);
 102
 103                }
 104                else
 105                {
 106                        if(TRUE == Adapter->IdleMode)
 107                        {
 108                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Device is already in Idle mode....");
 109                                return status ;
 110                        }
 111
 112                        uiRegRead = 0;
 113                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode \n");
 114
 115                        if (Adapter->chip_id== BCS220_2 ||
 116                                Adapter->chip_id == BCS220_2BC ||
 117                                        Adapter->chip_id== BCS250_BC ||
 118                                        Adapter->chip_id== BCS220_3)
 119                        {
 120
 121                                bytes = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
 122                                if (bytes < 0) {
 123                                        status = bytes;
 124                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n");
 125                                        return status;
 126                                }
 127
 128
 129                                uiRegRead |= (1<<17);
 130
 131                                status = wrmalt (Adapter,HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
 132                                if(status)
 133                                {
 134                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg\n");
 135                                        return status;
 136                                }
 137
 138                        }
 139                        SendIdleModeResponse(Adapter);
 140                }
 141        }
 142        else if(ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG)
 143        {
 144                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "OverRiding Service Flow Params");
 145                OverrideServiceFlowParams(Adapter,puiBuffer);
 146        }
 147        return status;
 148}
 149
 150static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int Pattern)
 151{
 152        int     status = STATUS_SUCCESS;
 153        unsigned int value;
 154        unsigned int chip_id ;
 155        unsigned long timeout = 0 ,itr = 0;
 156
 157        int     lenwritten = 0;
 158        unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
 159        struct bcm_interface_adapter *psInterfaceAdapter = Adapter->pvInterfaceAdapter;
 160
 161        //Abort Bus suspend if its already suspended
 162        if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend))
 163        {
 164                status = usb_autopm_get_interface(psInterfaceAdapter->interface);
 165                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Bus got wakeup..Aborting Idle mode... status:%d \n",status);
 166
 167        }
 168
 169        if((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
 170                                                                        ||
 171           (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE))
 172        {
 173                //write the SW abort pattern.
 174                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern);
 175                status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern));
 176                if(status)
 177                {
 178                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
 179                                return status;
 180                }
 181        }
 182
 183        if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
 184        {
 185                value = 0x80000000;
 186                status = wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value));
 187                if(status)
 188                {
 189                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed");
 190                        return status;
 191                }
 192        }
 193        else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
 194        {
 195                /*
 196                 * Get a Interrupt Out URB and send 8 Bytes Down
 197                 * To be Done in Thread Context.
 198                 * Not using Asynchronous Mechanism.
 199                 */
 200                status = usb_interrupt_msg (psInterfaceAdapter->udev,
 201                        usb_sndintpipe(psInterfaceAdapter->udev,
 202                        psInterfaceAdapter->sIntrOut.int_out_endpointAddr),
 203                        aucAbortPattern,
 204                        8,
 205                        &lenwritten,
 206                        5000);
 207                if(status)
 208                {
 209                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n",status);
 210                        return status;
 211                }
 212                else
 213                {
 214                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten);
 215                }
 216
 217                //mdelay(25);
 218
 219                timeout= jiffies +  msecs_to_jiffies(50) ;
 220                while( timeout > jiffies )
 221                {
 222                        itr++ ;
 223                        rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT));
 224                        if(0xbece3200==(chip_id&~(0xF0)))
 225                        {
 226                                chip_id = chip_id&~(0xF0);
 227                        }
 228                        if(chip_id == Adapter->chip_id)
 229                                break;
 230                }
 231                if(timeout < jiffies )
 232                {
 233                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Not able to read chip-id even after 25 msec");
 234                }
 235                else
 236                {
 237                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Number of completed iteration to read chip-id :%lu", itr);
 238                }
 239
 240                status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status));
 241                if(status)
 242                {
 243                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
 244                        return status;
 245                }
 246        }
 247        return status;
 248}
 249int InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter)
 250{
 251        ULONG   Status = 0;
 252        if(Adapter->bTriedToWakeUpFromlowPowerMode)
 253        {
 254                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Wake up already attempted.. ignoring\n");
 255        }
 256        else
 257        {
 258                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Writing Low Power Mode Abort pattern to the Device\n");
 259                Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
 260                InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern);
 261
 262        }
 263        return Status;
 264}
 265
 266void InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter)
 267{
 268        unsigned int uiRegVal = 0;
 269        INT Status = 0;
 270        int bytes;
 271
 272        if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
 273        {
 274                // clear idlemode interrupt.
 275                uiRegVal = 0;
 276                Status =wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegVal, sizeof(uiRegVal));
 277                if(Status)
 278                {
 279                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Failed with err :%d", Status);
 280                        return;
 281                }
 282        }
 283
 284    else
 285        {
 286
 287        //clear Interrupt EP registers.
 288                bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
 289                if (bytes < 0) {
 290                        Status = bytes;
 291                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status);
 292                        return;
 293                }
 294
 295                bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
 296                if (bytes < 0) {
 297                        Status = bytes;
 298                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status);
 299                        return;
 300                }
 301        }
 302}
 303
 304