]>
Commit | Line | Data |
---|---|---|
f8942e07 SH |
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. | |
25985edc | 14 | Other - If an error occurred. |
f8942e07 SH |
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. | |
25985edc | 29 | Other - If an error occurred. |
f8942e07 SH |
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 | ||
44a17eff | 45 | int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) |
f8942e07 SH |
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); | |
f8942e07 SH |
101 | |
102 | } | |
103 | else | |
104 | { | |
105 | if(TRUE == Adapter->IdleMode) | |
106 | { | |
107 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Device is already in Idle mode...."); | |
108 | return status ; | |
109 | } | |
110 | ||
111 | uiRegRead = 0; | |
112 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode \n"); | |
113 | ||
114 | if (Adapter->chip_id== BCS220_2 || | |
115 | Adapter->chip_id == BCS220_2BC || | |
116 | Adapter->chip_id== BCS250_BC || | |
117 | Adapter->chip_id== BCS220_3) | |
118 | { | |
119 | ||
120 | status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead)); | |
121 | if(status) | |
122 | { | |
123 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n"); | |
124 | return status; | |
125 | } | |
126 | ||
127 | ||
128 | uiRegRead |= (1<<17); | |
129 | ||
130 | status = wrmalt (Adapter,HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead)); | |
131 | if(status) | |
132 | { | |
133 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg\n"); | |
134 | return status; | |
135 | } | |
136 | ||
137 | } | |
138 | SendIdleModeResponse(Adapter); | |
139 | } | |
140 | } | |
141 | else if(ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG) | |
142 | { | |
143 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "OverRiding Service Flow Params"); | |
144 | OverrideServiceFlowParams(Adapter,puiBuffer); | |
145 | } | |
146 | return status; | |
147 | } | |
148 | ||
9dd47ee7 | 149 | static int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) |
f8942e07 SH |
150 | { |
151 | int status = STATUS_SUCCESS; | |
152 | unsigned int value; | |
153 | unsigned int chip_id ; | |
154 | unsigned long timeout = 0 ,itr = 0; | |
155 | ||
156 | int lenwritten = 0; | |
157 | unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; | |
158 | PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter; | |
159 | ||
160 | //Abort Bus suspend if its already suspended | |
161 | if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend)) | |
162 | { | |
163 | status = usb_autopm_get_interface(psInterfaceAdapter->interface); | |
164 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Bus got wakeup..Aborting Idle mode... status:%d \n",status); | |
165 | ||
166 | } | |
167 | ||
168 | if((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) | |
169 | || | |
170 | (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) | |
171 | { | |
172 | //write the SW abort pattern. | |
173 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern); | |
174 | status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern)); | |
175 | if(status) | |
176 | { | |
177 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to Register SW_ABORT_IDLEMODE_LOC failed.."); | |
178 | return status; | |
179 | } | |
180 | } | |
181 | ||
182 | if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) | |
183 | { | |
184 | value = 0x80000000; | |
185 | status = wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value)); | |
186 | if(status) | |
187 | { | |
188 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed"); | |
189 | return status; | |
190 | } | |
191 | } | |
192 | else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) | |
193 | { | |
194 | /* | |
195 | * Get a Interrupt Out URB and send 8 Bytes Down | |
196 | * To be Done in Thread Context. | |
197 | * Not using Asynchronous Mechanism. | |
198 | */ | |
199 | status = usb_interrupt_msg (psInterfaceAdapter->udev, | |
200 | usb_sndintpipe(psInterfaceAdapter->udev, | |
201 | psInterfaceAdapter->sIntrOut.int_out_endpointAddr), | |
202 | aucAbortPattern, | |
203 | 8, | |
204 | &lenwritten, | |
205 | 5000); | |
206 | if(status) | |
207 | { | |
208 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n",status); | |
209 | return status; | |
210 | } | |
211 | else | |
212 | { | |
213 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten); | |
214 | } | |
215 | ||
216 | //mdelay(25); | |
217 | ||
218 | timeout= jiffies + msecs_to_jiffies(50) ; | |
219 | while( timeout > jiffies ) | |
220 | { | |
221 | itr++ ; | |
222 | rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT)); | |
223 | if(0xbece3200==(chip_id&~(0xF0))) | |
224 | { | |
225 | chip_id = chip_id&~(0xF0); | |
226 | } | |
227 | if(chip_id == Adapter->chip_id) | |
228 | break; | |
229 | } | |
230 | if(timeout < jiffies ) | |
231 | { | |
232 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Not able to read chip-id even after 25 msec"); | |
233 | } | |
234 | else | |
235 | { | |
236 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Number of completed iteration to read chip-id :%lu", itr); | |
237 | } | |
238 | ||
239 | status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status)); | |
240 | if(status) | |
241 | { | |
242 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to Register SW_ABORT_IDLEMODE_LOC failed.."); | |
243 | return status; | |
244 | } | |
245 | } | |
246 | return status; | |
247 | } | |
248 | int InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter) | |
249 | { | |
250 | ULONG Status = 0; | |
251 | if(Adapter->bTriedToWakeUpFromlowPowerMode) | |
252 | { | |
253 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Wake up already attempted.. ignoring\n"); | |
254 | } | |
255 | else | |
256 | { | |
257 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Writing Low Power Mode Abort pattern to the Device\n"); | |
258 | Adapter->bTriedToWakeUpFromlowPowerMode = TRUE; | |
259 | InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern); | |
260 | ||
261 | } | |
262 | return Status; | |
263 | } | |
264 | ||
265 | void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter) | |
266 | { | |
267 | unsigned int uiRegVal = 0; | |
268 | INT Status = 0; | |
269 | if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) | |
270 | { | |
271 | // clear idlemode interrupt. | |
272 | uiRegVal = 0; | |
273 | Status =wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegVal, sizeof(uiRegVal)); | |
274 | if(Status) | |
275 | { | |
276 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Failed with err :%d", Status); | |
277 | return; | |
278 | } | |
279 | } | |
280 | ||
281 | else | |
282 | { | |
283 | ||
284 | //clear Interrupt EP registers. | |
285 | Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal)); | |
286 | if(Status) | |
287 | { | |
288 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status); | |
289 | return; | |
290 | } | |
291 | ||
292 | Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal)); | |
293 | if(Status) | |
294 | { | |
295 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status); | |
296 | return; | |
297 | } | |
298 | } | |
299 | } | |
300 |