Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
[pandora-kernel.git] / drivers / staging / bcm / InterfaceIdleMode.c
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 PMINI_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 occured.
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 PMINI_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 occured.
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(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
46 {
47         int     status = STATUS_SUCCESS;
48         unsigned int    uiRegRead = 0;
49
50         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer));
51
52         if(ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD)
53         {
54                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL," Got GO_TO_IDLE_MODE_PAYLOAD(210) Msg Subtype");
55                 if(ntohl(*(puiBuffer+1)) == 0 )
56                 {
57                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Got IDLE MODE WAKE UP Response From F/W");
58
59                         status = wrmalt (Adapter,SW_ABORT_IDLEMODE_LOC, &uiRegRead, sizeof(uiRegRead));
60                         if(status)
61                         {
62                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");
63                                 return status;
64                         }
65
66                         if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
67                         {
68                                 uiRegRead = 0x00000000 ;
69                                 status = wrmalt (Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegRead, sizeof(uiRegRead));
70                                 if(status)
71                                 {
72                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode     Reg");
73                                         return status;
74                                 }
75                         }
76                         //Below Register should not br read in case of Manual and Protocol Idle mode.
77                         else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
78                         {
79                                 //clear on read Register
80                                 status = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
81                                 if(status)
82                                 {
83                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");
84                                         return status;
85                                 }
86                                 //clear on read Register
87                                 status = rdmalt (Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
88                                 if(status)
89                                 {
90                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort     Reg1");
91                                         return status;
92                                 }
93                         }
94                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode");
95
96                         // Set Idle Mode Flag to False and Clear IdleMode reg.
97                         Adapter->IdleMode = FALSE;
98                         Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
99
100                         wake_up(&Adapter->lowpower_mode_wait_queue);
101                 #if 0
102                         if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
103                         {
104                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"LED Thread is Running. Hence Setting the LED Event as IDLEMODE_EXIT");
105                                 Adapter->DriverState = IDLEMODE_EXIT;
106                                 wake_up(&Adapter->LEDInfo.notify_led_event);
107                         }
108                 #endif
109
110                 }
111                 else
112                 {
113                         if(TRUE == Adapter->IdleMode)
114                         {
115                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Device is already in Idle mode....");
116                                 return status ;
117                         }
118
119                         uiRegRead = 0;
120                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode \n");
121
122                         if (Adapter->chip_id== BCS220_2 ||
123                                 Adapter->chip_id == BCS220_2BC ||
124                                         Adapter->chip_id== BCS250_BC ||
125                                         Adapter->chip_id== BCS220_3)
126                         {
127
128                                 status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
129                                 if(status)
130                                 {
131                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n");
132                                         return status;
133                                 }
134
135
136                                 uiRegRead |= (1<<17);
137
138                                 status = wrmalt (Adapter,HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
139                                 if(status)
140                                 {
141                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg\n");
142                                         return status;
143                                 }
144
145                         }
146                         SendIdleModeResponse(Adapter);
147                 }
148         }
149         else if(ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG)
150         {
151                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "OverRiding Service Flow Params");
152                 OverrideServiceFlowParams(Adapter,puiBuffer);
153         }
154         return status;
155 }
156
157
158 VOID InterfaceWriteIdleModeWakePattern(PMINI_ADAPTER Adapter)
159 {
160 /*      BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Low, 0x1d1e);
161         BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Low, 0x1d1e);
162         BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Upp, 0xd0ea);
163         BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Upp, 0xd0ea);*/
164         return;
165 }
166
167 int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern)
168 {
169         int     status = STATUS_SUCCESS;
170         unsigned int value;
171         unsigned int chip_id ;
172         unsigned long timeout = 0 ,itr = 0;
173
174         int     lenwritten = 0;
175         unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
176         PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter;
177
178         //Abort Bus suspend if its already suspended
179         if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend))
180         {
181                 status = usb_autopm_get_interface(psInterfaceAdapter->interface);
182                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Bus got wakeup..Aborting Idle mode... status:%d \n",status);
183
184         }
185
186         if((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
187                                                                         ||
188            (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE))
189         {
190                 //write the SW abort pattern.
191                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern);
192                 status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern));
193                 if(status)
194                 {
195                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
196                                 return status;
197                 }
198         }
199
200         if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
201         {
202                 value = 0x80000000;
203                 status = wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value));
204                 if(status)
205                 {
206                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed");
207                         return status;
208                 }
209         }
210         else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
211         {
212                 /*
213                  * Get a Interrupt Out URB and send 8 Bytes Down
214                  * To be Done in Thread Context.
215                  * Not using Asynchronous Mechanism.
216                  */
217                 status = usb_interrupt_msg (psInterfaceAdapter->udev,
218                         usb_sndintpipe(psInterfaceAdapter->udev,
219                         psInterfaceAdapter->sIntrOut.int_out_endpointAddr),
220                         aucAbortPattern,
221                         8,
222                         &lenwritten,
223                         5000);
224                 if(status)
225                 {
226                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n",status);
227                         return status;
228                 }
229                 else
230                 {
231                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten);
232                 }
233
234                 //mdelay(25);
235
236                 timeout= jiffies +  msecs_to_jiffies(50) ;
237                 while( timeout > jiffies )
238                 {
239                         itr++ ;
240                         rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT));
241                         if(0xbece3200==(chip_id&~(0xF0)))
242                         {
243                                 chip_id = chip_id&~(0xF0);
244                         }
245                         if(chip_id == Adapter->chip_id)
246                                 break;
247                 }
248                 if(timeout < jiffies )
249                 {
250                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Not able to read chip-id even after 25 msec");
251                 }
252                 else
253                 {
254                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Number of completed iteration to read chip-id :%lu", itr);
255                 }
256
257                 status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status));
258                 if(status)
259                 {
260                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
261                         return status;
262                 }
263         }
264         return status;
265 }
266 int InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter)
267 {
268         ULONG   Status = 0;
269         if(Adapter->bTriedToWakeUpFromlowPowerMode)
270         {
271                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Wake up already attempted.. ignoring\n");
272         }
273         else
274         {
275                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Writing Low Power Mode Abort pattern to the Device\n");
276                 Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
277                 InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern);
278
279         }
280         return Status;
281 }
282
283 void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)
284 {
285         unsigned int uiRegVal = 0;
286         INT Status = 0;
287         if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
288         {
289                 // clear idlemode interrupt.
290                 uiRegVal = 0;
291                 Status =wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegVal, sizeof(uiRegVal));
292                 if(Status)
293                 {
294                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Failed with err :%d", Status);
295                         return;
296                 }
297         }
298
299     else
300         {
301
302         //clear Interrupt EP registers.
303                 Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
304                 if(Status)
305                 {
306                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status);
307                         return;
308                 }
309
310         Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
311                 if(Status)
312                 {
313                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status);
314                         return;
315                 }
316         }
317 }
318