1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15/*++
16Copyright (c) Realtek Semiconductor Corp. All rights reserved.
17
18Module Name:
19	HalPwrSeqCmd.c
20
21Abstract:
22	Implement HW Power sequence configuration CMD handling routine for
23	Realtek devices.
24
25Major Change History:
26	When       Who               What
27	---------- ---------------   -------------------------------
28	2011-10-26 Lucas            Modify to be compatible with SD4-CE driver.
29	2011-07-07 Roger            Create.
30
31--*/
32#include <HalPwrSeqCmd.h>
33#include <usb_ops_linux.h>
34
35/*  */
36/*	Description: */
37/*		This routine deal with the Power Configuration CMDs parsing
38		for RTL8723/RTL8188E Series IC. */
39/*  */
40/*	Assumption: */
41/*		We should follow specific format which was released from
42		HW SD. */
43/*  */
44/*	2011.07.07, added by Roger. */
45/*  */
46u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
47		       u8 FabVersion, u8 InterfaceType,
48		       struct wlan_pwr_cfg PwrSeqCmd[])
49{
50	struct wlan_pwr_cfg PwrCfgCmd = { 0 };
51	u8 bPollingBit = false;
52	u32 AryIdx = 0;
53	u8 value = 0;
54	u32 offset = 0;
55	u32 pollingCount = 0;	/*  polling autoload done. */
56	u32 maxPollingCnt = 5000;
57
58	do {
59		PwrCfgCmd = PwrSeqCmd[AryIdx];
60
61		RT_TRACE(_module_hal_init_c_, _drv_info_,
62			 ("HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) "
63			  "fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) "
64			  "msk(%#x) value(%#x)\n",
65			  GET_PWR_CFG_OFFSET(PwrCfgCmd),
66			  GET_PWR_CFG_CUT_MASK(PwrCfgCmd),
67			  GET_PWR_CFG_FAB_MASK(PwrCfgCmd),
68			  GET_PWR_CFG_INTF_MASK(PwrCfgCmd),
69			  GET_PWR_CFG_BASE(PwrCfgCmd),
70			  GET_PWR_CFG_CMD(PwrCfgCmd),
71			  GET_PWR_CFG_MASK(PwrCfgCmd),
72			  GET_PWR_CFG_VALUE(PwrCfgCmd)));
73
74		/* 2 Only Handle the command whose FAB, CUT, and Interface are
75		   matched */
76		if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) &&
77		    (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
78		    (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) {
79			switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
80			case PWR_CMD_READ:
81				RT_TRACE(_module_hal_init_c_, _drv_info_,
82					 ("HalPwrSeqCmdParsing23a: "
83					  "PWR_CMD_READ\n"));
84				break;
85
86			case PWR_CMD_WRITE:
87				RT_TRACE(_module_hal_init_c_, _drv_info_,
88					 ("HalPwrSeqCmdParsing23a: "
89					  "PWR_CMD_WRITE\n"));
90				offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
91
92				/*  Read the value from system register */
93				value = rtl8723au_read8(padapter, offset);
94
95				value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd));
96				value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) &
97					  GET_PWR_CFG_MASK(PwrCfgCmd));
98
99				/*  Write the value back to sytem register */
100				rtl8723au_write8(padapter, offset, value);
101				break;
102
103			case PWR_CMD_POLLING:
104				RT_TRACE(_module_hal_init_c_, _drv_info_,
105					 ("HalPwrSeqCmdParsing23a: "
106					  "PWR_CMD_POLLING\n"));
107
108				bPollingBit = false;
109				offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
110				do {
111					value = rtl8723au_read8(padapter,
112								offset);
113
114					value &= GET_PWR_CFG_MASK(PwrCfgCmd);
115					if (value ==
116					    (GET_PWR_CFG_VALUE(PwrCfgCmd) &
117					     GET_PWR_CFG_MASK(PwrCfgCmd)))
118						bPollingBit = true;
119					else
120						udelay(10);
121
122					if (pollingCount++ > maxPollingCnt) {
123						DBG_8723A("Fail to polling "
124							  "Offset[%#x]\n",
125							  offset);
126						return false;
127					}
128				} while (!bPollingBit);
129
130				break;
131
132			case PWR_CMD_DELAY:
133				RT_TRACE(_module_hal_init_c_, _drv_info_,
134					 ("HalPwrSeqCmdParsing23a: "
135					  "PWR_CMD_DELAY\n"));
136				if (GET_PWR_CFG_VALUE(PwrCfgCmd) ==
137				    PWRSEQ_DELAY_US)
138					udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
139				else
140					udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd) *
141					       1000);
142				break;
143
144			case PWR_CMD_END:
145				/*  When this command is parsed, end
146				    the process */
147				RT_TRACE(_module_hal_init_c_, _drv_info_,
148					 ("HalPwrSeqCmdParsing23a: "
149					  "PWR_CMD_END\n"));
150				return true;
151				break;
152
153			default:
154				RT_TRACE(_module_hal_init_c_, _drv_err_,
155					 ("HalPwrSeqCmdParsing23a: "
156					  "Unknown CMD!!\n"));
157				break;
158			}
159		}
160
161		AryIdx++;	/* Add Array Index */
162	} while (1);
163
164	return true;
165}
166