diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceIdleMode.c')
-rw-r--r-- | drivers/staging/bcm/InterfaceIdleMode.c | 318 |
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 | /* | ||
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,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 | |||