diff options
author | Tom Rini <trini@konsulko.com> | 2015-08-12 15:46:36 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2015-08-13 07:19:41 -0400 |
commit | fcd78fa604d994477fd209b9faab4a974b103250 (patch) | |
tree | 17f5e8cecaa3579e441372e6ec5cfeecdec11c61 | |
parent | 4fbe41c4af483b082f525328796b7835536ae797 (diff) | |
parent | faa765d40760d84bff0de26a5a5f605621dbff39 (diff) | |
download | u-boot-imx-fcd78fa604d994477fd209b9faab4a974b103250.zip u-boot-imx-fcd78fa604d994477fd209b9faab4a974b103250.tar.gz u-boot-imx-fcd78fa604d994477fd209b9faab4a974b103250.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot-net
-rw-r--r-- | arch/arm/cpu/arm926ejs/lpc32xx/devices.c | 7 | ||||
-rw-r--r-- | drivers/net/davinci_emac.c | 3 | ||||
-rw-r--r-- | drivers/net/e1000.c | 34 | ||||
-rw-r--r-- | drivers/net/e1000.h | 3 | ||||
-rw-r--r-- | drivers/net/fm/eth.c | 5 | ||||
-rw-r--r-- | drivers/net/lpc32xx_eth.c | 55 | ||||
-rw-r--r-- | drivers/net/macb.c | 33 | ||||
-rw-r--r-- | drivers/net/macb.h | 9 | ||||
-rw-r--r-- | drivers/net/phy/broadcom.c | 29 | ||||
-rw-r--r-- | drivers/net/phy/marvell.c | 67 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 10 | ||||
-rw-r--r-- | drivers/net/phy/realtek.c | 8 | ||||
-rw-r--r-- | net/tftp.c | 2 |
13 files changed, 210 insertions, 55 deletions
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c index b0287be..c0c9c6c 100644 --- a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c +++ b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c @@ -45,7 +45,12 @@ void lpc32xx_mac_init(void) { /* Enable MAC interface */ writel(CLK_MAC_REG | CLK_MAC_SLAVE | CLK_MAC_MASTER - | CLK_MAC_MII, &clk->macclk_ctrl); +#if defined(CONFIG_RMII) + | CLK_MAC_RMII, +#else + | CLK_MAC_MII, +#endif + &clk->macclk_ctrl); } void lpc32xx_mlc_nand_init(void) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 427ad3e..0444795 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -598,7 +598,8 @@ static void davinci_eth_close(struct eth_device *dev) debug_emac("+ emac_close\n"); davinci_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */ - davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ + if (readl(&adap_emac->RXCONTROL) & 1) + davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ /* Reset EMAC module and disable interrupts in wrapper */ writel(1, &adap_emac->SOFTRESET); diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 96e6bb0..d5d48b1 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -126,6 +126,7 @@ static int e1000_detect_gig_phy(struct e1000_hw *hw); static void e1000_set_media_type(struct e1000_hw *hw); static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask); +static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask); static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); #ifndef CONFIG_E1000_NO_NVM @@ -729,7 +730,10 @@ void e1000_release_eeprom(struct e1000_hw *hw) eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); } + + e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM); } + /****************************************************************************** * Reads a 16 bit word from the EEPROM. * @@ -992,10 +996,6 @@ e1000_get_software_semaphore(struct e1000_hw *hw) DEBUGFUNC(); - swsm = E1000_READ_REG(hw, SWSM); - swsm &= ~E1000_SWSM_SMBI; - E1000_WRITE_REG(hw, SWSM, swsm); - if (hw->mac_type != e1000_80003es2lan) return E1000_SUCCESS; @@ -1102,6 +1102,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) return E1000_SUCCESS; } +/* Take ownership of the PHY */ static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) { @@ -1115,10 +1116,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) if (e1000_get_hw_eeprom_semaphore(hw)) return -E1000_ERR_SWFW_SYNC; - if (hw->mac_type == e1000_igb) - swfw_sync = E1000_READ_REG(hw, I210_SW_FW_SYNC); - else - swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; @@ -1141,6 +1139,21 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) return E1000_SUCCESS; } +static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync = 0; + + DEBUGFUNC(); + while (e1000_get_hw_eeprom_semaphore(hw)) + ; /* Empty */ + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + swfw_sync &= ~mask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + e1000_put_hw_eeprom_semaphore(hw); +} + static bool e1000_is_second_port(struct e1000_hw *hw) { switch (hw->mac_type) { @@ -4004,7 +4017,7 @@ e1000_wait_autoneg(struct e1000_hw *hw) DEBUGFUNC(); DEBUGOUT("Waiting for Auto-Neg to complete.\n"); - /* We will wait for autoneg to complete or 4.5 seconds to expire. */ + /* We will wait for autoneg to complete or timeout to expire. */ for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { /* Read the MII Status Register and wait for Auto-Neg * Complete bit to be set. @@ -4438,6 +4451,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) if (hw->mac_type >= e1000_82571) mdelay(10); + } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset. Then, take it out of reset. @@ -4462,6 +4476,8 @@ e1000_phy_hw_reset(struct e1000_hw *hw) E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } + e1000_swfw_sync_release(hw, swfw); + /* Wait for FW to finish PHY configuration. */ ret_val = e1000_get_phy_cfg_done(hw); if (ret_val != E1000_SUCCESS) diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index f3b77b1..23a81e6 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -2460,7 +2460,7 @@ struct e1000_hw { #define MII_CR_SPEED_100 0x2000 #define MII_CR_SPEED_10 0x0000 #define E1000_PHY_ADDRESS 0x01 -#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define PHY_AUTO_NEG_TIME 80 /* 8.0 Seconds */ #define PHY_FORCE_TIME 20 /* 2.0 Seconds */ #define PHY_REVISION_MASK 0xFFFFFFF0 #define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */ @@ -2496,7 +2496,6 @@ struct e1000_hw { #define ICH_GFPREG_BASE_MASK 0x1FFF #define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF -#define E1000_I210_SW_FW_SYNC 0x5B50 /* Software-Firmware Synchronization - RW */ #define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ /* SPI EEPROM Status Register */ diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index d7a37f3..6702f5a 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -520,6 +520,7 @@ static int fm_eth_recv(struct eth_device *dev) u16 status, len; u8 *data; u16 offset_out; + int ret = 1; fm_eth = (struct fm_eth *)dev->priv; pram = fm_eth->rx_pram; @@ -533,7 +534,7 @@ static int fm_eth_recv(struct eth_device *dev) net_process_received_packet(data, len); } else { printf("%s: Rx error\n", dev->name); - return 0; + ret = 0; } /* clear the RxBDs */ @@ -559,7 +560,7 @@ static int fm_eth_recv(struct eth_device *dev) } fm_eth->cur_rxbd = (void *)rxbd; - return 1; + return ret; } static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) diff --git a/drivers/net/lpc32xx_eth.c b/drivers/net/lpc32xx_eth.c index 8dcbb4a..f3ab0f4 100644 --- a/drivers/net/lpc32xx_eth.c +++ b/drivers/net/lpc32xx_eth.c @@ -151,7 +151,7 @@ struct lpc32xx_eth_registers { #define SUPP_SPEED 0x00000100 /* MCFG register bitfields/masks and offsets (see Table 292) */ -#define MCFG_CLOCK_SELECT_MASK 0x0000001C +#define MCFG_RESET_MII_MGMT 0x00008000 /* divide clock by 28 (see Table 293) */ #define MCFG_CLOCK_SELECT_DIV28 0x0000001C @@ -168,9 +168,10 @@ struct lpc32xx_eth_registers { #define COMMAND_RXENABLE 0x00000001 #define COMMAND_TXENABLE 0x00000002 #define COMMAND_PASSRUNTFRAME 0x00000040 +#define COMMAND_RMII 0x00000200 #define COMMAND_FULL_DUPLEX 0x00000400 /* Helper: general reset */ -#define COMMAND_RESETS 0x0000001C +#define COMMAND_RESETS 0x00000038 /* STATUS register bitfields/masks and offsets (see Table 283) */ #define STATUS_RXSTATUS 0x00000001 @@ -201,6 +202,7 @@ struct lpc32xx_eth_device { struct eth_device dev; struct lpc32xx_eth_registers *regs; struct lpc32xx_eth_buffers *bufs; + bool phy_rmii; }; #define LPC32XX_ETH_DEVICE_SIZE (sizeof(struct lpc32xx_eth_device)) @@ -359,7 +361,10 @@ int lpc32xx_eth_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr, static struct lpc32xx_eth_device lpc32xx_eth = { .regs = (struct lpc32xx_eth_registers *)LPC32XX_ETH_BASE, - .bufs = (struct lpc32xx_eth_buffers *)LPC32XX_ETH_BUFS + .bufs = (struct lpc32xx_eth_buffers *)LPC32XX_ETH_BUFS, +#if defined(CONFIG_RMII) + .phy_rmii = true, +#endif }; #define TX_TIMEOUT 10000 @@ -459,8 +464,22 @@ static int lpc32xx_eth_init(struct eth_device *dev) struct lpc32xx_eth_buffers *bufs = lpc32xx_eth_device->bufs; int index; - /* Release SOFT reset to let MII talk to PHY */ - clrbits_le32(®s->mac1, MAC1_SOFT_RESET); + /* Initial MAC initialization */ + writel(MAC1_PASS_ALL_RX_FRAMES, ®s->mac1); + writel(MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE, ®s->mac2); + writel(PKTSIZE_ALIGN, ®s->maxf); + + /* Retries: 15 (0xF). Collision window: 57 (0x37). */ + writel(0x370F, ®s->clrt); + + /* Set IP gap pt 2 to default 0x12 but pt 1 to non-default 0 */ + writel(0x0012, ®s->ipgr); + + /* pass runt (smaller than 64 bytes) frames */ + if (lpc32xx_eth_device->phy_rmii) + writel(COMMAND_PASSRUNTFRAME | COMMAND_RMII, ®s->command); + else + writel(COMMAND_PASSRUNTFRAME, ®s->command); /* Configure Full/Half Duplex mode */ if (miiphy_duplex(dev->name, CONFIG_PHY_ADDR) == FULL) { @@ -477,20 +496,6 @@ static int lpc32xx_eth_init(struct eth_device *dev) else writel(0, ®s->supp); - /* Initial MAC initialization */ - writel(MAC1_PASS_ALL_RX_FRAMES, ®s->mac1); - writel(MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE, ®s->mac2); - writel(PKTSIZE_ALIGN, ®s->maxf); - - /* Retries: 15 (0xF). Collision window: 57 (0x37). */ - writel(0x370F, ®s->clrt); - - /* Set IP gap pt 2 to default 0x12 but pt 1 to non-default 0 */ - writel(0x0012, ®s->ipgr); - - /* pass runt (smaller than 64 bytes) frames */ - writel(COMMAND_PASSRUNTFRAME, ®s->command); - /* Save station address */ writel((unsigned long) (dev->enetaddr[0] | (dev->enetaddr[1] << 8)), ®s->sa2); @@ -562,6 +567,8 @@ static int lpc32xx_eth_halt(struct eth_device *dev) #if defined(CONFIG_PHYLIB) int lpc32xx_eth_phylib_init(struct eth_device *dev, int phyid) { + struct lpc32xx_eth_device *lpc32xx_eth_device = + container_of(dev, struct lpc32xx_eth_device, dev); struct mii_dev *bus; struct phy_device *phydev; int ret; @@ -582,7 +589,11 @@ int lpc32xx_eth_phylib_init(struct eth_device *dev, int phyid) return -ENOMEM; } - phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_MII); + if (lpc32xx_eth_device->phy_rmii) + phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RMII); + else + phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_MII); + if (!phydev) { printf("phy_connect failed\n"); return -ENODEV; @@ -604,7 +615,7 @@ int lpc32xx_eth_initialize(bd_t *bis) * Set RMII management clock rate. With HCLK at 104 MHz and * a divider of 28, this will be 3.72 MHz. */ - + writel(MCFG_RESET_MII_MGMT, ®s->mcfg); writel(MCFG_CLOCK_SELECT_DIV28, ®s->mcfg); /* Reset all MAC logic */ @@ -630,7 +641,7 @@ int lpc32xx_eth_initialize(bd_t *bis) eth_register(dev); #if defined(CONFIG_PHYLIB) - lpc32xx_eth_phylib_init(dev, 0); + lpc32xx_eth_phylib_init(dev, CONFIG_PHY_ADDR); #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII) miiphy_register(dev->name, mii_reg_read, mii_reg_write); #endif diff --git a/drivers/net/macb.c b/drivers/net/macb.c index f949161..a5c1880 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -54,6 +54,7 @@ struct macb_dma_desc { #define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) #define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) +#define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1)) #define RXADDR_USED 0x00000001 #define RXADDR_WRAP 0x00000002 @@ -93,6 +94,9 @@ struct macb_device { unsigned long rx_ring_dma; unsigned long tx_ring_dma; + struct macb_dma_desc *dummy_desc; + unsigned long dummy_desc_dma; + const struct device *dev; struct eth_device netdev; unsigned short phy_addr; @@ -525,6 +529,30 @@ static int macb_phy_init(struct macb_device *macb) return 1; } +static int gmac_init_multi_queues(struct macb_device *macb) +{ + int i, num_queues = 1; + u32 queue_mask; + + /* bit 0 is never set but queue 0 always exists */ + queue_mask = gem_readl(macb, DCFG6) & 0xff; + queue_mask |= 0x1; + + for (i = 1; i < MACB_MAX_QUEUES; i++) + if (queue_mask & (1 << i)) + num_queues++; + + macb->dummy_desc->ctrl = TXBUF_USED; + macb->dummy_desc->addr = 0; + flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + + MACB_TX_DUMMY_DMA_DESC_SIZE); + + for (i = 1; i < num_queues; i++) + gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1); + + return 0; +} + static int macb_init(struct eth_device *netdev, bd_t *bd) { struct macb_device *macb = to_macb(netdev); @@ -565,6 +593,9 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) macb_writel(macb, TBQP, macb->tx_ring_dma); if (macb_is_gem(macb)) { + /* Check the multi queue and initialize the queue for tx */ + gmac_init_multi_queues(macb); + /* * When the GMAC IP with GE feature, this bit is used to * select interface between RGMII and GMII. @@ -712,6 +743,8 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) &macb->rx_ring_dma); macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, &macb->tx_ring_dma); + macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE, + &macb->dummy_desc_dma); /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 06f7c66..5bb48f4 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -60,6 +60,13 @@ /* GEM specific register offsets */ #define GEM_DCFG1 0x0280 +#define GEM_DCFG6 0x0294 + +#define MACB_MAX_QUEUES 8 + +/* GEM specific multi queues register offset */ +/* hw_q can be 0~7 */ +#define GEM_TBQP(hw_q) (0x0440 + ((hw_q) << 2)) /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 @@ -309,5 +316,7 @@ readl((port)->regs + GEM_##reg) #define gem_writel(port, reg, value) \ writel((value), (port)->regs + GEM_##reg) +#define gem_writel_queue_TBQP(port, value, queue_num) \ + writel((value), (port)->regs + GEM_TBQP(queue_num)) #endif /* __DRIVERS_MACB_H__ */ diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 4512763..4b2808e 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -137,6 +137,24 @@ static int bcm5482_config(struct phy_device *phydev) return 0; } +static int bcm_cygnus_startup(struct phy_device *phydev) +{ + /* Read the Status (2x to make sure link is right) */ + genphy_update_link(phydev); + genphy_parse_link(phydev); + + return 0; +} + +static int bcm_cygnus_config(struct phy_device *phydev) +{ + genphy_config_aneg(phydev); + + phy_reset(phydev); + + return 0; +} + /* * Find out if PHY is in copper or serdes mode by looking at Expansion Reg * 0x42 - "Operating Mode Status Register" @@ -264,11 +282,22 @@ static struct phy_driver BCM5482S_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver BCM_CYGNUS_driver = { + .name = "Broadcom CYGNUS GPHY", + .uid = 0xae025200, + .mask = 0xfffff0, + .features = PHY_GBIT_FEATURES, + .config = &bcm_cygnus_config, + .startup = &bcm_cygnus_startup, + .shutdown = &genphy_shutdown, +}; + int phy_broadcom_init(void) { phy_register(&BCM5482S_driver); phy_register(&BCM5464S_driver); phy_register(&BCM5461S_driver); + phy_register(&BCM_CYGNUS_driver); return 0; } diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 9437c3b..eab1558 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -303,30 +303,58 @@ static int m88e1518_config(struct phy_device *phydev) * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 * /88E1514 Rev A0, Errata Section 3.1 */ + + /* EEE initialization */ + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); + + /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); /* page 0xff */ - phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); - phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); - phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); - phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146); - phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233); - phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); - phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); - phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); /* reg page 0 */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); /* reg page 18 */ - /* Write HWCFG_MODE = SGMII to Copper */ + /* Select page 18 */ + phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); + + /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ m88e1518_phy_writebits(phydev, 20, 0, 3, 1); - /* Phy reset */ + /* PHY reset is necessary after changing MODE[2:0] */ m88e1518_phy_writebits(phydev, 20, 15, 1, 1); - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); /* reg page 18 */ + + /* Reset page selection */ + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); + udelay(100); } return m88e1111s_config(phydev); } +/* Marvell 88E1510 */ +static int m88e1510_config(struct phy_device *phydev) +{ + /* Select page 3 */ + phy_write(phydev, MDIO_DEVAD_NONE, 22, 3); + + /* Enable INTn output on LED[2] */ + m88e1518_phy_writebits(phydev, 18, 7, 1, 1); + + /* Configure LEDs */ + m88e1518_phy_writebits(phydev, 16, 0, 4, 3); /* LED[0]:0011 (ACT) */ + m88e1518_phy_writebits(phydev, 16, 4, 4, 6); /* LED[1]:0110 (LINK) */ + + /* Reset page selection */ + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); + + return m88e1518_config(phydev); +} + /* Marvell 88E1118 */ static int m88e1118_config(struct phy_device *phydev) { @@ -539,6 +567,16 @@ static struct phy_driver M88E1149S_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver M88E1510_driver = { + .name = "Marvell 88E1510", + .uid = 0x1410dd0, + .mask = 0xffffff0, + .features = PHY_GBIT_FEATURES, + .config = &m88e1510_config, + .startup = &m88e1011s_startup, + .shutdown = &genphy_shutdown, +}; + static struct phy_driver M88E1518_driver = { .name = "Marvell 88E1518", .uid = 0x1410dd1, @@ -569,6 +607,7 @@ int phy_marvell_init(void) phy_register(&M88E1118R_driver); phy_register(&M88E1111S_driver); phy_register(&M88E1011S_driver); + phy_register(&M88E1510_driver); phy_register(&M88E1518_driver); return 0; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index c8d08e8..65c731a 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -554,7 +554,7 @@ static struct phy_driver *get_phy_driver(struct phy_device *phydev, } static struct phy_device *phy_device_create(struct mii_dev *bus, int addr, - int phy_id, + u32 phy_id, phy_interface_t interface) { struct phy_device *dev; @@ -763,11 +763,13 @@ struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask, phy_interface_t interface) { /* Reset the bus */ - if (bus->reset) + if (bus->reset) { bus->reset(bus); - /* Wait 15ms to make sure the PHY has come out of hard reset */ - udelay(15000); + /* Wait 15ms to make sure the PHY has come out of hard reset */ + udelay(15000); + } + return get_phy_device_by_mask(bus, phy_mask, interface); } diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 79452a8..bba48da 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -41,6 +41,7 @@ #define MIIM_RTL8211F_PAGE_SELECT 0x1f #define MIIM_RTL8211F_TX_DELAY 0x100 +#define MIIM_RTL8211F_LCR 0x10 /* RealTek RTL8211x */ static int rtl8211x_config(struct phy_device *phydev) @@ -79,6 +80,13 @@ static int rtl8211f_config(struct phy_device *phydev) MIIM_RTL8211F_PAGE_SELECT, 0x0); } + /* Set green LED for Link, yellow LED for Active */ + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT, 0xd04); + phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x617f); + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT, 0x0); + genphy_config_aneg(phydev); return 0; @@ -249,6 +249,8 @@ static void show_block_marker(void) if (tftp_tsize) { ulong pos = tftp_cur_block * tftp_block_size + tftp_block_wrap_offset; + if (pos > tftp_tsize) + pos = tftp_tsize; while (tftp_tsize_num_hash < pos * 50 / tftp_tsize) { putc('#'); |