1#include "headers.h"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
78 else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
79 {
80
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
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
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
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
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
197
198
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
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
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
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