From f81ecb5d3300bf92d17302d3712f30585c182da9 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 17 Aug 2009 15:55:38 -0500 Subject: 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 diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 777783a..b8dd9f2 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 */ -- cgit v0.10.2 From bb1ca3b27f7fba8c73cb10279a6a8b8b69a308ff Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 20 Aug 2009 10:12:28 +0200 Subject: arm:kirkwood Define kirkwood phy address magic number Signed-off-by: Simon Kagstrom Signed-off-by: Ben Warren diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c index f31fefc..065e335 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; -- cgit v0.10.2 From cad713bf7548b9e90433dac8270165402a6c9cc3 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 20 Aug 2009 10:13:06 +0200 Subject: 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 diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c index 065e335..9f36633 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; } -- cgit v0.10.2 From 477fa6378fbd3e47a5e2e83d0dd3970d5b1c8371 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 20 Aug 2009 10:14:11 +0200 Subject: 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 diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c index 9f36633..479035d 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 9c893d1..16d5214 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__ */ -- cgit v0.10.2 From b1e849f2201bbbf3ca81fde164f154f9caf7f0e9 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Wed, 4 Feb 2009 15:14:05 -0600 Subject: 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 diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index a9ba683..9c9fd37 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; } -- cgit v0.10.2