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