Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1#include "headers.h"
  2
  3/*
  4Function:	InterfaceIdleModeWakeup
  5
  6Description:	This is the hardware specific Function for
  7		waking up HW device from Idle mode.
  8		A software abort pattern is written to the
  9		device to wake it and necessary power state
 10		transitions from host are performed here.
 11
 12Input parameters: IN struct bcm_mini_adapter *Adapter
 13		  - Miniport Adapter Context
 14
 15Return:		BCM_STATUS_SUCCESS - If Wakeup of the HW Interface
 16				     was successful.
 17		Other              - If an error occurred.
 18*/
 19
 20/*
 21Function:	InterfaceIdleModeRespond
 22
 23Description:	This is the hardware specific Function for
 24		responding to Idle mode request from target.
 25		Necessary power state transitions from host for
 26		idle mode or other device specific initializations
 27		are performed here.
 28
 29Input parameters: IN struct bcm_mini_adapter * Adapter
 30		  - Miniport Adapter Context
 31
 32Return:		BCM_STATUS_SUCCESS - If Idle mode response related
 33				     HW configuration was successful.
 34		Other              - If an error occurred.
 35*/
 36
 37/*
 38"dmem bfc02f00  100" tells how many time device went in Idle mode.
 39this value will be at address bfc02fa4.just before value d0ea1dle.
 40
 41Set time value by writing at bfc02f98 7d0
 42
 43checking the Ack timer expire on kannon by running command
 44d qcslog .. if it shows e means host has not send response
 45to f/w with in 200 ms. Response should be
 46send to f/w with in 200 ms after the Idle/Shutdown req issued
 47
 48*/
 49
 50
 51int InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter,
 52			unsigned int *puiBuffer)
 53{
 54	int	status = STATUS_SUCCESS;
 55	unsigned int	uiRegRead = 0;
 56	int bytes;
 57
 58	if (ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD) {
 59		if (ntohl(*(puiBuffer+1)) == 0) {
 60
 61			status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC,
 62					&uiRegRead, sizeof(uiRegRead));
 63			if (status)
 64				return status;
 65
 66			if (Adapter->ulPowerSaveMode ==
 67				DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
 68				uiRegRead = 0x00000000;
 69				status = wrmalt(Adapter,
 70					DEBUG_INTERRUPT_GENERATOR_REGISTOR,
 71					&uiRegRead, sizeof(uiRegRead));
 72				if (status)
 73					return status;
 74			}
 75			/* Below Register should not br read in case of
 76			 * Manual and Protocol Idle mode */
 77			else if (Adapter->ulPowerSaveMode !=
 78				DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
 79				/* clear on read Register */
 80				bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0,
 81					&uiRegRead, sizeof(uiRegRead));
 82				if (bytes < 0) {
 83					status = bytes;
 84					return status;
 85				}
 86				/* clear on read Register */
 87				bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1,
 88					&uiRegRead, sizeof(uiRegRead));
 89				if (bytes < 0) {
 90					status = bytes;
 91					return status;
 92				}
 93			}
 94
 95			/* Set Idle Mode Flag to False and
 96			 * Clear IdleMode reg. */
 97			Adapter->IdleMode = false;
 98			Adapter->bTriedToWakeUpFromlowPowerMode = false;
 99
