]>
Commit | Line | Data |
---|---|---|
fc9a8e8d KM |
1 | /* |
2 | * Ethernet driver for TI K2HK EVM. | |
3 | * | |
4 | * (C) Copyright 2012-2014 | |
5 | * Texas Instruments Incorporated, <www.ti.com> | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0+ | |
8 | */ | |
9 | #include <common.h> | |
10 | #include <command.h> | |
11 | ||
12 | #include <net.h> | |
13 | #include <miiphy.h> | |
14 | #include <malloc.h> | |
15 | #include <asm/arch/emac_defs.h> | |
16 | #include <asm/arch/psc_defs.h> | |
ef454717 | 17 | #include <asm/ti-common/keystone_nav.h> |
fc9a8e8d KM |
18 | |
19 | unsigned int emac_dbg; | |
20 | ||
21 | unsigned int emac_open; | |
22 | static unsigned int sys_has_mdio = 1; | |
23 | ||
24 | #ifdef KEYSTONE2_EMAC_GIG_ENABLE | |
25 | #define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x) | |
26 | #else | |
27 | #define emac_gigabit_enable(x) /* no gigabit to enable */ | |
28 | #endif | |
29 | ||
30 | #define RX_BUFF_NUMS 24 | |
31 | #define RX_BUFF_LEN 1520 | |
32 | #define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN | |
33 | ||
34 | static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16); | |
35 | ||
36 | struct rx_buff_desc net_rx_buffs = { | |
37 | .buff_ptr = rx_buffs, | |
38 | .num_buffs = RX_BUFF_NUMS, | |
39 | .buff_len = RX_BUFF_LEN, | |
40 | .rx_flow = 22, | |
41 | }; | |
42 | ||
43 | static void keystone2_eth_mdio_enable(void); | |
44 | ||
45 | static int gen_get_link_speed(int phy_addr); | |
46 | ||
47 | /* EMAC Addresses */ | |
fc9a8e8d KM |
48 | static volatile struct mdio_regs *adap_mdio = |
49 | (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; | |
50 | ||
51 | int keystone2_eth_read_mac_addr(struct eth_device *dev) | |
52 | { | |
53 | struct eth_priv_t *eth_priv; | |
54 | u32 maca = 0; | |
55 | u32 macb = 0; | |
56 | ||
57 | eth_priv = (struct eth_priv_t *)dev->priv; | |
58 | ||
59 | /* Read the e-fuse mac address */ | |
60 | if (eth_priv->slave_port == 1) { | |
61 | maca = __raw_readl(MAC_ID_BASE_ADDR); | |
62 | macb = __raw_readl(MAC_ID_BASE_ADDR + 4); | |
63 | } | |
64 | ||
65 | dev->enetaddr[0] = (macb >> 8) & 0xff; | |
66 | dev->enetaddr[1] = (macb >> 0) & 0xff; | |
67 | dev->enetaddr[2] = (maca >> 24) & 0xff; | |
68 | dev->enetaddr[3] = (maca >> 16) & 0xff; | |
69 | dev->enetaddr[4] = (maca >> 8) & 0xff; | |
70 | dev->enetaddr[5] = (maca >> 0) & 0xff; | |
71 | ||
72 | return 0; | |
73 | } | |
74 | ||
75 | static void keystone2_eth_mdio_enable(void) | |
76 | { | |
77 | u_int32_t clkdiv; | |
78 | ||
79 | clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; | |
80 | ||
81 | writel((clkdiv & 0xffff) | | |
82 | MDIO_CONTROL_ENABLE | | |
83 | MDIO_CONTROL_FAULT | | |
84 | MDIO_CONTROL_FAULT_ENABLE, | |
85 | &adap_mdio->control); | |
86 | ||
87 | while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE) | |
88 | ; | |
89 | } | |
90 | ||
91 | /* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ | |
92 | int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) | |
93 | { | |
94 | int tmp; | |
95 | ||
96 | while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) | |
97 | ; | |
98 | ||
99 | writel(MDIO_USERACCESS0_GO | | |
100 | MDIO_USERACCESS0_WRITE_READ | | |
101 | ((reg_num & 0x1f) << 21) | | |
102 | ((phy_addr & 0x1f) << 16), | |
103 | &adap_mdio->useraccess0); | |
104 | ||
105 | /* Wait for command to complete */ | |
106 | while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO) | |
107 | ; | |
108 | ||
109 | if (tmp & MDIO_USERACCESS0_ACK) { | |
110 | *data = tmp & 0xffff; | |
111 | return 0; | |
112 | } | |
113 | ||
114 | *data = -1; | |
115 | return -1; | |
116 | } | |
117 | ||
118 | /* | |
119 | * Write to a PHY register via MDIO inteface. | |
120 | * Blocks until operation is complete. | |
121 | */ | |
122 | int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) | |
123 | { | |
124 | while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) | |
125 | ; | |
126 | ||
127 | writel(MDIO_USERACCESS0_GO | | |
128 | MDIO_USERACCESS0_WRITE_WRITE | | |
129 | ((reg_num & 0x1f) << 21) | | |
130 | ((phy_addr & 0x1f) << 16) | | |
131 | (data & 0xffff), | |
132 | &adap_mdio->useraccess0); | |
133 | ||
134 | /* Wait for command to complete */ | |
135 | while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) | |
136 | ; | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
141 | /* PHY functions for a generic PHY */ | |
142 | static int gen_get_link_speed(int phy_addr) | |
143 | { | |
144 | u_int16_t tmp; | |
145 | ||
146 | if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) && | |
147 | (tmp & 0x04)) { | |
148 | return 0; | |
149 | } | |
150 | ||
151 | return -1; | |
152 | } | |
153 | ||
154 | static void __attribute__((unused)) | |
155 | keystone2_eth_gigabit_enable(struct eth_device *dev) | |
156 | { | |
157 | u_int16_t data; | |
158 | struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; | |
159 | ||
160 | if (sys_has_mdio) { | |
161 | if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) || | |
162 | !(data & (1 << 6))) /* speed selection MSB */ | |
163 | return; | |
164 | } | |
165 | ||
166 | /* | |
167 | * Check if link detected is giga-bit | |
168 | * If Gigabit mode detected, enable gigbit in MAC | |
169 | */ | |
b2cfe322 HZ |
170 | writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + |
171 | CPGMACSL_REG_CTL) | | |
fc9a8e8d | 172 | EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, |
b2cfe322 | 173 | DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL); |
fc9a8e8d KM |
174 | } |
175 | ||
176 | int keystone_sgmii_link_status(int port) | |
177 | { | |
178 | u32 status = 0; | |
179 | ||
180 | status = __raw_readl(SGMII_STATUS_REG(port)); | |
181 | ||
182 | return status & SGMII_REG_STATUS_LINK; | |
183 | } | |
184 | ||
185 | ||
186 | int keystone_get_link_status(struct eth_device *dev) | |
187 | { | |
188 | struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; | |
189 | int sgmii_link; | |
190 | int link_state = 0; | |
191 | #if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1 | |
192 | int j; | |
193 | ||
194 | for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0); | |
195 | j++) { | |
196 | #endif | |
197 | sgmii_link = | |
198 | keystone_sgmii_link_status(eth_priv->slave_port - 1); | |
199 | ||
200 | if (sgmii_link) { | |
201 | link_state = 1; | |
202 | ||
203 | if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) | |
204 | if (gen_get_link_speed(eth_priv->phy_addr)) | |
205 | link_state = 0; | |
206 | } | |
207 | #if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1 | |
208 | } | |
209 | #endif | |
210 | return link_state; | |
211 | } | |
212 | ||
213 | int keystone_sgmii_config(int port, int interface) | |
214 | { | |
215 | unsigned int i, status, mask; | |
216 | unsigned int mr_adv_ability, control; | |
217 | ||
218 | switch (interface) { | |
219 | case SGMII_LINK_MAC_MAC_AUTONEG: | |
220 | mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | | |
221 | SGMII_REG_MR_ADV_LINK | | |
222 | SGMII_REG_MR_ADV_FULL_DUPLEX | | |
223 | SGMII_REG_MR_ADV_GIG_MODE); | |
224 | control = (SGMII_REG_CONTROL_MASTER | | |
225 | SGMII_REG_CONTROL_AUTONEG); | |
226 | ||
227 | break; | |
228 | case SGMII_LINK_MAC_PHY: | |
229 | case SGMII_LINK_MAC_PHY_FORCED: | |
230 | mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; | |
231 | control = SGMII_REG_CONTROL_AUTONEG; | |
232 | ||
233 | break; | |
234 | case SGMII_LINK_MAC_MAC_FORCED: | |
235 | mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | | |
236 | SGMII_REG_MR_ADV_LINK | | |
237 | SGMII_REG_MR_ADV_FULL_DUPLEX | | |
238 | SGMII_REG_MR_ADV_GIG_MODE); | |
239 | control = SGMII_REG_CONTROL_MASTER; | |
240 | ||
241 | break; | |
242 | case SGMII_LINK_MAC_FIBER: | |
243 | mr_adv_ability = 0x20; | |
244 | control = SGMII_REG_CONTROL_AUTONEG; | |
245 | ||
246 | break; | |
247 | default: | |
248 | mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; | |
249 | control = SGMII_REG_CONTROL_AUTONEG; | |
250 | } | |
251 | ||
252 | __raw_writel(0, SGMII_CTL_REG(port)); | |
253 | ||
254 | /* | |
255 | * Wait for the SerDes pll to lock, | |
256 | * but don't trap if lock is never read | |
257 | */ | |
258 | for (i = 0; i < 1000; i++) { | |
259 | udelay(2000); | |
260 | status = __raw_readl(SGMII_STATUS_REG(port)); | |
261 | if ((status & SGMII_REG_STATUS_LOCK) != 0) | |
262 | break; | |
263 | } | |
264 | ||
265 | __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port)); | |
266 | __raw_writel(control, SGMII_CTL_REG(port)); | |
267 | ||
268 | ||
269 | mask = SGMII_REG_STATUS_LINK; | |
270 | ||
271 | if (control & SGMII_REG_CONTROL_AUTONEG) | |
272 | mask |= SGMII_REG_STATUS_AUTONEG; | |
273 | ||
274 | for (i = 0; i < 1000; i++) { | |
275 | status = __raw_readl(SGMII_STATUS_REG(port)); | |
276 | if ((status & mask) == mask) | |
277 | break; | |
278 | } | |
279 | ||
280 | return 0; | |
281 | } | |
282 | ||
283 | int mac_sl_reset(u32 port) | |
284 | { | |
285 | u32 i, v; | |
286 | ||
287 | if (port >= DEVICE_N_GMACSL_PORTS) | |
288 | return GMACSL_RET_INVALID_PORT; | |
289 | ||
290 | /* Set the soft reset bit */ | |
e6c9428a KI |
291 | writel(CPGMAC_REG_RESET_VAL_RESET, |
292 | DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); | |
fc9a8e8d KM |
293 | |
294 | /* Wait for the bit to clear */ | |
295 | for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { | |
e6c9428a | 296 | v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); |
fc9a8e8d KM |
297 | if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != |
298 | CPGMAC_REG_RESET_VAL_RESET) | |
299 | return GMACSL_RET_OK; | |
300 | } | |
301 | ||
302 | /* Timeout on the reset */ | |
303 | return GMACSL_RET_WARN_RESET_INCOMPLETE; | |
304 | } | |
305 | ||
306 | int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) | |
307 | { | |
308 | u32 v, i; | |
309 | int ret = GMACSL_RET_OK; | |
310 | ||
311 | if (port >= DEVICE_N_GMACSL_PORTS) | |
312 | return GMACSL_RET_INVALID_PORT; | |
313 | ||
314 | if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) { | |
315 | cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN; | |
316 | ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG; | |
317 | } | |
318 | ||
319 | /* Must wait if the device is undergoing reset */ | |
320 | for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { | |
e6c9428a | 321 | v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); |
fc9a8e8d KM |
322 | if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != |
323 | CPGMAC_REG_RESET_VAL_RESET) | |
324 | break; | |
325 | } | |
326 | ||
327 | if (i == DEVICE_EMACSL_RESET_POLL_COUNT) | |
328 | return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE; | |
329 | ||
e6c9428a KI |
330 | writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); |
331 | writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); | |
fc9a8e8d KM |
332 | |
333 | return ret; | |
334 | } | |
335 | ||
336 | int ethss_config(u32 ctl, u32 max_pkt_size) | |
337 | { | |
338 | u32 i; | |
339 | ||
340 | /* Max length register */ | |
e6c9428a | 341 | writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN); |
fc9a8e8d KM |
342 | |
343 | /* Control register */ | |
e6c9428a | 344 | writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL); |
fc9a8e8d KM |
345 | |
346 | /* All statistics enabled by default */ | |
e6c9428a KI |
347 | writel(CPSW_REG_VAL_STAT_ENABLE_ALL, |
348 | DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN); | |
fc9a8e8d KM |
349 | |
350 | /* Reset and enable the ALE */ | |
e6c9428a KI |
351 | writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | |
352 | CPSW_REG_VAL_ALE_CTL_BYPASS, | |
353 | DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL); | |
fc9a8e8d KM |
354 | |
355 | /* All ports put into forward mode */ | |
356 | for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++) | |
e6c9428a KI |
357 | writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE, |
358 | DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)); | |
fc9a8e8d KM |
359 | |
360 | return 0; | |
361 | } | |
362 | ||
363 | int ethss_start(void) | |
364 | { | |
365 | int i; | |
366 | struct mac_sl_cfg cfg; | |
367 | ||
368 | cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER; | |
369 | cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL; | |
370 | ||
371 | for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) { | |
372 | mac_sl_reset(i); | |
373 | mac_sl_config(i, &cfg); | |
374 | } | |
375 | ||
376 | return 0; | |
377 | } | |
378 | ||
379 | int ethss_stop(void) | |
380 | { | |
381 | int i; | |
382 | ||
383 | for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) | |
384 | mac_sl_reset(i); | |
385 | ||
386 | return 0; | |
387 | } | |
388 | ||
389 | int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) | |
390 | { | |
391 | if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) | |
392 | num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE; | |
393 | ||
9ea9021a KI |
394 | return ksnav_send(&netcp_pktdma, buffer, |
395 | num_bytes, (slave_port_num) << 16); | |
fc9a8e8d KM |
396 | } |
397 | ||
398 | /* Eth device open */ | |
399 | static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) | |
400 | { | |
401 | u_int32_t clkdiv; | |
402 | int link; | |
403 | struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; | |
404 | ||
405 | debug("+ emac_open\n"); | |
406 | ||
407 | net_rx_buffs.rx_flow = eth_priv->rx_flow; | |
408 | ||
409 | sys_has_mdio = | |
410 | (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; | |
411 | ||
412 | psc_enable_module(KS2_LPSC_PA); | |
413 | psc_enable_module(KS2_LPSC_CPGMAC); | |
414 | ||
415 | sgmii_serdes_setup_156p25mhz(); | |
416 | ||
417 | if (sys_has_mdio) | |
418 | keystone2_eth_mdio_enable(); | |
419 | ||
420 | keystone_sgmii_config(eth_priv->slave_port - 1, | |
421 | eth_priv->sgmii_link_type); | |
422 | ||
423 | udelay(10000); | |
424 | ||
425 | /* On chip switch configuration */ | |
426 | ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); | |
427 | ||
428 | /* TODO: add error handling code */ | |
429 | if (qm_init()) { | |
430 | printf("ERROR: qm_init()\n"); | |
431 | return -1; | |
432 | } | |
9ea9021a | 433 | if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) { |
fc9a8e8d KM |
434 | qm_close(); |
435 | printf("ERROR: netcp_init()\n"); | |
436 | return -1; | |
437 | } | |
438 | ||
439 | /* | |
440 | * Streaming switch configuration. If not present this | |
441 | * statement is defined to void in target.h. | |
442 | * If present this is usually defined to a series of register writes | |
443 | */ | |
444 | hw_config_streaming_switch(); | |
445 | ||
446 | if (sys_has_mdio) { | |
447 | /* Init MDIO & get link state */ | |
448 | clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; | |
449 | writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | | |
450 | MDIO_CONTROL_FAULT, &adap_mdio->control) | |
451 | ; | |
452 | ||
453 | /* We need to wait for MDIO to start */ | |
454 | udelay(1000); | |
455 | ||
456 | link = keystone_get_link_status(dev); | |
457 | if (link == 0) { | |
9ea9021a | 458 | ksnav_close(&netcp_pktdma); |
fc9a8e8d KM |
459 | qm_close(); |
460 | return -1; | |
461 | } | |
462 | } | |
463 | ||
464 | emac_gigabit_enable(dev); | |
465 | ||
466 | ethss_start(); | |
467 | ||
468 | debug("- emac_open\n"); | |
469 | ||
470 | emac_open = 1; | |
471 | ||
472 | return 0; | |
473 | } | |
474 | ||
475 | /* Eth device close */ | |
476 | void keystone2_eth_close(struct eth_device *dev) | |
477 | { | |
478 | debug("+ emac_close\n"); | |
479 | ||
480 | if (!emac_open) | |
481 | return; | |
482 | ||
483 | ethss_stop(); | |
484 | ||
9ea9021a | 485 | ksnav_close(&netcp_pktdma); |
fc9a8e8d KM |
486 | qm_close(); |
487 | ||
488 | emac_open = 0; | |
489 | ||
490 | debug("- emac_close\n"); | |
491 | } | |
492 | ||
493 | static int tx_send_loop; | |
494 | ||
495 | /* | |
496 | * This function sends a single packet on the network and returns | |
497 | * positive number (number of bytes transmitted) or negative for error | |
498 | */ | |
499 | static int keystone2_eth_send_packet(struct eth_device *dev, | |
500 | void *packet, int length) | |
501 | { | |
502 | int ret_status = -1; | |
503 | struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; | |
504 | ||
505 | tx_send_loop = 0; | |
506 | ||
507 | if (keystone_get_link_status(dev) == 0) | |
508 | return -1; | |
509 | ||
510 | emac_gigabit_enable(dev); | |
511 | ||
512 | if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) | |
513 | return ret_status; | |
514 | ||
515 | if (keystone_get_link_status(dev) == 0) | |
516 | return -1; | |
517 | ||
518 | emac_gigabit_enable(dev); | |
519 | ||
520 | return length; | |
521 | } | |
522 | ||
523 | /* | |
524 | * This function handles receipt of a packet from the network | |
525 | */ | |
526 | static int keystone2_eth_rcv_packet(struct eth_device *dev) | |
527 | { | |
528 | void *hd; | |
529 | int pkt_size; | |
530 | u32 *pkt; | |
531 | ||
9ea9021a | 532 | hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size); |
fc9a8e8d KM |
533 | if (hd == NULL) |
534 | return 0; | |
535 | ||
536 | NetReceive((uchar *)pkt, pkt_size); | |
537 | ||
9ea9021a | 538 | ksnav_release_rxhd(&netcp_pktdma, hd); |
fc9a8e8d KM |
539 | |
540 | return pkt_size; | |
541 | } | |
542 | ||
543 | /* | |
544 | * This function initializes the EMAC hardware. | |
545 | */ | |
546 | int keystone2_emac_initialize(struct eth_priv_t *eth_priv) | |
547 | { | |
548 | struct eth_device *dev; | |
549 | ||
550 | dev = malloc(sizeof(struct eth_device)); | |
551 | if (dev == NULL) | |
552 | return -1; | |
553 | ||
554 | memset(dev, 0, sizeof(struct eth_device)); | |
555 | ||
556 | strcpy(dev->name, eth_priv->int_name); | |
557 | dev->priv = eth_priv; | |
558 | ||
559 | keystone2_eth_read_mac_addr(dev); | |
560 | ||
561 | dev->iobase = 0; | |
562 | dev->init = keystone2_eth_open; | |
563 | dev->halt = keystone2_eth_close; | |
564 | dev->send = keystone2_eth_send_packet; | |
565 | dev->recv = keystone2_eth_rcv_packet; | |
566 | ||
567 | eth_register(dev); | |
568 | ||
569 | return 0; | |
570 | } | |
571 | ||
572 | void sgmii_serdes_setup_156p25mhz(void) | |
573 | { | |
574 | unsigned int cnt; | |
575 | ||
576 | /* | |
577 | * configure Serializer/Deserializer (SerDes) hardware. SerDes IP | |
578 | * hardware vendor published only register addresses and their values | |
579 | * to be used for configuring SerDes. So had to use hardcoded values | |
580 | * below. | |
581 | */ | |
582 | clrsetbits_le32(0x0232a000, 0xffff0000, 0x00800000); | |
583 | clrsetbits_le32(0x0232a014, 0x0000ffff, 0x00008282); | |
584 | clrsetbits_le32(0x0232a060, 0x00ffffff, 0x00142438); | |
585 | clrsetbits_le32(0x0232a064, 0x00ffff00, 0x00c3c700); | |
586 | clrsetbits_le32(0x0232a078, 0x0000ff00, 0x0000c000); | |
587 | ||
588 | clrsetbits_le32(0x0232a204, 0xff0000ff, 0x38000080); | |
589 | clrsetbits_le32(0x0232a208, 0x000000ff, 0x00000000); | |
590 | clrsetbits_le32(0x0232a20c, 0xff000000, 0x02000000); | |
591 | clrsetbits_le32(0x0232a210, 0xff000000, 0x1b000000); | |
592 | clrsetbits_le32(0x0232a214, 0x0000ffff, 0x00006fb8); | |
593 | clrsetbits_le32(0x0232a218, 0xffff00ff, 0x758000e4); | |
594 | clrsetbits_le32(0x0232a2ac, 0x0000ff00, 0x00004400); | |
595 | clrsetbits_le32(0x0232a22c, 0x00ffff00, 0x00200800); | |
596 | clrsetbits_le32(0x0232a280, 0x00ff00ff, 0x00820082); | |
597 | clrsetbits_le32(0x0232a284, 0xffffffff, 0x1d0f0385); | |
598 | ||
599 | clrsetbits_le32(0x0232a404, 0xff0000ff, 0x38000080); | |
600 | clrsetbits_le32(0x0232a408, 0x000000ff, 0x00000000); | |
601 | clrsetbits_le32(0x0232a40c, 0xff000000, 0x02000000); | |
602 | clrsetbits_le32(0x0232a410, 0xff000000, 0x1b000000); | |
603 | clrsetbits_le32(0x0232a414, 0x0000ffff, 0x00006fb8); | |
604 | clrsetbits_le32(0x0232a418, 0xffff00ff, 0x758000e4); | |
605 | clrsetbits_le32(0x0232a4ac, 0x0000ff00, 0x00004400); | |
606 | clrsetbits_le32(0x0232a42c, 0x00ffff00, 0x00200800); | |
607 | clrsetbits_le32(0x0232a480, 0x00ff00ff, 0x00820082); | |
608 | clrsetbits_le32(0x0232a484, 0xffffffff, 0x1d0f0385); | |
609 | ||
610 | clrsetbits_le32(0x0232a604, 0xff0000ff, 0x38000080); | |
611 | clrsetbits_le32(0x0232a608, 0x000000ff, 0x00000000); | |
612 | clrsetbits_le32(0x0232a60c, 0xff000000, 0x02000000); | |
613 | clrsetbits_le32(0x0232a610, 0xff000000, 0x1b000000); | |
614 | clrsetbits_le32(0x0232a614, 0x0000ffff, 0x00006fb8); | |
615 | clrsetbits_le32(0x0232a618, 0xffff00ff, 0x758000e4); | |
616 | clrsetbits_le32(0x0232a6ac, 0x0000ff00, 0x00004400); | |
617 | clrsetbits_le32(0x0232a62c, 0x00ffff00, 0x00200800); | |
618 | clrsetbits_le32(0x0232a680, 0x00ff00ff, 0x00820082); | |
619 | clrsetbits_le32(0x0232a684, 0xffffffff, 0x1d0f0385); | |
620 | ||
621 | clrsetbits_le32(0x0232a804, 0xff0000ff, 0x38000080); | |
622 | clrsetbits_le32(0x0232a808, 0x000000ff, 0x00000000); | |
623 | clrsetbits_le32(0x0232a80c, 0xff000000, 0x02000000); | |
624 | clrsetbits_le32(0x0232a810, 0xff000000, 0x1b000000); | |
625 | clrsetbits_le32(0x0232a814, 0x0000ffff, 0x00006fb8); | |
626 | clrsetbits_le32(0x0232a818, 0xffff00ff, 0x758000e4); | |
627 | clrsetbits_le32(0x0232a8ac, 0x0000ff00, 0x00004400); | |
628 | clrsetbits_le32(0x0232a82c, 0x00ffff00, 0x00200800); | |
629 | clrsetbits_le32(0x0232a880, 0x00ff00ff, 0x00820082); | |
630 | clrsetbits_le32(0x0232a884, 0xffffffff, 0x1d0f0385); | |
631 | ||
632 | clrsetbits_le32(0x0232aa00, 0x0000ff00, 0x00000800); | |
633 | clrsetbits_le32(0x0232aa08, 0xffff0000, 0x38a20000); | |
634 | clrsetbits_le32(0x0232aa30, 0x00ffff00, 0x008a8a00); | |
635 | clrsetbits_le32(0x0232aa84, 0x0000ff00, 0x00000600); | |
636 | clrsetbits_le32(0x0232aa94, 0xff000000, 0x10000000); | |
637 | clrsetbits_le32(0x0232aaa0, 0xff000000, 0x81000000); | |
638 | clrsetbits_le32(0x0232aabc, 0xff000000, 0xff000000); | |
639 | clrsetbits_le32(0x0232aac0, 0x000000ff, 0x0000008b); | |
640 | clrsetbits_le32(0x0232ab08, 0xffff0000, 0x583f0000); | |
641 | clrsetbits_le32(0x0232ab0c, 0x000000ff, 0x0000004e); | |
642 | clrsetbits_le32(0x0232a000, 0x000000ff, 0x00000003); | |
643 | clrsetbits_le32(0x0232aa00, 0x000000ff, 0x0000005f); | |
644 | ||
645 | clrsetbits_le32(0x0232aa48, 0x00ffff00, 0x00fd8c00); | |
646 | clrsetbits_le32(0x0232aa54, 0x00ffffff, 0x002fec72); | |
647 | clrsetbits_le32(0x0232aa58, 0xffffff00, 0x00f92100); | |
648 | clrsetbits_le32(0x0232aa5c, 0xffffffff, 0x00040060); | |
649 | clrsetbits_le32(0x0232aa60, 0xffffffff, 0x00008000); | |
650 | clrsetbits_le32(0x0232aa64, 0xffffffff, 0x0c581220); | |
651 | clrsetbits_le32(0x0232aa68, 0xffffffff, 0xe13b0602); | |
652 | clrsetbits_le32(0x0232aa6c, 0xffffffff, 0xb8074cc1); | |
653 | clrsetbits_le32(0x0232aa70, 0xffffffff, 0x3f02e989); | |
654 | clrsetbits_le32(0x0232aa74, 0x000000ff, 0x00000001); | |
655 | clrsetbits_le32(0x0232ab20, 0x00ff0000, 0x00370000); | |
656 | clrsetbits_le32(0x0232ab1c, 0xff000000, 0x37000000); | |
657 | clrsetbits_le32(0x0232ab20, 0x000000ff, 0x0000005d); | |
658 | ||
659 | /*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/ | |
660 | clrbits_le32(0x0232a010, 1 << 28); | |
661 | ||
662 | /* Enable TX and RX via the LANExCTL_STS 0x0000 + x*4 */ | |
663 | clrbits_le32(0x0232a228, 1 << 29); | |
664 | writel(0xF800F8C0, 0x0232bfe0); | |
665 | clrbits_le32(0x0232a428, 1 << 29); | |
666 | writel(0xF800F8C0, 0x0232bfe4); | |
667 | clrbits_le32(0x0232a628, 1 << 29); | |
668 | writel(0xF800F8C0, 0x0232bfe8); | |
669 | clrbits_le32(0x0232a828, 1 << 29); | |
670 | writel(0xF800F8C0, 0x0232bfec); | |
671 | ||
672 | /*Enable pll via the pll_ctrl 0x0014*/ | |
673 | writel(0xe0000000, 0x0232bff4) | |
674 | ; | |
675 | ||
676 | /*Waiting for SGMII Serdes PLL lock.*/ | |
677 | for (cnt = 10000; cnt > 0 && ((readl(0x02090114) & 0x10) == 0); cnt--) | |
678 | ; | |
679 | ||
680 | for (cnt = 10000; cnt > 0 && ((readl(0x02090214) & 0x10) == 0); cnt--) | |
681 | ; | |
682 | ||
683 | for (cnt = 10000; cnt > 0 && ((readl(0x02090414) & 0x10) == 0); cnt--) | |
684 | ; | |
685 | ||
686 | for (cnt = 10000; cnt > 0 && ((readl(0x02090514) & 0x10) == 0); cnt--) | |
687 | ; | |
688 | ||
689 | udelay(45000); | |
690 | } | |
691 | ||
692 | void sgmii_serdes_shutdown(void) | |
693 | { | |
694 | /* | |
695 | * shutdown SerDes hardware. SerDes hardware vendor published only | |
696 | * register addresses and their values. So had to use hardcoded | |
697 | * values below. | |
698 | */ | |
699 | clrbits_le32(0x0232bfe0, 3 << 29 | 3 << 13); | |
700 | setbits_le32(0x02320228, 1 << 29); | |
701 | clrbits_le32(0x0232bfe4, 3 << 29 | 3 << 13); | |
702 | setbits_le32(0x02320428, 1 << 29); | |
703 | clrbits_le32(0x0232bfe8, 3 << 29 | 3 << 13); | |
704 | setbits_le32(0x02320628, 1 << 29); | |
705 | clrbits_le32(0x0232bfec, 3 << 29 | 3 << 13); | |
706 | setbits_le32(0x02320828, 1 << 29); | |
707 | ||
708 | clrbits_le32(0x02320034, 3 << 29); | |
709 | setbits_le32(0x02320010, 1 << 28); | |
710 | } |