• 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: Control higmac register
18  */
19 
20 #include "util.h"
21 #include "higmac.h"
22 #include "ctrl.h"
23 
24 #if defined(CONFIG_TARGET_HI3531DV200) || defined(CONFIG_TARGET_HI3535AV100)
higmac_set_macif(struct higmac_netdev_local * ld,int mode,unsigned int speed)25 void higmac_set_macif(struct higmac_netdev_local *ld, int mode, unsigned int speed)
26 {
27 	void __iomem *p = (void __iomem *)CRG_REG_BASE;
28 	unsigned long v;
29 
30 	/* enable change: port_mode */
31 	higmac_writel_bits(ld, 1, MODE_CHANGE_EN, BIT_MODE_CHANGE_EN);
32 	if (speed == SPEED_MODE_1000M)
33 		speed = 5; /* regval is 5 for 1000M */
34 	higmac_writel_bits(ld, speed, PORT_MODE, BITS_PORT_MODE);
35 	/* disable change: port_mode */
36 	higmac_writel_bits(ld, 0, MODE_CHANGE_EN, BIT_MODE_CHANGE_EN);
37 
38 	/* soft reset mac_if */
39 	if (ld->index) {
40 #if GMAC_AT_LEAST_2PORT
41 		v = readl(p + REG_ETH1_MACIF_CRG);
42 		v |= BIT_MACIF1_RST;
43 		writel(v, p + REG_ETH1_MACIF_CRG);
44 #endif
45 	} else {
46 		v = readl(p + REG_ETH0_MACIF_CRG);
47 		v |= BIT_MACIF0_RST;
48 		writel(v, p + REG_ETH0_MACIF_CRG);
49 	}
50 
51 	/* config mac_if */
52 	if (ld->index) {
53 #if GMAC_AT_LEAST_2PORT
54 		writel(mode, HIGMAC_MACIF1_CTRL);
55 #endif
56 	} else {
57 		writel(mode, HIGMAC_MACIF0_CTRL);
58 	}
59 
60 	if (ld->index) {
61 #if GMAC_AT_LEAST_2PORT
62 		v = readl(p + REG_ETH1_MACIF_CRG);
63 		v &= ~BIT_MACIF1_RST;
64 		writel(v, p + REG_ETH1_MACIF_CRG);
65 #endif
66 	} else {
67 		v = readl(p + REG_ETH0_MACIF_CRG);
68 		v &= ~BIT_MACIF0_RST;
69 		writel(v, p + REG_ETH0_MACIF_CRG);
70 	}
71 }
72 #else
higmac_set_macif(struct higmac_netdev_local * ld,int mode,unsigned int speed)73 void higmac_set_macif(struct higmac_netdev_local *ld, int mode, unsigned int speed)
74 {
75 	void __iomem *p = (void __iomem *)CRG_REG_BASE;
76 	unsigned long v;
77 
78 	/* enable change: port_mode */
79 	higmac_writel_bits(ld, 1, MODE_CHANGE_EN, BIT_MODE_CHANGE_EN);
80 	if (speed == SPEED_MODE_1000M)
81 		speed = 5; /* regval is 5 for 1000M */
82 	higmac_writel_bits(ld, speed, PORT_MODE, BITS_PORT_MODE);
83 	/* disable change: port_mode */
84 	higmac_writel_bits(ld, 0, MODE_CHANGE_EN, BIT_MODE_CHANGE_EN);
85 
86 	/* soft reset mac_if */
87 	v = readl(p + REG_ETH_CRG);
88 	if (ld->index) {
89 #if GMAC_AT_LEAST_2PORT
90 		v |= BIT_MACIF1_RST;
91 #endif
92 	} else {
93 		v |= BIT_MACIF0_RST;
94 	}
95 	writel(v, p + REG_ETH_CRG);
96 
97 	/* config mac_if */
98 	if (ld->index) {
99 #if GMAC_AT_LEAST_2PORT
100 		writel(mode, HIGMAC_MACIF1_CTRL);
101 #endif
102 	} else {
103 		writel(mode, HIGMAC_MACIF0_CTRL);
104 	}
105 
106 	v = readl(p + REG_ETH_CRG);
107 	if (ld->index) {
108 #if GMAC_AT_LEAST_2PORT
109 		v &= ~BIT_MACIF1_RST;
110 #endif
111 	} else {
112 		v &= ~BIT_MACIF0_RST;
113 	}
114 	writel(v, p + REG_ETH_CRG);
115 }
116 #endif
117 
higmac_hw_set_macaddress(struct higmac_netdev_local * ld,const unsigned char * mac,int len)118 int higmac_hw_set_macaddress(struct higmac_netdev_local *ld, const unsigned char *mac,
119 		  int len)
120 {
121 	unsigned long reg;
122 
123 	if (len < MAC_LEN)
124 		return -1;
125 
126 	reg = mac[1] | (mac[0] << 8); /* mac 0 [8:15], mac 1 [0:7] */
127 	higmac_writel(ld, reg, STATION_ADDR_HIGH);
128 	/* mac 2 [24:31], mac 3 [16:23], mac 4 [8:15], mac 5 [0:7] */
129 	reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24);
130 	higmac_writel(ld, reg, STATION_ADDR_LOW);
131 
132 	return 0;
133 }
134 
higmac_hw_get_macaddress(struct higmac_netdev_local * ld,unsigned char * mac,int len)135 int higmac_hw_get_macaddress(struct higmac_netdev_local *ld, unsigned char *mac,
136 		  int len)
137 {
138 	unsigned long reg;
139 
140 	if (len < MAC_LEN)
141 		return -1;
142 
143 	reg = higmac_readl(ld, STATION_ADDR_HIGH);
144 	mac[0] = (reg >> 8) & 0xff; /* mac[0] [8:15] bit */
145 	mac[1] = reg & 0xff; /* mac[1] [0:7] bit */
146 
147 	reg = higmac_readl(ld, STATION_ADDR_LOW);
148 	mac[2] = (reg >> 24) & 0xff; /* mac[2] [24:31] bit */
149 	mac[3] = (reg >> 16) & 0xff; /* mac[3] [16:23] bit */
150 	mac[4] = (reg >> 8) & 0xff; /* mac[4] [8:15] bit */
151 	mac[5] = reg & 0xff; /* mac[5] [0:7] bit */
152 
153 	return 0;
154 }
155 
_higmac_read_irqstatus(struct higmac_netdev_local * ld)156 static inline int _higmac_read_irqstatus(struct higmac_netdev_local *ld)
157 {
158 	int status;
159 
160 	status = higmac_readl(ld, STATUS_PMU_INT);
161 
162 	return status;
163 }
164 
higmac_clear_irqstatus(struct higmac_netdev_local * ld,int irqs)165 int higmac_clear_irqstatus(struct higmac_netdev_local *ld, int irqs)
166 {
167 	int status;
168 
169 	higmac_writel(ld, irqs, RAW_PMU_INT);
170 	status = _higmac_read_irqstatus(ld);
171 
172 	return status;
173 }
174 
higmac_glb_preinit_dummy(struct higmac_netdev_local * ld)175 int higmac_glb_preinit_dummy(struct higmac_netdev_local *ld)
176 {
177 	/* drop packet enable */
178 	higmac_writel(ld, 0x3F, REC_FILT_CONTROL);
179 	higmac_writel_bits(ld, 0, REC_FILT_CONTROL, BIT_BC_DROP_EN);
180 
181 	/* clear all interrupt status */
182 	higmac_clear_irqstatus(ld, RAW_INT_ALL_MASK);
183 
184 	/* disable interrupts */
185 	higmac_writel(ld, ~RAW_INT_ALL_MASK, ENA_PMU_INT);
186 
187 	return 0;
188 }
189 
190 #if defined(CONFIG_TARGET_HI3531DV200) || defined(CONFIG_TARGET_HI3535AV100)
higmac_external_phy_reset(void)191 void higmac_external_phy_reset(void)
192 {
193 	unsigned int v;
194 
195 #ifdef	HIGAMC_USE_GPIO_RESET_PHY
196 	/* use GPIO0_1 to reset external phy */
197 	/* Set Direction output */
198 	v = readl(HIGMAC_RESET_GPIO_BASE + HIGMAC_RESET_GPIO_DIR_OFS);
199 	v |= HIGMAC_RESET_GPIO_DIR_OUT;
200 	writel(v, HIGMAC_RESET_GPIO_BASE + HIGMAC_RESET_GPIO_DIR_OFS);
201 
202 	/* Set GPIO0_1 to 1 */
203 	writel(HIGMAC_RESET_GPIO_VALUE, HIGMAC_RESET_GPIO_BASE
204 			+ HIGMAC_RESET_GPIO_DATA_OFS);
205 	udelay(50000); /* wait 50000us */
206 	/* Set GPIO0_1=0 to reset phy */
207 	writel(~HIGMAC_RESET_GPIO_VALUE, HIGMAC_RESET_GPIO_BASE
208 			+ HIGMAC_RESET_GPIO_DATA_OFS);
209 	udelay(200000); /* wait 200000us */
210 
211 	/* Set GPIO0_1=1 to cancel reset phy */
212 	writel(HIGMAC_RESET_GPIO_VALUE, HIGMAC_RESET_GPIO_BASE
213 			+ HIGMAC_RESET_GPIO_DATA_OFS);
214 	udelay(50000); /* wait 50000us */
215 #else
216 	/* use CRG register to reset external phy */
217 	v = readl(CRG_REG_BASE + REG_ETH0_PHY_CRG);
218 	v |= BIT_EXT_PHY0_RST; /* reset */
219 	writel(v, CRG_REG_BASE + REG_ETH0_PHY_CRG);
220 #if GMAC_AT_LEAST_2PORT
221 	v = readl(CRG_REG_BASE + REG_ETH1_PHY_CRG);
222 	v |= BIT_EXT_PHY1_RST;
223 	writel(v, CRG_REG_BASE + REG_ETH1_PHY_CRG);
224 #endif
225 
226 	udelay(50 * 1000); /* wait 50 * 1000us for phy reset time */
227 
228 	v = readl(CRG_REG_BASE + REG_ETH0_PHY_CRG);
229 	v &= ~BIT_EXT_PHY0_RST; /* undo reset */
230 	writel(v, CRG_REG_BASE + REG_ETH0_PHY_CRG);
231 #if GMAC_AT_LEAST_2PORT
232 	v = readl(CRG_REG_BASE + REG_ETH1_PHY_CRG);
233 	v &= ~BIT_EXT_PHY1_RST;
234 	writel(v, CRG_REG_BASE + REG_ETH1_PHY_CRG);
235 #endif
236 
237 	udelay(60 * 1000); /* wait 60 * 1000us for future MDIO operation */
238 #endif
239 }
240 
higmac_init_phy(void)241 void higmac_init_phy(void)
242 {
243 	uintptr_t p;
244 	volatile unsigned int v;
245 
246 	p = (unsigned long)(CRG_REG_BASE);
247 
248 	v = readl(p + REG_ETH0_PHY_CRG);
249 
250 	/* phy clk select 25MHz */
251 	v &= ~BIT_EXT_PHY0_CLK_SELECT;
252 	v |= PHY0_CLK_25M;
253 	writel(v, p + REG_ETH0_PHY_CRG);
254 #if GMAC_AT_LEAST_2PORT
255 	v = readl(p + REG_ETH1_PHY_CRG);
256 	v &= ~BIT_EXT_PHY1_CLK_SELECT;
257 	v |= PHY1_CLK_25M;
258 	writel(v, p + REG_ETH1_PHY_CRG);
259 #endif
260 }
261 
higmac_soft_reset_eth(void)262 void higmac_soft_reset_eth(void)
263 {
264 	uintptr_t p;
265 	volatile unsigned int v;
266 
267 	p = (unsigned long)(CRG_REG_BASE);
268 
269 	/* soft reset */
270 	v = readl(p + REG_ETH0_GSF_CRG);
271 	v |= BIT_GMAC0_RST;
272 	writel(v, p + REG_ETH0_GSF_CRG);
273 #if GMAC_AT_LEAST_2PORT
274 	v = readl(p + REG_ETH1_GSF_CRG);
275 	v |= BIT_GMAC1_RST;
276 	writel(v, p + REG_ETH1_GSF_CRG);
277 #endif
278 
279 	udelay(100); /* wait 100us */
280 
281 	v = readl(p + REG_ETH0_GSF_CRG);
282 	v &= ~BIT_GMAC0_RST;
283 	writel(v, p + REG_ETH0_GSF_CRG);
284 #if GMAC_AT_LEAST_2PORT
285 	v = readl(p + REG_ETH1_GSF_CRG);
286 	v &= ~BIT_GMAC1_RST;
287 	writel(v, p + REG_ETH1_GSF_CRG);
288 #endif
289 }
290 
291 
higmac_sys_init(void)292 void higmac_sys_init(void)
293 {
294 	uintptr_t p;
295 	volatile unsigned int v;
296 
297 	p = (unsigned long)(CRG_REG_BASE);
298 
299 	higmac_init_phy();
300 
301 	/* enable clk */
302 	v = readl(p + REG_ETH0_GSF_CRG);
303 	v |= BIT_GMAC0_CLK_EN;
304 	writel(v, p + REG_ETH0_GSF_CRG);
305 
306 	v = readl(p + REG_ETH0_MACIF_CRG);
307 	v |= BIT_GMACIF0_CLK_EN;
308 	writel(v, p + REG_ETH0_MACIF_CRG);
309 
310 #if GMAC_AT_LEAST_2PORT
311 	v = readl(p + REG_ETH1_GSF_CRG);
312 	v |= BIT_GMAC1_CLK_EN;
313 	writel(v, p + REG_ETH1_GSF_CRG);
314 
315 	v = readl(p + REG_ETH1_MACIF_CRG);
316 	v |= BIT_GMACIF1_CLK_EN;
317 	writel(v, p + REG_ETH1_MACIF_CRG);
318 #endif
319 
320 #ifdef CONFIG_HIGMAC_RMII0_CLK_USE_EXTERNAL_PAD
321 	v = readl(p + REG_ETH0_MACIF_CRG);
322 	if (higmac_board_info[0].phy_intf == INTERFACE_MODE_RMII)
323 		v |= BIT_RMII0_CLKSEL_PAD; /* rmii select pad clk */
324 	writel(v, p + REG_ETH0_MACIF_CRG);
325 #endif
326 #if GMAC_AT_LEAST_2PORT
327 #ifdef CONFIG_HIGMAC_RMII1_CLK_USE_EXTERNAL_PAD
328 	v = readl(p + REG_ETH1_MACIF_CRG);
329 	if (higmac_board_info[1].phy_intf == INTERFACE_MODE_RMII)
330 		v |= BIT_RMII1_CLKSEL_PAD; /* rmii select pad clk */
331 	writel(v, p + REG_ETH1_MACIF_CRG);
332 #endif
333 #endif
334 
335 	higmac_soft_reset_eth();
336 
337 	writel(0xe, HIGMAC_DUAL_MAC_CRF_ACK_TH);
338 
339 	higmac_external_phy_reset();
340 }
341 #else
higmac_external_phy_reset(void)342 void higmac_external_phy_reset(void)
343 {
344 	unsigned int v;
345 
346 #ifdef HIGAMC_USE_GPIO_RESET_PHY
347 	/* use GPIO0_1 to reset external phy */
348 	/* Set Direction output */
349 	v = readl(HIGMAC_RESET_GPIO_BASE + HIGMAC_RESET_GPIO_DIR_OFS);
350 	v |= HIGMAC_RESET_GPIO_DIR_OUT;
351 	writel(v, HIGMAC_RESET_GPIO_BASE + HIGMAC_RESET_GPIO_DIR_OFS);
352 
353 	/* Set GPIO0_1 value 1 */
354 	writel(HIGMAC_RESET_GPIO_VALUE, HIGMAC_RESET_GPIO_BASE
355 			+ HIGMAC_RESET_GPIO_DATA_OFS);
356 	udelay(50000); /* wait 50000us */
357 	/* Set GPIO0_1=0 to reset phy */
358 	writel(~HIGMAC_RESET_GPIO_VALUE, HIGMAC_RESET_GPIO_BASE
359 			+ HIGMAC_RESET_GPIO_DATA_OFS);
360 	udelay(200000); /* wait 200000us */
361 
362 	/* Set GPIO0_1=1 to cancel reset phy */
363 	writel(HIGMAC_RESET_GPIO_VALUE, HIGMAC_RESET_GPIO_BASE
364 			+ HIGMAC_RESET_GPIO_DATA_OFS);
365 	udelay(50000); /* wait 50000us */
366 #else
367 	/* use CRG register to reset external phy */
368 	v = readl(CRG_REG_BASE + REG_ETH_CRG);
369 	v |= BIT_EXT_PHY0_RST; /* reset */
370 #if GMAC_AT_LEAST_2PORT
371 	v |= BIT_EXT_PHY1_RST;
372 #endif
373 	writel(v, CRG_REG_BASE + REG_ETH_CRG);
374 
375 	udelay(50 * 1000); /* wait 50 * 1000us for phy reset time */
376 
377 	v = readl(CRG_REG_BASE + REG_ETH_CRG);
378 	v &= ~BIT_EXT_PHY0_RST; /* undo reset */
379 #if GMAC_AT_LEAST_2PORT
380 	v &= ~BIT_EXT_PHY1_RST;
381 #endif
382 	writel(v, CRG_REG_BASE + REG_ETH_CRG);
383 
384 	udelay(60 * 1000); /* wait 60 * 1000us for future MDIO operation */
385 #endif
386 }
387 
higmac_sys_init(void)388 void higmac_sys_init(void)
389 {
390 	unsigned long p;
391 	volatile unsigned int v;
392 
393 	p = (unsigned long)(CRG_REG_BASE);
394 
395 	v = readl((uintptr_t)(p + REG_ETH_CRG));
396 
397 	/* phy clk select 25MHz */
398 	v &= ~BIT_EXT_PHY0_CLK_SELECT;
399 	v |= PHY0_CLK_25M;
400 #if GMAC_AT_LEAST_2PORT
401 	v &= ~BIT_EXT_PHY1_CLK_SELECT;
402 	v |= PHY1_CLK_25M;
403 #endif
404 	/* enable clk */
405 	v |= (BIT_GMAC0_CLK_EN | BIT_GMACIF0_CLK_EN);
406 #if GMAC_AT_LEAST_2PORT
407 	v |= BIT_GSF_PUB_CLK_EN;
408 	v |= (BIT_GMAC1_CLK_EN | BIT_GMACIF1_CLK_EN);
409 #endif
410 
411 #ifdef CONFIG_HIGMAC_RMII0_CLK_USE_EXTERNAL_PAD
412 	if (higmac_board_info[0].phy_intf == INTERFACE_MODE_RMII)
413 		v |= BIT_RMII0_CLKSEL_PAD; /* rmii select pad clk */
414 
415 #endif
416 #if GMAC_AT_LEAST_2PORT
417 #ifdef CONFIG_HIGMAC_RMII1_CLK_USE_EXTERNAL_PAD
418 	if (higmac_board_info[1].phy_intf == INTERFACE_MODE_RMII)
419 		v |= BIT_RMII1_CLKSEL_PAD; /* rmii select pad clk */
420 #endif
421 #endif
422 
423 	writel(v, (uintptr_t)(p + REG_ETH_CRG));
424 
425 	/* soft reset */
426 	v = readl((uintptr_t)(p + REG_ETH_CRG));
427 	v |= BIT_GMAC0_RST;
428 #if GMAC_AT_LEAST_2PORT
429 	v |= BIT_GMAC1_RST;
430 #endif
431 	writel(v, (uintptr_t)(p + REG_ETH_CRG));
432 
433 	udelay(100); /* delay 100us */
434 
435 	v = readl((uintptr_t)(p + REG_ETH_CRG));
436 	v &= ~BIT_GMAC0_RST;
437 #if GMAC_AT_LEAST_2PORT
438 	v &= ~BIT_GMAC1_RST;
439 #endif
440 	writel(v, (uintptr_t)(p + REG_ETH_CRG));
441 
442 	writel(0xe, HIGMAC_DUAL_MAC_CRF_ACK_TH);
443 
444 	higmac_external_phy_reset();
445 }
446 #endif
447 
higmac_sys_exit(void)448 void higmac_sys_exit(void)
449 {
450 }
451 
higmac_sys_allstop(void)452 void higmac_sys_allstop(void)
453 {
454 }
455 
higmac_set_hwq_depth(struct higmac_netdev_local * ld)456 int higmac_set_hwq_depth(struct higmac_netdev_local *ld)
457 {
458 	if (HIGMAC_HWQ_RX_FQ_DEPTH > HIGMAC_MAX_QUEUE_DEPTH) {
459 		BUG();
460 		return -1;
461 	}
462 
463 	higmac_writel_bits(ld, 1, RX_FQ_REG_EN, \
464 		BITS_RX_FQ_DEPTH_EN);
465 
466 	higmac_writel_bits(ld, HIGMAC_HWQ_RX_FQ_DEPTH << DESC_WORD_SHIFT,
467 		RX_FQ_DEPTH, BITS_RX_FQ_DEPTH);
468 
469 	higmac_writel_bits(ld, 0, RX_FQ_REG_EN, \
470 		BITS_RX_FQ_DEPTH_EN);
471 
472 	if (HIGMAC_HWQ_RX_BQ_DEPTH > HIGMAC_MAX_QUEUE_DEPTH) {
473 		BUG();
474 		return -1;
475 	}
476 
477 	higmac_writel_bits(ld, 1, RX_BQ_REG_EN, \
478 		BITS_RX_BQ_DEPTH_EN);
479 
480 	higmac_writel_bits(ld, HIGMAC_HWQ_RX_BQ_DEPTH << DESC_WORD_SHIFT,
481 		RX_BQ_DEPTH, BITS_RX_BQ_DEPTH);
482 
483 	higmac_writel_bits(ld, 0, RX_BQ_REG_EN, \
484 		BITS_RX_BQ_DEPTH_EN);
485 
486 	if (HIGMAC_HWQ_TX_BQ_DEPTH > HIGMAC_MAX_QUEUE_DEPTH) {
487 		BUG();
488 		return -1;
489 	}
490 
491 	higmac_writel_bits(ld, 1, TX_BQ_REG_EN, \
492 		BITS_TX_BQ_DEPTH_EN);
493 
494 	higmac_writel_bits(ld, HIGMAC_HWQ_TX_BQ_DEPTH << DESC_WORD_SHIFT,
495 		TX_BQ_DEPTH, BITS_TX_BQ_DEPTH);
496 
497 	higmac_writel_bits(ld, 0, TX_BQ_REG_EN, \
498 		BITS_TX_BQ_DEPTH_EN);
499 
500 	if (HIGMAC_HWQ_TX_RQ_DEPTH > HIGMAC_MAX_QUEUE_DEPTH) {
501 		BUG();
502 		return -1;
503 	}
504 
505 	higmac_writel_bits(ld, 1, TX_RQ_REG_EN, \
506 		BITS_TX_RQ_DEPTH_EN);
507 
508 	higmac_writel_bits(ld, HIGMAC_HWQ_TX_RQ_DEPTH << DESC_WORD_SHIFT,
509 		TX_RQ_DEPTH, BITS_TX_RQ_DEPTH);
510 
511 	higmac_writel_bits(ld, 0, TX_RQ_REG_EN, \
512 		BITS_TX_RQ_DEPTH_EN);
513 
514 	return 0;
515 }
516 
higmac_set_rx_fq_hwq_addr(struct higmac_netdev_local * ld,phys_addr_t phy_addr)517 int higmac_set_rx_fq_hwq_addr(struct higmac_netdev_local *ld,
518 		  phys_addr_t phy_addr)
519 {
520 	higmac_writel_bits(ld, 1, RX_FQ_REG_EN, \
521 		BITS_RX_FQ_START_ADDR_EN);
522 
523 	higmac_writel(ld, (u32)phy_addr, RX_FQ_START_ADDR);
524 #if defined(CONFIG_64BIT)
525 	higmac_writel_bits(ld, (u32)((u64)phy_addr >> REG_BIT_WIDTH), RX_FQ_DEPTH,
526 		BITS_RX_FQ_ADDR_HI8);
527 #endif
528 
529 	higmac_writel_bits(ld, 0, RX_FQ_REG_EN, \
530 		BITS_RX_FQ_START_ADDR_EN);
531 
532 	return 0;
533 }
534 
higmac_set_rx_bq_hwq_addr(struct higmac_netdev_local * ld,phys_addr_t phy_addr)535 int higmac_set_rx_bq_hwq_addr(struct higmac_netdev_local *ld,
536 		  phys_addr_t phy_addr)
537 {
538 	higmac_writel_bits(ld, 1, RX_BQ_REG_EN, \
539 		BITS_RX_BQ_START_ADDR_EN);
540 
541 	higmac_writel(ld, (u32)phy_addr, RX_BQ_START_ADDR);
542 #if defined(CONFIG_64BIT)
543 	higmac_writel_bits(ld, (u32)((u64)phy_addr >> REG_BIT_WIDTH), RX_BQ_DEPTH,
544 		BITS_RX_BQ_ADDR_HI8);
545 #endif
546 
547 	higmac_writel_bits(ld, 0, RX_BQ_REG_EN, \
548 		BITS_RX_BQ_START_ADDR_EN);
549 
550 	return 0;
551 }
552 
higmac_set_tx_bq_hwq_addr(struct higmac_netdev_local * ld,phys_addr_t phy_addr)553 int higmac_set_tx_bq_hwq_addr(struct higmac_netdev_local *ld,
554 		  phys_addr_t phy_addr)
555 {
556 	higmac_writel_bits(ld, 1, TX_BQ_REG_EN, \
557 		BITS_TX_BQ_START_ADDR_EN);
558 
559 	higmac_writel(ld, (u32)phy_addr, TX_BQ_START_ADDR);
560 #if defined(CONFIG_64BIT)
561 	higmac_writel_bits(ld, (u32)((u64)phy_addr >> REG_BIT_WIDTH), TX_BQ_DEPTH,
562 		BITS_TX_BQ_ADDR_HI8);
563 #endif
564 
565 	higmac_writel_bits(ld, 0, TX_BQ_REG_EN, \
566 		BITS_TX_BQ_START_ADDR_EN);
567 
568 	return 0;
569 }
570 
higmac_set_tx_rq_hwq_addr(struct higmac_netdev_local * ld,phys_addr_t phy_addr)571 int higmac_set_tx_rq_hwq_addr(struct higmac_netdev_local *ld,
572 		  phys_addr_t phy_addr)
573 {
574 	higmac_writel_bits(ld, 1, TX_RQ_REG_EN, \
575 		BITS_TX_RQ_START_ADDR_EN);
576 
577 	higmac_writel(ld, (u32)phy_addr, TX_RQ_START_ADDR);
578 #if defined(CONFIG_64BIT)
579 	higmac_writel_bits(ld, (u32)((u64)phy_addr >> REG_BIT_WIDTH), TX_RQ_DEPTH,
580 		BITS_TX_RQ_ADDR_HI8);
581 #endif
582 
583 	higmac_writel_bits(ld, 0, TX_RQ_REG_EN, \
584 		BITS_TX_RQ_START_ADDR_EN);
585 
586 	return 0;
587 }
588 
higmac_desc_enable(struct higmac_netdev_local * ld,u32 desc_ena)589 void higmac_desc_enable(struct higmac_netdev_local *ld, u32 desc_ena)
590 {
591 	u32 old;
592 
593 	old = higmac_readl(ld, DESC_WR_RD_ENA);
594 	higmac_writel(ld, old | desc_ena, DESC_WR_RD_ENA);
595 }
596 
higmac_desc_disable(struct higmac_netdev_local * ld,u32 desc_dis)597 void higmac_desc_disable(struct higmac_netdev_local *ld, u32 desc_dis)
598 {
599 	u32 old;
600 
601 	old = higmac_readl(ld, DESC_WR_RD_ENA);
602 	higmac_writel(ld, old & (~desc_dis), DESC_WR_RD_ENA);
603 }
604 
higmac_desc_flush(struct higmac_netdev_local * ld)605 void higmac_desc_flush(struct higmac_netdev_local *ld)
606 {
607 	higmac_writel_bits(ld, 1, STOP_CMD, BITS_TX_STOP_EN);
608 	while (higmac_readl_bits(ld, FLUSH_CMD, BITS_TX_FLUSH_FLAG) != 1);
609 	higmac_writel_bits(ld, 1, FLUSH_CMD, BITS_TX_FLUSH_CMD);
610 	while (higmac_readl_bits(ld, FLUSH_CMD, BITS_TX_FLUSH_FLAG) != 0);
611 	higmac_writel_bits(ld, 0, FLUSH_CMD, BITS_TX_FLUSH_CMD);
612 	higmac_writel_bits(ld, 0, STOP_CMD, BITS_TX_STOP_EN);
613 
614 	higmac_writel_bits(ld, 1, STOP_CMD, BITS_RX_STOP_EN);
615 	while (higmac_readl_bits(ld, FLUSH_CMD, BITS_RX_FLUSH_FLAG) != 1);
616 	higmac_writel_bits(ld, 1, FLUSH_CMD, BITS_RX_FLUSH_CMD);
617 	while (higmac_readl_bits(ld, FLUSH_CMD, BITS_RX_FLUSH_FLAG) != 0);
618 	higmac_writel_bits(ld, 0, FLUSH_CMD, BITS_RX_FLUSH_CMD);
619 	higmac_writel_bits(ld, 0, STOP_CMD, BITS_RX_STOP_EN);
620 }
621 
higmac_readl(struct higmac_netdev_local * ld,u32 ofs)622 u32 higmac_readl(struct higmac_netdev_local *ld, u32 ofs)
623 {
624 	u32 reg = readl((uintptr_t)(ld->iobase + ofs));
625 	higmac_trace(HIGMAC_TRACE_ETH, "readl(0x%04X) = 0x%08X", ofs, reg);
626 	return reg;
627 }
628 
higmac_writel(struct higmac_netdev_local * ld,u32 v,u32 ofs)629 void higmac_writel(struct higmac_netdev_local *ld, u32 v, u32 ofs)
630 {
631 	writel(v, (uintptr_t)(ld->iobase + ofs));
632 	higmac_trace(HIGMAC_TRACE_ETH, "writel(0x%04X) = 0x%08X", ofs, v);
633 }
634 
higmac_readl_bits(struct higmac_netdev_local * ld,u32 ofs,u32 bits_desc)635 u32 higmac_readl_bits(struct higmac_netdev_local *ld, u32 ofs, u32 bits_desc)
636 {
637 	u32 _bits_desc = bits_desc;
638 	u32 _shift = _bits_desc >> 16; /* shift 16 bit */
639 	u32 _mask = ((_bits_desc & 0x3F) < 32) ? /* 32bit register */
640 		(((1 << (_bits_desc & 0x3F)) - 1) << _shift) : 0xffffffff;
641 	u32 reg = (higmac_readl(ld, ofs) & _mask) >> _shift;
642 	return reg;
643 }
644 
higmac_writel_bits(struct higmac_netdev_local * ld,u32 v,u32 ofs,u32 bits_desc)645 void higmac_writel_bits(struct higmac_netdev_local *ld, u32 v, u32 ofs, u32 bits_desc)
646 {
647 	u32 _bits_desc = bits_desc;
648 	u32 _shift = _bits_desc >> 16; /* shift 16 bit */
649 	u32 _reg = higmac_readl(ld, ofs);
650 	u32 _mask = ((_bits_desc & 0x3F) < 32) ? /* 32bit register */
651 		(((1 << (_bits_desc & 0x3F)) - 1) << _shift) : 0xffffffff;
652 	higmac_writel(ld, (_reg & (~_mask)) | ((v << _shift) & _mask), ofs);
653 }
654 
higmac_trace(int level,const char * fmt,...)655 void higmac_trace(int level, const char *fmt, ...)
656 {
657 	if (level >= HIGMAC_TRACE_LEVEL) {
658 		va_list args;
659 		va_start(args, fmt);
660 		printf("higmac_trace:");
661 		printf(fmt, args);
662 		printf("\n");
663 		va_end(args);
664 	}
665 }
666 
higmac_error(const char * fmt,...)667 void higmac_error(const char *fmt, ...)
668 {
669 	va_list args;
670 	va_start(args, fmt);
671 	printf("higmac:");
672 	printf(fmt, args);
673 	printf("\n");
674 	va_end(args);
675 }
676 
higmac_assert(bool cond)677 void higmac_assert(bool cond)
678 {
679 	if (!cond)
680 		printf("Assert:higmac:%s:%d\n", __FILE__, __LINE__);
681 }
682