7 #include <asm/addrspace.h>
9 #include "ar7240_soc.h"
11 #include "ag7240_phy.h"
13 #if (CONFIG_COMMANDS & CFG_CMD_MII)
16 #define _1000BASET 1000
21 #define ag7240_unit2mac(_unit) ag7240_macs[(_unit)]
22 #define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(1) : ag7240_unit2mac(0)
23 #define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
25 uint16_t ag7240_miiphy_read(char *devname, uint32_t phaddr, uint8_t reg);
27 void ag7240_miiphy_write(char *devname, uint32_t phaddr, uint8_t reg, uint16_t data);
29 ag7240_mac_t *ag7240_macs[CFG_AG7240_NMACS];
31 extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);
33 extern int athrs26_phy_setup(int unit);
34 extern int athrs26_phy_is_up(int unit);
35 extern int athrs26_phy_is_fdx(int unit);
36 extern int athrs26_phy_speed(int unit);
37 extern void athrs26_reg_init(void);
38 extern void athrs26_reg_init_lan(void);
39 extern int athrs26_mdc_check(void);
42 extern int athr_phy_setup(int unit);
43 extern int athr_phy_is_up(int unit);
44 extern int athr_phy_is_fdx(int unit);
45 extern int athr_phy_speed(int unit);
46 extern void athr_reg_init(void);
49 //#define AG7240_DEBUG
51 static int ag7240_send(struct eth_device *dev, volatile void *packet, int length) {
54 ag7240_mac_t *mac = (ag7240_mac_t *) dev->priv;
56 ag7240_desc_t *f = mac->fifo_tx[mac->next_tx];
60 f->pkt_start_addr = virt_to_phys(packet);
62 ag7240_tx_give_to_dma(f);
63 flush_cache((u32) packet, length);
64 ag7240_reg_wr(mac, AG7240_DMA_TX_DESC, virt_to_phys(f));
65 ag7240_reg_wr(mac, AG7240_DMA_TX_CTRL, AG7240_TXE);
67 for (i = 0; i < MAX_WAIT; i++) {
69 if (!ag7240_tx_owned_by_dma(f))
74 printf("Tx Timed out\n");
77 f->pkt_start_addr = 0;
80 if (++mac->next_tx >= NO_OF_TX_FIFOS) {
87 static int ag7240_recv(struct eth_device *dev) {
92 mac = (ag7240_mac_t *) dev->priv;
95 f = mac->fifo_rx[mac->next_rx];
97 if (ag7240_rx_owned_by_dma(f)) {
101 length = f->pkt_size;
103 NetReceive(NetRxPackets[mac->next_rx], length - 4);
104 flush_cache((u32) NetRxPackets[mac->next_rx], PKTSIZE_ALIGN);
106 ag7240_rx_give_to_dma(f);
108 if (++mac->next_rx >= NO_OF_RX_FIFOS) {
113 if (!(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))) {
114 ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(f));
115 ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 1);
122 * Called in ag7240_hw_start() function
124 void ag7240_mii_setup(ag7240_mac_t *mac) {
126 u32 cpu_freq, ddr_freq, ahb_freq;
129 #ifdef CFG_ATHRS27_PHY
131 printf("WASP ----> S27 PHY \n");
133 ar7240_reg_wr(0xb8050024, 0x271); // 25MHz ref clock
134 //ar7240_reg_wr(0xb8050024, 0x570); // 40MHz ref clock
135 ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
136 ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
141 #ifdef CONFIG_AR7242_S16_PHY
143 printf("WASP ----> S16 PHY *\n");
145 if(mac->mac_unit == 0)
146 ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
148 ar7240_reg_rmw_clear(AG7240_ETH_SWITCH_CLK_SPARE, (1 << 6));
149 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
150 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
156 #ifdef CONFIG_F1E_PHY
158 printf("WASP ----> F1 PHY *\n");
160 if(mac->mac_unit == 0)
161 ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
163 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
164 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
170 if ((ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK) == AR7240_REV_1_2) {
172 if (mac->mac_unit == 0) {
173 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
174 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
177 ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
179 switch (ahb_freq / 1000000) {
198 if ((is_ar7241() || is_ar7242())) {
200 /* External MII mode */
201 if (mac->mac_unit == 0 && is_ar7242()) {
203 ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
204 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
205 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
209 ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
210 ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
211 printf("Virian MDC CFG Value ==> %x\n", mgmt_cfg_val);
213 } else if (is_ar933x()) {
214 //GE0 receives Rx/Tx clock, and use S26 phy
215 ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_MII_GE0_SLAVE);
217 if (mac->mac_unit == 1) {
219 while (check_cnt++ < 10) {
220 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
221 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
222 #ifdef CFG_ATHRS26_PHY
223 if (athrs26_mdc_check() == 0) {
228 if (check_cnt == 11) {
229 printf("%s: MDC check failed\n", __func__);
232 } else { /* Python 1.0 & 1.1 */
233 if (mac->mac_unit == 0) {
235 while (check_cnt++ < 10) {
236 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
237 ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
238 #ifdef CFG_ATHRS26_PHY
239 if (athrs26_mdc_check() == 0) {
244 if (check_cnt == 11) {
245 printf("%s: MDC check failed\n", __func__);
253 static void ag7240_hw_start(ag7240_mac_t *mac) {
256 ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN | AG7240_MAC_CFG1_TX_EN));
257 ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN | AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_1000));
259 ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN | AG7240_MAC_CFG1_TX_EN));
260 ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN | AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_10_100));
263 ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_0, 0x1f00);
264 ag7240_mii_setup(mac);
266 ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);
267 ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);
269 ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);
271 // TODO: check this register
273 * When enable the web failsafe mode in uboot,you can't drop the broadcast
274 * frames now,the PC first will tx a ARP request packet, it's a broadcast packet.
276 ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x66b82);
278 * Setting Drop CRC Errors, Pause Frames, Length Error frames
279 * and Multi/Broad cast frames.
281 //ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x7eccf);
284 ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_3, 0x1f00140);
285 //printf("cfg1:\t%#x\ncfg2:\t%#x\n", ag7240_reg_rd(mac, AG7240_MAC_CFG1), ag7240_reg_rd(mac, AG7240_MAC_CFG2));
288 static int ag7240_check_link(ag7240_mac_t *mac) {
289 int link = 0, duplex = 0, speed = 0;
294 ag7240_phy_link(mac->mac_unit, &link);
295 ag7240_phy_duplex(mac->mac_unit, &duplex);
296 ag7240_phy_speed(mac->mac_unit, &speed);
301 if((s != NULL) && (strcmp(s, "nc") != 0)){
302 printf("Link down: %s\n", mac->dev->name);
309 ag7240_set_mac_if(mac, 1);
310 ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
311 if (is_ar7242() && (mac->mac_unit == 0)) {
312 ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x1c000000);
314 #ifdef CONFIG_F1E_PHY
315 if (is_wasp() && (mac->mac_unit == 0)) {
316 ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x0e000000);
319 if (is_wasp() && (mac->mac_unit == 0)) {
320 ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x06000000);
326 ag7240_set_mac_if(mac, 0);
327 ag7240_set_mac_speed(mac, 1);
328 ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
329 if ((is_ar7242() || is_wasp()) && (mac->mac_unit == 0)){
330 ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x0101);
335 ag7240_set_mac_if(mac, 0);
336 ag7240_set_mac_speed(mac, 0);
337 ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
338 if ((is_ar7242() || is_wasp()) && (mac->mac_unit == 0)){
339 ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x1616);
344 if((s != NULL) && (strcmp(s, "nc") != 0)){
345 printf("## Error: invalid speed detected\n");
350 if (mac->link && (duplex == mac->duplex) && (speed == mac->speed)){
354 mac->duplex = duplex;
357 if((s != NULL) && (strcmp(s, "nc") != 0)){
358 printf("Ethernet mode (duplex/speed): %d/%d Mbps\n", duplex, speed);
361 ag7240_set_mac_duplex(mac, duplex);
367 * For every command we re-setup the ring and start with clean h/w rx state
369 static int ag7240_clean_rx(struct eth_device *dev, bd_t * bd) {
373 ag7240_mac_t *mac = (ag7240_mac_t*)dev->priv;
375 if (!ag7240_check_link(mac)){
381 for (i = 0; i < NO_OF_RX_FIFOS; i++) {
382 fr = mac->fifo_rx[i];
383 fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);
384 flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
385 ag7240_rx_give_to_dma(fr);
388 ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));
389 ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, AG7240_RXE);
393 // TODO: do we need this?
401 static int ag7240_alloc_fifo(int ndesc, ag7240_desc_t ** fifo) {
406 size = sizeof(ag7240_desc_t) * ndesc;
407 size += CFG_CACHELINE_SIZE - 1;
409 if ((p = malloc(size)) == NULL) {
410 printf("Cant allocate fifos\n");
414 p = (uchar *) (((u32) p + CFG_CACHELINE_SIZE - 1) & ~(CFG_CACHELINE_SIZE - 1));
415 p = UNCACHED_SDRAM(p);
417 for (i = 0; i < ndesc; i++)
418 fifo[i] = (ag7240_desc_t *) p + i;
423 static int ag7240_setup_fifos(ag7240_mac_t *mac) {
426 if (ag7240_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx))
429 for (i = 0; i < NO_OF_TX_FIFOS; i++) {
430 mac->fifo_tx[i]->next_desc = (i == NO_OF_TX_FIFOS - 1) ? virt_to_phys(mac->fifo_tx[0]) : virt_to_phys(mac->fifo_tx[i + 1]);
431 ag7240_tx_own(mac->fifo_tx[i]);
434 if (ag7240_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx))
437 for (i = 0; i < NO_OF_RX_FIFOS; i++) {
438 mac->fifo_rx[i]->next_desc = (i == NO_OF_RX_FIFOS - 1) ? virt_to_phys(mac->fifo_rx[0]) : virt_to_phys(mac->fifo_rx[i + 1]);
444 static void ag7240_halt(struct eth_device *dev) {
445 ag7240_mac_t *mac = (ag7240_mac_t *) dev->priv;
446 ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 0);
447 while (ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))
452 * Get MAC address stored in flash
454 static void ag7240_get_ethaddr(struct eth_device *dev) {
455 unsigned char *mac = dev->enetaddr;
456 #ifdef OFFSET_MAC_ADDRESS
457 unsigned char buffer[6];
459 // get MAC address from flash and check it
460 memcpy(buffer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS), 6);
463 * check first LSBit (I/G bit) and second LSBit (U/L bit) in MSByte of vendor part
464 * both of them should be 0:
465 * I/G bit == 0 -> Individual MAC address (unicast address)
466 * U/L bit == 0 -> Burned-In-Address (BIA) MAC address
468 if(CHECK_BIT((buffer[0] & 0xFF), 0) == 0 && CHECK_BIT((buffer[0] & 0xFF), 1) == 0){
469 mac[0] = (buffer[0] & 0xFF);
470 mac[1] = (buffer[1] & 0xFF);
471 mac[2] = (buffer[2] & 0xFF);
472 mac[3] = (buffer[3] & 0xFF);
473 mac[4] = (buffer[4] & 0xFF);
474 mac[5] = (buffer[5] & 0xFF);
476 // 00-03-7F (Atheros Communications, Inc.)
484 printf("## Error: MAC address in FLASH is invalid, using fixed!\n");
487 // 00-03-7F (Atheros Communications, Inc.)
497 int ag7240_enet_initialize(bd_t * bis) {
498 struct eth_device *dev[CFG_AG7240_NMACS];
499 u32 mask, mac_h, mac_l;
503 printf("ag7240_enet_initialize...\n");
506 // TODO check this register!
507 ar7240_reg_wr(HORNET_BOOTSTRAP_STATUS, ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) & ~HORNET_BOOTSTRAP_MDIO_SLAVE_MASK);
513 * To get s26 out of reset, we have to...
514 * bit0~bit3: has to be deasserted
515 * bit4: has to be asserted
517 rd = ar7240_reg_rd(AR7240_S26_CLK_CTRL_OFFSET) & ~(0x1f);
519 ar7240_reg_wr(AR7240_S26_CLK_CTRL_OFFSET, rd);
521 if (ar7240_reg_rd(AR7240_RESET) != 0) {
522 ar7240_reg_wr(AR7240_RESET, 0);
526 for (i = 0; i < CFG_AG7240_NMACS; i++) {
528 if ((dev[i] = (struct eth_device *) malloc(sizeof(struct eth_device))) == NULL) {
529 puts("## Error: malloc failed\n");
533 if ((ag7240_macs[i] = (ag7240_mac_t *) malloc(sizeof(ag7240_mac_t))) == NULL) {
534 puts("## Error: malloc failed\n");
538 memset(ag7240_macs[i], 0, sizeof(ag7240_macs[i]));
539 memset(dev[i], 0, sizeof(dev[i]));
541 sprintf(dev[i]->name, "eth%d", i);
542 ag7240_get_ethaddr(dev[i]);
544 ag7240_macs[i]->mac_unit = i;
545 ag7240_macs[i]->mac_base = i ? AR7240_GE1_BASE : AR7240_GE0_BASE;
546 ag7240_macs[i]->dev = dev[i];
549 dev[i]->init = ag7240_clean_rx;
550 dev[i]->halt = ag7240_halt;
551 dev[i]->send = ag7240_send;
552 dev[i]->recv = ag7240_recv;
553 dev[i]->priv = (void *) ag7240_macs[i];
556 for (i = 0; i < CFG_AG7240_NMACS; i++) {
558 eth_register(dev[i]);
560 #if(CONFIG_COMMANDS & CFG_CMD_MII)
561 miiphy_register(dev[i]->name, ag7240_miiphy_read, ag7240_miiphy_write);
564 ag7240_reg_rmw_set(ag7240_macs[i], AG7240_MAC_CFG1, AG7240_MAC_CFG1_SOFT_RST | AG7240_MAC_CFG1_RX_RST | AG7240_MAC_CFG1_TX_RST);
567 mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY | AR7240_RESET_GE1_MAC | AR7240_RESET_GE1_PHY);
569 if (is_ar7241() || is_ar7242() || is_wasp()){
570 mask = mask | AR7240_RESET_GE0_MDIO | AR7240_RESET_GE1_MDIO;
573 ar7240_reg_rmw_set(AR7240_RESET, mask);
579 ar7240_reg_rmw_clear(AR7240_RESET, mask);
590 ag7240_hw_start(ag7240_macs[i]);
592 ag7240_setup_fifos(ag7240_macs[i]);
599 unsigned char *mac = dev[i]->enetaddr;
600 printf("\nInterface %s MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", dev[i]->name, mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff, mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
603 mac_l = (dev[i]->enetaddr[4] << 8) | (dev[i]->enetaddr[5]);
604 mac_h = (dev[i]->enetaddr[0] << 24) | (dev[i]->enetaddr[1] << 16) | (dev[i]->enetaddr[2] << 8) | (dev[i]->enetaddr[3] << 0);
606 ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR1, mac_l);
607 ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR2, mac_h);
609 /* if using header for register configuration, we have to */
610 /* configure s26 register after frame transmission is enabled */
612 if (ag7240_macs[i]->mac_unit == 0) { /* WAN Phy */
613 #ifdef CONFIG_AR7242_S16_PHY
614 if (is_ar7242() || is_wasp()) {
619 #ifdef CFG_ATHRS26_PHY
621 printf("s26 reg init \n");
625 #ifdef CFG_ATHRS27_PHY
627 printf("s27 reg init \n");
631 #ifdef CONFIG_F1E_PHY
633 printf("F1Phy reg init \n");
639 #ifdef CFG_ATHRS26_PHY
641 printf("athrs26_reg_init_lan\n");
643 athrs26_reg_init_lan();
645 #ifdef CFG_ATHRS27_PHY
647 printf("s27 reg init lan \n");
649 athrs27_reg_init_lan();
654 printf("ag7240_phy_setup\n");
658 ag7240_phy_setup(ag7240_macs[i]->mac_unit);
661 printf("Interface %s is up\n", dev[i]->name);
668 /* Modified by lsz for reduceing CMD_MII, but ag7240 need this 090306 */
669 uint16_t ag7240_miiphy_read(char *devname, uint32_t phy_addr, uint8_t reg) {
670 ag7240_mac_t *mac = ag7240_name2mac(devname);
671 uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg, val;
673 uint16_t ii = 0xFFFF;
676 * Check for previous transactions are complete. Added to avoid
677 * race condition while running at higher frequencies.
681 rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
682 } while (rddata && --ii);
685 printf("ERROR:%s:%d transaction failed\n", __func__, __LINE__);
687 ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
688 ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
689 ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, AG7240_MGMT_CMD_READ);
693 rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
694 } while (rddata && --ii);
697 printf("ERROR! Leave ag7240_miiphy_read without polling correct status!\n");
699 val = ag7240_reg_rd(mac, AG7240_MII_MGMT_STATUS);
700 ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
705 void ag7240_miiphy_write(char *devname, uint32_t phy_addr, uint8_t reg, uint16_t data) {
706 ag7240_mac_t *mac = ag7240_name2mac(devname);
707 uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg;
709 uint16_t ii = 0xFFFF;
712 * Check for previous transactions are complete. Added to avoid
713 * race condition while running at higher frequencies.
717 rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
718 } while (rddata && --ii);
721 printf("ERROR:%s:%d transaction failed\n", __func__, __LINE__);
723 ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
724 ag7240_reg_wr(mac, AG7240_MII_MGMT_CTRL, data);
727 rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
728 } while (rddata && --ii);
731 printf("ERROR! Leave ag7240_miiphy_write without polling correct status!\n");