100			wake_up(&Adapter->lowpower_mode_wait_queue);
101
102		} else {
103			if (TRUE == Adapter->IdleMode)
104				return status;
105
106			uiRegRead = 0;
107
108			if (Adapter->chip_id == BCS220_2 ||
109				Adapter->chip_id == BCS220_2BC ||
110					Adapter->chip_id == BCS250_BC ||
111					Adapter->chip_id == BCS220_3) {
112
113				bytes = rdmalt(Adapter, HPM_CONFIG_MSW,
114					&uiRegRead, sizeof(uiRegRead));
115				if (bytes < 0) {
116					status = bytes;
117					return status;
118				}
119
120
121				uiRegRead |= (1<<17);
122
123				status = wrmalt(Adapter, HPM_CONFIG_MSW,
124					&uiRegRead, sizeof(uiRegRead));
125				if (status)
126					return status;
127			}
128			SendIdleModeResponse(Adapter);
129		}
130	} else if (ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG) {
131		OverrideServiceFlowParams(Adapter, puiBuffer);
132	}
133	return status;
134}
135
136static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter,
137				unsigned int Pattern)
138{
139	int status = STATUS_SUCCESS;
140	unsigned int value;
141	unsigned int chip_id;
142	unsigned long timeout = 0, itr = 0;
143
144	int lenwritten = 0;
145	unsigned char aucAbortPattern[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
146						0xFF, 0xFF, 0xFF};
147	struct bcm_interface_adapter *psInterfaceAdapter =
148				Adapter->pvInterfaceAdapter;
149
150	/* Abort Bus suspend if its already suspended */
151	if ((TRUE == psInterfaceAdapter->bSuspended) &&
152			(TRUE == Adapter->bDoSuspend))
153		status = usb_autopm_get_interface(
154				psInterfaceAdapter->interface);
155
156	if ((Adapter->ulPowerSaveMode ==
157			DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) ||
158	   (Adapter->ulPowerSaveMode ==
159			DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) {
160		/* write the SW abort pattern. */
161		status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC,
162				&Pattern, sizeof(Pattern));
163		if (status)
164			return status;
165	}
166
167	if (Adapter->ulPowerSaveMode ==
168		DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
169		value = 0x80000000;
170		status = wrmalt(Adapter,
171				DEBUG_INTERRUPT_GENERATOR_REGISTOR,
172				&value, sizeof(value));
173		if (status)
174			return status;
175	} else if (Adapter->ulPowerSaveMode !=
176			DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
177		/*
178		 * Get a Interrupt Out URB and send 8 Bytes Down
179		 * To be Done in Thread Context.
180		 * Not using Asynchronous Mechanism.
181		 */
182		status = usb_interrupt_msg(psInterfaceAdapter->udev,
183			usb_sndintpipe(psInterfaceAdapter->udev,
184			psInterfaceAdapter->sIntrOut.int_out_endpointAddr),
185			aucAbortPattern,
186			8,
187			&lenwritten,
188			5000);
189		if (status)
190			return status;
191		else
192			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
193				IDLE_MODE, DBG_LVL_ALL,
194				"NOB Sent down :%d", lenwritten);
195
196		/* mdelay(25); */
197
198		timeout = jiffies +  msecs_to_jiffies(50);
199		while (time_after(timeout, jiffies)) {
200			itr++;
201			rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT));
202			if (0xbece3200 == (chip_id&~(0xF0)))
203				chip_id = chip_id&~(0xF0);
204			if (chip_id == Adapter->chip_id)
205				break;
206		}
207		if (time_before(timeout, jiffies))
208			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
209				IDLE_MODE, DBG_LVL_ALL,
210				"Not able to read chip-id even after 25 msec");
211		else
212			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
213				IDLE_MODE, DBG_LVL_ALL,
214				"Number of completed iteration to"
215				"read chip-id :%lu", itr);
216
217		status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC,
218				&Pattern, sizeof(status));
219		if (status)
220			return status;
221	}
222	return status;
223}
224int InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter)
225{
226	ULONG	Status = 0;
227	if (Adapter->bTriedToWakeUpFromlowPowerMode) {
228		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
229		IDLE_MODE, DBG_LVL_ALL,
230		"Wake up already attempted.. ignoring\n");
231	} else {
232		Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
233		InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern);
234
235	}
236	return Status;
237}
238
239void InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter)
240{
241	unsigned int uiRegVal = 0;
242	INT Status = 0;
243	int bytes;
244
245	if (Adapter->ulPowerSaveMode ==
246		DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
247		/* clear idlemode interrupt. */
248		uiRegVal = 0;
249		Status = wrmalt(Adapter,
250			DEBUG_INTERRUPT_GENERATOR_REGISTOR,
251			&uiRegVal, sizeof(uiRegVal));
252		if (Status)
253			return;
254	}
255
256	else {
257
258/* clear Interrupt EP registers. */
259		bytes = rdmalt(Adapter,
260			DEVICE_INT_OUT_EP_REG0,
261			&uiRegVal, sizeof(uiRegVal));
262		if (bytes < 0) {
263			Status = bytes;
264			return;
265		}
266
267		bytes = rdmalt(Adapter,
268			DEVICE_INT_OUT_EP_REG1,
269			&uiRegVal, sizeof(uiRegVal));
270		if (bytes < 0) {
271			Status = bytes;
272			return;
273		}
274	}
275}
276