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 
InterfaceIdleModeRespond(PMINI_ADAPTER Adapter,unsigned int * puiBuffer)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 
InterfaceAbortIdlemode(PMINI_ADAPTER Adapter,unsigned int Pattern)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 }
InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter)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 
InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)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 
301