Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
InterfaceIdleMode.c
Go to the documentation of this file.
1 #include "headers.h"
2 
3 /*
4 Function: InterfaceIdleModeWakeup
5 
6 Description: 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 
10 Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
11 
12 
13 Return: BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful.
14  Other - If an error occurred.
15 */
16 
17 
18 /*
19 Function: InterfaceIdleModeRespond
20 
21 Description: 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 
25 Input parameters: IN struct bcm_mini_adapter * Adapter - Miniport Adapter Context
26 
27 
28 Return: 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.
34 this value will be at address bfc02fa4.just before value d0ea1dle.
35 
36 Set time value by writing at bfc02f98 7d0
37 
38 checking the Ack timer expire on kannon by running command
39 d qcslog .. if it shows e means host has not send response to f/w with in 200 ms. Response should be
40 send to f/w with in 200 ms after the Idle/Shutdown req issued
41 
42 */
43 
44 
45 int 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 
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.
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;
100 
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 
150 static 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  PS_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 
170  ||
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 
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  }
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 }
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");
260  InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern);
261 
262  }
263  return Status;
264 }
265 
267 {
268  unsigned int uiRegVal = 0;
269  INT Status = 0;
270  int bytes;
271 
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