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 	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 			//Below Register should not br read in case of Manual and Protocol Idle mode.
78 			else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
79 			{
80 				//clear on read Register
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 				//clear on read Register
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 			// Set Idle Mode Flag to False and Clear IdleMode reg.
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 
InterfaceAbortIdlemode(PMINI_ADAPTER Adapter,unsigned int Pattern)150 static int InterfaceAbortIdlemode(PMINI_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 	PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter;
160 
161 	//Abort Bus suspend if its already suspended
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 		//write the SW abort pattern.
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 		 * Get a Interrupt Out URB and send 8 Bytes Down
197 		 * To be Done in Thread Context.
198 		 * Not using Asynchronous Mechanism.
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 		//mdelay(25);
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 }
InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter)249 int InterfaceIdleModeWakeup(PMINI_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 
InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)266 void InterfaceHandleShutdownModeWakeup(PMINI_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 		// clear idlemode interrupt.
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         //clear Interrupt EP registers.
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