-#include <config.h>\r
-#include <common.h>\r
-#include <malloc.h>\r
-#include <net.h>\r
-#include <command.h>\r
-#include <asm/io.h>\r
-#include <asm/addrspace.h>\r
-#include <asm/types.h>\r
-#include "ar7240_soc.h"\r
-#include "ag934x.h"\r
-#include "ag934x_phy.h"\r
-\r
-#define _1000BASET 1000\r
-#define _100BASET 100\r
-#define _10BASET 10\r
-\r
-#define ag7240_unit2mac(_unit) ag7240_macs[(_unit)]\r
-#define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(1) : ag7240_unit2mac(0)\r
-#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))\r
-\r
-uint16_t ag7240_miiphy_read(char *devname, uint32_t phaddr, uint8_t reg);\r
-void ag7240_miiphy_write(char *devname, uint32_t phaddr, uint8_t reg, uint16_t data);\r
-ag7240_mac_t *ag7240_macs[CFG_AG7240_NMACS];\r
-extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);\r
-\r
-#ifdef CFG_ATHRS26_PHY\r
-extern int athrs26_phy_setup(int unit);\r
-extern int athrs26_phy_is_up(int unit);\r
-extern int athrs26_phy_is_fdx(int unit);\r
-extern int athrs26_phy_speed(int unit);\r
-extern void athrs26_reg_init(void);\r
-extern void athrs26_reg_init_lan(void);\r
-extern int athrs26_mdc_check(void);\r
-#endif\r
-\r
-#ifdef CFG_ATHRS17_PHY\r
-extern void athrs17_reg_init(void);\r
-#endif\r
-\r
-#ifdef CFG_ATHRS27_PHY\r
-extern int athrs27_phy_setup(int unit);\r
-extern int athrs27_phy_is_up(int unit);\r
-extern int athrs27_phy_is_fdx(int unit);\r
-extern int athrs27_phy_speed(int unit);\r
-extern void athrs27_reg_init(void);\r
-extern void athrs27_reg_init_lan(void);\r
-extern int athrs27_mdc_check(void);\r
-#endif\r
-\r
-#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)\r
-extern int athr_phy_setup(int unit);\r
-extern int athr_phy_is_up(int unit);\r
-extern int athr_phy_is_fdx(int unit);\r
-extern int athr_phy_speed(int unit);\r
-extern void athr_reg_init(void);\r
-#endif\r
-\r
-#ifdef CONFIG_VIR_PHY\r
-extern int athr_vir_phy_setup(int unit);\r
-extern int athr_vir_phy_is_up(int unit);\r
-extern int athr_vir_phy_is_fdx(int unit);\r
-extern int athr_vir_phy_speed(int unit);\r
-extern void athr_vir_reg_init(void);\r
-#endif\r
-\r
-\r
-static int ag7240_send(struct eth_device *dev, volatile void *packet, int length){\r
- int i;\r
-\r
- ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;\r
-\r
- ag7240_desc_t *f = mac->fifo_tx[mac->next_tx];\r
-\r
- f->pkt_size = length;\r
- f->res1 = 0;\r
- f->pkt_start_addr = virt_to_phys(packet);\r
-\r
- ag7240_tx_give_to_dma(f);\r
- flush_cache((u32)packet, length);\r
- ag7240_reg_wr(mac, AG7240_DMA_TX_DESC, virt_to_phys(f));\r
- ag7240_reg_wr(mac, AG7240_DMA_TX_CTRL, AG7240_TXE);\r
-\r
- for(i = 0; i < MAX_WAIT; i++){\r
- udelay(10);\r
- if(!ag7240_tx_owned_by_dma(f)){\r
- break;\r
- }\r
- }\r
-\r
- f->pkt_start_addr = 0;\r
- f->pkt_size = 0;\r
-\r
- if(++mac->next_tx >= NO_OF_TX_FIFOS){\r
- mac->next_tx = 0;\r
- }\r
-\r
- return(0);\r
-}\r
-\r
-static int ag7240_recv(struct eth_device *dev){\r
- int length;\r
- ag7240_desc_t *f;\r
- ag7240_mac_t *mac;\r
-\r
- mac = (ag7240_mac_t *)dev->priv;\r
-\r
- for(;;){\r
- f = mac->fifo_rx[mac->next_rx];\r
- if(ag7240_rx_owned_by_dma(f)){\r
- break;\r
- }\r
-\r
- length = f->pkt_size;\r
-\r
- NetReceive(NetRxPackets[mac->next_rx] , length - 4);\r
- flush_cache((u32)NetRxPackets[mac->next_rx] , PKTSIZE_ALIGN);\r
-\r
- ag7240_rx_give_to_dma(f);\r
-\r
- if(++mac->next_rx >= NO_OF_RX_FIFOS)\r
- mac->next_rx = 0;\r
- }\r
-\r
- if(!(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))){\r
- ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(f));\r
- ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 1);\r
- }\r
-\r
- return(0);\r
-}\r
-\r
-/*\r
- * Called in ag7240_hw_start() function\r
- */\r
-void ag7240_mii_setup(ag7240_mac_t *mac){\r
- u32 mgmt_cfg_val;\r
- u32 cpu_freq,ddr_freq,ahb_freq;\r
- u32 check_cnt;\r
-\r
- if((ar7240_reg_rd(WASP_BOOTSTRAP_REG) & WASP_REF_CLK_25) == 0){\r
-#ifndef CFG_DUAL_PHY_SUPPORT\r
- ar7240_reg_wr(AR934X_SWITCH_CLOCK_SPARE, 0x271);\r
-#endif\r
- } else {\r
- ar7240_reg_wr(AR934X_SWITCH_CLOCK_SPARE, 0x570);\r
- }\r
-\r
-#if defined(CONFIG_AR7242_S16_PHY) || defined(CFG_ATHRS17_PHY)\r
- if(is_wasp() && mac->mac_unit == 0){\r
-#ifdef CONFIG_AR7242_S16_PHY\r
- //printf("WASP ----> S16 PHY *\n");\r
-#else\r
- //printf("WASP ----> S17 PHY *\n");\r
-#endif\r
- mgmt_cfg_val = 4;\r
- \r
- if(mac->mac_unit == 0){\r
- ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);\r
- }\r
-\r
- udelay(1000);\r
-\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
-\r
- return;\r
- }\r
-#endif\r
-\r
-#ifdef CFG_ATHRS27_PHY\r
- if(is_wasp()){\r
- //printf("WASP ----> S27 PHY \n");\r
- mgmt_cfg_val = 2;\r
- ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
- return;\r
- }\r
-#endif\r
-\r
-#ifdef CONFIG_F2E_PHY\r
- if(is_wasp()){\r
- //printf("WASP ----> F2 PHY *\n");\r
- mgmt_cfg_val = 6;\r
- ar7240_reg_wr(AG7240_ETH_CFG, (AG7240_ETH_CFG_RMII_MASTER_MODE | AG7240_ETH_CFG_RMII_GE0 | AG7240_ETH_CFG_RMII_HISPD_GE0));\r
- \r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
-\r
- return;\r
- }\r
-#endif\r
-\r
-#if defined(CONFIG_F1E_PHY) || defined(CONFIG_VIR_PHY)\r
- if(is_wasp()){\r
-#ifdef CONFIG_VIR_PHY\r
- //printf("WASP ----> VIR PHY *\n");\r
-#else\r
- //printf("WASP ----> F1 PHY *\n");\r
-#endif\r
- if(mac->mac_unit == 0){\r
- ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);\r
- }\r
-\r
- mgmt_cfg_val = 6;\r
-\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
-\r
- return;\r
- }\r
-#endif\r
-\r
- if((ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK) == AR7240_REV_1_2){\r
- mgmt_cfg_val = 0x2;\r
-\r
- if(mac->mac_unit == 0){\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
- }\r
- } else {\r
- ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);\r
- \r
- // TODO: ??\r
- switch(ahb_freq/1000000){\r
- case 150:\r
- mgmt_cfg_val = 0x7;\r
- break;\r
- case 175:\r
- mgmt_cfg_val = 0x5;\r
- break;\r
- case 200:\r
- mgmt_cfg_val = 0x4;\r
- break;\r
- case 210:\r
- mgmt_cfg_val = 0x9;\r
- break;\r
- case 220:\r
- mgmt_cfg_val = 0x9;\r
- break;\r
- default:\r
- mgmt_cfg_val = 0x7;\r
- }\r
- \r
- if((is_ar7241() || is_ar7242())){\r
- /* External MII mode */\r
- if(mac->mac_unit == 0 && is_ar7242()){\r
- mgmt_cfg_val = 0x6;\r
- ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
- }\r
- \r
- /* Virian */\r
- mgmt_cfg_val = 0x4;\r
- ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
- //printf("Virian MDC CFG Value ==> %x\n",mgmt_cfg_val);\r
- } else if(is_ar933x()){\r
- //GE0 receives Rx/Tx clock, and use S26 phy\r
- ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_MII_GE0_SLAVE);\r
- mgmt_cfg_val = 0xF;\r
- \r
- if(mac->mac_unit == 1){\r
- check_cnt = 0;\r
- while(check_cnt++ < 10){\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
-#ifdef CFG_ATHRS26_PHY\r
- if(athrs26_mdc_check() == 0){\r
- break;\r
- }\r
-#endif\r
- }\r
- \r
- //if(check_cnt == 11)\r
- //printf("%s: MDC check failed\n", __func__);\r
- }\r
- } else { /* Python 1.0 & 1.1 */\r
- if(mac->mac_unit == 0){\r
- check_cnt = 0;\r
- \r
- while(check_cnt++ < 10){\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));\r
- ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);\r
-#ifdef CFG_ATHRS26_PHY\r
- if(athrs26_mdc_check() == 0){\r
- break;\r
- }\r
-#endif\r
- }\r
- \r
- //if(check_cnt == 11)\r
- //printf("%s: MDC check failed\n", __func__);\r
- }\r
- }\r
- }\r
-}\r
-\r
-static void ag7240_hw_start(ag7240_mac_t *mac){\r
-\r
- if(mac->mac_unit){\r
- ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN | AG7240_MAC_CFG1_TX_EN));\r
- ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN | AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_1000));\r
- } else {\r
- ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN | AG7240_MAC_CFG1_TX_EN));\r
- 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));\r
- }\r
- \r
- ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_0, 0x1f00);\r
- ag7240_mii_setup(mac);\r
-\r
- ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);\r
- ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);\r
-\r
- ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);\r
-\r
- // TODO: check this register\r
- /*\r
- * When enable the web failsafe mode in uboot,you can't drop the broadcast\r
- * frames now,the PC first will tx a ARP request packet, it's a broadcast packet.\r
- */\r
- ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x66b82);\r
- /* \r
- * Setting Drop CRC Errors, Pause Frames,Length Error frames \r
- * and Multi/Broad cast frames. \r
- */\r
- //ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x7eccf);\r
-\r
- ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_3, 0x1f00140);\r
- //printf(": cfg1 %#x cfg2 %#x\n", ag7240_reg_rd(mac, AG7240_MAC_CFG1), ag7240_reg_rd(mac, AG7240_MAC_CFG2));\r
-}\r
-\r
-static int ag7240_check_link(ag7240_mac_t *mac){\r
- int link = 0, duplex = 0, speed = 0;\r
- char *s;\r
-\r
- s = getenv("stdin");\r
-\r
- ag7240_phy_link(mac->mac_unit, &link);\r
- ag7240_phy_duplex(mac->mac_unit, &duplex);\r
- ag7240_phy_speed(mac->mac_unit, &speed);\r
-\r
- mac->link = link;\r
-\r
- if(!mac->link){\r
- if((s != NULL) && (strcmp(s, "nc") != 0)){\r
- printf("Link down: %s\n", mac->dev->name);\r
- }\r
- return(0);\r
- }\r
-\r
- switch(speed){\r
- case _1000BASET:\r
- ag7240_set_mac_if(mac, 1);\r
- ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));\r
- \r
- if(is_ar7242() && (mac->mac_unit == 0)){\r
- ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x1c000000);\r
- }\r
-#ifdef CONFIG_F1E_PHY\r
- if(is_wasp() && (mac->mac_unit == 0)){\r
- ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x0e000000);\r
- }\r
-#elif CONFIG_VIR_PHY\r
- if(is_wasp() && (mac->mac_unit == 0)){\r
- ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x82000000);\r
- ar7240_reg_wr(AG7240_ETH_CFG, 0x000c0001);\r
- }\r
-#else \r
- if(is_wasp() && (mac->mac_unit == 0) && !is_f2e()){\r
- ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x06000000);\r
- }\r
-#endif\r
- if(is_wasp() && mac->mac_unit == 0 && is_f1e() ){\r
- ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RXD_DELAY);\r
- ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RDV_DELAY);\r
- }\r
- break;\r
-\r
- case _100BASET:\r
- ag7240_set_mac_if(mac, 0);\r
- ag7240_set_mac_speed(mac, 1);\r
- ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));\r
- \r
- if((is_ar7242() || is_wasp()) && (mac->mac_unit == 0) && !is_f2e()){\r
- ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x0101);\r
- }\r
-\r
- if(is_wasp() && mac->mac_unit == 0 && is_f1e()){\r
- ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RXD_DELAY);\r
- ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RDV_DELAY);\r
- }\r
- break;\r
-\r
- case _10BASET:\r
- ag7240_set_mac_if(mac, 0);\r
- ag7240_set_mac_speed(mac, 0);\r
- ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));\r
-\r
- if((is_ar7242() || is_wasp()) && (mac->mac_unit == 0) && !is_f2e()){\r
- ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1616);\r
- }\r
-\r
- if(is_wasp() && mac->mac_unit == 0 && is_f1e()){\r
- ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RXD_DELAY);\r
- ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RDV_DELAY);\r
- }\r
- \r
- if(is_f2e()){\r
- ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RMII_HISPD_GE0);\r
- }\r
- break;\r
-\r
- default:\r
- if((s != NULL) && (strcmp(s, "nc") != 0)){\r
- printf("## Error: invalid speed detected\n");\r
- }\r
- return(0);\r
- }\r
-\r
- if(mac->link && (duplex == mac->duplex) && (speed == mac->speed)){\r
- return(1);\r
- }\r
-\r
- mac->duplex = duplex;\r
- mac->speed = speed;\r
-\r
- if((s != NULL) && (strcmp(s, "nc") != 0)){\r
- printf("Ethernet mode (duplex/speed): %d/%d Mbps\n", duplex, speed);\r
- }\r
-\r
- ag7240_set_mac_duplex(mac, duplex);\r
-\r
- return(1);\r
-}\r
-\r
-/*\r
- * For every command we re-setup the ring and start with clean h/w rx state\r
- */\r
-static int ag7240_clean_rx(struct eth_device *dev, bd_t * bd){\r
- int i;\r
- ag7240_desc_t *fr;\r
- ag7240_mac_t *mac = (ag7240_mac_t*)dev->priv;\r
-\r
- if(!ag7240_check_link(mac)){\r
- return(0);\r
- }\r
-\r
- mac->next_rx = 0;\r
- \r
- for(i = 0; i < NO_OF_RX_FIFOS; i++){\r
- fr = mac->fifo_rx[i];\r
- fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);\r
- flush_cache((u32)NetRxPackets[i], PKTSIZE_ALIGN);\r
- ag7240_rx_give_to_dma(fr);\r
- }\r
-\r
- ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));\r
- ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, AG7240_RXE); /* rx start */\r
- \r
- udelay(1000 * 1000);\r
- return(1);\r
-}\r
-\r
-static int ag7240_alloc_fifo(int ndesc, ag7240_desc_t ** fifo){\r
- int i;\r
- u32 size;\r
- uchar *p = NULL;\r
-\r
- size = sizeof(ag7240_desc_t) * ndesc;\r
- size += CFG_CACHELINE_SIZE - 1;\r
-\r
- if((p = malloc(size)) == NULL){\r
- printf("## Error: cant allocate fifos\n");\r
- return(-1);\r
- }\r
-\r
- p = (uchar *)(((u32)p + CFG_CACHELINE_SIZE - 1) & ~(CFG_CACHELINE_SIZE - 1));\r
- p = UNCACHED_SDRAM(p);\r
-\r
- for(i = 0; i < ndesc; i++){\r
- fifo[i] = (ag7240_desc_t *)p + i;\r
- }\r
-\r
- return(0);\r
-}\r
-\r
-static int ag7240_setup_fifos(ag7240_mac_t *mac){\r
- int i;\r
-\r
- if(ag7240_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx)){\r
- return(1);\r
- }\r
-\r
- for(i = 0; i < NO_OF_TX_FIFOS; i++){\r
- 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]);\r
- ag7240_tx_own(mac->fifo_tx[i]);\r
- }\r
-\r
- if(ag7240_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx)){\r
- return(1);\r
- }\r
-\r
- for(i = 0; i < NO_OF_RX_FIFOS; i++){\r
- 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]);\r
- }\r
-\r
- return(1);\r
-}\r
-\r
-static void ag7240_halt(struct eth_device *dev){\r
- ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;\r
- ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 0);\r
- while(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL));\r
-}\r
-\r
-/*\r
- * Get MAC address stored in flash\r
- */\r
-static void ag7240_get_ethaddr(struct eth_device *dev){\r
- unsigned char *mac = dev->enetaddr;\r
-#ifdef OFFSET_MAC_ADDRESS\r
- unsigned char buffer[6];\r
-\r
- // get MAC address from flash and check it\r
- memcpy(buffer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS), 6);\r
-\r
- /*\r
- * check first LSBit (I/G bit) and second LSBit (U/L bit) in MSByte of vendor part\r
- * both of them should be 0:\r
- * I/G bit == 0 -> Individual MAC address (unicast address)\r
- * U/L bit == 0 -> Burned-In-Address (BIA) MAC address\r
- */\r
- if(CHECK_BIT((buffer[0] & 0xFF), 0) == 0 && CHECK_BIT((buffer[0] & 0xFF), 1) == 0){\r
- mac[0] = (buffer[0] & 0xFF);\r
- mac[1] = (buffer[1] & 0xFF);\r
- mac[2] = (buffer[2] & 0xFF);\r
- mac[3] = (buffer[3] & 0xFF);\r
- mac[4] = (buffer[4] & 0xFF);\r
- mac[5] = (buffer[5] & 0xFF);\r
- } else {\r
- // 00-03-7F (Atheros Communications, Inc.)\r
- mac[0] = 0x00;\r
- mac[1] = 0x03;\r
- mac[2] = 0x7f;\r
- mac[3] = 0x09;\r
- mac[4] = 0x0b;\r
- mac[5] = 0xad;\r
-\r
+#include <config.h>
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include "ar7240_soc.h"
+#include "ag934x.h"
+#include "ag934x_phy.h"
+
+#define _1000BASET 1000
+#define _100BASET 100
+#define _10BASET 10
+
+#define ag7240_unit2mac(_unit) ag7240_macs[(_unit)]
+#define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(1) : ag7240_unit2mac(0)
+#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
+
+uint16_t ag7240_miiphy_read(char *devname, uint32_t phaddr, uint8_t reg);
+void ag7240_miiphy_write(char *devname, uint32_t phaddr, uint8_t reg, uint16_t data);
+ag7240_mac_t *ag7240_macs[CFG_AG7240_NMACS];
+extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);
+
+#ifdef CFG_ATHRS26_PHY
+extern int athrs26_phy_setup(int unit);
+extern int athrs26_phy_is_up(int unit);
+extern int athrs26_phy_is_fdx(int unit);
+extern int athrs26_phy_speed(int unit);
+extern void athrs26_reg_init(void);
+extern void athrs26_reg_init_lan(void);
+extern int athrs26_mdc_check(void);
+#endif
+
+#ifdef CFG_ATHRS17_PHY
+extern void athrs17_reg_init(void);
+#endif
+
+#ifdef CFG_ATHRS27_PHY
+extern int athrs27_phy_setup(int unit);
+extern int athrs27_phy_is_up(int unit);
+extern int athrs27_phy_is_fdx(int unit);
+extern int athrs27_phy_speed(int unit);
+extern void athrs27_reg_init(void);
+extern void athrs27_reg_init_lan(void);
+extern int athrs27_mdc_check(void);
+#endif
+
+#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)
+extern int athr_phy_setup(int unit);
+extern int athr_phy_is_up(int unit);
+extern int athr_phy_is_fdx(int unit);
+extern int athr_phy_speed(int unit);
+extern void athr_reg_init(void);
+#endif
+
+#ifdef CONFIG_VIR_PHY
+extern int athr_vir_phy_setup(int unit);
+extern int athr_vir_phy_is_up(int unit);
+extern int athr_vir_phy_is_fdx(int unit);
+extern int athr_vir_phy_speed(int unit);
+extern void athr_vir_reg_init(void);
+#endif
+
+
+static int ag7240_send(struct eth_device *dev, volatile void *packet, int length){
+ int i;
+
+ ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
+
+ ag7240_desc_t *f = mac->fifo_tx[mac->next_tx];
+
+ f->pkt_size = length;
+ f->res1 = 0;
+ f->pkt_start_addr = virt_to_phys(packet);
+
+ ag7240_tx_give_to_dma(f);
+ flush_cache((u32)packet, length);
+ ag7240_reg_wr(mac, AG7240_DMA_TX_DESC, virt_to_phys(f));
+ ag7240_reg_wr(mac, AG7240_DMA_TX_CTRL, AG7240_TXE);
+
+ for(i = 0; i < MAX_WAIT; i++){
+ udelay(10);
+ if(!ag7240_tx_owned_by_dma(f)){
+ break;
+ }
+ }
+
+ f->pkt_start_addr = 0;
+ f->pkt_size = 0;
+
+ if(++mac->next_tx >= NO_OF_TX_FIFOS){
+ mac->next_tx = 0;
+ }
+
+ return(0);
+}
+
+static int ag7240_recv(struct eth_device *dev){
+ int length;
+ ag7240_desc_t *f;
+ ag7240_mac_t *mac;
+
+ mac = (ag7240_mac_t *)dev->priv;
+
+ for(;;){
+ f = mac->fifo_rx[mac->next_rx];
+ if(ag7240_rx_owned_by_dma(f)){
+ break;
+ }
+
+ length = f->pkt_size;
+
+ NetReceive(NetRxPackets[mac->next_rx] , length - 4);
+ flush_cache((u32)NetRxPackets[mac->next_rx] , PKTSIZE_ALIGN);
+
+ ag7240_rx_give_to_dma(f);
+
+ if(++mac->next_rx >= NO_OF_RX_FIFOS)
+ mac->next_rx = 0;
+ }
+
+ if(!(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))){
+ ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(f));
+ ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 1);
+ }
+
+ return(0);
+}
+
+/*
+ * Called in ag7240_hw_start() function
+ */
+void ag7240_mii_setup(ag7240_mac_t *mac){
+ u32 mgmt_cfg_val;
+ u32 cpu_freq,ddr_freq,ahb_freq;
+ u32 check_cnt;
+
+ if((ar7240_reg_rd(WASP_BOOTSTRAP_REG) & WASP_REF_CLK_25) == 0){
+#ifndef CFG_DUAL_PHY_SUPPORT
+ ar7240_reg_wr(AR934X_SWITCH_CLOCK_SPARE, 0x271);
+#endif
+ } else {
+ ar7240_reg_wr(AR934X_SWITCH_CLOCK_SPARE, 0x570);
+ }
+
+#if defined(CONFIG_AR7242_S16_PHY) || defined(CFG_ATHRS17_PHY)
+ if(is_wasp() && mac->mac_unit == 0){
+#ifdef CONFIG_AR7242_S16_PHY
+ //printf("WASP ----> S16 PHY *\n");
+#else
+ //printf("WASP ----> S17 PHY *\n");
+#endif
+ mgmt_cfg_val = 4;
+
+ if(mac->mac_unit == 0){
+ ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
+ }
+
+ udelay(1000);
+
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+
+ return;
+ }
+#endif
+
+#ifdef CFG_ATHRS27_PHY
+ if(is_wasp()){
+ //printf("WASP ----> S27 PHY \n");
+ mgmt_cfg_val = 2;
+ ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+ return;
+ }
+#endif
+
+#ifdef CONFIG_F2E_PHY
+ if(is_wasp()){
+ //printf("WASP ----> F2 PHY *\n");
+ mgmt_cfg_val = 6;
+ ar7240_reg_wr(AG7240_ETH_CFG, (AG7240_ETH_CFG_RMII_MASTER_MODE | AG7240_ETH_CFG_RMII_GE0 | AG7240_ETH_CFG_RMII_HISPD_GE0));
+
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+
+ return;
+ }
+#endif
+
+#if defined(CONFIG_F1E_PHY) || defined(CONFIG_VIR_PHY)
+ if(is_wasp()){
+#ifdef CONFIG_VIR_PHY
+ //printf("WASP ----> VIR PHY *\n");
+#else
+ //printf("WASP ----> F1 PHY *\n");
+#endif
+ if(mac->mac_unit == 0){
+ ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
+ }
+
+ mgmt_cfg_val = 6;
+
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+
+ return;
+ }
+#endif
+
+ if((ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK) == AR7240_REV_1_2){
+ mgmt_cfg_val = 0x2;
+
+ if(mac->mac_unit == 0){
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+ }
+ } else {
+ ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
+
+ // TODO: ??
+ switch(ahb_freq/1000000){
+ case 150:
+ mgmt_cfg_val = 0x7;
+ break;
+ case 175:
+ mgmt_cfg_val = 0x5;
+ break;
+ case 200:
+ mgmt_cfg_val = 0x4;
+ break;
+ case 210:
+ mgmt_cfg_val = 0x9;
+ break;
+ case 220:
+ mgmt_cfg_val = 0x9;
+ break;
+ default:
+ mgmt_cfg_val = 0x7;
+ }
+
+ if((is_ar7241() || is_ar7242())){
+ /* External MII mode */
+ if(mac->mac_unit == 0 && is_ar7242()){
+ mgmt_cfg_val = 0x6;
+ ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+ }
+
+ /* Virian */
+ mgmt_cfg_val = 0x4;
+ ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+ //printf("Virian MDC CFG Value ==> %x\n",mgmt_cfg_val);
+ } else if(is_ar933x()){
+ //GE0 receives Rx/Tx clock, and use S26 phy
+ ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_MII_GE0_SLAVE);
+ mgmt_cfg_val = 0xF;
+
+ if(mac->mac_unit == 1){
+ check_cnt = 0;
+ while(check_cnt++ < 10){
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+#ifdef CFG_ATHRS26_PHY
+ if(athrs26_mdc_check() == 0){
+ break;
+ }
+#endif
+ }
+
+ //if(check_cnt == 11)
+ //printf("%s: MDC check failed\n", __func__);
+ }
+ } else { /* Python 1.0 & 1.1 */
+ if(mac->mac_unit == 0){
+ check_cnt = 0;
+
+ while(check_cnt++ < 10){
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
+ ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
+#ifdef CFG_ATHRS26_PHY
+ if(athrs26_mdc_check() == 0){
+ break;
+ }
+#endif
+ }
+
+ //if(check_cnt == 11)
+ //printf("%s: MDC check failed\n", __func__);
+ }
+ }
+ }
+}
+
+static void ag7240_hw_start(ag7240_mac_t *mac){
+
+ if(mac->mac_unit){
+ ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN | AG7240_MAC_CFG1_TX_EN));
+ ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN | AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_1000));
+ } else {
+ ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN | AG7240_MAC_CFG1_TX_EN));
+ 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));
+ }
+
+ ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_0, 0x1f00);
+ ag7240_mii_setup(mac);
+
+ ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);
+ ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);
+
+ ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);
+
+ // TODO: check this register
+ /*
+ * When enable the web failsafe mode in uboot,you can't drop the broadcast
+ * frames now,the PC first will tx a ARP request packet, it's a broadcast packet.
+ */
+ ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x66b82);
+ /*
+ * Setting Drop CRC Errors, Pause Frames,Length Error frames
+ * and Multi/Broad cast frames.
+ */
+ //ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x7eccf);
+
+ ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_3, 0x1f00140);
+ //printf(": cfg1 %#x cfg2 %#x\n", ag7240_reg_rd(mac, AG7240_MAC_CFG1), ag7240_reg_rd(mac, AG7240_MAC_CFG2));
+}
+
+static int ag7240_check_link(ag7240_mac_t *mac){
+ int link = 0, duplex = 0, speed = 0;
+ char *s;
+
+ s = getenv("stdin");
+
+ ag7240_phy_link(mac->mac_unit, &link);
+ ag7240_phy_duplex(mac->mac_unit, &duplex);
+ ag7240_phy_speed(mac->mac_unit, &speed);
+
+ mac->link = link;
+
+ if(!mac->link){
+ if((s != NULL) && (strcmp(s, "nc") != 0)){
+ printf("Link down: %s\n", mac->dev->name);
+ }
+ return(0);
+ }
+
+ switch(speed){
+ case _1000BASET:
+ ag7240_set_mac_if(mac, 1);
+ ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
+
+ if(is_ar7242() && (mac->mac_unit == 0)){
+ ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x1c000000);
+ }
+#ifdef CONFIG_F1E_PHY
+ if(is_wasp() && (mac->mac_unit == 0)){
+ ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x0e000000);
+ }
+#elif CONFIG_VIR_PHY
+ if(is_wasp() && (mac->mac_unit == 0)){
+ ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x82000000);
+ ar7240_reg_wr(AG7240_ETH_CFG, 0x000c0001);
+ }
+#else
+ if(is_wasp() && (mac->mac_unit == 0) && !is_f2e()){
+ ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x06000000);
+ }
+#endif
+ if(is_wasp() && mac->mac_unit == 0 && is_f1e() ){
+ ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RXD_DELAY);
+ ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RDV_DELAY);
+ }
+ break;
+
+ case _100BASET:
+ ag7240_set_mac_if(mac, 0);
+ ag7240_set_mac_speed(mac, 1);
+ ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
+
+ if((is_ar7242() || is_wasp()) && (mac->mac_unit == 0) && !is_f2e()){
+ ar7240_reg_wr(AR7242_ETH_XMII_CONFIG, 0x0101);
+ }
+
+ if(is_wasp() && mac->mac_unit == 0 && is_f1e()){
+ ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RXD_DELAY);
+ ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RDV_DELAY);
+ }
+ break;
+
+ case _10BASET:
+ ag7240_set_mac_if(mac, 0);
+ ag7240_set_mac_speed(mac, 0);
+ ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
+
+ if((is_ar7242() || is_wasp()) && (mac->mac_unit == 0) && !is_f2e()){
+ ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1616);
+ }
+
+ if(is_wasp() && mac->mac_unit == 0 && is_f1e()){
+ ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RXD_DELAY);
+ ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RDV_DELAY);
+ }
+
+ if(is_f2e()){
+ ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RMII_HISPD_GE0);
+ }
+ break;
+
+ default:
+ if((s != NULL) && (strcmp(s, "nc") != 0)){
+ printf("## Error: invalid speed detected\n");
+ }
+ return(0);
+ }
+
+ if(mac->link && (duplex == mac->duplex) && (speed == mac->speed)){
+ return(1);
+ }
+
+ mac->duplex = duplex;
+ mac->speed = speed;
+
+ if((s != NULL) && (strcmp(s, "nc") != 0)){
+ printf("Ethernet mode (duplex/speed): %d/%d Mbps\n", duplex, speed);
+ }
+
+ ag7240_set_mac_duplex(mac, duplex);
+
+ return(1);
+}
+
+/*
+ * For every command we re-setup the ring and start with clean h/w rx state
+ */
+static int ag7240_clean_rx(struct eth_device *dev, bd_t * bd){
+ int i;
+ ag7240_desc_t *fr;
+ ag7240_mac_t *mac = (ag7240_mac_t*)dev->priv;
+
+ if(!ag7240_check_link(mac)){
+ return(0);
+ }
+
+ mac->next_rx = 0;
+
+ for(i = 0; i < NO_OF_RX_FIFOS; i++){
+ fr = mac->fifo_rx[i];
+ fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);
+ flush_cache((u32)NetRxPackets[i], PKTSIZE_ALIGN);
+ ag7240_rx_give_to_dma(fr);
+ }
+
+ ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));
+ ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, AG7240_RXE); /* rx start */
+
+ udelay(1000 * 1000);
+ return(1);
+}
+
+static int ag7240_alloc_fifo(int ndesc, ag7240_desc_t ** fifo){
+ int i;
+ u32 size;
+ uchar *p = NULL;
+
+ size = sizeof(ag7240_desc_t) * ndesc;
+ size += CFG_CACHELINE_SIZE - 1;
+
+ if((p = malloc(size)) == NULL){
+ printf("## Error: cant allocate fifos\n");
+ return(-1);
+ }
+
+ p = (uchar *)(((u32)p + CFG_CACHELINE_SIZE - 1) & ~(CFG_CACHELINE_SIZE - 1));
+ p = UNCACHED_SDRAM(p);
+
+ for(i = 0; i < ndesc; i++){
+ fifo[i] = (ag7240_desc_t *)p + i;
+ }
+
+ return(0);
+}
+
+static int ag7240_setup_fifos(ag7240_mac_t *mac){
+ int i;
+
+ if(ag7240_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx)){
+ return(1);
+ }
+
+ for(i = 0; i < NO_OF_TX_FIFOS; i++){
+ 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]);
+ ag7240_tx_own(mac->fifo_tx[i]);
+ }
+
+ if(ag7240_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx)){
+ return(1);
+ }
+
+ for(i = 0; i < NO_OF_RX_FIFOS; i++){
+ 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]);
+ }
+
+ return(1);
+}
+
+static void ag7240_halt(struct eth_device *dev){
+ ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
+ ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 0);
+ while(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL));
+}
+
+/*
+ * Get MAC address stored in flash
+ */
+static void ag7240_get_ethaddr(struct eth_device *dev){
+ unsigned char *mac = dev->enetaddr;
+#ifdef OFFSET_MAC_ADDRESS
+ unsigned char buffer[6];
+
+ // get MAC address from flash and check it
+ memcpy(buffer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS), 6);
+
+ /*
+ * check first LSBit (I/G bit) and second LSBit (U/L bit) in MSByte of vendor part
+ * both of them should be 0:
+ * I/G bit == 0 -> Individual MAC address (unicast address)
+ * U/L bit == 0 -> Burned-In-Address (BIA) MAC address
+ */
+ if(CHECK_BIT((buffer[0] & 0xFF), 0) == 0 && CHECK_BIT((buffer[0] & 0xFF), 1) == 0){
+ mac[0] = (buffer[0] & 0xFF);
+ mac[1] = (buffer[1] & 0xFF);
+ mac[2] = (buffer[2] & 0xFF);
+ mac[3] = (buffer[3] & 0xFF);
+ mac[4] = (buffer[4] & 0xFF);
+ mac[5] = (buffer[5] & 0xFF);
+ } else {
+ // 00-03-7F (Atheros Communications, Inc.)
+ mac[0] = 0x00;
+ mac[1] = 0x03;
+ mac[2] = 0x7f;
+ mac[3] = 0x09;
+ mac[4] = 0x0b;
+ mac[5] = 0xad;
+
printf("## Error: MAC address in FLASH is invalid, using fixed!\n");
- }\r
-#else\r
- // 00-03-7F (Atheros Communications, Inc.)\r
- mac[0] = 0x00;\r
- mac[1] = 0x03;\r
- mac[2] = 0x7f;\r
- mac[3] = 0x09;\r
- mac[4] = 0x0b;\r
- mac[5] = 0xad;\r
-#endif\r
-}\r
-\r
-int ag7240_enet_initialize(bd_t * bis){\r
- struct eth_device *dev[CFG_AG7240_NMACS];\r
- u32 mask, mac_h, mac_l;\r
- int i;\r
-\r
- //printf("ag934x_enet_initialize...\n");\r
-\r
- /*\r
- if(is_ar933x() && (ar7240_reg_rd(AR7240_RESET)!=0)){\r
- ar7240_reg_wr(AR7240_RESET,0);\r
- }\r
-\r
- if(is_ar933x()) //Turn on LED\r
- ar7240_reg_wr(AR7240_GPIO_BASE + 0x28 , ar7240_reg_rd(AR7240_GPIO_BASE + 0x28) | (0xF8));\r
- */\r
-\r
- for(i = 0;i < CFG_AG7240_NMACS;i++){\r
- if((dev[i] = (struct eth_device *)malloc(sizeof(struct eth_device))) == NULL){\r
- //puts("malloc failed\n");\r
- return(0);\r
- }\r
-\r
- if((ag7240_macs[i] = (ag7240_mac_t *)malloc(sizeof(ag7240_mac_t))) == NULL){\r
- //puts("malloc failed\n");\r
- return(0);\r
- }\r
-\r
- memset(ag7240_macs[i], 0, sizeof(ag7240_macs[i]));\r
- memset(dev[i], 0, sizeof(dev[i]));\r
-\r
- sprintf(dev[i]->name, "eth%d", i);\r
- ag7240_get_ethaddr(dev[i]);\r
-\r
- ag7240_macs[i]->mac_unit = i;\r
- ag7240_macs[i]->mac_base = i ? AR7240_GE1_BASE : AR7240_GE0_BASE ;\r
- ag7240_macs[i]->dev = dev[i];\r
-\r
- dev[i]->iobase = 0;\r
- dev[i]->init = ag7240_clean_rx;\r
- dev[i]->halt = ag7240_halt;\r
- dev[i]->send = ag7240_send;\r
- dev[i]->recv = ag7240_recv;\r
- dev[i]->priv = (void *)ag7240_macs[i];\r
- }\r
- \r
- for(i = 0;i < CFG_AG7240_NMACS;i++){\r
- eth_register(dev[i]);\r
- \r
-#if(CONFIG_COMMANDS & CFG_CMD_MII)\r
- miiphy_register(dev[i]->name, ag7240_miiphy_read, ag7240_miiphy_write);\r
-#endif\r
-\r
- 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);\r
-\r
- if(!i){\r
- mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY | AR7240_RESET_GE1_MAC | AR7240_RESET_GE1_PHY);\r
-\r
- if(is_ar7241() || is_ar7242() || is_wasp()){\r
- mask = mask | AR7240_RESET_GE0_MDIO | AR7240_RESET_GE1_MDIO;\r
- }\r
-\r
- //printf(" wasp reset mask:%x \n",mask);\r
-\r
- ar7240_reg_rmw_set(AR7240_RESET, mask);\r
- udelay(1000 * 100);\r
-\r
- ar7240_reg_rmw_clear(AR7240_RESET, mask);\r
- udelay(1000 * 100);\r
-\r
- udelay(10 * 1000);\r
- }\r
-\r
- ag7240_hw_start(ag7240_macs[i]);\r
- ag7240_setup_fifos(ag7240_macs[i]);\r
-\r
- udelay(100 * 1000);\r
-\r
- //unsigned char *mac = dev[i]->enetaddr;\r
- //printf("%s: %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);\r
-\r
- mac_l = (dev[i]->enetaddr[4] << 8) | (dev[i]->enetaddr[5]);\r
- mac_h = (dev[i]->enetaddr[0] << 24) | (dev[i]->enetaddr[1] << 16) | (dev[i]->enetaddr[2] << 8) | (dev[i]->enetaddr[3] << 0);\r
-\r
- ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR1, mac_l);\r
- ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR2, mac_h);\r
-\r
- /* if using header for register configuration, we have to */\r
- /* configure s26 register after frame transmission is enabled */\r
- if(ag7240_macs[i]->mac_unit == 0){ /* WAN Phy */\r
-#ifdef CONFIG_AR7242_S16_PHY\r
- if(is_ar7242() || is_wasp()){\r
- athrs16_reg_init();\r
- } else\r
-#endif\r
- {\r
-#ifdef CFG_ATHRS17_PHY\r
- athrs17_reg_init();\r
-#endif\r
-\r
-#ifdef CFG_ATHRS26_PHY\r
- athrs26_reg_init();\r
-#endif\r
-\r
-#ifdef CFG_ATHRS27_PHY\r
- //printf("s27 reg init \n");\r
- athrs27_reg_init();\r
-#endif\r
-\r
-#ifdef CONFIG_F1E_PHY\r
- //printf("F1Phy reg init \n");\r
- athr_reg_init();\r
-#endif\r
-\r
-#ifdef CONFIG_VIR_PHY\r
- //printf("VIRPhy reg init \n");\r
- athr_vir_reg_init();\r
-#endif\r
-\r
-#ifdef CONFIG_F2E_PHY\r
- //printf("F2Phy reg init \n");\r
- athr_reg_init();\r
-#endif\r
-\r
- }\r
- } else {\r
-#ifdef CFG_ATHRS26_PHY\r
- athrs26_reg_init_lan();\r
-#endif\r
-\r
-#ifdef CFG_ATHRS27_PHY\r
- //printf("s27 reg init lan \n");\r
- athrs27_reg_init_lan();\r
-#endif\r
- }\r
-\r
- ag7240_phy_setup(ag7240_macs[i]->mac_unit);\r
- //printf("%s up\n",dev[i]->name);\r
- }\r
-\r
- return(1);\r
-}\r
-\r
-uint16_t ag7240_miiphy_read(char *devname, uint32_t phy_addr, uint8_t reg){\r
- ag7240_mac_t *mac = ag7240_name2mac(devname);\r
- uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg, val;\r
- volatile int rddata;\r
- uint16_t ii = 0xFFFF;\r
-\r
- /*\r
- * Check for previous transactions are complete. Added to avoid\r
- * race condition while running at higher frequencies.\r
- */\r
- do {\r
- udelay(5);\r
- rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;\r
- } while(rddata && --ii);\r
-\r
- //if(ii == 0)\r
- //printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);\r
-\r
- ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);\r
- ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);\r
- ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, AG7240_MGMT_CMD_READ);\r
-\r
- do {\r
- udelay(5);\r
- rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;\r
- } while(rddata && --ii);\r
-\r
- //if(ii==0)\r
- //printf("Error!!! Leave ag7240_miiphy_read without polling correct status!\n");\r
-\r
- val = ag7240_reg_rd(mac, AG7240_MII_MGMT_STATUS);\r
- ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);\r
-\r
- return(val);\r
-}\r
-\r
-void ag7240_miiphy_write(char *devname, uint32_t phy_addr, uint8_t reg, uint16_t data){\r
- ag7240_mac_t *mac = ag7240_name2mac(devname);\r
- uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg;\r
- volatile int rddata;\r
- uint16_t ii = 0xFFFF;\r
-\r
- /*\r
- * Check for previous transactions are complete. Added to avoid\r
- * race condition while running at higher frequencies.\r
- */\r
- do {\r
- udelay(5);\r
- rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;\r
- } while(rddata && --ii);\r
-\r
- //if(ii == 0)\r
- //printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);\r
-\r
- ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);\r
- ag7240_reg_wr(mac, AG7240_MII_MGMT_CTRL, data);\r
-\r
- do {\r
- rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;\r
- } while(rddata && --ii);\r
-\r
-}\r
+ }
+#else
+ // 00-03-7F (Atheros Communications, Inc.)
+ mac[0] = 0x00;
+ mac[1] = 0x03;
+ mac[2] = 0x7f;
+ mac[3] = 0x09;
+ mac[4] = 0x0b;
+ mac[5] = 0xad;
+#endif
+}
+
+int ag7240_enet_initialize(bd_t * bis){
+ struct eth_device *dev[CFG_AG7240_NMACS];
+ u32 mask, mac_h, mac_l;
+ int i;
+
+ //printf("ag934x_enet_initialize...\n");
+
+ /*
+ if(is_ar933x() && (ar7240_reg_rd(AR7240_RESET)!=0)){
+ ar7240_reg_wr(AR7240_RESET,0);
+ }
+
+ if(is_ar933x()) //Turn on LED
+ ar7240_reg_wr(AR7240_GPIO_BASE + 0x28 , ar7240_reg_rd(AR7240_GPIO_BASE + 0x28) | (0xF8));
+ */
+
+ for(i = 0;i < CFG_AG7240_NMACS;i++){
+ if((dev[i] = (struct eth_device *)malloc(sizeof(struct eth_device))) == NULL){
+ //puts("malloc failed\n");
+ return(0);
+ }
+
+ if((ag7240_macs[i] = (ag7240_mac_t *)malloc(sizeof(ag7240_mac_t))) == NULL){
+ //puts("malloc failed\n");
+ return(0);
+ }
+
+ memset(ag7240_macs[i], 0, sizeof(ag7240_macs[i]));
+ memset(dev[i], 0, sizeof(dev[i]));
+
+ sprintf(dev[i]->name, "eth%d", i);
+ ag7240_get_ethaddr(dev[i]);
+
+ ag7240_macs[i]->mac_unit = i;
+ ag7240_macs[i]->mac_base = i ? AR7240_GE1_BASE : AR7240_GE0_BASE ;
+ ag7240_macs[i]->dev = dev[i];
+
+ dev[i]->iobase = 0;
+ dev[i]->init = ag7240_clean_rx;
+ dev[i]->halt = ag7240_halt;
+ dev[i]->send = ag7240_send;
+ dev[i]->recv = ag7240_recv;
+ dev[i]->priv = (void *)ag7240_macs[i];
+ }
+
+ for(i = 0;i < CFG_AG7240_NMACS;i++){
+ eth_register(dev[i]);
+
+#if(CONFIG_COMMANDS & CFG_CMD_MII)
+ miiphy_register(dev[i]->name, ag7240_miiphy_read, ag7240_miiphy_write);
+#endif
+
+ 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);
+
+ if(!i){
+ mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY | AR7240_RESET_GE1_MAC | AR7240_RESET_GE1_PHY);
+
+ if(is_ar7241() || is_ar7242() || is_wasp()){
+ mask = mask | AR7240_RESET_GE0_MDIO | AR7240_RESET_GE1_MDIO;
+ }
+
+ //printf(" wasp reset mask:%x \n",mask);
+
+ ar7240_reg_rmw_set(AR7240_RESET, mask);
+ udelay(1000 * 100);
+
+ ar7240_reg_rmw_clear(AR7240_RESET, mask);
+ udelay(1000 * 100);
+
+ udelay(10 * 1000);
+ }
+
+ ag7240_hw_start(ag7240_macs[i]);
+ ag7240_setup_fifos(ag7240_macs[i]);
+
+ udelay(100 * 1000);
+
+ //unsigned char *mac = dev[i]->enetaddr;
+ //printf("%s: %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);
+
+ mac_l = (dev[i]->enetaddr[4] << 8) | (dev[i]->enetaddr[5]);
+ mac_h = (dev[i]->enetaddr[0] << 24) | (dev[i]->enetaddr[1] << 16) | (dev[i]->enetaddr[2] << 8) | (dev[i]->enetaddr[3] << 0);
+
+ ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR1, mac_l);
+ ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR2, mac_h);
+
+ /* if using header for register configuration, we have to */
+ /* configure s26 register after frame transmission is enabled */
+ if(ag7240_macs[i]->mac_unit == 0){ /* WAN Phy */
+#ifdef CONFIG_AR7242_S16_PHY
+ if(is_ar7242() || is_wasp()){
+ athrs16_reg_init();
+ } else
+#endif
+ {
+#ifdef CFG_ATHRS17_PHY
+ athrs17_reg_init();
+#endif
+
+#ifdef CFG_ATHRS26_PHY
+ athrs26_reg_init();
+#endif
+
+#ifdef CFG_ATHRS27_PHY
+ //printf("s27 reg init \n");
+ athrs27_reg_init();
+#endif
+
+#ifdef CONFIG_F1E_PHY
+ //printf("F1Phy reg init \n");
+ athr_reg_init();
+#endif
+
+#ifdef CONFIG_VIR_PHY
+ //printf("VIRPhy reg init \n");
+ athr_vir_reg_init();
+#endif
+
+#ifdef CONFIG_F2E_PHY
+ //printf("F2Phy reg init \n");
+ athr_reg_init();
+#endif
+
+ }
+ } else {
+#ifdef CFG_ATHRS26_PHY
+ athrs26_reg_init_lan();
+#endif
+
+#ifdef CFG_ATHRS27_PHY
+ //printf("s27 reg init lan \n");
+ athrs27_reg_init_lan();
+#endif
+ }
+
+ ag7240_phy_setup(ag7240_macs[i]->mac_unit);
+ //printf("%s up\n",dev[i]->name);
+ }
+
+ return(1);
+}
+
+uint16_t ag7240_miiphy_read(char *devname, uint32_t phy_addr, uint8_t reg){
+ ag7240_mac_t *mac = ag7240_name2mac(devname);
+ uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg, val;
+ volatile int rddata;
+ uint16_t ii = 0xFFFF;
+
+ /*
+ * Check for previous transactions are complete. Added to avoid
+ * race condition while running at higher frequencies.
+ */
+ do {
+ udelay(5);
+ rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
+ } while(rddata && --ii);
+
+ //if(ii == 0)
+ //printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);
+
+ ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
+ ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
+ ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, AG7240_MGMT_CMD_READ);
+
+ do {
+ udelay(5);
+ rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
+ } while(rddata && --ii);
+
+ //if(ii==0)
+ //printf("Error!!! Leave ag7240_miiphy_read without polling correct status!\n");
+
+ val = ag7240_reg_rd(mac, AG7240_MII_MGMT_STATUS);
+ ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
+
+ return(val);
+}
+
+void ag7240_miiphy_write(char *devname, uint32_t phy_addr, uint8_t reg, uint16_t data){
+ ag7240_mac_t *mac = ag7240_name2mac(devname);
+ uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg;
+ volatile int rddata;
+ uint16_t ii = 0xFFFF;
+
+ /*
+ * Check for previous transactions are complete. Added to avoid
+ * race condition while running at higher frequencies.
+ */
+ do {
+ udelay(5);
+ rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
+ } while(rddata && --ii);
+
+ //if(ii == 0)
+ //printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);
+
+ ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
+ ag7240_reg_wr(mac, AG7240_MII_MGMT_CTRL, data);
+
+ do {
+ rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
+ } while(rddata && --ii);
+
+}