From f81ecb5d3300bf92d17302d3712f30585c182da9 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 17 Aug 2009 15:55:38 -0500 Subject: [PATCH 1/5] e1000: fix PCI memory addressing The Intel E1000 driver was making assumptions about the relationship between some virtual, physical, and PCI addresses. Also fix some bad usage of the DEBUGOUT macro Signed-off-by: Timur Tabi Acked-by: Kumar Gala Signed-off-by: Ben Warren --- drivers/net/e1000.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 777783a91..b8dd9f2fe 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -46,8 +46,7 @@ tested on both gig copper and gig fiber boards #define TOUT_LOOP 100000 -#undef virt_to_bus -#define virt_to_bus(x) ((unsigned long)x) +#define virt_to_bus(devno, v) pci_virt_to_mem(devno, (void *) (v)) #define bus_to_phys(devno, a) pci_mem_to_phys(devno, a) #define mdelay(n) udelay((n)*1000) @@ -357,7 +356,7 @@ e1000_acquire_eeprom(struct e1000_hw *hw) struct e1000_eeprom_info *eeprom = &hw->eeprom; uint32_t eecd, i = 0; - DEBUGOUT(); + DEBUGFUNC(); if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) return -E1000_ERR_SWFW_SYNC; @@ -418,7 +417,7 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) int32_t ret_val = E1000_SUCCESS; uint16_t eeprom_size; - DEBUGOUT(); + DEBUGFUNC(); switch (hw->mac_type) { case e1000_82542_rev2_0: @@ -2355,7 +2354,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) int32_t ret_val; uint16_t phy_data; - DEBUGOUT(); + DEBUGFUNC(); if (hw->phy_reset_disable) return E1000_SUCCESS; @@ -5017,7 +5016,7 @@ e1000_transmit(struct eth_device *nic, volatile void *packet, int length) txp = tx_base + tx_tail; tx_tail = (tx_tail + 1) % 8; - txp->buffer_addr = cpu_to_le64(virt_to_bus(packet)); + txp->buffer_addr = cpu_to_le64(virt_to_bus(hw->pdev, packet)); txp->lower.data = cpu_to_le32(hw->txd_cmd | length); txp->upper.data = 0; E1000_WRITE_REG(hw, TDT, tx_tail); @@ -5145,6 +5144,8 @@ e1000_initialize(bd_t * bis) int idx = 0; u32 PciCommandWord; + DEBUGFUNC(); + while (1) { /* Find PCI device(s) */ if ((devno = pci_find_devices(supported, idx++)) < 0) { break; @@ -5170,7 +5171,6 @@ e1000_initialize(bd_t * bis) hw = (struct e1000_hw *) malloc(sizeof (*hw)); hw->pdev = devno; nic->priv = hw; - nic->iobase = bus_to_phys(devno, iobase); sprintf(nic->name, "e1000#%d", card_number); @@ -5180,7 +5180,8 @@ e1000_initialize(bd_t * bis) hw->autoneg_failed = 0; hw->autoneg = 1; hw->get_link_status = TRUE; - hw->hw_addr = (typeof(hw->hw_addr)) iobase; + hw->hw_addr = + pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hw->mac_type = e1000_undefined; /* MAC and Phy settings */ From bb1ca3b27f7fba8c73cb10279a6a8b8b69a308ff Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 20 Aug 2009 10:12:28 +0200 Subject: [PATCH 2/5] arm:kirkwood Define kirkwood phy address magic number Signed-off-by: Simon Kagstrom Signed-off-by: Ben Warren --- drivers/net/kirkwood_egiga.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c index f31fefcb0..065e33511 100644 --- a/drivers/net/kirkwood_egiga.c +++ b/drivers/net/kirkwood_egiga.c @@ -38,6 +38,8 @@ #include #include "kirkwood_egiga.h" +#define KIRKWOOD_PHY_ADR_REQUEST 0xee + /* * smi_reg_read - miiphy_read callback function. * @@ -52,7 +54,8 @@ static int smi_reg_read(char *devname, u8 phy_adr, u8 reg_ofs, u16 * data) u32 timeout; /* Phyadr read request */ - if (phy_adr == 0xEE && reg_ofs == 0xEE) { + if (phy_adr == KIRKWOOD_PHY_ADR_REQUEST && + reg_ofs == KIRKWOOD_PHY_ADR_REQUEST) { /* */ *data = (u16) (KWGBEREG_RD(regs->phyadr) & PHYADR_MASK); return 0; @@ -127,7 +130,8 @@ static int smi_reg_write(char *devname, u8 phy_adr, u8 reg_ofs, u16 data) u32 timeout; /* Phyadr write request*/ - if (phy_adr == 0xEE && reg_ofs == 0xEE) { + if (phy_adr == KIRKWOOD_PHY_ADR_REQUEST && + reg_ofs == KIRKWOOD_PHY_ADR_REQUEST) { KWGBEREG_WR(regs->phyadr, data); return 0; } @@ -444,7 +448,8 @@ static int kwgbe_init(struct eth_device *dev) #if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) u16 phyadr; - miiphy_read(dev->name, 0xEE, 0xEE, &phyadr); + miiphy_read(dev->name, KIRKWOOD_PHY_ADR_REQUEST, + KIRKWOOD_PHY_ADR_REQUEST, &phyadr); if (!miiphy_link(dev->name, phyadr)) { printf("%s: No link on %s\n", __FUNCTION__, dev->name); return -1; @@ -670,7 +675,8 @@ int kirkwood_egiga_initialize(bd_t * bis) #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) miiphy_register(dev->name, smi_reg_read, smi_reg_write); /* Set phy address of the port */ - miiphy_write(dev->name, 0xEE, 0xEE, PHY_BASE_ADR + devnum); + miiphy_write(dev->name, KIRKWOOD_PHY_ADR_REQUEST, + KIRKWOOD_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum); #endif } return 0; From cad713bf7548b9e90433dac8270165402a6c9cc3 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 20 Aug 2009 10:13:06 +0200 Subject: [PATCH 3/5] Wait for the link to come up on kirkwood network init This patch makes the device wait for up to 5 seconds for the link to come up, similar to what many of the other network drivers do. This avoids confusing situations where, e.g., a tftp fails when initiated early after U-boot has started (before the link has come up). Signed-off-by: Simon Kagstrom Signed-off-by: Ben Warren --- drivers/net/kirkwood_egiga.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c index 065e33511..9f3663379 100644 --- a/drivers/net/kirkwood_egiga.c +++ b/drivers/net/kirkwood_egiga.c @@ -400,6 +400,7 @@ static int kwgbe_init(struct eth_device *dev) { struct kwgbe_device *dkwgbe = to_dkwgbe(dev); struct kwgbe_registers *regs = dkwgbe->regs; + int i; /* setup RX rings */ kwgbe_init_rx_desc_ring(dkwgbe); @@ -447,13 +448,20 @@ static int kwgbe_init(struct eth_device *dev) #if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) - u16 phyadr; - miiphy_read(dev->name, KIRKWOOD_PHY_ADR_REQUEST, - KIRKWOOD_PHY_ADR_REQUEST, &phyadr); - if (!miiphy_link(dev->name, phyadr)) { - printf("%s: No link on %s\n", __FUNCTION__, dev->name); - return -1; + /* Wait up to 5s for the link status */ + for (i = 0; i < 5; i++) { + u16 phyadr; + + miiphy_read(dev->name, KIRKWOOD_PHY_ADR_REQUEST, + KIRKWOOD_PHY_ADR_REQUEST, &phyadr); + /* Return if we get link up */ + if (miiphy_link(dev->name, phyadr)) + return 0; + udelay(1000000); } + + printf("No link on %s\n", dev->name); + return -1; #endif return 0; } From 477fa6378fbd3e47a5e2e83d0dd3970d5b1c8371 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 20 Aug 2009 10:14:11 +0200 Subject: [PATCH 4/5] arm: kirkwood: See to it that sent data is 8-byte aligned U-boot might use non-8-byte-aligned addresses for sending data, which the kwgbe_send doesn't accept (bootp does this for me). This patch copies the data to be sent to a malloced temporary buffer if it is non-aligned. Signed-off-by: Simon Kagstrom Signed-off-by: Ben Warren --- drivers/net/kirkwood_egiga.c | 21 +++++++++++++++++---- drivers/net/kirkwood_egiga.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c index 9f3663379..479035d55 100644 --- a/drivers/net/kirkwood_egiga.c +++ b/drivers/net/kirkwood_egiga.c @@ -500,18 +500,26 @@ static int kwgbe_send(struct eth_device *dev, volatile void *dataptr, struct kwgbe_device *dkwgbe = to_dkwgbe(dev); struct kwgbe_registers *regs = dkwgbe->regs; struct kwgbe_txdesc *p_txdesc = dkwgbe->p_txdesc; + void *p = (void *)dataptr; u32 cmd_sts; + /* Copy buffer if it's misaligned */ if ((u32) dataptr & 0x07) { - printf("Err..(%s) xmit dataptr not 64bit aligned\n", - __FUNCTION__); - return -1; + if (datasize > PKTSIZE_ALIGN) { + printf("Non-aligned data too large (%d)\n", + datasize); + return -1; + } + + memcpy(dkwgbe->p_aligned_txbuf, p, datasize); + p = dkwgbe->p_aligned_txbuf; } + p_txdesc->cmd_sts = KWGBE_ZERO_PADDING | KWGBE_GEN_CRC; p_txdesc->cmd_sts |= KWGBE_TX_FIRST_DESC | KWGBE_TX_LAST_DESC; p_txdesc->cmd_sts |= KWGBE_BUFFER_OWNED_BY_DMA; p_txdesc->cmd_sts |= KWGBE_TX_EN_INTERRUPT; - p_txdesc->buf_ptr = (u8 *) dataptr; + p_txdesc->buf_ptr = (u8 *) p; p_txdesc->byte_cnt = datasize; /* Apply send command using zeroth RXUQ */ @@ -628,8 +636,13 @@ int kirkwood_egiga_initialize(bd_t * bis) * PKTSIZE_ALIGN + 1))) goto error3; + if (!(dkwgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN))) + goto error4; + if (!(dkwgbe->p_txdesc = (struct kwgbe_txdesc *) memalign(PKTALIGN, sizeof(struct kwgbe_txdesc) + 1))) { + free(dkwgbe->p_aligned_txbuf); + error4: free(dkwgbe->p_rxbuf); error3: free(dkwgbe->p_rxdesc); diff --git a/drivers/net/kirkwood_egiga.h b/drivers/net/kirkwood_egiga.h index 9c893d131..16d52141e 100644 --- a/drivers/net/kirkwood_egiga.h +++ b/drivers/net/kirkwood_egiga.h @@ -499,6 +499,7 @@ struct kwgbe_device { struct kwgbe_rxdesc *p_rxdesc; struct kwgbe_rxdesc *p_rxdesc_curr; u8 *p_rxbuf; + u8 *p_aligned_txbuf; }; #endif /* __EGIGA_H__ */ From b1e849f2201bbbf3ca81fde164f154f9caf7f0e9 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Wed, 4 Feb 2009 15:14:05 -0600 Subject: [PATCH 5/5] tsec: Wait for auto-negotiation to complete without link Previously, waiting for auto-negotiation would only occur if a valid link had been detected. Problems arose when attempting to use a tsec immediately after bootup but before link was achieved, eg: => dhcp Auto-neg error, defaulting to 10BT/HD eTSEC1: No link. Auto-neg error, defaulting to 10BT/HD eTSEC2: No link. => With this patch applied the same operation as above resulted in: => dhcp Waiting for PHY auto negotiation to complete. done Enet starting in 1000BT/FD Speed: 1000, full duplex Signed-off-by: Peter Tyser Signed-off-by: Ben Warren --- drivers/net/tsec.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index a9ba68399..9c9fd377c 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -356,8 +356,8 @@ uint mii_cr_init(uint mii_reg, struct tsec_private * priv) return MIIM_CR_INIT; } -/* Parse the status register for link, and then do - * auto-negotiation +/* + * Wait for auto-negotiation to complete, then determine link */ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) { @@ -366,8 +366,7 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) * (ie - we're capable and it's not done) */ mii_reg = read_phy_reg(priv, MIIM_STATUS); - if ((mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE) - && !(mii_reg & PHY_BMSR_AUTN_COMP)) { + if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) { int i = 0; puts("Waiting for PHY auto negotiation to complete"); @@ -388,15 +387,15 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) mii_reg = read_phy_reg(priv, MIIM_STATUS); } puts(" done\n"); - priv->link = 1; + + /* Link status bit is latched low, read it again */ + mii_reg = read_phy_reg(priv, MIIM_STATUS); + udelay(500000); /* another 500 ms (results in faster booting) */ - } else { - if (mii_reg & MIIM_STATUS_LINK) - priv->link = 1; - else - priv->link = 0; } + priv->link = mii_reg & MIIM_STATUS_LINK ? 1 : 0; + return 0; }