xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8188eu/hal/HalPwrSeqCmd.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2017 Realtek Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of version 2 of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  *****************************************************************************/
16 /*++
17 Copyright (c) Realtek Semiconductor Corp. All rights reserved.
18 
19 Module Name:
20 	HalPwrSeqCmd.c
21 
22 Abstract:
23 	Implement HW Power sequence configuration CMD handling routine for Realtek devices.
24 
25 Major 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 
34 
35 /*
36  *	Description:
37  *		This routine deal with the Power Configuration CMDs parsing for RTL8723/RTL8188E Series IC.
38  *
39  *	Assumption:
40  *		We should follow specific format which was released from HW SD.
41  *
42  *	2011.07.07, added by Roger.
43  *   */
HalPwrSeqCmdParsing(PADAPTER padapter,u8 CutVersion,u8 FabVersion,u8 InterfaceType,WLAN_PWR_CFG PwrSeqCmd[])44 u8 HalPwrSeqCmdParsing(
45 	PADAPTER		padapter,
46 	u8				CutVersion,
47 	u8				FabVersion,
48 	u8				InterfaceType,
49 	WLAN_PWR_CFG	PwrSeqCmd[])
50 {
51 	WLAN_PWR_CFG	PwrCfgCmd = {0};
52 	u8				bPollingBit = _FALSE;
53 	u8				bHWICSupport = _FALSE;
54 	u32				AryIdx = 0;
55 	u8				value = 0;
56 	u32				offset = 0;
57 	u8				flag = 0;
58 	u32				pollingCount = 0; /* polling autoload done. */
59 	u32				maxPollingCnt = 5000;
60 
61 	do {
62 		PwrCfgCmd = PwrSeqCmd[AryIdx];
63 
64 
65 		/* 2 Only Handle the command whose FAB, CUT, and Interface are matched */
66 		if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) &&
67 		    (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
68 		    (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) {
69 			switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
70 			case PWR_CMD_READ:
71 				break;
72 
73 			case PWR_CMD_WRITE:
74 				offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
75 
76 #ifdef CONFIG_SDIO_HCI
77 				/*  */
78 				/* <Roger_Notes> We should deal with interface specific address mapping for some interfaces, e.g., SDIO interface */
79 				/* 2011.07.07. */
80 				/*  */
81 				if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) {
82 					/* Read Back SDIO Local value */
83 					value = SdioLocalCmd52Read1Byte(padapter, offset);
84 
85 					value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd));
86 					value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd));
87 
88 					/* Write Back SDIO Local value */
89 					SdioLocalCmd52Write1Byte(padapter, offset, value);
90 				} else
91 #endif
92 				{
93 #ifdef CONFIG_GSPI_HCI
94 					if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO)
95 						offset = SPI_LOCAL_OFFSET | offset;
96 #endif
97 					/* Read the value from system register */
98 					value = rtw_read8(padapter, offset);
99 
100 					value = value & (~(GET_PWR_CFG_MASK(PwrCfgCmd)));
101 					value = value | (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd));
102 
103 					/* Write the value back to sytem register */
104 					rtw_write8(padapter, offset, value);
105 				}
106 				break;
107 
108 			case PWR_CMD_POLLING:
109 
110 				bPollingBit = _FALSE;
111 				offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
112 
113 				rtw_hal_get_hwreg(padapter, HW_VAR_PWR_CMD, &bHWICSupport);
114 				if (bHWICSupport && offset == 0x06) {
115 					flag = 0;
116 					maxPollingCnt = 100000;
117 				} else
118 					maxPollingCnt = 5000;
119 
120 #ifdef CONFIG_GSPI_HCI
121 				if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO)
122 					offset = SPI_LOCAL_OFFSET | offset;
123 #endif
124 				do {
125 #ifdef CONFIG_SDIO_HCI
126 					if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO)
127 						value = SdioLocalCmd52Read1Byte(padapter, offset);
128 					else
129 #endif
130 						value = rtw_read8(padapter, offset);
131 
132 					value = value & GET_PWR_CFG_MASK(PwrCfgCmd);
133 					if (value == (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd)))
134 						bPollingBit = _TRUE;
135 					else
136 						rtw_udelay_os(10);
137 
138 					if (pollingCount++ > maxPollingCnt) {
139 						RTW_ERR("HalPwrSeqCmdParsing: Fail to polling Offset[%#x]=%02x\n", offset, value);
140 
141 						/* For PCIE + USB package poll power bit timeout issue only modify 8821AE and 8723BE */
142 						if (bHWICSupport && offset == 0x06  && flag == 0) {
143 
144 							RTW_ERR("[WARNING] PCIE polling(0x%X) timeout(%d), Toggle 0x04[3] and try again.\n", offset, maxPollingCnt);
145 							if (IS_HARDWARE_TYPE_8723DE(padapter))
146 								PlatformEFIOWrite1Byte(padapter, 0x40, (PlatformEFIORead1Byte(padapter, 0x40)) & (~BIT3));
147 
148 							PlatformEFIOWrite1Byte(padapter, 0x04, PlatformEFIORead1Byte(padapter, 0x04) | BIT3);
149 							PlatformEFIOWrite1Byte(padapter, 0x04, PlatformEFIORead1Byte(padapter, 0x04) & ~BIT3);
150 
151 							if (IS_HARDWARE_TYPE_8723DE(padapter))
152 								PlatformEFIOWrite1Byte(padapter, 0x40, PlatformEFIORead1Byte(padapter, 0x40)|BIT3);
153 
154 							/* Retry Polling Process one more time */
155 							pollingCount = 0;
156 							flag = 1;
157 						} else {
158 							return _FALSE;
159 						}
160 					}
161 				} while (!bPollingBit);
162 
163 				break;
164 
165 			case PWR_CMD_DELAY:
166 				if (GET_PWR_CFG_VALUE(PwrCfgCmd) == PWRSEQ_DELAY_US)
167 					rtw_udelay_os(GET_PWR_CFG_OFFSET(PwrCfgCmd));
168 				else
169 					rtw_udelay_os(GET_PWR_CFG_OFFSET(PwrCfgCmd) * 1000);
170 				break;
171 
172 			case PWR_CMD_END:
173 				/* When this command is parsed, end the process */
174 				return _TRUE;
175 				break;
176 
177 			default:
178 				break;
179 			}
180 		}
181 
182 		AryIdx++;/* Add Array Index */
183 	} while (1);
184 
185 	return _TRUE;
186 }
187