aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/InterfaceIdleMode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/bcm/InterfaceIdleMode.c')
-rw-r--r--drivers/staging/bcm/InterfaceIdleMode.c318
1 files changed, 318 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c
new file mode 100644
index 00000000000..d99fc7c31a1
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceIdleMode.c
@@ -0,0 +1,318 @@
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 PMINI_ADAPTER Adapter - Miniport Adapter Context
11
12
13Return: BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful.
14 Other - If an error occured.
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 PMINI_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 occured.
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(PMINI_ADAPTER Adapter,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
158VOID 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
167int 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}
266int 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
283void 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