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