]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/bcm/InterfaceIdleMode.c
Merge branch 'regmap-linus' into regmap-next
[mirror_ubuntu-bionic-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 occurred.
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 occurred.
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
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
149 static int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern)
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