1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 /*++
8 Copyright (c) Realtek Semiconductor Corp. All rights reserved.
9 
10 Module Name:
11 	HalPwrSeqCmd.c
12 
13 Abstract:
14 	Implement HW Power sequence configuration CMD handling routine for Realtek devices.
15 
16 Major Change History:
17 	When       Who               What
18 	---------- ---------------   -------------------------------
19 	2011-10-26 Lucas            Modify to be compatible with SD4-CE driver.
20 	2011-07-07 Roger            Create.
21 
22 --*/
23 #include <drv_types.h>
24 #include <rtw_debug.h>
25 #include <HalPwrSeqCmd.h>
26 
27 
28 /*  */
29 /*  Description: */
30 /*  This routine deal with the Power Configuration CMDs parsing for RTL8723/RTL8188E Series IC. */
31 /*  */
32 /*  Assumption: */
33 /*  We should follow specific format which was released from HW SD. */
34 /*  */
35 /*  2011.07.07, added by Roger. */
36 /*  */
HalPwrSeqCmdParsing(struct adapter * padapter,u8 CutVersion,u8 FabVersion,u8 InterfaceType,WLAN_PWR_CFG PwrSeqCmd[])37 u8 HalPwrSeqCmdParsing(
38 	struct adapter *padapter,
39 	u8 CutVersion,
40 	u8 FabVersion,
41 	u8 InterfaceType,
42 	WLAN_PWR_CFG PwrSeqCmd[]
43 )
44 {
45 	WLAN_PWR_CFG PwrCfgCmd;
46 	u8 bPollingBit = false;
47 	u32 AryIdx = 0;
48 	u8 value = 0;
49 	u32 offset = 0;
50 	u32 pollingCount = 0; /*  polling autoload done. */
51 	u32 maxPollingCnt = 5000;
52 
53 	do {
54 		PwrCfgCmd = PwrSeqCmd[AryIdx];
55 
56 		RT_TRACE(
57 			_module_hal_init_c_,
58 			_drv_info_,
59 			(
60 				"HalPwrSeqCmdParsing: offset(%#x) cut_msk(%#x) fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) msk(%#x) value(%#x)\n",
61 				GET_PWR_CFG_OFFSET(PwrCfgCmd),
62 				GET_PWR_CFG_CUT_MASK(PwrCfgCmd),
63 				GET_PWR_CFG_FAB_MASK(PwrCfgCmd),
64 				GET_PWR_CFG_INTF_MASK(PwrCfgCmd),
65 				GET_PWR_CFG_BASE(PwrCfgCmd),
66 				GET_PWR_CFG_CMD(PwrCfgCmd),
67 				GET_PWR_CFG_MASK(PwrCfgCmd),
68 				GET_PWR_CFG_VALUE(PwrCfgCmd)
69 			)
70 		);
71 
72 		/* 2 Only Handle the command whose FAB, CUT, and Interface are matched */
73 		if (
74 			(GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) &&
75 			(GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
76 			(GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)
77 		) {
78 			switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
79 			case PWR_CMD_READ:
80 				RT_TRACE(
81 					_module_hal_init_c_,
82 					_drv_info_,
83 					("HalPwrSeqCmdParsing: PWR_CMD_READ\n")
84 				);
85 				break;
86 
87 			case PWR_CMD_WRITE:
88 				RT_TRACE(
89 					_module_hal_init_c_,
90 					_drv_info_,
91 					("HalPwrSeqCmdParsing: PWR_CMD_WRITE\n")
92 				);
93 				offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
94 
95 				/*  */
96 				/*  <Roger_Notes> We should deal with interface specific address mapping for some interfaces, e.g., SDIO interface */
97 				/*  2011.07.07. */
98 				/*  */
99 				if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) {
100 					/*  Read Back SDIO Local value */
101 					value = SdioLocalCmd52Read1Byte(padapter, offset);
102 
103 					value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd));
104 					value |= (
105 						GET_PWR_CFG_VALUE(PwrCfgCmd) &
106 						GET_PWR_CFG_MASK(PwrCfgCmd)
107 					);
108 
109 					/*  Write Back SDIO Local value */
110 					SdioLocalCmd52Write1Byte(padapter, offset, value);
111 				} else {
112 					/*  Read the value from system register */
113 					value = rtw_read8(padapter, offset);
114 
115 					value &= (~(GET_PWR_CFG_MASK(PwrCfgCmd)));
116 					value |= (
117 						GET_PWR_CFG_VALUE(PwrCfgCmd)
118 						&GET_PWR_CFG_MASK(PwrCfgCmd)
119 					);
120 
121 					/*  Write the value back to system register */
122 					rtw_write8(padapter, offset, value);
123 				}
124 				break;
125 
126 			case PWR_CMD_POLLING:
127 				RT_TRACE(
128 					_module_hal_init_c_,
129 					_drv_info_,
130 					("HalPwrSeqCmdParsing: PWR_CMD_POLLING\n")
131 				);
132 
133 				bPollingBit = false;
134 				offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
135 				do {
136 					if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO)
137 						value = SdioLocalCmd52Read1Byte(padapter, offset);
138 					else
139 						value = rtw_read8(padapter, offset);
140 
141 					value = value&GET_PWR_CFG_MASK(PwrCfgCmd);
142 					if (
143 						value == (GET_PWR_CFG_VALUE(PwrCfgCmd) &
144 						GET_PWR_CFG_MASK(PwrCfgCmd))
145 					)
146 						bPollingBit = true;
147 					else
148 						udelay(10);
149 
150 					if (pollingCount++ > maxPollingCnt) {
151 						DBG_871X(
152 							"Fail to polling Offset[%#x]=%02x\n",
153 							offset,
154 							value
155 						);
156 						return false;
157 					}
158 				} while (!bPollingBit);
159 
160 				break;
161 
162 			case PWR_CMD_DELAY:
163 				RT_TRACE(
164 					_module_hal_init_c_,
165 					_drv_info_,
166 					("HalPwrSeqCmdParsing: PWR_CMD_DELAY\n")
167 				);
168 				if (GET_PWR_CFG_VALUE(PwrCfgCmd) == PWRSEQ_DELAY_US)
169 					udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
170 				else
171 					udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd)*1000);
172 				break;
173 
174 			case PWR_CMD_END:
175 				/*  When this command is parsed, end the process */
176 				RT_TRACE(
177 					_module_hal_init_c_,
178 					_drv_info_,
179 					("HalPwrSeqCmdParsing: PWR_CMD_END\n")
180 				);
181 				return true;
182 
183 			default:
184 				RT_TRACE(
185 					_module_hal_init_c_,
186 					_drv_err_,
187 					("HalPwrSeqCmdParsing: Unknown CMD!!\n")
188 				);
189 				break;
190 			}
191 		}
192 
193 		AryIdx++;/* Add Array Index */
194 	} while (1);
195 
196 	return true;
197 }
198