• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute  it and/or modify it
5  * under  the terms of  the GNU General  Public License as published by the
6  * Free Software Foundation;  either version 2 of the  License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Description: Hieth system operation
18  */
19 
20 
21 #include <config.h>
22 #include "hieth.h"
23 #include "sys.h"
24 
25 #if defined(CONFIG_GODBOX) || defined(CONFIG_GODBOX_V1)
26 #define HIETH_CRG_REG (REG_BASE_CRG + REG_PERI_CRG26)
27 #else
28 #define HIETH_CRG_REG (CRG_REG_BASE + REG_ETH_CRG)
29 #endif
30 
31 #define ETH_SOFT_RESET bit(0)
32 #if defined(CONFIG_GODBOX) || defined(CONFIG_GODBOX_V1)
33 #define ETH_CLK_ENABLE bit(8)
34 #elif defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
35 #define ETH_CLK_ENABLE bit(4)
36 #else
37 #define ETH_CLK_ENABLE bit(1)
38 #endif
39 
40 #if defined(HISFV_RESET_PHY_BY_CRG)
41 #if defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
42 #define ETH_EXTERNAL_PHY_RESET bit(0)
43 #else
44 #define ETH_EXTERNAL_PHY_RESET bit(3)
45 #endif
46 #endif
47 
48 #if defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
49 #define ETH_CORE_CLK_SELECT_54M bit(12)
50 #else
51 #define ETH_CORE_CLK_SELECT_54M bit(7)
52 #endif
53 
54 #if defined(CONFIG_HI3520D)
55 #define HIETH_SYSCTL_REG       (SYS_CTRL_REG_BASE + PERIPHCTRL24)
56 #define ETH_INTERNAL_PHY_RESET bit(2)
57 #define HIETH_EFUSE_REG        (CRG_REG_BASE + EFUSE_CTRL_CRG)
58 #define HIETH_EFUSE_DATA_REG   (EFUSE_REG_BASE + EFUSE_DATA_SEL)
59 #elif defined(CONFIG_HI3536DV100)
60 #define HIETH_SYSCTL_REG        (MISC_REG_BASE + REG_FEPHY_CTRL1)
61 #define BIT_FEPHY_SEL           bit(5)
62 #define BIT_PHY_RMII_MODE       bit(8)
63 #define ETH_INTERNAL_PHY_RESET  bit(9)
64 #define ETH_INTERNAL_PHY_CLK_EN bit(10)
65 #endif
66 
67 #if defined(CONFIG_TARGET_HI3516EV200)
68 #define HIETH_SYSCTL_REG        (SYS_CTRL_REG_BASE + MISC_CTRL9)
69 #define ETH_INTERNAL_PHY_RESET  bit(3)
70 #define ETH_INTERNAL_PHY_CLK_EN bit(2)
71 #endif
72 
73 #if defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
74 #define HIETH_SYSCTL_REG        (SYS_CTRL_REG_BASE + REG_FEPHY_CTRL0)
75 #define ETH_INTERNAL_PHY_RESET  bit(0)
76 #define ETH_INTERNAL_PHY_CLK_EN bit(4)
77 #endif
78 
79 #if defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
80 #define HIETH_CRG_INPHY_CLK_REG   (CRG_REG_BASE + REG_INFEPHY_CLK_RST)
81 #define HIETH_CRG_EXTPHY_CLK_REG  (CRG_REG_BASE + REG_EXTFEPHY_CLK_RST)
82 #else
83 #define HIETH_CRG_INPHY_CLK_REG   HIETH_CRG_REG
84 #define HIETH_CRG_EXTPHY_CLK_REG  HIETH_CRG_REG
85 #endif
86 
87 #if defined(CONFIG_TARGET_HI3516EV300)
88 #define HIETH_SYSCTL_REG        (SYS_CTRL_REG_BASE + MISC_CTRL9)
89 #define ETH_INTERNAL_PHY_RESET  bit(3)
90 #define ETH_INTERNAL_PHY_CLK_EN bit(2)
91 #endif
92 
93 #if defined(CONFIG_TARGET_HI3518EV300)
94 #define HIETH_SYSCTL_REG        (SYS_CTRL_REG_BASE + MISC_CTRL9)
95 #define ETH_INTERNAL_PHY_RESET  bit(3)
96 #define ETH_INTERNAL_PHY_CLK_EN bit(2)
97 #endif
98 
99 #if defined(CONFIG_TARGET_HI3516DV200)
100 #define HIETH_SYSCTL_REG        (SYS_CTRL_REG_BASE + MISC_CTRL9)
101 #define ETH_INTERNAL_PHY_RESET  bit(3)
102 #define ETH_INTERNAL_PHY_CLK_EN bit(2)
103 #endif
104 
105 #if defined(CONFIG_HI3536DV100)
hieth_use_fephy(void)106 static unsigned char hieth_use_fephy(void)
107 {
108 	return !(readl(HIETH_SYSCTL_REG) & BIT_FEPHY_SEL);
109 }
110 #endif
111 
112 #if defined(INNER_PHY) && defined(CONFIG_HI3520D)
set_efuse_unread(void)113 void set_efuse_unread(void)
114 {
115 	u32 reg_value;
116 
117 	reg_value = readl(HIETH_EFUSE_REG);
118 	reg_value |= 0x1;
119 	writel(reg_value, HIETH_EFUSE_REG);
120 
121 	reg_value = readl(HIETH_EFUSE_DATA_REG);
122 	reg_value |= 0x1;
123 	writel(reg_value, HIETH_EFUSE_DATA_REG);
124 
125 	mdelay(300); /* delay 300ms */
126 
127 	reg_value = readl(HIETH_EFUSE_REG);
128 	reg_value &= ~0x1;
129 	writel(reg_value, HIETH_EFUSE_REG);
130 }
131 #else
set_efuse_unread(void)132 void set_efuse_unread(void)
133 {
134 }
135 #endif
136 
137 #ifdef INNER_PHY
set_inner_phy_addr(u32 phy_addr)138 void set_inner_phy_addr(u32 phy_addr)
139 {
140 	u32 reg_value;
141 
142 #if defined(CONFIG_HI3536DV100)
143 	if (!hieth_use_fephy())
144 		phy_addr += 1;
145 #endif
146 	reg_value = readl(HIETH_SYSCTL_REG);
147 	reg_value &= ~0x1f;
148 	phy_addr &= 0x1f;
149 	reg_value |= phy_addr;
150 	writel(reg_value, HIETH_SYSCTL_REG);
151 }
152 #else
set_inner_phy_addr(u32 phyaddr)153 void set_inner_phy_addr(u32 phyaddr)
154 {
155 }
156 #endif
157 
158 #if defined(INNER_PHY) && defined(CONFIG_HI3520D)
revise_led_shine(void)159 void revise_led_shine(void)
160 {
161 #define MDIO_RWCTRL      0x1100
162 #define tmp_mdio_ready() \
163 	(readl(REG_BASE_SF + MDIO_RWCTRL) & bit(15))
164 
165 	unsigned int reg_value;
166 	/* select page 7 */
167 	do {
168 		reg_value = 0x0007235f;
169 		writel(reg_value, REG_BASE_SF + MDIO_RWCTRL);
170 		udelay(10); /* delay 10us */
171 	} while (!tmp_mdio_ready());
172 
173 	/* enable LED modify function */
174 	do {
175 		reg_value = 0xc03c2353;
176 		writel(reg_value, REG_BASE_SF + MDIO_RWCTRL);
177 		udelay(10); /* delay 10us */
178 	} while (!tmp_mdio_ready());
179 
180 	/* set green LED shine all the while when link up,
181 	 * yellow LED blink when data coming
182 	 */
183 	do {
184 		reg_value = 0x00382351;
185 		writel(reg_value, REG_BASE_SF + MDIO_RWCTRL);
186 		udelay(10); /* delay 10us */
187 	} while (!tmp_mdio_ready());
188 
189 	return;
190 }
191 #else
revise_led_shine(void)192 void revise_led_shine(void)
193 {
194 }
195 #endif
196 
197 #if defined(INNER_PHY) && defined(CONFIG_HI3520D)
set_phy_valtage(void)198 void set_phy_valtage(void)
199 {
200 #define MDIO_RWCTRL      0x1100
201 #define tmp_mdio_ready() \
202 	(readl(REG_BASE_SF + MDIO_RWCTRL) & bit(15))
203 
204 	unsigned int reg_value;
205 	/* select page 1 */
206 	do {
207 		reg_value = 0x0001235f;
208 		writel(reg_value, REG_BASE_SF + MDIO_RWCTRL);
209 		udelay(10); /* delay 10us */
210 	} while (!tmp_mdio_ready());
211 
212 	/* set fe-phy in lower valtage */
213 	do {
214 		reg_value = 0x94482352;
215 		writel(reg_value, REG_BASE_SF + MDIO_RWCTRL);
216 		udelay(10); /* delay 10us */
217 	} while (!tmp_mdio_ready());
218 
219 	/* select page 0 */
220 	do {
221 		reg_value = 0x0000235f;
222 		writel(reg_value, REG_BASE_SF + MDIO_RWCTRL);
223 		udelay(10); /* delay 10us */
224 	} while (!tmp_mdio_ready());
225 }
226 #else
set_phy_valtage(void)227 void set_phy_valtage(void)
228 {
229 }
230 #endif
231 
hieth_reset(int rst)232 static void hieth_reset(int rst)
233 {
234 	u32 val;
235 
236 	val = _readl(HIETH_CRG_REG);
237 	if (rst) {
238 		val |= ETH_SOFT_RESET;
239 	} else {
240 		val &= ~ETH_SOFT_RESET;
241 	}
242 	_writel(val, HIETH_CRG_REG);
243 
244 	udelay(100); /* delay 100us */
245 }
246 
hieth_clk_ena(void)247 static inline void hieth_clk_ena(void)
248 {
249 	u32 val = _readl(HIETH_CRG_REG);
250 	val |= (ETH_CORE_CLK_SELECT_54M | ETH_CLK_ENABLE);
251 	_writel(val, HIETH_CRG_REG);
252 }
253 
hieth_clk_dis(void)254 static inline void hieth_clk_dis(void)
255 {
256 	u32 val = _readl(HIETH_CRG_REG);
257 	val &= ~ETH_CLK_ENABLE;
258 	_writel(val, HIETH_CRG_REG);
259 }
260 
261 #if defined(CONFIG_HI3536DV100) || defined(INNER_PHY)
hieth_fephy_trim(void)262 static void hieth_fephy_trim(void)
263 {
264 	/* To simplify internal FEPHY trim process,
265 	 * we just delay 300ms to wait FEPHY auto-trim completed.
266 	 * Not read trim data from EFUSE register.
267 	 */
268 	mdelay(350); /* delay 350ms */
269 }
270 #endif
271 
272 #if defined(CONFIG_HI3536DV100)
hieth_set_crg_phy_mode(unsigned char is_rmii_mode)273 void hieth_set_crg_phy_mode(unsigned char is_rmii_mode)
274 {
275 	u32 val;
276 
277 	val = readl(HIETH_CRG_REG);
278 	if (is_rmii_mode) {
279 		val |= BIT_PHY_RMII_MODE;
280 	} else {
281 		val &= ~BIT_PHY_RMII_MODE;
282 	}
283 	writel(val, HIETH_CRG_REG);
284 }
285 #endif
286 
hieth_reset_internal_phy(void)287 static void hieth_reset_internal_phy(void)
288 {
289 #ifdef INNER_PHY
290 	u32 rst;
291 
292 #if defined(CONFIG_HI3536DV100)
293 	if (!hieth_use_fephy()) {
294 		return;
295 	}
296 #endif
297 	/* disable MDCK clock to make sure FEPHY reset success */
298 	hieth_clk_dis();
299 
300 	rst = readl(HIETH_CRG_INPHY_CLK_REG);
301 	rst |= ETH_INTERNAL_PHY_CLK_EN;
302 	/* internal FEPHY only support MII mode */
303 #if defined(CONFIG_HI3536DV100)
304 	rst &= ~BIT_PHY_RMII_MODE;
305 #endif
306 	writel(rst, HIETH_CRG_INPHY_CLK_REG);
307 	udelay(10); /* delay 10us */
308 
309 	rst = _readl(HIETH_CRG_INPHY_CLK_REG);
310 	rst |= ETH_INTERNAL_PHY_RESET;
311 	_writel(rst, HIETH_CRG_INPHY_CLK_REG);
312 	/* delay at least 10ms */
313 	mdelay(15); /* delay 15ms */
314 
315 	rst = _readl(HIETH_CRG_INPHY_CLK_REG);
316 	rst &= ~ETH_INTERNAL_PHY_RESET;
317 	_writel(rst, HIETH_CRG_INPHY_CLK_REG);
318 	/* delay at least 15ms for MDIO operation */
319 	mdelay(20); /* delay 20ms */
320 
321 	hieth_clk_ena();
322 	/* delay 5ms after enable MDCK to make sure FEPHY trim safe */
323 	mdelay(5); /* delay 5ms */
324 	hieth_fephy_trim();
325 #endif
326 }
327 
hieth_reset_external_phy_by_crg(void)328 static void hieth_reset_external_phy_by_crg(void)
329 {
330 #if defined(HISFV_RESET_PHY_BY_CRG)
331 	u32 v;
332 
333 	/************************************************/
334 	/* reset external phy with default reset pin */
335 	v = readl(HIETH_CRG_EXTPHY_CLK_REG);
336 	v |= ETH_EXTERNAL_PHY_RESET;
337 	writel(v, HIETH_CRG_EXTPHY_CLK_REG);
338 
339 	mdelay(50); /* delay 50ms */
340 
341 	/* then, cancel reset, and should delay some time */
342 	v = readl(HIETH_CRG_EXTPHY_CLK_REG);
343 	v &= ~ETH_EXTERNAL_PHY_RESET;
344 	writel(v, HIETH_CRG_EXTPHY_CLK_REG);
345 
346 	mdelay(50); /* delay 50ms */
347 #endif
348 }
349 
hieth_reset_external_phy_by_gpio(void)350 static void hieth_reset_external_phy_by_gpio(void)
351 {
352 #ifdef HISFV_RESET_GPIO_EN
353 	unsigned int val;
354 	/* gpiox[x] set to reset, then delay 200ms */
355 	val = __raw_readw(HISFV_RESET_GPIO_BASE + HISFV_RESET_GPIO_DIR);
356 	val |= (HISFV_RESET_GPIO_DIR_OUT << HISFV_RESET_GPIO_BIT);
357 	__raw_writew(val, HISFV_RESET_GPIO_BASE + HISFV_RESET_GPIO_DIR);
358 	__raw_writew(HISFV_RESET_GPIO_DATA,
359 				 HISFV_RESET_GPIO_BASE +
360 				 (4 << HISFV_RESET_GPIO_BIT)); /* offset addr 4 */
361 
362 	mdelay(200); /* delay 200ms */
363 
364 	/* then,cancel reset,and should delay 200ms */
365 	val = __raw_readw(HISFV_RESET_GPIO_BASE + HISFV_RESET_GPIO_DIR);
366 	val |= (HISFV_RESET_GPIO_DIR_OUT << HISFV_RESET_GPIO_BIT);
367 	__raw_writew(val, HISFV_RESET_GPIO_BASE + HISFV_RESET_GPIO_DIR);
368 	__raw_writew(((!HISFV_RESET_GPIO_DATA) << HISFV_RESET_GPIO_BIT),
369 				 HISFV_RESET_GPIO_BASE +
370 				 (4 << HISFV_RESET_GPIO_BIT)); /* offset addr 4 */
371 
372 	mdelay(20); /* delay 20ms */
373 #endif
374 }
375 
hieth_phy_reset(void)376 static void hieth_phy_reset(void)
377 {
378 	hieth_reset_internal_phy();
379 	hieth_reset_external_phy_by_crg();
380 	hieth_reset_external_phy_by_gpio();
381 }
382 
hieth_funsel_config(void)383 static void hieth_funsel_config(void)
384 {
385 }
386 
hieth_funsel_restore(void)387 static void hieth_funsel_restore(void)
388 {
389 }
390 
391 /**************************************************/
hieth_sys_startup(void)392 void hieth_sys_startup(void)
393 {
394 	hieth_clk_ena();
395 	/* undo reset */
396 	hieth_reset(0);
397 }
398 
hieth_sys_allstop(void)399 void hieth_sys_allstop(void)
400 {
401 }
402 
hieth_sys_init(void)403 void hieth_sys_init(void)
404 {
405 	hieth_funsel_config();
406 	hieth_sys_allstop();
407 	hieth_clk_ena();
408 	hieth_reset(1);
409 	hieth_reset(0);
410 	hieth_phy_reset();
411 	revise_led_shine();
412 }
413 
hieth_sys_exit(void)414 void hieth_sys_exit(void)
415 {
416 	hieth_funsel_restore();
417 	hieth_sys_allstop();
418 }
419