From f754f5dc6fe4b6cfbd28a9a6d9d08059d9312101 Mon Sep 17 00:00:00 2001 From: rockly Date: Sat, 3 Aug 2013 18:09:05 +0800 Subject: [PATCH 01/40] net: tftp: Make sure timeout will not effect wrap offset When the block 0 store to the memory of client and timeout at this moment. Because of no ACK packet, the server will send block 0 again, if this client reconnect to the server at this time, TftpBlockWrapOffset will become larger than it should be. Signed-off-by: Rockly Patch: 264417 --- net/tftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tftp.c b/net/tftp.c index 6d333d5..2e06808 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -281,7 +281,7 @@ static void update_block_number(void) * number of 0 this means that there was a wrap * around of the (16 bit) counter. */ - if (TftpBlock == 0) { + if (TftpBlock == 0 && TftpLastBlock != 0) { TftpBlockWrap++; TftpBlockWrapOffset += TftpBlkSize * TFTP_SEQUENCE_SIZE; TftpTimeoutCount = 0; /* we've done well, reset thhe timeout */ From 626ee1e32eeb4fc89e0f406d6067ed6e71d8302f Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Thu, 8 Aug 2013 16:33:35 +0800 Subject: [PATCH 02/40] phylib: update atheros ar803x phy As AR8031 and AR8033 have same PHY ID 0x4dd074, they use the common driver. Currently AR8031_driver didn't work for AR8033, hence updated it to have it work on AR8031/AR8033. Signed-off-by: Shengzhou Liu --- drivers/net/phy/atheros.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 0f2dfd6..7a1453f 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -48,11 +48,11 @@ static struct phy_driver AR8021_driver = { }; static struct phy_driver AR8031_driver = { - .name = "AR8031", + .name = "AR8031/AR8033", .uid = 0x4dd074, .mask = 0xfffff0, .features = PHY_GBIT_FEATURES, - .config = genphy_config, + .config = ar8021_config, .startup = genphy_startup, .shutdown = genphy_shutdown, }; From 57d33d4b4063ef731c35ba5b7b03e2e510c4ee65 Mon Sep 17 00:00:00 2001 From: Stephan Bauroth Date: Thu, 8 Aug 2013 13:44:41 +0200 Subject: [PATCH 03/40] net: trivial: Fix typos in mii field descriptions Signed-off-by: Stephan Bauroth Patch: 265707 --- common/cmd_mii.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/cmd_mii.c b/common/cmd_mii.c index d3dd6b1..b82a7ce 100644 --- a/common/cmd_mii.c +++ b/common/cmd_mii.c @@ -78,9 +78,9 @@ static const MII_field_desc_t reg_3_desc_tbl[] = { static const MII_field_desc_t reg_4_desc_tbl[] = { { 15, 15, 0x01, "next page able" }, - { 14, 14, 0x01, "reserved" }, + { 14, 14, 0x01, "(reserved)" }, { 13, 13, 0x01, "remote fault" }, - { 12, 12, 0x01, "reserved" }, + { 12, 12, 0x01, "(reserved)" }, { 11, 11, 0x01, "asymmetric pause" }, { 10, 10, 0x01, "pause enable" }, { 9, 9, 0x01, "100BASE-T4 able" }, From 0611c6017c9fc56a731ee5f8bbd91c7ee1a50849 Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Sun, 11 Aug 2013 17:08:23 +0200 Subject: [PATCH 04/40] NET: mvgbe: avoid unused variable warning when used without phylib support Avoid a recently introduced unused variable warning for boards that use mvgbe but not phylib. Signed-off-by: Sascha Silbe Patch: 266334 --- drivers/net/mvgbe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c index 6c901d1..0cd06b6 100644 --- a/drivers/net/mvgbe.c +++ b/drivers/net/mvgbe.c @@ -420,8 +420,9 @@ static int mvgbe_init(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); struct mvgbe_registers *regs = dmvgbe->regs; -#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ - && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) +#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ + !defined(CONFIG_PHYLIB) && \ + defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) int i; #endif /* setup RX rings */ From 870cc23f07c725e6218a77b25314193ef6fbd1b4 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 22 Aug 2013 13:22:01 +0900 Subject: [PATCH 05/40] net: sh-eth: Change cache API of SH The cache API of SH was changed from dcache_wback_range to flush_dcache_range. sh-eth uses dcache_wback_range. This patch changes to flush_dcache_range. Signed-off-by: Nobuhiro Iwamatsu --- drivers/net/sh_eth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index d5a83e0..4cfd1e5 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -25,9 +25,10 @@ #ifndef CONFIG_SH_ETHER_PHY_ADDR # error "Please define CONFIG_SH_ETHER_PHY_ADDR" #endif + #ifdef CONFIG_SH_ETHER_CACHE_WRITEBACK #define flush_cache_wback(addr, len) \ - dcache_wback_range((u32)addr, (u32)(addr + len - 1)) + flush_dcache_range((u32)addr, (u32)(addr + len - 1)) #else #define flush_cache_wback(...) #endif From f8b7507d41e9d2607e876b74f6ce79235f6bd618 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 22 Aug 2013 13:22:02 +0900 Subject: [PATCH 06/40] net: sh-eth: Add control for padding size of packet descriptor sh-eth can change the alignment size of a packet descriptor according to BUS size. This patch adds this function. Signed-off-by: Hisashi Nakamura Signed-off-by: Nobuhiro Iwamatsu --- drivers/net/sh_eth.c | 13 ++++++++----- drivers/net/sh_eth.h | 27 ++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 4cfd1e5..c038929 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -238,15 +238,17 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth) * Allocate rx data buffers. They must be 32 bytes aligned and in * P2 area */ - port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + 31); + port_info->rx_buf_malloc = malloc( + NUM_RX_DESC * MAX_BUF_SIZE + RX_BUF_ALIGNE_SIZE - 1); if (!port_info->rx_buf_malloc) { printf(SHETHER_NAME ": malloc failed\n"); ret = -ENOMEM; goto err_buf_malloc; } - tmp_addr = (u32)(((int)port_info->rx_buf_malloc + (32 - 1)) & - ~(32 - 1)); + tmp_addr = (u32)(((int)port_info->rx_buf_malloc + + (RX_BUF_ALIGNE_SIZE - 1)) & + ~(RX_BUF_ALIGNE_SIZE - 1)); port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr); /* Initialize all descriptors */ @@ -352,8 +354,9 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) struct phy_device *phy; /* Configure e-dmac registers */ - sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) | EDMR_EL, - EDMR); + sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) | + (EMDR_DESC | EDMR_EL), EDMR); + sh_eth_write(eth, 0, EESIPR); sh_eth_write(eth, 0, TRSCER); sh_eth_write(eth, 0, TFTR); diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 9ad800e..35a1eee 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -31,6 +31,11 @@ #define ADDR_TO_P2(addr) (addr) #endif /* defined(CONFIG_SH) */ +/* base padding size is 16 */ +#ifndef CONFIG_SH_ETHER_ALIGNE_SIZE +#define CONFIG_SH_ETHER_ALIGNE_SIZE 16 +#endif + /* Number of supported ports */ #define MAX_PORT_NUM 2 @@ -45,15 +50,16 @@ /* The size of the tx descriptor is determined by how much padding is used. 4, 20, or 52 bytes of padding can be used */ -#define TX_DESC_PADDING 4 -#define TX_DESC_SIZE (12 + TX_DESC_PADDING) +#define TX_DESC_PADDING (CONFIG_SH_ETHER_ALIGNE_SIZE - 12) +/* same as CONFIG_SH_ETHER_ALIGNE_SIZE */ +#define TX_DESC_SIZE (12 + TX_DESC_PADDING) /* Tx descriptor. We always use 3 bytes of padding */ struct tx_desc_s { volatile u32 td0; u32 td1; u32 td2; /* Buffer start */ - u32 padding; + u8 padding[TX_DESC_PADDING]; /* aligned cache line size */ }; /* There is no limitation in the number of rx descriptors */ @@ -61,15 +67,18 @@ struct tx_desc_s { /* The size of the rx descriptor is determined by how much padding is used. 4, 20, or 52 bytes of padding can be used */ -#define RX_DESC_PADDING 4 +#define RX_DESC_PADDING (CONFIG_SH_ETHER_ALIGNE_SIZE - 12) +/* same as CONFIG_SH_ETHER_ALIGNE_SIZE */ #define RX_DESC_SIZE (12 + RX_DESC_PADDING) +/* aligned cache line size */ +#define RX_BUF_ALIGNE_SIZE (CONFIG_SH_ETHER_ALIGNE_SIZE > 32 ? 64 : 32) /* Rx descriptor. We always use 4 bytes of padding */ struct rx_desc_s { volatile u32 rd0; volatile u32 rd1; u32 rd2; /* Buffer start */ - u32 padding; + u8 padding[TX_DESC_PADDING]; /* aligned cache line size */ }; struct sh_eth_info { @@ -320,6 +329,14 @@ enum DMAC_M_BIT { #endif }; +#if CONFIG_SH_ETHER_ALIGNE_SIZE == 64 +# define EMDR_DESC EDMR_DL1 +#elif CONFIG_SH_ETHER_ALIGNE_SIZE == 32 +# define EMDR_DESC EDMR_DL0 +#elif CONFIG_SH_ETHER_ALIGNE_SIZE == 16 /* Default */ +# define EMDR_DESC 0 +#endif + /* RFLR */ #define RFLR_RFL_MIN 0x05EE /* Recv Frame length 1518 byte */ From 92f0713408859952cf82a9a4f368b2459cd1619f Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 22 Aug 2013 13:22:03 +0900 Subject: [PATCH 07/40] net: sh-eth: Add invalidate cache control for rmobile (ARM SoC) The sh-eth of rmobile needs to use invalidate_cache* function. This patch adds invalidate_cache* function. Signed-off-by: Hisashi Nakamura Signed-off-by: Nobuhiro Iwamatsu Patch: 268948 --- drivers/net/sh_eth.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index c038929..6a78df0 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -26,13 +26,30 @@ # error "Please define CONFIG_SH_ETHER_PHY_ADDR" #endif -#ifdef CONFIG_SH_ETHER_CACHE_WRITEBACK -#define flush_cache_wback(addr, len) \ - flush_dcache_range((u32)addr, (u32)(addr + len - 1)) +#if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && !defined(CONFIG_SYS_DCACHE_OFF) +#define flush_cache_wback(addr, len) \ + flush_dcache_range((u32)addr, (u32)(addr + len - 1)) #else #define flush_cache_wback(...) #endif +#if defined(CONFIG_SH_ETHER_CACHE_INVALIDATE) && defined(CONFIG_ARM) +#define invalidate_cache(addr, len) \ + { \ + u32 line_size = CONFIG_SH_ETHER_ALIGNE_SIZE; \ + u32 start, end; \ + \ + start = (u32)addr; \ + end = start + len; \ + start &= ~(line_size - 1); \ + end = ((end + line_size - 1) & ~(line_size - 1)); \ + \ + invalidate_dcache_range(start, end); \ + } +#else +#define invalidate_cache(...) +#endif + #define TIMEOUT_CNT 1000 int sh_eth_send(struct eth_device *dev, void *packet, int len) @@ -70,8 +87,11 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len) /* Wait until packet is transmitted */ timeout = TIMEOUT_CNT; - while (port_info->tx_desc_cur->td0 & TD_TACT && timeout--) + do { + invalidate_cache(port_info->tx_desc_cur, + sizeof(struct tx_desc_s)); udelay(100); + } while (port_info->tx_desc_cur->td0 & TD_TACT && timeout--); if (timeout < 0) { printf(SHETHER_NAME ": transmit timeout\n"); @@ -95,12 +115,14 @@ int sh_eth_recv(struct eth_device *dev) uchar *packet; /* Check if the rx descriptor is ready */ + invalidate_cache(port_info->rx_desc_cur, sizeof(struct rx_desc_s)); if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) { /* Check for errors */ if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) { len = port_info->rx_desc_cur->rd1 & 0xffff; packet = (uchar *) ADDR_TO_P2(port_info->rx_desc_cur->rd2); + invalidate_cache(packet, len); NetReceive(packet, len); } @@ -109,7 +131,6 @@ int sh_eth_recv(struct eth_device *dev) port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE; else port_info->rx_desc_cur->rd0 = RD_RACT; - /* Point to the next descriptor */ port_info->rx_desc_cur++; if (port_info->rx_desc_cur >= From 8707678cc420050285b7694292760c29d080192c Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 22 Aug 2013 13:22:04 +0900 Subject: [PATCH 08/40] net: sh-eth: Add support R8A7790 R8A7790 has the same sh-ether IP core as other SH/rmobile. This patch adds support of R8A7790. Signed-off-by: Hisashi Nakamura Signed-off-by: Nobuhiro Iwamatsu --- drivers/net/sh_eth.c | 5 ++++- drivers/net/sh_eth.h | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 6a78df0..9020752 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -4,6 +4,7 @@ * Copyright (C) 2008, 2011 Renesas Solutions Corp. * Copyright (c) 2008, 2011 Nobuhiro Iwamatsu * Copyright (c) 2007 Carlos Munoz + * Copyright (C) 2013 Renesas Electronics Corporation * * SPDX-License-Identifier: GPL-2.0+ */ @@ -409,6 +410,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) #if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740) sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII); +#elif defined(CONFIG_R8A7790) + sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR); #endif /* Configure phy */ ret = sh_eth_phy_config(eth); @@ -432,7 +435,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) sh_eth_write(eth, GECMR_100B, GECMR); #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752) sh_eth_write(eth, 1, RTRATE); -#elif defined(CONFIG_CPU_SH7724) +#elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) val = ECMR_RTM; #endif } else if (phy->speed == 10) { diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 35a1eee..43b8ac9 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -166,6 +166,7 @@ enum { TLFRCR, CERCR, CEECR, + RMIIMR, /* R8A7790 */ MAFCR, RTRATE, CSMR, @@ -272,6 +273,7 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { [RMCR] = 0x0058, [TFUCR] = 0x0064, [RFOCR] = 0x0068, + [RMIIMR] = 0x006C, [FCFTR] = 0x0070, [RPADIR] = 0x0078, [TRIMD] = 0x007c, @@ -299,6 +301,9 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { #elif defined(CONFIG_R8A7740) #define SH_ETH_TYPE_GETHER #define BASE_IO_ADDR 0xE9A00000 +#elif defined(CONFIG_R8A7790) +#define SH_ETH_TYPE_ETHER +#define BASE_IO_ADDR 0xEE700200 #endif /* @@ -502,6 +507,8 @@ enum FELIC_MODE_BIT { ECMR_PRM = 0x00000001, #ifdef CONFIG_CPU_SH7724 ECMR_RTM = 0x00000010, +#elif defined(CONFIG_R8A7790) + ECMR_RTM = 0x00000004, #endif }; From e97a78cfed113dfbf9a0db712624bca69065c3a1 Mon Sep 17 00:00:00 2001 From: Arpit Goel Date: Fri, 23 Aug 2013 20:18:05 +0530 Subject: [PATCH 09/40] net: phy/vitesse: Add support for VSC8514 phy module This patch adds support for VSC8514 PHY module which can be found on Freescale's T1040RDB boards. Signed-off-by: Arpit Goel Signed-off-by: Bhupesh Sharma --- drivers/net/phy/vitesse.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 5cf103e..c555979 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -49,6 +49,15 @@ #define MIIM_VSC8574_18G_QSGMII 0x80e0 #define MIIM_VSC8574_18G_CMDSTAT 0x8000 +/* Vitesse VSC8514 control register */ +#define MIIM_VSC8514_GENERAL18 0x12 +#define MIIM_VSC8514_GENERAL19 0x13 +#define MIIM_VSC8514_GENERAL23 0x17 + +/* Vitesse VSC8514 gerenal purpose register 18 */ +#define MIIM_VSC8514_18G_QSGMII 0x80e0 +#define MIIM_VSC8514_18G_CMDSTAT 0x8000 + /* CIS8201 */ static int vitesse_config(struct phy_device *phydev) { @@ -148,7 +157,7 @@ static int vsc8601_config(struct phy_device *phydev) static int vsc8574_config(struct phy_device *phydev) { u32 val; - /* configure regiser 19G for MAC */ + /* configure register 19G for MAC */ phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, PHY_EXT_PAGE_ACCESS_GENERAL); @@ -188,6 +197,53 @@ static int vsc8574_config(struct phy_device *phydev) return 0; } +static int vsc8514_config(struct phy_device *phydev) +{ + u32 val; + int timeout = 1000000; + + /* configure register to access 19G */ + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_GENERAL); + + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL19); + if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { + /* set bit 15:14 to '01' for QSGMII mode */ + val = (val & 0x3fff) | (1 << 14); + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL19, val); + /* Enable 4 ports MAC QSGMII */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18, + MIIM_VSC8514_18G_QSGMII); + } else { + /*TODO Add SGMII functionality once spec sheet + * for VSC8514 defines complete functionality + */ + } + + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18); + /* When bit 15 is cleared the command has completed */ + while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--) + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18); + + if (0 == timeout) { + printf("PHY 8514 config failed\n"); + return -1; + } + + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); + + /* configure register to access 23 */ + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23); + /* set bits 10:8 to '000' */ + val = (val & 0xf8ff); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val); + + genphy_config_aneg(phydev); + + return 0; +} + static struct phy_driver VSC8211_driver = { .name = "Vitesse VSC8211", .uid = 0xfc4b0, @@ -238,6 +294,16 @@ static struct phy_driver VSC8574_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver VSC8514_driver = { + .name = "Vitesse VSC8514", + .uid = 0x70570, + .mask = 0xffff0, + .features = PHY_GBIT_FEATURES, + .config = &vsc8514_config, + .startup = &vitesse_startup, + .shutdown = &genphy_shutdown, +}; + static struct phy_driver VSC8601_driver = { .name = "Vitesse VSC8601", .uid = 0x70420, @@ -298,6 +364,7 @@ int phy_vitesse_init(void) phy_register(&VSC8211_driver); phy_register(&VSC8221_driver); phy_register(&VSC8574_driver); + phy_register(&VSC8514_driver); phy_register(&VSC8662_driver); phy_register(&cis8201_driver); phy_register(&cis8204_driver); From 42205047674d7fc9e0aa747273fbc7dcfbac3183 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Sun, 1 Sep 2013 04:40:52 +0530 Subject: [PATCH 10/40] net/phy: realtek: Fix the PHY ID mask to ensure the correct Realtek PHY is detected The 'get_phy_driver' code in 'drivers/net/phy/phy.c' uses the following method to determine which driver is to be loaded for a particular PHY module: list_for_each(entry, &phy_drivers) { drv = list_entry(entry, struct phy_driver, list); if ((drv->uid & drv->mask) == (phy_id & drv->mask)) return drv; } This means that a drv->mask of 0xfffff0 will return incorrect phy driver for the logic above, even if the drv->uid is anything other than something ending with a 0x0. For e.g. if the RTL8211E drv->uid is 0x1cc915 and drv->mask is 0xffffff and the RTL8211B drv->uid is 0x1cc910 and drv->mask is 0xffffff0, then the phy driver selected will always be RTL8211B even though the underlying phy connected on the board is a 8211E module. This patch fixes this issue. Signed-off-by: Bhupesh Sharma --- drivers/net/phy/realtek.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index ddbbc35..a3ace68 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -102,7 +102,7 @@ static int rtl8211x_startup(struct phy_device *phydev) static struct phy_driver RTL8211B_driver = { .name = "RealTek RTL8211B", .uid = 0x1cc910, - .mask = 0xfffff0, + .mask = 0xffffff, .features = PHY_GBIT_FEATURES, .config = &rtl8211x_config, .startup = &rtl8211x_startup, @@ -113,7 +113,7 @@ static struct phy_driver RTL8211B_driver = { static struct phy_driver RTL8211E_driver = { .name = "RealTek RTL8211E", .uid = 0x1cc915, - .mask = 0xfffff0, + .mask = 0xffffff, .features = PHY_GBIT_FEATURES, .config = &rtl8211x_config, .startup = &rtl8211x_startup, @@ -124,7 +124,7 @@ static struct phy_driver RTL8211E_driver = { static struct phy_driver RTL8211DN_driver = { .name = "RealTek RTL8211DN", .uid = 0x1cc914, - .mask = 0xfffff0, + .mask = 0xffffff, .features = PHY_GBIT_FEATURES, .config = &rtl8211x_config, .startup = &rtl8211x_startup, From 71817a16f1f0848b268ea627197e2b65cdc550ed Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 2 Sep 2013 15:42:28 +0200 Subject: [PATCH 11/40] phy: add missing constants for Micrel KSZ9031 Signed-off-by: Stefano Babic --- include/micrel.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/micrel.h b/include/micrel.h index e1c62d8..04c9ecf 100644 --- a/include/micrel.h +++ b/include/micrel.h @@ -15,6 +15,11 @@ #define MII_KSZ9031_MOD_DATA_POST_INC_RW 0x8000 #define MII_KSZ9031_MOD_DATA_POST_INC_W 0xC000 +#define MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW 0x4 +#define MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW 0x5 +#define MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW 0x6 +#define MII_KSZ9031_EXT_RGMII_CLOCK_SKEW 0x8 + struct phy_device; int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val); int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum); From e8194d58bd342631977d1e09d873784d145c7077 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 2 Sep 2013 15:42:29 +0200 Subject: [PATCH 12/40] net: fix mask for phy Micrel KSZ9031 Signed-off-by: Stefano Babic --- drivers/net/phy/micrel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index a7450f8..f3e3054 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -174,7 +174,7 @@ int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr, static struct phy_driver ksz9031_driver = { .name = "Micrel ksz9031", .uid = 0x221620, - .mask = 0xfffffe, + .mask = 0xfffff0, .features = PHY_GBIT_FEATURES, .config = &genphy_config, .startup = &ksz90xx_startup, From b71841b978fc33f961383b255693a70a1dd64031 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 2 Sep 2013 15:42:30 +0200 Subject: [PATCH 13/40] net: add extended function to phy API Some phys (Micrel) has extended registers that must be accessed in a special way. Add pointers to the phy driver structure to allow to use these functions with mdio command. Signed-off-by: Stefano Babic --- include/phy.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/phy.h b/include/phy.h index f0f522a..d3001f1 100644 --- a/include/phy.h +++ b/include/phy.h @@ -125,6 +125,9 @@ struct phy_driver { /* Called when bringing down the controller */ int (*shutdown)(struct phy_device *phydev); + int (*readext)(struct phy_device *phydev, int addr, int devad, int reg); + int (*writeext)(struct phy_device *phydev, int addr, int devad, int reg, + u16 val); struct list_head list; }; From 9ced16fefa35910b4d2cbc9c4688a037bda7f423 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 2 Sep 2013 15:42:31 +0200 Subject: [PATCH 14/40] net: add function to read/write extended registers in Micrel Phy Signed-off-by: Stefano Babic --- drivers/net/phy/micrel.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index f3e3054..5d7e3be 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -100,6 +100,19 @@ int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum) return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR); } + +static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr, + int regnum) +{ + return ksz9021_phy_extended_read(phydev, regnum); +} + +static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) +{ + return ksz9021_phy_extended_write(phydev, regnum, val); +} + /* Micrel ksz9021 */ static int ksz9021_config(struct phy_device *phydev) { @@ -131,6 +144,8 @@ static struct phy_driver ksz9021_driver = { .config = &ksz9021_config, .startup = &ksz90xx_startup, .shutdown = &genphy_shutdown, + .writeext = &ksz9021_phy_extwrite, + .readext = &ksz9021_phy_extread, }; #endif @@ -171,6 +186,21 @@ int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr, return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA); } +static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr, + int regnum) +{ + return ksz9031_phy_extended_read(phydev, devaddr, regnum, + MII_KSZ9031_MOD_DATA_NO_POST_INC); +}; + +static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) +{ + return ksz9031_phy_extended_write(phydev, devaddr, regnum, + MII_KSZ9031_MOD_DATA_POST_INC_RW, val); +}; + + static struct phy_driver ksz9031_driver = { .name = "Micrel ksz9031", .uid = 0x221620, @@ -179,6 +209,8 @@ static struct phy_driver ksz9031_driver = { .config = &genphy_config, .startup = &ksz90xx_startup, .shutdown = &genphy_shutdown, + .writeext = &ksz9031_phy_extwrite, + .readext = &ksz9031_phy_extread, }; int phy_micrel_init(void) From 26b807c4f8d95f7e1a9b16b5d0caebc6606d3dc6 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 2 Sep 2013 15:42:32 +0200 Subject: [PATCH 15/40] net: add support for extended registers to mdio command Some phys (Micrel) have additional registers that can be accessed using a special sequence. This patch allows to use standard "mdio" command to accesss these registers. Signed-off-by: Stefano Babic --- common/cmd_mdio.c | 75 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/common/cmd_mdio.c b/common/cmd_mdio.c index 65a1f10..fb13d05 100644 --- a/common/cmd_mdio.c +++ b/common/cmd_mdio.c @@ -41,9 +41,11 @@ static int extract_range(char *input, int *plo, int *phi) return 0; } -static int mdio_write_ranges(struct mii_dev *bus, int addrlo, +static int mdio_write_ranges(struct phy_device *phydev, struct mii_dev *bus, + int addrlo, int addrhi, int devadlo, int devadhi, - int reglo, int reghi, unsigned short data) + int reglo, int reghi, unsigned short data, + int extended) { int addr, devad, reg; int err = 0; @@ -51,7 +53,12 @@ static int mdio_write_ranges(struct mii_dev *bus, int addrlo, for (addr = addrlo; addr <= addrhi; addr++) { for (devad = devadlo; devad <= devadhi; devad++) { for (reg = reglo; reg <= reghi; reg++) { - err = bus->write(bus, addr, devad, reg, data); + if (!extended) + err = bus->write(bus, addr, devad, + reg, data); + else + err = phydev->drv->writeext(phydev, + addr, devad, reg, data); if (err) goto err_out; @@ -63,9 +70,10 @@ err_out: return err; } -static int mdio_read_ranges(struct mii_dev *bus, int addrlo, +static int mdio_read_ranges(struct phy_device *phydev, struct mii_dev *bus, + int addrlo, int addrhi, int devadlo, int devadhi, - int reglo, int reghi) + int reglo, int reghi, int extended) { int addr, devad, reg; @@ -77,7 +85,12 @@ static int mdio_read_ranges(struct mii_dev *bus, int addrlo, for (reg = reglo; reg <= reghi; reg++) { int val; - val = bus->read(bus, addr, devad, reg); + if (!extended) + val = bus->read(bus, addr, devad, reg); + else + val = phydev->drv->readext(phydev, addr, + devad, reg); + if (val < 0) { printf("Error\n"); @@ -126,9 +139,10 @@ static int extract_reg_range(char *input, int *devadlo, int *devadhi, } static int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus, + struct phy_device **phydev, int *addrlo, int *addrhi) { - struct phy_device *phydev; + struct phy_device *dev = *phydev; if ((argc < 1) || (argc > 2)) return -1; @@ -154,11 +168,11 @@ static int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus, * device by the given name. If none are found, we call * extract_range() on the string, and see if it's an address range. */ - phydev = mdio_phydev_for_ethname(argv[0]); + dev = mdio_phydev_for_ethname(argv[0]); - if (phydev) { - *addrlo = *addrhi = phydev->addr; - *bus = phydev->bus; + if (dev) { + *addrlo = *addrhi = dev->addr; + *bus = dev->bus; return 0; } @@ -175,6 +189,8 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned short data; int pos = argc - 1; struct mii_dev *bus; + struct phy_device *phydev = NULL; + int extended = 0; if (argc < 2) return CMD_RET_USAGE; @@ -197,6 +213,29 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (flag & CMD_FLAG_REPEAT) op[0] = last_op[0]; + if (strlen(argv[1]) > 1) { + op[1] = argv[1][1]; + if (op[1] == 'x') { + phydev = mdio_phydev_for_ethname(argv[2]); + + if (phydev) { + addrlo = phydev->addr; + addrhi = addrlo; + bus = phydev->bus; + extended = 1; + } else { + return -1; + } + + if (!phydev->drv || + (!phydev->drv->writeext && (op[0] == 'w')) || + (!phydev->drv->readext && (op[0] == 'r'))) { + puts("PHY does not have extended functions\n"); + return -1; + } + } + } + switch (op[0]) { case 'w': if (pos > 1) @@ -210,7 +249,7 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) default: if (pos > 1) if (extract_phy_range(&(argv[2]), pos - 1, &bus, - &addrlo, &addrhi)) + &phydev, &addrlo, &addrhi)) return -1; break; @@ -227,13 +266,13 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) switch (op[0]) { case 'w': - mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi, - reglo, reghi, data); + mdio_write_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi, + reglo, reghi, data, extended); break; case 'r': - mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi, - reglo, reghi); + mdio_read_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi, + reglo, reghi, extended); break; } @@ -262,6 +301,10 @@ U_BOOT_CMD( "read PHY's register at .\n" "mdio write [.] - " "write PHY's register at .\n" + "mdio rx [.] - " + "read PHY's extended register at .\n" + "mdio wx [.] - " + "write PHY's extended register at .\n" " may be:\n" " \n" " \n" From 7a36b9c1acb43c6be82b05c21cba1d0f14712d8c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 20 Sep 2013 16:03:41 +0200 Subject: [PATCH 16/40] net: rtl8169: Fix format string currticks() is defined as get_timer(0), which returns an unsigned long, so use %lu instead of %d to print the result. Signed-off-by: Thierry Reding Patch: 276473 --- drivers/net/rtl8169.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 13fa9c0..9dc10a5 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -501,8 +501,8 @@ static int rtl_send(struct eth_device *dev, void *packet, int length) if (currticks() >= to) { #ifdef DEBUG_RTL8169_TX - puts ("tx timeout/error\n"); - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); + puts("tx timeout/error\n"); + printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif ret = 0; } else { @@ -604,7 +604,7 @@ static void rtl8169_hw_start(struct eth_device *dev) RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); #ifdef DEBUG_RTL8169 - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); + printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif } @@ -642,7 +642,7 @@ static void rtl8169_init_ring(struct eth_device *dev) } #ifdef DEBUG_RTL8169 - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); + printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif } @@ -683,7 +683,7 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis) txb[5] = dev->enetaddr[5]; #ifdef DEBUG_RTL8169 - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); + printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif return 0; } From 65a6691ed3e3396c6aa8b8ca39b9e2631f37a974 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 20 Sep 2013 16:03:44 +0200 Subject: [PATCH 17/40] net: rtl8169: Add support for RTL8168evl/8111evl This chip is compatible with other RTL8168 chips and can be found on the NVIDIA Cardhu and Beaver boards. Signed-off-by: Thierry Reding Patch: 276475 --- drivers/net/rtl8169.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 9dc10a5..290c988 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -246,6 +246,7 @@ static struct { {"RTL-8169sc/8110sc", 0x18, 0xff7e1880,}, {"RTL-8168b/8111sb", 0x30, 0xff7e1880,}, {"RTL-8168b/8111sb", 0x38, 0xff7e1880,}, + {"RTL-8168evl/8111evl", 0x2e, 0xff7e1880,}, {"RTL-8101e", 0x34, 0xff7e1880,}, {"RTL-8100e", 0x32, 0xff7e1880,}, }; From dfcaa61c33e1fc5f737318cfdbcf7f7b49f237a3 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sun, 22 Sep 2013 09:55:49 +0200 Subject: [PATCH 18/40] net, phy: fix AR8031 phy_mask AR8035 driver will be never applied because of wrong mask for AR8031 driver. Fix this. Signed-off-by: Heiko Schocher Reported-by: Pavel Nakonechny Cc: Andy Fleming Cc: Joe Hershberger Patch: 276944 --- drivers/net/phy/atheros.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 7a1453f..f225d93 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -50,7 +50,7 @@ static struct phy_driver AR8021_driver = { static struct phy_driver AR8031_driver = { .name = "AR8031/AR8033", .uid = 0x4dd074, - .mask = 0xfffff0, + .mask = 0xffffff, .features = PHY_GBIT_FEATURES, .config = ar8021_config, .startup = genphy_startup, From 47ce8890486be72ce6b634c590a0c6baa2447084 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 24 Sep 2013 15:38:33 +0900 Subject: [PATCH 19/40] net: sh-eth: Add support R8A7791 R8A7791 has the same sh-ether IP core as other SH/rmobile. This patch adds support of R8A7791. Signed-off-by: Nobuhiro Iwamatsu CC: Nobuhiro Iwamatsu CC: Joe Hershberger --- drivers/net/sh_eth.c | 5 +++-- drivers/net/sh_eth.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 9020752..5e132f2 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -410,7 +410,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) #if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740) sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII); -#elif defined(CONFIG_R8A7790) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR); #endif /* Configure phy */ @@ -435,7 +435,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) sh_eth_write(eth, GECMR_100B, GECMR); #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752) sh_eth_write(eth, 1, RTRATE); -#elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) +#elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \ + defined(CONFIG_R8A7791) val = ECMR_RTM; #endif } else if (phy->speed == 10) { diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 43b8ac9..8aa7109 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -301,7 +301,7 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { #elif defined(CONFIG_R8A7740) #define SH_ETH_TYPE_GETHER #define BASE_IO_ADDR 0xE9A00000 -#elif defined(CONFIG_R8A7790) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) #define SH_ETH_TYPE_ETHER #define BASE_IO_ADDR 0xEE700200 #endif @@ -507,7 +507,7 @@ enum FELIC_MODE_BIT { ECMR_PRM = 0x00000001, #ifdef CONFIG_CPU_SH7724 ECMR_RTM = 0x00000010, -#elif defined(CONFIG_R8A7790) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) ECMR_RTM = 0x00000004, #endif From 227ad7b2b6fab024fff6f60613b0e90c9e3a6724 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Wed, 25 Sep 2013 17:33:10 +0400 Subject: [PATCH 20/40] net: designware: Respect "bus mode" register contents on SW reset "bus mode" register contains lots of fields and some of them don't expect to be written with 0 (zero). So since we're only interested in resetting MAC (which is done with setting the least significant bit of this register with "0") I believe it's better to modify only 1 bit of the register. Signed-off-by: Alexey Brodkin Acked-by: Vipin Kumar Patch: 277864 --- drivers/net/designware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 8413d57..22155b4 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -96,7 +96,7 @@ static int mac_reset(struct eth_device *dev) ulong start; int timeout = CONFIG_MACRESET_TIMEOUT; - writel(DMAMAC_SRST, &dma_p->busmode); + writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); if (priv->interface != PHY_INTERFACE_MODE_RGMII) writel(MII_PORTSELECT, &mac_p->conf); From ed102be70f762afc39bda165ba57ea84dc9be39e Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Wed, 25 Sep 2013 19:27:48 +0400 Subject: [PATCH 21/40] net: designware: Fix alignment of buffer descriptors It's important that buffer descriptors are aligned in accordance to GMAC data bus width (32/64/128-bit). It's safe to align to 128-bit (16-bytes) for every bus width type. If buffer descriptor is improperly aligned GMAC discards lower bits of provided address and as a result reads from improper location that doesn't match expected fields. Commit ef76025a99247cdb8f927a2c9f15400678dfb599 "net: Multiple updates/enhancements to designware.c" introduced another structure member "link_printed" right before buffer descriptors while "padding" member was left untouched. This together with alignment of structure itself to 16-byte boundary forces buffer descriptoprs always to be 4-byte aligned that causes driver complete disfunction if GMAC bus width is 64 or 128-bit. Proposed change makes sure all buffer descriptors are 16-byte (128-bit) aligned. Signed-off-by: Alexey Brodkin Patch: 277902 --- drivers/net/designware.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/designware.h b/drivers/net/designware.h index e80002a..5440c92 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -112,7 +112,7 @@ struct dmamacdescr { u32 dmamac_cntl; void *dmamac_addr; struct dmamacdescr *dmamac_next; -}; +} __aligned(16); /* * txrx_status definitions @@ -224,8 +224,7 @@ struct dw_eth_dev { u32 tx_currdescnum; u32 rx_currdescnum; u32 phy_configured; - int link_printed; - u32 padding; + u32 link_printed; struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM]; struct dmamacdescr rx_mac_descrtable[CONFIG_RX_DESCR_NUM]; @@ -237,7 +236,7 @@ struct dw_eth_dev { struct eth_dma_regs *dma_regs_p; struct eth_device *dev; -} __attribute__ ((aligned(8))); +}; /* Speed specific definitions */ #define SPEED_10M 1 From 9c4cffacec7b76299e74cb09e074a21fb6609dbe Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:39 +0300 Subject: [PATCH 22/40] net: Fix mcast function pointer prototype This fixes the following compiler warnings when activating CONFIG_MCAST_TFTP: tsec.c: In function 'tsec_mcast_addr': tsec.c:130:2: warning: passing argument 2 of 'ether_crc' makes pointer from integer without a cast [enabled by default] In file included from /work/u-boot-net/include/common.h:874:0, from tsec.c:15: /work/u-boot-net/include/net.h:189:5: note: expected 'const unsigned char *' but argument is of type 'u8' tsec.c: In function 'tsec_initialize': tsec.c:646:13: warning: assignment from incompatible pointer type [enabled by default] eth.c: In function 'eth_mcast_join': eth.c:358:2: warning: passing argument 2 of 'eth_current->mcast' makes integer from pointer without a cast [enabled by default] eth.c:358:2: note: expected 'u32' but argument is of type 'u8 *' In the eth_mcast_join() implementation, eth_current->mcast() takes a u8 pointer to the multicast mac address and not a ip address value as implied by its prototype. Fix parameter type mismatch for tsec_macst_addr() (tsec.c): ether_crc() takes a u8 pointer not a u8 value. mcast() is given a u8 pointer to the multicats mac address. Update parameter type for the rest of mcast() instances. Signed-off-by: Claudiu Manoil Patch: 278989 --- drivers/net/rtl8139.c | 2 +- drivers/net/tsec.c | 4 ++-- include/net.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 4186699..208ce5c 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -188,7 +188,7 @@ static int rtl_transmit(struct eth_device *dev, void *packet, int length); static int rtl_poll(struct eth_device *dev); static void rtl_disable(struct eth_device *dev); #ifdef CONFIG_MCAST_TFTP/* This driver already accepts all b/mcast */ -static int rtl_bcast_addr (struct eth_device *dev, u8 bcast_mac, u8 set) +static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, u8 set) { return (0); } diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index f5e314b..3428dd0 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -120,14 +120,14 @@ static void tsec_configure_serdes(struct tsec_private *priv) * for PowerPC (tm) is usually the case) in the tregister holds * the entry. */ static int -tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set) +tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set) { struct tsec_private *priv = privlist[1]; volatile tsec_t *regs = priv->regs; volatile u32 *reg_array, value; u8 result, whichbit, whichreg; - result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); + result = (u8)((ether_crc(MAC_ADDR_LEN, mcast_mac) >> 24) & 0xff); whichbit = result & 0x1f; /* the 5 LSB = which bit to set */ whichreg = result >> 5; /* the 3 MSB = which reg to set it in */ value = (1 << (31-whichbit)); diff --git a/include/net.h b/include/net.h index 5aedc17..0802fad 100644 --- a/include/net.h +++ b/include/net.h @@ -89,7 +89,7 @@ struct eth_device { int (*recv) (struct eth_device *); void (*halt) (struct eth_device *); #ifdef CONFIG_MCAST_TFTP - int (*mcast) (struct eth_device *, u32 ip, u8 set); + int (*mcast) (struct eth_device *, const u8 *enetaddr, u8 set); #endif int (*write_hwaddr) (struct eth_device *); struct eth_device *next; From 876d4515e38dfcec4346968caf6a0c9c8176ea0b Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:40 +0300 Subject: [PATCH 23/40] net: tsec: Fix and cleanup tsec_mcast_addr() There are several implementation issues for tsec_mcast_addr() addressed by this patch: * unmanaged, not portable r/w access to registers; fixed with setbits_be32()/ clrbits_be32() * use of volatile pointers * unnecessary forced cast to u8 for the ether_crc() result * removed redundant parens * corrected some comment slips Signed-off-by: Claudiu Manoil Patch: 279000 --- drivers/net/tsec.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 3428dd0..9ffc801 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -113,32 +113,31 @@ static void tsec_configure_serdes(struct tsec_private *priv) * result. * 2) Use the 8 most significant bits as a hash into a 256-entry * table. The table is controlled through 8 32-bit registers: - * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is - * gaddr7. This means that the 3 most significant bits in the + * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry + * 255. This means that the 3 most significant bits in the * hash index which gaddr register to use, and the 5 other bits * indicate which bit (assuming an IBM numbering scheme, which - * for PowerPC (tm) is usually the case) in the tregister holds + * for PowerPC (tm) is usually the case) in the register holds * the entry. */ static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set) { struct tsec_private *priv = privlist[1]; - volatile tsec_t *regs = priv->regs; - volatile u32 *reg_array, value; - u8 result, whichbit, whichreg; + struct tsec __iomem *regs = priv->regs; + u32 result, value; + u8 whichbit, whichreg; - result = (u8)((ether_crc(MAC_ADDR_LEN, mcast_mac) >> 24) & 0xff); - whichbit = result & 0x1f; /* the 5 LSB = which bit to set */ - whichreg = result >> 5; /* the 3 MSB = which reg to set it in */ - value = (1 << (31-whichbit)); + result = ether_crc(MAC_ADDR_LEN, mcast_mac); + whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */ + whichreg = result >> 29; /* the 3 MSB = which reg to set it in */ - reg_array = &(regs->hash.gaddr0); + value = 1 << (31-whichbit); + + if (set) + setbits_be32(®s->hash.gaddr0 + whichreg, value); + else + clrbits_be32(®s->hash.gaddr0 + whichreg, value); - if (set) { - reg_array[whichreg] |= value; - } else { - reg_array[whichreg] &= ~value; - } return 0; } #endif /* Multicast TFTP ? */ From b200204e8e2a2eee081d576ed578d87b75813b46 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:41 +0300 Subject: [PATCH 24/40] net: tsec: Fix priv pointer in tsec_mcast_addr() Access to privlist[1] (hardcoded referece to the 2nd tsec's priv area) is neither correct nor does it make sense in the current context. Each tsec dev has access to its own priv instance only, and hence to its own set of group address registers (GADDR) to filter multicast addresses. This fix leads to removal of the unused (faulty) privlist[] and related global static vars. Note that mcast() can be called only after eth_device allocation and init, and hence after priv area allocation, so dev->priv is correctly initialized upon mcast() call. Signed-off-by: Claudiu Manoil Patch: 278990 --- drivers/net/tsec.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 9ffc801..9371ffa 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -33,11 +33,6 @@ typedef volatile struct rtxbd { rxbd8_t rxbd[PKTBUFSRX]; } RTXBD; -#define MAXCONTROLLERS (8) - -static struct tsec_private *privlist[MAXCONTROLLERS]; -static int num_tsecs = 0; - #ifdef __GNUC__ static RTXBD rtx __attribute__ ((aligned(8))); #else @@ -122,7 +117,7 @@ static void tsec_configure_serdes(struct tsec_private *priv) static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set) { - struct tsec_private *priv = privlist[1]; + struct tsec_private *priv = (struct tsec_private *)dev->priv; struct tsec __iomem *regs = priv->regs; u32 result, value; u8 whichbit, whichreg; @@ -625,7 +620,6 @@ static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info) if (NULL == priv) return 0; - privlist[num_tsecs++] = priv; priv->regs = tsec_info->regs; priv->phyregs_sgmii = tsec_info->miiregs_sgmii; From aec84bf6719f9efcc754acfb08b8ca866c8a5e95 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:42 +0300 Subject: [PATCH 25/40] net: tsec: Cleanup tsec regs init and fix __iomem warns Remove tsec_t typedef. Define macros as getters of tsec and mdio register memory regions, for consistent initialization of various 'regs' fields and also to manage overly long initialization lines. Use the __iomem address space marker to address sparse warnings in tsec.c where IO accessors are used, like: tsec.c:394:19: warning: incorrect type in argument 1 (different address spaces) tsec.c:394:19: expected unsigned int volatile [noderef] *addr tsec.c:394:19: got unsigned int * [...] Add the __iomem address space marker for the tsec pointers to struct tsec_mii_mng memory mapped register regions. This solves the sparse warnings for mixig normal pointers with __iomem pointers for tsec. Signed-off-by: Claudiu Manoil --- drivers/net/tsec.c | 26 +++++++++++++------------- include/tsec.h | 39 +++++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 9371ffa..adb6c12 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -5,7 +5,7 @@ * terms of the GNU Public License, Version 2, incorporated * herein by reference. * - * Copyright 2004-2011 Freescale Semiconductor, Inc. + * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc. * (C) Copyright 2003, Motorola, Inc. * author Andy Fleming * @@ -52,7 +52,7 @@ static struct tsec_info_struct tsec_info[] = { #endif #ifdef CONFIG_MPC85XX_FEC { - .regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000), + .regs = TSEC_GET_REGS(2, 0x2000), .devname = CONFIG_MPC85XX_FEC_NAME, .phyaddr = FEC_PHY_ADDR, .flags = FEC_FLAGS, @@ -141,7 +141,7 @@ tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set) * those we don't care about (unless zero is bad, in which case, * choose a more appropriate value) */ -static void init_registers(tsec_t *regs) +static void init_registers(struct tsec __iomem *regs) { /* Clear IEVENT */ out_be32(®s->ievent, IEVENT_INIT_CLEAR); @@ -188,7 +188,7 @@ static void init_registers(tsec_t *regs) */ static void adjust_link(struct tsec_private *priv, struct phy_device *phydev) { - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; u32 ecntrl, maccfg2; if (!phydev->link) { @@ -242,7 +242,7 @@ static void adjust_link(struct tsec_private *priv, struct phy_device *phydev) void redundant_init(struct eth_device *dev) { struct tsec_private *priv = dev->priv; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; uint t, count = 0; int fail = 1; static const u8 pkt[] = { @@ -321,7 +321,7 @@ static void startup_tsec(struct eth_device *dev) { int i; struct tsec_private *priv = (struct tsec_private *)dev->priv; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; /* reset the indices to zero */ rxIdx = 0; @@ -375,7 +375,7 @@ static int tsec_send(struct eth_device *dev, void *packet, int length) int i; int result = 0; struct tsec_private *priv = (struct tsec_private *)dev->priv; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; /* Find an empty buffer descriptor */ for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { @@ -411,7 +411,7 @@ static int tsec_recv(struct eth_device *dev) { int length; struct tsec_private *priv = (struct tsec_private *)dev->priv; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { @@ -447,7 +447,7 @@ static int tsec_recv(struct eth_device *dev) static void tsec_halt(struct eth_device *dev) { struct tsec_private *priv = (struct tsec_private *)dev->priv; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); setbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); @@ -473,7 +473,7 @@ static int tsec_init(struct eth_device *dev, bd_t * bd) char tmpbuf[MAC_ADDR_LEN]; int i; struct tsec_private *priv = (struct tsec_private *)dev->priv; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; int ret; /* Make sure the controller is stopped */ @@ -521,7 +521,7 @@ static int tsec_init(struct eth_device *dev, bd_t * bd) static phy_interface_t tsec_get_interface(struct tsec_private *priv) { - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; u32 ecntrl; ecntrl = in_be32(®s->ecntrl); @@ -570,7 +570,7 @@ static int init_phy(struct eth_device *dev) { struct tsec_private *priv = (struct tsec_private *)dev->priv; struct phy_device *phydev; - tsec_t *regs = priv->regs; + struct tsec __iomem *regs = priv->regs; u32 supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -677,7 +677,7 @@ int tsec_standard_init(bd_t *bis) { struct fsl_pq_mdio_info info; - info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; + info.regs = TSEC_GET_MDIO_REGS_BASE(1); info.name = DEFAULT_MII_NAME; fsl_pq_mdio_init(bis, &info); diff --git a/include/tsec.h b/include/tsec.h index f0f3d4d..c30aafb 100644 --- a/include/tsec.h +++ b/include/tsec.h @@ -7,7 +7,7 @@ * terms of the GNU Public License, Version 2, incorporated * herein by reference. * - * Copyright 2004, 2007, 2009, 2011 Freescale Semiconductor, Inc. + * Copyright 2004, 2007, 2009, 2011, 2013 Freescale Semiconductor, Inc. * (C) Copyright 2003, Motorola, Inc. * maintained by Xianghua Xiao (x.xiao@motorola.com) * author Andy Fleming @@ -27,13 +27,26 @@ #define CONFIG_SYS_MDIO_BASE_ADDR (MDIO_BASE_ADDR + 0x520) +#define TSEC_GET_REGS(num, offset) \ + (struct tsec __iomem *)\ + (TSEC_BASE_ADDR + (((num) - 1) * (offset))) + +#define TSEC_GET_REGS_BASE(num) \ + TSEC_GET_REGS((num), TSEC_SIZE) + +#define TSEC_GET_MDIO_REGS(num, offset) \ + (struct tsec_mii_mng __iomem *)\ + (CONFIG_SYS_MDIO_BASE_ADDR + ((num) - 1) * (offset)) + +#define TSEC_GET_MDIO_REGS_BASE(num) \ + TSEC_GET_MDIO_REGS((num), TSEC_MDIO_OFFSET) + #define DEFAULT_MII_NAME "FSL_MDIO" #define STD_TSEC_INFO(num) \ { \ - .regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)), \ - .miiregs_sgmii = (struct tsec_mii_mng *)(CONFIG_SYS_MDIO_BASE_ADDR \ - + (num - 1) * TSEC_MDIO_OFFSET), \ + .regs = TSEC_GET_REGS_BASE(num), \ + .miiregs_sgmii = TSEC_GET_MDIO_REGS_BASE(num), \ .devname = CONFIG_TSEC##num##_NAME, \ .phyaddr = TSEC##num##_PHY_ADDR, \ .flags = TSEC##num##_FLAGS, \ @@ -42,9 +55,8 @@ #define SET_STD_TSEC_INFO(x, num) \ { \ - x.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)); \ - x.miiregs_sgmii = (struct tsec_mii_mng *)(CONFIG_SYS_MDIO_BASE_ADDR \ - + (num - 1) * TSEC_MDIO_OFFSET); \ + x.regs = TSEC_GET_REGS_BASE(num); \ + x.miiregs_sgmii = TSEC_GET_MDIO_REGS_BASE(num); \ x.devname = CONFIG_TSEC##num##_NAME; \ x.phyaddr = TSEC##num##_PHY_ADDR; \ x.flags = TSEC##num##_FLAGS;\ @@ -281,8 +293,7 @@ typedef struct tsec_hash_regs uint res2[24]; } tsec_hash_t; -typedef struct tsec -{ +struct tsec { /* General Control and Status Registers (0x2_n000) */ uint res000[4]; @@ -374,7 +385,7 @@ typedef struct tsec /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */ uint resc00[256]; -} tsec_t; +}; #define TSEC_GIGABIT (1 << 0) @@ -383,8 +394,8 @@ typedef struct tsec #define TSEC_SGMII (1 << 2) /* MAC-PHY interface uses SGMII */ struct tsec_private { - tsec_t *regs; - struct tsec_mii_mng *phyregs_sgmii; + struct tsec __iomem *regs; + struct tsec_mii_mng __iomem *phyregs_sgmii; struct phy_device *phydev; phy_interface_t interface; struct mii_dev *bus; @@ -394,8 +405,8 @@ struct tsec_private { }; struct tsec_info_struct { - tsec_t *regs; - struct tsec_mii_mng *miiregs_sgmii; + struct tsec __iomem *regs; + struct tsec_mii_mng __iomem *miiregs_sgmii; char *devname; char *mii_devname; phy_interface_t interface; From 5be00a0164892eb695fefa41fb24258072ee2185 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:43 +0300 Subject: [PATCH 26/40] net: fsl_mdio: Fix warnings for __iomem pointers Add the __iomem address space marker for the tsec pointers to struct tsec_mii_mng memory mapped register regions. This solves the sparse warnings for mixig normal pointers with __iomem pointers for tsec. E.g.: fsl_mdio.c:34:19: warning: incorrect type in argument 1 (different address spaces) fsl_mdio.c:34:19: expected unsigned int volatile [noderef] *addr fsl_mdio.c:34:19: got unsigned int * [...] tsec.c:91:35: warning: incorrect type in argument 1 (different address spaces) tsec.c:91:35: expected struct tsec_mii_mng *phyregs tsec.c:91:35: got struct tsec_mii_mng [noderef] *phyregs_sgmii [...] tsec.c:680:19: warning: incorrect type in assignment (different address spaces) tsec.c:680:19: expected struct tsec_mii_mng *regs tsec.c:680:19: got struct tsec_mii_mng [noderef] * [...] Signed-off-by: Claudiu Manoil --- drivers/net/fsl_mdio.c | 17 ++++++++++------- include/fsl_mdio.h | 8 ++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/fsl_mdio.c b/drivers/net/fsl_mdio.c index ce36bd7..1d88e65 100644 --- a/drivers/net/fsl_mdio.c +++ b/drivers/net/fsl_mdio.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2010 Freescale Semiconductor, Inc. + * Copyright 2009-2010, 2013 Freescale Semiconductor, Inc. * Jun-jie Zhang * Mingkai Hu * @@ -13,7 +13,7 @@ #include #include -void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr, +void tsec_local_mdio_write(struct tsec_mii_mng __iomem *phyregs, int port_addr, int dev_addr, int regnum, int value) { int timeout = 1000000; @@ -26,7 +26,7 @@ void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr, ; } -int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr, +int tsec_local_mdio_read(struct tsec_mii_mng __iomem *phyregs, int port_addr, int dev_addr, int regnum) { int value; @@ -57,7 +57,8 @@ int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr, static int fsl_pq_mdio_reset(struct mii_dev *bus) { - struct tsec_mii_mng *regs = bus->priv; + struct tsec_mii_mng __iomem *regs = + (struct tsec_mii_mng __iomem *)bus->priv; /* Reset MII (due to new addresses) */ out_be32(®s->miimcfg, MIIMCFG_RESET_MGMT); @@ -72,7 +73,8 @@ static int fsl_pq_mdio_reset(struct mii_dev *bus) int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum) { - struct tsec_mii_mng *phyregs = bus->priv; + struct tsec_mii_mng __iomem *phyregs = + (struct tsec_mii_mng __iomem *)bus->priv; return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum); } @@ -80,7 +82,8 @@ int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum) int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum, u16 value) { - struct tsec_mii_mng *phyregs = bus->priv; + struct tsec_mii_mng __iomem *phyregs = + (struct tsec_mii_mng __iomem *)bus->priv; tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value); @@ -101,7 +104,7 @@ int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info) bus->reset = fsl_pq_mdio_reset; sprintf(bus->name, info->name); - bus->priv = info->regs; + bus->priv = (void *)info->regs; return mdio_register(bus); } diff --git a/include/fsl_mdio.h b/include/fsl_mdio.h index 9c0b762..b58713d 100644 --- a/include/fsl_mdio.h +++ b/include/fsl_mdio.h @@ -1,5 +1,5 @@ /* - * Copyright 2009-2012 Freescale Semiconductor, Inc. + * Copyright 2009-2012, 2013 Freescale Semiconductor, Inc. * Jun-jie Zhang * Mingkai Hu * @@ -31,9 +31,9 @@ #define MIIMIND_BUSY 0x00000001 #define MIIMIND_NOTVALID 0x00000004 -void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr, +void tsec_local_mdio_write(struct tsec_mii_mng __iomem *phyregs, int port_addr, int dev_addr, int reg, int value); -int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr, +int tsec_local_mdio_read(struct tsec_mii_mng __iomem *phyregs, int port_addr, int dev_addr, int regnum); int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum); int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum, @@ -44,7 +44,7 @@ int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr, int regnum); struct fsl_pq_mdio_info { - struct tsec_mii_mng *regs; + struct tsec_mii_mng __iomem *regs; char *name; }; int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info); From 18b338fb3486ac91291e1f94561cb47fd0f4aef2 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:44 +0300 Subject: [PATCH 27/40] net: tsec: Fix CamelCase issues around BD code Fix bufPtr and the rxIdx/ txIdx occurrences to solve the related checkpatch warnings for the coming patches. Signed-off-by: Claudiu Manoil --- drivers/net/tsec.c | 60 +++++++++++++++++++++++++++--------------------------- include/tsec.h | 4 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index adb6c12..289229a 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -25,8 +25,8 @@ DECLARE_GLOBAL_DATA_PTR; #define TX_BUF_CNT 2 -static uint rxIdx; /* index of the current RX buffer */ -static uint txIdx; /* index of the current TX buffer */ +static uint rx_idx; /* index of the current RX buffer */ +static uint tx_idx; /* index of the current TX buffer */ typedef volatile struct rtxbd { txbd8_t txbd[TX_BUF_CNT]; @@ -278,20 +278,20 @@ void redundant_init(struct eth_device *dev) tsec_send(dev, (void *)pkt, sizeof(pkt)); /* Wait for buffer to be received */ - for (t = 0; rtx.rxbd[rxIdx].status & RXBD_EMPTY; t++) { + for (t = 0; rtx.rxbd[rx_idx].status & RXBD_EMPTY; t++) { if (t >= 10 * TOUT_LOOP) { printf("%s: tsec: rx error\n", dev->name); break; } } - if (!memcmp(pkt, (void *)NetRxPackets[rxIdx], sizeof(pkt))) + if (!memcmp(pkt, (void *)NetRxPackets[rx_idx], sizeof(pkt))) fail = 0; - rtx.rxbd[rxIdx].length = 0; - rtx.rxbd[rxIdx].status = - RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); - rxIdx = (rxIdx + 1) % PKTBUFSRX; + rtx.rxbd[rx_idx].length = 0; + rtx.rxbd[rx_idx].status = + RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); + rx_idx = (rx_idx + 1) % PKTBUFSRX; if (in_be32(®s->ievent) & IEVENT_BSY) { out_be32(®s->ievent, IEVENT_BSY); @@ -324,21 +324,21 @@ static void startup_tsec(struct eth_device *dev) struct tsec __iomem *regs = priv->regs; /* reset the indices to zero */ - rxIdx = 0; - txIdx = 0; + rx_idx = 0; + tx_idx = 0; #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129 uint svr; #endif /* Point to the buffer descriptors */ - out_be32(®s->tbase, (unsigned int)(&rtx.txbd[txIdx])); - out_be32(®s->rbase, (unsigned int)(&rtx.rxbd[rxIdx])); + out_be32(®s->tbase, (unsigned int)(&rtx.txbd[tx_idx])); + out_be32(®s->rbase, (unsigned int)(&rtx.rxbd[rx_idx])); /* Initialize the Rx Buffer descriptors */ for (i = 0; i < PKTBUFSRX; i++) { rtx.rxbd[i].status = RXBD_EMPTY; rtx.rxbd[i].length = 0; - rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i]; + rtx.rxbd[i].bufptr = (uint) NetRxPackets[i]; } rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; @@ -346,7 +346,7 @@ static void startup_tsec(struct eth_device *dev) for (i = 0; i < TX_BUF_CNT; i++) { rtx.txbd[i].status = 0; rtx.txbd[i].length = 0; - rtx.txbd[i].bufPtr = 0; + rtx.txbd[i].bufptr = 0; } rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; @@ -378,31 +378,31 @@ static int tsec_send(struct eth_device *dev, void *packet, int length) struct tsec __iomem *regs = priv->regs; /* Find an empty buffer descriptor */ - for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { + for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) { if (i >= TOUT_LOOP) { debug("%s: tsec: tx buffers full\n", dev->name); return result; } } - rtx.txbd[txIdx].bufPtr = (uint) packet; - rtx.txbd[txIdx].length = length; - rtx.txbd[txIdx].status |= + rtx.txbd[tx_idx].bufptr = (uint) packet; + rtx.txbd[tx_idx].length = length; + rtx.txbd[tx_idx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); /* Tell the DMA to go */ out_be32(®s->tstat, TSTAT_CLEAR_THALT); /* Wait for buffer to be transmitted */ - for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { + for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) { if (i >= TOUT_LOOP) { debug("%s: tsec: tx error\n", dev->name); return result; } } - txIdx = (txIdx + 1) % TX_BUF_CNT; - result = rtx.txbd[txIdx].status & TXBD_STATS; + tx_idx = (tx_idx + 1) % TX_BUF_CNT; + result = rtx.txbd[tx_idx].status & TXBD_STATS; return result; } @@ -413,25 +413,25 @@ static int tsec_recv(struct eth_device *dev) struct tsec_private *priv = (struct tsec_private *)dev->priv; struct tsec __iomem *regs = priv->regs; - while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { + while (!(rtx.rxbd[rx_idx].status & RXBD_EMPTY)) { - length = rtx.rxbd[rxIdx].length; + length = rtx.rxbd[rx_idx].length; /* Send the packet up if there were no errors */ - if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { - NetReceive(NetRxPackets[rxIdx], length - 4); + if (!(rtx.rxbd[rx_idx].status & RXBD_STATS)) { + NetReceive(NetRxPackets[rx_idx], length - 4); } else { printf("Got error %x\n", - (rtx.rxbd[rxIdx].status & RXBD_STATS)); + (rtx.rxbd[rx_idx].status & RXBD_STATS)); } - rtx.rxbd[rxIdx].length = 0; + rtx.rxbd[rx_idx].length = 0; /* Set the wrap bit if this is the last element in the list */ - rtx.rxbd[rxIdx].status = - RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); + rtx.rxbd[rx_idx].status = + RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); - rxIdx = (rxIdx + 1) % PKTBUFSRX; + rx_idx = (rx_idx + 1) % PKTBUFSRX; } if (in_be32(®s->ievent) & IEVENT_BSY) { diff --git a/include/tsec.h b/include/tsec.h index c30aafb..6bc43ef 100644 --- a/include/tsec.h +++ b/include/tsec.h @@ -202,14 +202,14 @@ typedef struct txbd8 { ushort status; /* Status Fields */ ushort length; /* Buffer length */ - uint bufPtr; /* Buffer Pointer */ + uint bufptr; /* Buffer Pointer */ } txbd8_t; typedef struct rxbd8 { ushort status; /* Status Fields */ ushort length; /* Buffer Length */ - uint bufPtr; /* Buffer Pointer */ + uint bufptr; /* Buffer Pointer */ } rxbd8_t; typedef struct rmon_mib From 9c9141fd04f0991209dab9fe2716ce19b2a4f552 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Fri, 4 Oct 2013 19:13:53 +0300 Subject: [PATCH 28/40] net: tsec: Use portable types and accessors for BDs Currently, the buffer descriptor (BD) fields cannot be correctly accessed by a little endian processor. This patch fixes the issue by making the access of BDs to be portable among different cpu architectures. Use portable data types for the Rx/Tx buffer descriptor fields. Use portable I/O accessors to insure that the big endian BDs are correctly accessed by little endian cpus too, and to insure proper sync with the H/W. Removed the redundant RTXBD "volatile" type, as proper synchronization around BD data accesses is provided by the I/O accessors now. The "sparse" tool was also used to verify the correctness of these changes. Cc: Scott Wood Signed-off-by: Claudiu Manoil --- drivers/net/tsec.c | 88 ++++++++++++++++++++++++++++-------------------------- include/tsec.h | 22 +++++++------- 2 files changed, 56 insertions(+), 54 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 289229a..e354fad 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -28,13 +28,10 @@ DECLARE_GLOBAL_DATA_PTR; static uint rx_idx; /* index of the current RX buffer */ static uint tx_idx; /* index of the current TX buffer */ -typedef volatile struct rtxbd { - txbd8_t txbd[TX_BUF_CNT]; - rxbd8_t rxbd[PKTBUFSRX]; -} RTXBD; - #ifdef __GNUC__ -static RTXBD rtx __attribute__ ((aligned(8))); +static struct txbd8 __iomem txbd[TX_BUF_CNT] __aligned(8); +static struct rxbd8 __iomem rxbd[PKTBUFSRX] __aligned(8); + #else #error "rtx must be 64-bit aligned" #endif @@ -275,10 +272,11 @@ void redundant_init(struct eth_device *dev) clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); do { + uint16_t status; tsec_send(dev, (void *)pkt, sizeof(pkt)); /* Wait for buffer to be received */ - for (t = 0; rtx.rxbd[rx_idx].status & RXBD_EMPTY; t++) { + for (t = 0; in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY; t++) { if (t >= 10 * TOUT_LOOP) { printf("%s: tsec: rx error\n", dev->name); break; @@ -288,9 +286,11 @@ void redundant_init(struct eth_device *dev) if (!memcmp(pkt, (void *)NetRxPackets[rx_idx], sizeof(pkt))) fail = 0; - rtx.rxbd[rx_idx].length = 0; - rtx.rxbd[rx_idx].status = - RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); + out_be16(&rxbd[rx_idx].length, 0); + status = RXBD_EMPTY; + if ((rx_idx + 1) == PKTBUFSRX) + status |= RXBD_WRAP; + out_be16(&rxbd[rx_idx].status, status); rx_idx = (rx_idx + 1) % PKTBUFSRX; if (in_be32(®s->ievent) & IEVENT_BSY) { @@ -319,9 +319,10 @@ void redundant_init(struct eth_device *dev) */ static void startup_tsec(struct eth_device *dev) { - int i; struct tsec_private *priv = (struct tsec_private *)dev->priv; struct tsec __iomem *regs = priv->regs; + uint16_t status; + int i; /* reset the indices to zero */ rx_idx = 0; @@ -331,24 +332,26 @@ static void startup_tsec(struct eth_device *dev) #endif /* Point to the buffer descriptors */ - out_be32(®s->tbase, (unsigned int)(&rtx.txbd[tx_idx])); - out_be32(®s->rbase, (unsigned int)(&rtx.rxbd[rx_idx])); + out_be32(®s->tbase, (u32)&txbd[0]); + out_be32(®s->rbase, (u32)&rxbd[0]); /* Initialize the Rx Buffer descriptors */ for (i = 0; i < PKTBUFSRX; i++) { - rtx.rxbd[i].status = RXBD_EMPTY; - rtx.rxbd[i].length = 0; - rtx.rxbd[i].bufptr = (uint) NetRxPackets[i]; + out_be16(&rxbd[i].status, RXBD_EMPTY); + out_be16(&rxbd[i].length, 0); + out_be32(&rxbd[i].bufptr, (u32)NetRxPackets[i]); } - rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; + status = in_be16(&rxbd[PKTBUFSRX - 1].status); + out_be16(&rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP); /* Initialize the TX Buffer Descriptors */ for (i = 0; i < TX_BUF_CNT; i++) { - rtx.txbd[i].status = 0; - rtx.txbd[i].length = 0; - rtx.txbd[i].bufptr = 0; + out_be16(&txbd[i].status, 0); + out_be16(&txbd[i].length, 0); + out_be32(&txbd[i].bufptr, 0); } - rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; + status = in_be16(&txbd[TX_BUF_CNT - 1].status); + out_be16(&txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP); #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129 svr = get_svr(); @@ -372,29 +375,31 @@ static void startup_tsec(struct eth_device *dev) */ static int tsec_send(struct eth_device *dev, void *packet, int length) { - int i; - int result = 0; struct tsec_private *priv = (struct tsec_private *)dev->priv; struct tsec __iomem *regs = priv->regs; + uint16_t status; + int result = 0; + int i; /* Find an empty buffer descriptor */ - for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) { + for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) { if (i >= TOUT_LOOP) { debug("%s: tsec: tx buffers full\n", dev->name); return result; } } - rtx.txbd[tx_idx].bufptr = (uint) packet; - rtx.txbd[tx_idx].length = length; - rtx.txbd[tx_idx].status |= - (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); + out_be32(&txbd[tx_idx].bufptr, (u32)packet); + out_be16(&txbd[tx_idx].length, length); + status = in_be16(&txbd[tx_idx].status); + out_be16(&txbd[tx_idx].status, status | + (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT)); /* Tell the DMA to go */ out_be32(®s->tstat, TSTAT_CLEAR_THALT); /* Wait for buffer to be transmitted */ - for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) { + for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) { if (i >= TOUT_LOOP) { debug("%s: tsec: tx error\n", dev->name); return result; @@ -402,34 +407,33 @@ static int tsec_send(struct eth_device *dev, void *packet, int length) } tx_idx = (tx_idx + 1) % TX_BUF_CNT; - result = rtx.txbd[tx_idx].status & TXBD_STATS; + result = in_be16(&txbd[tx_idx].status) & TXBD_STATS; return result; } static int tsec_recv(struct eth_device *dev) { - int length; struct tsec_private *priv = (struct tsec_private *)dev->priv; struct tsec __iomem *regs = priv->regs; - while (!(rtx.rxbd[rx_idx].status & RXBD_EMPTY)) { - - length = rtx.rxbd[rx_idx].length; + while (!(in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY)) { + int length = in_be16(&rxbd[rx_idx].length); + uint16_t status = in_be16(&rxbd[rx_idx].status); /* Send the packet up if there were no errors */ - if (!(rtx.rxbd[rx_idx].status & RXBD_STATS)) { + if (!(status & RXBD_STATS)) NetReceive(NetRxPackets[rx_idx], length - 4); - } else { - printf("Got error %x\n", - (rtx.rxbd[rx_idx].status & RXBD_STATS)); - } + else + printf("Got error %x\n", (status & RXBD_STATS)); - rtx.rxbd[rx_idx].length = 0; + out_be16(&rxbd[rx_idx].length, 0); + status = RXBD_EMPTY; /* Set the wrap bit if this is the last element in the list */ - rtx.rxbd[rx_idx].status = - RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); + if ((rx_idx + 1) == PKTBUFSRX) + status |= RXBD_WRAP; + out_be16(&rxbd[rx_idx].status, status); rx_idx = (rx_idx + 1) % PKTBUFSRX; } diff --git a/include/tsec.h b/include/tsec.h index 6bc43ef..95054be 100644 --- a/include/tsec.h +++ b/include/tsec.h @@ -198,19 +198,17 @@ #define RXBD_TRUNCATED 0x0001 #define RXBD_STATS 0x003f -typedef struct txbd8 -{ - ushort status; /* Status Fields */ - ushort length; /* Buffer length */ - uint bufptr; /* Buffer Pointer */ -} txbd8_t; +struct txbd8 { + uint16_t status; /* Status Fields */ + uint16_t length; /* Buffer length */ + uint32_t bufptr; /* Buffer Pointer */ +}; -typedef struct rxbd8 -{ - ushort status; /* Status Fields */ - ushort length; /* Buffer Length */ - uint bufptr; /* Buffer Pointer */ -} rxbd8_t; +struct rxbd8 { + uint16_t status; /* Status Fields */ + uint16_t length; /* Buffer Length */ + uint32_t bufptr; /* Buffer Pointer */ +}; typedef struct rmon_mib { From 82ef75ca5c69c7d053c07f509a901d2ad2e29570 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:46 +0300 Subject: [PATCH 29/40] net: tsec: Use portable regs type (uint->u32) Use cross arch portable u32 instead of uint for the tsec registers. Remove the typedefs for the register struct definitions in the process. Fix long lines. Signed-off-by: Claudiu Manoil --- drivers/net/tsec.c | 2 +- include/tsec.h | 278 ++++++++++++++++++++++++++--------------------------- 2 files changed, 139 insertions(+), 141 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index e354fad..082cdec 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -166,7 +166,7 @@ static void init_registers(struct tsec __iomem *regs) out_be32(®s->rctrl, 0x00000000); /* Init RMON mib registers */ - memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); + memset((void *)®s->rmon, 0, sizeof(regs->rmon)); out_be32(®s->rmon.cam1, 0xffffffff); out_be32(®s->rmon.cam2, 0xffffffff); diff --git a/include/tsec.h b/include/tsec.h index 95054be..1046426 100644 --- a/include/tsec.h +++ b/include/tsec.h @@ -210,179 +210,177 @@ struct rxbd8 { uint32_t bufptr; /* Buffer Pointer */ }; -typedef struct rmon_mib -{ +struct tsec_rmon_mib { /* Transmit and Receive Counters */ - uint tr64; /* Transmit and Receive 64-byte Frame Counter */ - uint tr127; /* Transmit and Receive 65-127 byte Frame Counter */ - uint tr255; /* Transmit and Receive 128-255 byte Frame Counter */ - uint tr511; /* Transmit and Receive 256-511 byte Frame Counter */ - uint tr1k; /* Transmit and Receive 512-1023 byte Frame Counter */ - uint trmax; /* Transmit and Receive 1024-1518 byte Frame Counter */ - uint trmgv; /* Transmit and Receive 1519-1522 byte Good VLAN Frame */ + u32 tr64; /* Tx/Rx 64-byte Frame Counter */ + u32 tr127; /* Tx/Rx 65-127 byte Frame Counter */ + u32 tr255; /* Tx/Rx 128-255 byte Frame Counter */ + u32 tr511; /* Tx/Rx 256-511 byte Frame Counter */ + u32 tr1k; /* Tx/Rx 512-1023 byte Frame Counter */ + u32 trmax; /* Tx/Rx 1024-1518 byte Frame Counter */ + u32 trmgv; /* Tx/Rx 1519-1522 byte Good VLAN Frame */ /* Receive Counters */ - uint rbyt; /* Receive Byte Counter */ - uint rpkt; /* Receive Packet Counter */ - uint rfcs; /* Receive FCS Error Counter */ - uint rmca; /* Receive Multicast Packet (Counter) */ - uint rbca; /* Receive Broadcast Packet */ - uint rxcf; /* Receive Control Frame Packet */ - uint rxpf; /* Receive Pause Frame Packet */ - uint rxuo; /* Receive Unknown OP Code */ - uint raln; /* Receive Alignment Error */ - uint rflr; /* Receive Frame Length Error */ - uint rcde; /* Receive Code Error */ - uint rcse; /* Receive Carrier Sense Error */ - uint rund; /* Receive Undersize Packet */ - uint rovr; /* Receive Oversize Packet */ - uint rfrg; /* Receive Fragments */ - uint rjbr; /* Receive Jabber */ - uint rdrp; /* Receive Drop */ + u32 rbyt; /* Receive Byte Counter */ + u32 rpkt; /* Receive Packet Counter */ + u32 rfcs; /* Receive FCS Error Counter */ + u32 rmca; /* Receive Multicast Packet (Counter) */ + u32 rbca; /* Receive Broadcast Packet */ + u32 rxcf; /* Receive Control Frame Packet */ + u32 rxpf; /* Receive Pause Frame Packet */ + u32 rxuo; /* Receive Unknown OP Code */ + u32 raln; /* Receive Alignment Error */ + u32 rflr; /* Receive Frame Length Error */ + u32 rcde; /* Receive Code Error */ + u32 rcse; /* Receive Carrier Sense Error */ + u32 rund; /* Receive Undersize Packet */ + u32 rovr; /* Receive Oversize Packet */ + u32 rfrg; /* Receive Fragments */ + u32 rjbr; /* Receive Jabber */ + u32 rdrp; /* Receive Drop */ /* Transmit Counters */ - uint tbyt; /* Transmit Byte Counter */ - uint tpkt; /* Transmit Packet */ - uint tmca; /* Transmit Multicast Packet */ - uint tbca; /* Transmit Broadcast Packet */ - uint txpf; /* Transmit Pause Control Frame */ - uint tdfr; /* Transmit Deferral Packet */ - uint tedf; /* Transmit Excessive Deferral Packet */ - uint tscl; /* Transmit Single Collision Packet */ + u32 tbyt; /* Transmit Byte Counter */ + u32 tpkt; /* Transmit Packet */ + u32 tmca; /* Transmit Multicast Packet */ + u32 tbca; /* Transmit Broadcast Packet */ + u32 txpf; /* Transmit Pause Control Frame */ + u32 tdfr; /* Transmit Deferral Packet */ + u32 tedf; /* Transmit Excessive Deferral Packet */ + u32 tscl; /* Transmit Single Collision Packet */ /* (0x2_n700) */ - uint tmcl; /* Transmit Multiple Collision Packet */ - uint tlcl; /* Transmit Late Collision Packet */ - uint txcl; /* Transmit Excessive Collision Packet */ - uint tncl; /* Transmit Total Collision */ - - uint res2; - - uint tdrp; /* Transmit Drop Frame */ - uint tjbr; /* Transmit Jabber Frame */ - uint tfcs; /* Transmit FCS Error */ - uint txcf; /* Transmit Control Frame */ - uint tovr; /* Transmit Oversize Frame */ - uint tund; /* Transmit Undersize Frame */ - uint tfrg; /* Transmit Fragments Frame */ + u32 tmcl; /* Transmit Multiple Collision Packet */ + u32 tlcl; /* Transmit Late Collision Packet */ + u32 txcl; /* Transmit Excessive Collision Packet */ + u32 tncl; /* Transmit Total Collision */ + + u32 res2; + + u32 tdrp; /* Transmit Drop Frame */ + u32 tjbr; /* Transmit Jabber Frame */ + u32 tfcs; /* Transmit FCS Error */ + u32 txcf; /* Transmit Control Frame */ + u32 tovr; /* Transmit Oversize Frame */ + u32 tund; /* Transmit Undersize Frame */ + u32 tfrg; /* Transmit Fragments Frame */ /* General Registers */ - uint car1; /* Carry Register One */ - uint car2; /* Carry Register Two */ - uint cam1; /* Carry Register One Mask */ - uint cam2; /* Carry Register Two Mask */ -} rmon_mib_t; - -typedef struct tsec_hash_regs -{ - uint iaddr0; /* Individual Address Register 0 */ - uint iaddr1; /* Individual Address Register 1 */ - uint iaddr2; /* Individual Address Register 2 */ - uint iaddr3; /* Individual Address Register 3 */ - uint iaddr4; /* Individual Address Register 4 */ - uint iaddr5; /* Individual Address Register 5 */ - uint iaddr6; /* Individual Address Register 6 */ - uint iaddr7; /* Individual Address Register 7 */ - uint res1[24]; - uint gaddr0; /* Group Address Register 0 */ - uint gaddr1; /* Group Address Register 1 */ - uint gaddr2; /* Group Address Register 2 */ - uint gaddr3; /* Group Address Register 3 */ - uint gaddr4; /* Group Address Register 4 */ - uint gaddr5; /* Group Address Register 5 */ - uint gaddr6; /* Group Address Register 6 */ - uint gaddr7; /* Group Address Register 7 */ - uint res2[24]; -} tsec_hash_t; + u32 car1; /* Carry Register One */ + u32 car2; /* Carry Register Two */ + u32 cam1; /* Carry Register One Mask */ + u32 cam2; /* Carry Register Two Mask */ +}; + +struct tsec_hash_regs { + u32 iaddr0; /* Individual Address Register 0 */ + u32 iaddr1; /* Individual Address Register 1 */ + u32 iaddr2; /* Individual Address Register 2 */ + u32 iaddr3; /* Individual Address Register 3 */ + u32 iaddr4; /* Individual Address Register 4 */ + u32 iaddr5; /* Individual Address Register 5 */ + u32 iaddr6; /* Individual Address Register 6 */ + u32 iaddr7; /* Individual Address Register 7 */ + u32 res1[24]; + u32 gaddr0; /* Group Address Register 0 */ + u32 gaddr1; /* Group Address Register 1 */ + u32 gaddr2; /* Group Address Register 2 */ + u32 gaddr3; /* Group Address Register 3 */ + u32 gaddr4; /* Group Address Register 4 */ + u32 gaddr5; /* Group Address Register 5 */ + u32 gaddr6; /* Group Address Register 6 */ + u32 gaddr7; /* Group Address Register 7 */ + u32 res2[24]; +}; struct tsec { /* General Control and Status Registers (0x2_n000) */ - uint res000[4]; + u32 res000[4]; - uint ievent; /* Interrupt Event */ - uint imask; /* Interrupt Mask */ - uint edis; /* Error Disabled */ - uint res01c; - uint ecntrl; /* Ethernet Control */ - uint minflr; /* Minimum Frame Length */ - uint ptv; /* Pause Time Value */ - uint dmactrl; /* DMA Control */ - uint tbipa; /* TBI PHY Address */ + u32 ievent; /* Interrupt Event */ + u32 imask; /* Interrupt Mask */ + u32 edis; /* Error Disabled */ + u32 res01c; + u32 ecntrl; /* Ethernet Control */ + u32 minflr; /* Minimum Frame Length */ + u32 ptv; /* Pause Time Value */ + u32 dmactrl; /* DMA Control */ + u32 tbipa; /* TBI PHY Address */ - uint res034[3]; - uint res040[48]; + u32 res034[3]; + u32 res040[48]; /* Transmit Control and Status Registers (0x2_n100) */ - uint tctrl; /* Transmit Control */ - uint tstat; /* Transmit Status */ - uint res108; - uint tbdlen; /* Tx BD Data Length */ - uint res110[5]; - uint ctbptr; /* Current TxBD Pointer */ - uint res128[23]; - uint tbptr; /* TxBD Pointer */ - uint res188[30]; + u32 tctrl; /* Transmit Control */ + u32 tstat; /* Transmit Status */ + u32 res108; + u32 tbdlen; /* Tx BD Data Length */ + u32 res110[5]; + u32 ctbptr; /* Current TxBD Pointer */ + u32 res128[23]; + u32 tbptr; /* TxBD Pointer */ + u32 res188[30]; /* (0x2_n200) */ - uint res200; - uint tbase; /* TxBD Base Address */ - uint res208[42]; - uint ostbd; /* Out of Sequence TxBD */ - uint ostbdp; /* Out of Sequence Tx Data Buffer Pointer */ - uint res2b8[18]; + u32 res200; + u32 tbase; /* TxBD Base Address */ + u32 res208[42]; + u32 ostbd; /* Out of Sequence TxBD */ + u32 ostbdp; /* Out of Sequence Tx Data Buffer Pointer */ + u32 res2b8[18]; /* Receive Control and Status Registers (0x2_n300) */ - uint rctrl; /* Receive Control */ - uint rstat; /* Receive Status */ - uint res308; - uint rbdlen; /* RxBD Data Length */ - uint res310[4]; - uint res320; - uint crbptr; /* Current Receive Buffer Pointer */ - uint res328[6]; - uint mrblr; /* Maximum Receive Buffer Length */ - uint res344[16]; - uint rbptr; /* RxBD Pointer */ - uint res388[30]; + u32 rctrl; /* Receive Control */ + u32 rstat; /* Receive Status */ + u32 res308; + u32 rbdlen; /* RxBD Data Length */ + u32 res310[4]; + u32 res320; + u32 crbptr; /* Current Receive Buffer Pointer */ + u32 res328[6]; + u32 mrblr; /* Maximum Receive Buffer Length */ + u32 res344[16]; + u32 rbptr; /* RxBD Pointer */ + u32 res388[30]; /* (0x2_n400) */ - uint res400; - uint rbase; /* RxBD Base Address */ - uint res408[62]; + u32 res400; + u32 rbase; /* RxBD Base Address */ + u32 res408[62]; /* MAC Registers (0x2_n500) */ - uint maccfg1; /* MAC Configuration #1 */ - uint maccfg2; /* MAC Configuration #2 */ - uint ipgifg; /* Inter Packet Gap/Inter Frame Gap */ - uint hafdup; /* Half-duplex */ - uint maxfrm; /* Maximum Frame */ - uint res514; - uint res518; + u32 maccfg1; /* MAC Configuration #1 */ + u32 maccfg2; /* MAC Configuration #2 */ + u32 ipgifg; /* Inter Packet Gap/Inter Frame Gap */ + u32 hafdup; /* Half-duplex */ + u32 maxfrm; /* Maximum Frame */ + u32 res514; + u32 res518; - uint res51c; + u32 res51c; - uint resmdio[6]; + u32 resmdio[6]; - uint res538; + u32 res538; - uint ifstat; /* Interface Status */ - uint macstnaddr1; /* Station Address, part 1 */ - uint macstnaddr2; /* Station Address, part 2 */ - uint res548[46]; + u32 ifstat; /* Interface Status */ + u32 macstnaddr1; /* Station Address, part 1 */ + u32 macstnaddr2; /* Station Address, part 2 */ + u32 res548[46]; /* (0x2_n600) */ - uint res600[32]; + u32 res600[32]; /* RMON MIB Registers (0x2_n680-0x2_n73c) */ - rmon_mib_t rmon; - uint res740[48]; + struct tsec_rmon_mib rmon; + u32 res740[48]; /* Hash Function Registers (0x2_n800) */ - tsec_hash_t hash; + struct tsec_hash_regs hash; - uint res900[128]; + u32 res900[128]; /* Pattern Registers (0x2_nb00) */ - uint resb00[62]; - uint attr; /* Default Attribute Register */ - uint attreli; /* Default Attribute Extract Length and Index */ + u32 resb00[62]; + u32 attr; /* Default Attribute Register */ + u32 attreli; /* Default Attribute Extract Length and Index */ /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */ - uint resc00[256]; + u32 resc00[256]; }; #define TSEC_GIGABIT (1 << 0) From b1690bc39cfdba82be34b1a98abc319339070698 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 30 Sep 2013 12:44:47 +0300 Subject: [PATCH 30/40] net: tsec: Fix mac addr setup portability, cleanup Fix the 32-bit memory access that is not "endianess safe", i.e. not giving the desired byte layout for LE cpus: tempval = *((uint *) (tmpbuf + 4)), where 'char tmpbuf[]'. Free the stack from rendundant local vars: tmpbuf[] and i. Use a portable type (u32) for the 32bit tsec register value holder: tempval. Signed-off-by: Claudiu Manoil --- drivers/net/tsec.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 082cdec..e9138f0 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -473,11 +473,9 @@ static void tsec_halt(struct eth_device *dev) */ static int tsec_init(struct eth_device *dev, bd_t * bd) { - uint tempval; - char tmpbuf[MAC_ADDR_LEN]; - int i; struct tsec_private *priv = (struct tsec_private *)dev->priv; struct tsec __iomem *regs = priv->regs; + u32 tempval; int ret; /* Make sure the controller is stopped */ @@ -490,16 +488,16 @@ static int tsec_init(struct eth_device *dev, bd_t * bd) out_be32(®s->ecntrl, ECNTRL_INIT_SETTINGS); /* Copy the station address into the address registers. - * Backwards, because little endian MACS are dumb */ - for (i = 0; i < MAC_ADDR_LEN; i++) - tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; - - tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | - tmpbuf[3]; + * For a station address of 0x12345678ABCD in transmission + * order (BE), MACnADDR1 is set to 0xCDAB7856 and + * MACnADDR2 is set to 0x34120000. + */ + tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) | + (dev->enetaddr[3] << 8) | dev->enetaddr[2]; out_be32(®s->macstnaddr1, tempval); - tempval = *((uint *) (tmpbuf + 4)); + tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16); out_be32(®s->macstnaddr2, tempval); From 317745785341774644b8bb1cbb0300155f31cee6 Mon Sep 17 00:00:00 2001 From: Chunhe Lan Date: Fri, 1 Nov 2013 17:17:44 +0800 Subject: [PATCH 31/40] net/phy: Fix the phy id mask of AR8031 The both AR8031 and AR8035 belong to Atheros 803x serial PHY. So the phy id mask of AR8031 is the same to the phy id mask of AR8035. The right mask value is 0x4fffff. This patch has been tested on the P1010 and P1023. Signed-off-by: Chunhe Lan Cc: Joe Hershberger Patch: 287748 --- drivers/net/phy/atheros.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index f225d93..215658a 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -50,7 +50,7 @@ static struct phy_driver AR8021_driver = { static struct phy_driver AR8031_driver = { .name = "AR8031/AR8033", .uid = 0x4dd074, - .mask = 0xffffff, + .mask = 0x4fffff, .features = PHY_GBIT_FEATURES, .config = ar8021_config, .startup = genphy_startup, From e003ba5bfc57ff7d065967e263fa24e3ef28ea0a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 2 Nov 2013 16:40:42 -0200 Subject: [PATCH 32/40] net: phy: atheros: Fix masks for AR8035 and AR8021 The masks were ignoring the last 4 bits which didn't allow detection differences between the ar8031 and ar8035. Signed-off-by: Jon Nettleton Signed-off-by: Fabio Estevam Patch: 288018 --- drivers/net/phy/atheros.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 215658a..b20b4df 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -40,7 +40,7 @@ static int ar8035_config(struct phy_device *phydev) static struct phy_driver AR8021_driver = { .name = "AR8021", .uid = 0x4dd040, - .mask = 0xfffff0, + .mask = 0x4fffff, .features = PHY_GBIT_FEATURES, .config = ar8021_config, .startup = genphy_startup, From 8e52533d109571915a0006533e2e1adb01face00 Mon Sep 17 00:00:00 2001 From: Andrew Ruder Date: Tue, 22 Oct 2013 19:10:28 -0500 Subject: [PATCH 33/40] net: tftpsrv: Get correct client MAC address NetServerEther was not being cleared in the tftp server code, so the destination MAC address would be whatever the last destination MAC address was. Scenario: U-Boot: dhcp tftpsrv Host: Send device WRQ Device: Responds with ACK to dhcp server mac address with host ip address By clearing NetServerEther, we force a lookup of the host MAC address to go with the associated host IP. Signed-off-by: Andrew Ruder --- net/tftp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/tftp.c b/net/tftp.c index 2e06808..966d1cf 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -849,6 +849,9 @@ TftpStartServer(void) TftpState = STATE_RECV_WRQ; net_set_udp_handler(TftpHandler); + + /* zero out server ether in case the server ip has changed */ + memset(NetServerEther, 0, 6); } #endif /* CONFIG_CMD_TFTPSRV */ From 8712adfd0595ea68ce06fb22420489dacc3a6cc6 Mon Sep 17 00:00:00 2001 From: Rojhalat Ibrahim Date: Mon, 7 Oct 2013 18:30:39 +0200 Subject: [PATCH 34/40] drivers/net/e1000: Introduce CONFIG_E1000_NO_NVM The e1000 driver expects to always have some kind of non-volatile memory attached directly to the ethernet controller chip. This means that I would have to add an additional separate flash chip to my custom board just to store essentially the MAC address. Since I don't want to do that, this patch introduces a new config option CONFIG_E1000_NO_NVM. If defined it disables all accesses to the NVM. I have tested the patch with a 82574 controller. Signed-off-by: Rojhalat Ibrahim --- drivers/net/e1000.c | 34 +++++++++++++++++++++++++++++----- drivers/net/e1000.h | 9 +++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 57aa53d..9a66e68 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -114,12 +114,13 @@ static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, static int32_t e1000_phy_hw_reset(struct e1000_hw *hw); static int e1000_phy_reset(struct e1000_hw *hw); static int e1000_detect_gig_phy(struct e1000_hw *hw); -static void e1000_put_hw_eeprom_semaphore(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 int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); +#ifndef CONFIG_E1000_NO_NVM +static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw); static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); @@ -885,6 +886,7 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw) return -E1000_ERR_EEPROM; } +#endif /* CONFIG_E1000_NO_NVM */ /***************************************************************************** * Set PHY to class A mode @@ -897,6 +899,7 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw) static int32_t e1000_set_phy_mode(struct e1000_hw *hw) { +#ifndef CONFIG_E1000_NO_NVM int32_t ret_val; uint16_t eeprom_data; @@ -923,10 +926,11 @@ e1000_set_phy_mode(struct e1000_hw *hw) hw->phy_reset_disable = false; } } - +#endif return E1000_SUCCESS; } +#ifndef CONFIG_E1000_NO_NVM /*************************************************************************** * * Obtaining software semaphore bit (SMBI) before resetting PHY. @@ -965,6 +969,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw) return E1000_SUCCESS; } +#endif /*************************************************************************** * This function clears HW semaphore bits. @@ -977,6 +982,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw) static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) { +#ifndef CONFIG_E1000_NO_NVM uint32_t swsm; DEBUGFUNC(); @@ -991,6 +997,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) } else swsm &= ~(E1000_SWSM_SWESMBI); E1000_WRITE_REG(hw, SWSM, swsm); +#endif } /*************************************************************************** @@ -1007,6 +1014,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) { +#ifndef CONFIG_E1000_NO_NVM int32_t timeout; uint32_t swsm; @@ -1043,7 +1051,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) "SWESMBI bit is set.\n"); return -E1000_ERR_EEPROM; } - +#endif return E1000_SUCCESS; } @@ -1097,6 +1105,7 @@ static bool e1000_is_second_port(struct e1000_hw *hw) } } +#ifndef CONFIG_E1000_NO_NVM /****************************************************************************** * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the * second function of dual function devices @@ -1136,6 +1145,7 @@ e1000_read_mac_addr(struct eth_device *nic) #endif return 0; } +#endif /****************************************************************************** * Initializes receive address filters. @@ -1764,9 +1774,11 @@ static int e1000_setup_link(struct eth_device *nic) { struct e1000_hw *hw = nic->priv; - uint32_t ctrl_ext; int32_t ret_val; +#ifndef CONFIG_E1000_NO_NVM + uint32_t ctrl_ext; uint16_t eeprom_data; +#endif DEBUGFUNC(); @@ -1775,6 +1787,7 @@ e1000_setup_link(struct eth_device *nic) if (e1000_check_phy_reset_block(hw)) return E1000_SUCCESS; +#ifndef CONFIG_E1000_NO_NVM /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or @@ -1788,7 +1801,7 @@ e1000_setup_link(struct eth_device *nic) DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } - +#endif if (hw->fc == e1000_fc_default) { switch (hw->mac_type) { case e1000_ich8lan: @@ -1797,6 +1810,7 @@ e1000_setup_link(struct eth_device *nic) hw->fc = e1000_fc_full; break; default: +#ifndef CONFIG_E1000_NO_NVM ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); if (ret_val) { @@ -1809,6 +1823,7 @@ e1000_setup_link(struct eth_device *nic) EEPROM_WORD0F_ASM_DIR) hw->fc = e1000_fc_tx_pause; else +#endif hw->fc = e1000_fc_full; break; } @@ -1828,6 +1843,7 @@ e1000_setup_link(struct eth_device *nic) DEBUGOUT("After fix-ups FlowControl is now = %x\n", hw->fc); +#ifndef CONFIG_E1000_NO_NVM /* Take the 4 bits from EEPROM word 0x0F that determine the initial * polarity value for the SW controlled pins, and setup the * Extended Device Control reg with that info. @@ -1840,6 +1856,7 @@ e1000_setup_link(struct eth_device *nic) SWDPIO__EXT_SHIFT); E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); } +#endif /* Call the necessary subroutine to configure the link. */ ret_val = (hw->media_type == e1000_media_type_fiber) ? @@ -5196,6 +5213,7 @@ e1000_initialize(bd_t * bis) e1000_reset_hw(hw); list_add_tail(&hw->list_node, &e1000_hw_list); +#ifndef CONFIG_E1000_NO_NVM /* Validate the EEPROM and get chipset information */ #if !defined(CONFIG_MVBC_1G) if (e1000_init_eeprom_params(hw)) { @@ -5206,11 +5224,17 @@ e1000_initialize(bd_t * bis) continue; #endif e1000_read_mac_addr(nic); +#endif e1000_get_bus_type(hw); +#ifndef CONFIG_E1000_NO_NVM printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n ", nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2], nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]); +#else + memset(nic->enetaddr, 0, 6); + printf("e1000: no NVM\n"); +#endif /* Set up the function pointers and register the device */ nic->init = e1000_init; diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index 25884f5..ff87af2 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -63,11 +63,14 @@ struct e1000_hw_stats; /* Internal E1000 helper functions */ struct e1000_hw *e1000_find_card(unsigned int cardnum); + +#ifndef CONFIG_E1000_NO_NVM int32_t e1000_acquire_eeprom(struct e1000_hw *hw); void e1000_standby_eeprom(struct e1000_hw *hw); void e1000_release_eeprom(struct e1000_hw *hw); void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); +#endif #ifdef CONFIG_E1000_SPI int do_e1000_spi(cmd_tbl_t *cmdtp, struct e1000_hw *hw, @@ -1019,6 +1022,7 @@ struct e1000_hw_stats { uint64_t tsctfc; }; +#ifndef CONFIG_E1000_NO_NVM struct e1000_eeprom_info { e1000_eeprom_type type; uint16_t word_size; @@ -1029,6 +1033,7 @@ e1000_eeprom_type type; bool use_eerd; bool use_eewr; }; +#endif typedef enum { e1000_smart_speed_default = 0, @@ -1081,10 +1086,14 @@ struct e1000_hw { uint32_t io_base; #endif uint32_t asf_firmware_present; +#ifndef CONFIG_E1000_NO_NVM uint32_t eeprom_semaphore_present; +#endif uint32_t swfw_sync_present; uint32_t swfwhw_semaphore_present; +#ifndef CONFIG_E1000_NO_NVM struct e1000_eeprom_info eeprom; +#endif e1000_ms_type master_slave; e1000_ms_type original_master_slave; e1000_ffe_config ffe_config_state; From c583ee16cb5db73fc299bb679ecb75a5abb3ca47 Mon Sep 17 00:00:00 2001 From: Andrew Ruder Date: Tue, 22 Oct 2013 19:09:02 -0500 Subject: [PATCH 35/40] net: dm9000: random mac address support When an unprogrammed EEPROM is attached to a dm9000, the dm9000 will come up with a invalid MAC address of ff:ff:ff:ff:ff:ff. Add code that gets enabled if CONFIG_RANDOM_MACADDR is enabled that generates a random (and valid) locally administered MAC address that allows the system to network boot until a real MAC address can be configured. Signed-off-by: Andrew Ruder --- drivers/net/dm9000x.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index f7170e0..b68d808 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -342,6 +342,15 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS); printf("MAC: %pM\n", dev->enetaddr); + if (!is_valid_ether_addr(dev->enetaddr)) { +#ifdef CONFIG_RANDOM_MACADDR + printf("Bad MAC address (uninitialized EEPROM?), randomizing\n"); + eth_random_enetaddr(dev->enetaddr); + printf("MAC: %pM\n", dev->enetaddr); +#else + printf("WARNING: Bad MAC address (uninitialized EEPROM?)\n"); +#endif + } /* fill device MAC address registers */ for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) From 3a530d1b3e947c09e882dda8883aa608458a598c Mon Sep 17 00:00:00 2001 From: David Dueck Date: Tue, 5 Nov 2013 17:23:02 +0100 Subject: [PATCH 36/40] phy: Use supported field during autonegotiation The current code incorrectly detects gigabit capabilities for some 100Mbit/s phys. (lan8720a) Signed-off-by: David Dueck --- drivers/net/phy/phy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 62925bb..c691fbb 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -275,13 +275,14 @@ int genphy_parse_link(struct phy_device *phydev) int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); /* We're using autonegotiation */ - if (mii_reg & BMSR_ANEGCAPABLE) { + if (phydev->supported & SUPPORTED_Autoneg) { u32 lpa = 0; int gblpa = 0; u32 estatus = 0; /* Check for gigabit capability */ - if (mii_reg & BMSR_ERCAP) { + if (phydev->supported & (SUPPORTED_1000baseT_Full | + SUPPORTED_1000baseT_Half)) { /* We want a list of states supported by * both PHYs in the link */ From f27f3b5266d28b8d3e80e0e8f4cafdd14268b62a Mon Sep 17 00:00:00 2001 From: David Dueck Date: Tue, 5 Nov 2013 17:23:03 +0100 Subject: [PATCH 37/40] phy: Use general phy code for smsc lan8720a Signed-off-by: David Dueck --- drivers/net/phy/smsc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 60ed92d..bfd9815 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -12,6 +12,7 @@ */ #include +/* This code does not check the partner abilities. */ static int smsc_parse_status(struct phy_device *phydev) { int mii_reg; @@ -64,7 +65,7 @@ static struct phy_driver lan8710_driver = { .mask = 0xffff0, .features = PHY_BASIC_FEATURES, .config = &genphy_config_aneg, - .startup = &smsc_startup, + .startup = &genphy_startup, .shutdown = &genphy_shutdown, }; From a5144237ac6dce3a38a73a51c217636a37d1e0b6 Mon Sep 17 00:00:00 2001 From: Srikanth Thokala Date: Fri, 8 Nov 2013 22:55:48 +0530 Subject: [PATCH 38/40] net: zynq_gem: Add d-cache support Added d-cache support for zynq_gem.c, Observed a difference of +0.8 MiB/s when downloading a file of size of 3007944Bytes. With d-cache OFF: ---------------- Filename 'uImage'. Load address: 0x800 Loading: ################################################################# ################################################################# ################################################################# ########## 1.3 MiB/s done Bytes transferred = 3007944 (2de5c8 hex) With d-cache ON: --------------- Filename 'uImage'. Load address: 0x800 Loading: ################################################################# ################################################################# ################################################################# ########## 2.1 MiB/s done Bytes transferred = 3007944 (2de5c8 hex) Changes on zynq_gem for d-cache support: - Tx and Rx buffers are cache-aligned - Updated logic for invalidating Rx buffers and flushing Tx buffers. - Tx and Rx BD's are allocated from non-cacheable region. (When BDs are cached, we don't see a consistent link) - Use TX BD status intead of txsr status checks. Signed-off-by: Srikanth Thokala Signed-off-by: Jagannadha Sutradharudu Teki Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 82 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 236a753..6a017a8 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -43,11 +43,6 @@ #define ZYNQ_GEM_TXBUF_WRAP_MASK 0x40000000 #define ZYNQ_GEM_TXBUF_LAST_MASK 0x00008000 /* Last buffer */ -#define ZYNQ_GEM_TXSR_HRESPNOK_MASK 0x00000100 /* Transmit hresp not OK */ -#define ZYNQ_GEM_TXSR_URUN_MASK 0x00000040 /* Transmit underrun */ -/* Transmit buffs exhausted mid frame */ -#define ZYNQ_GEM_TXSR_BUFEXH_MASK 0x00000010 - #define ZYNQ_GEM_NWCTRL_TXEN_MASK 0x00000008 /* Enable transmit */ #define ZYNQ_GEM_NWCTRL_RXEN_MASK 0x00000004 /* Enable receive */ #define ZYNQ_GEM_NWCTRL_MDEN_MASK 0x00000010 /* Enable MDIO port */ @@ -90,6 +85,11 @@ */ #define PHY_DETECT_MASK 0x1808 +/* TX BD status masks */ +#define ZYNQ_GEM_TXBUF_FRMLEN_MASK 0x000007ff +#define ZYNQ_GEM_TXBUF_EXHAUSTED 0x08000000 +#define ZYNQ_GEM_TXBUF_UNDERRUN 0x10000000 + /* Device registers */ struct zynq_gem_regs { u32 nwctrl; /* Network Control reg */ @@ -123,12 +123,18 @@ struct emac_bd { }; #define RX_BUF 3 +/* Page table entries are set to 1MB, or multiples of 1MB + * (not < 1MB). driver uses less bd's so use 1MB bdspace. + */ +#define BD_SPACE 0x100000 +/* BD separation space */ +#define BD_SEPRN_SPACE 64 /* Initialized, rxbd_current, rx_first_buf must be 0 after init */ struct zynq_gem_priv { - struct emac_bd tx_bd; - struct emac_bd rx_bd[RX_BUF]; - char rxbuffers[RX_BUF * PKTSIZE_ALIGN]; + struct emac_bd *tx_bd; + struct emac_bd *rx_bd; + char *rxbuffers; u32 rxbd_current; u32 rx_first_buf; int phyaddr; @@ -299,20 +305,18 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) readl(®s->stat[i]); /* Setup RxBD space */ - memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); - /* Create the RxBD ring */ - memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); + memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd)); for (i = 0; i < RX_BUF; i++) { priv->rx_bd[i].status = 0xF0000000; priv->rx_bd[i].addr = - (u32)((char *)&(priv->rxbuffers) + + ((u32)(priv->rxbuffers) + (i * PKTSIZE_ALIGN)); } /* WRAP bit to last BD */ priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; /* Write RxBDs to IP */ - writel((u32)&(priv->rx_bd), ®s->rxqbase); + writel((u32)priv->rx_bd, ®s->rxqbase); /* Setup for DMA Configuration register */ writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); @@ -368,32 +372,35 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) static int zynq_gem_send(struct eth_device *dev, void *ptr, int len) { - u32 status; + u32 addr, size; struct zynq_gem_priv *priv = dev->priv; struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; - const u32 mask = ZYNQ_GEM_TXSR_HRESPNOK_MASK | \ - ZYNQ_GEM_TXSR_URUN_MASK | ZYNQ_GEM_TXSR_BUFEXH_MASK; /* setup BD */ - writel((u32)&(priv->tx_bd), ®s->txqbase); + writel((u32)priv->tx_bd, ®s->txqbase); /* Setup Tx BD */ - memset((void *)&(priv->tx_bd), 0, sizeof(struct emac_bd)); + memset(priv->tx_bd, 0, sizeof(struct emac_bd)); + + priv->tx_bd->addr = (u32)ptr; + priv->tx_bd->status = (len & ZYNQ_GEM_TXBUF_FRMLEN_MASK) | + ZYNQ_GEM_TXBUF_LAST_MASK; - priv->tx_bd.addr = (u32)ptr; - priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK; + addr = (u32) ptr; + addr &= ~(ARCH_DMA_MINALIGN - 1); + size = roundup(len, ARCH_DMA_MINALIGN); + flush_dcache_range(addr, addr + size); + barrier(); /* Start transmit */ setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_STARTTX_MASK); - /* Read the stat register to know if the packet has been transmitted */ - status = readl(®s->txsr); - if (status & mask) - printf("Something has gone wrong here!? Status is 0x%x.\n", - status); + /* Read TX BD status */ + if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_UNDERRUN) + printf("TX underrun\n"); + if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED) + printf("TX buffers exhausted in mid frame\n"); - /* Clear Tx status register before leaving . */ - writel(status, ®s->txsr); return 0; } @@ -416,8 +423,12 @@ static int zynq_gem_recv(struct eth_device *dev) frame_len = current_bd->status & ZYNQ_GEM_RXBUF_LEN_MASK; if (frame_len) { - NetReceive((u8 *) (current_bd->addr & - ZYNQ_GEM_RXBUF_ADD_MASK), frame_len); + u32 addr = current_bd->addr & ZYNQ_GEM_RXBUF_ADD_MASK; + addr &= ~(ARCH_DMA_MINALIGN - 1); + u32 size = roundup(frame_len, ARCH_DMA_MINALIGN); + invalidate_dcache_range(addr, addr + size); + + NetReceive((u8 *)addr, frame_len); if (current_bd->status & ZYNQ_GEM_RXBUF_SOF_MASK) priv->rx_first_buf = priv->rxbd_current; @@ -471,6 +482,7 @@ int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio) { struct eth_device *dev; struct zynq_gem_priv *priv; + void *bd_space; dev = calloc(1, sizeof(*dev)); if (dev == NULL) @@ -483,6 +495,18 @@ int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio) } priv = dev->priv; + /* Align rxbuffers to ARCH_DMA_MINALIGN */ + priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN); + memset(priv->rxbuffers, 0, RX_BUF * PKTSIZE_ALIGN); + + /* Align bd_space to 1MB */ + bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE); + mmu_set_region_dcache_behaviour((u32)bd_space, BD_SPACE, DCACHE_OFF); + + /* Initialize the bd spaces for tx and rx bd's */ + priv->tx_bd = (struct emac_bd *)bd_space; + priv->rx_bd = (struct emac_bd *)((u32)bd_space + BD_SEPRN_SPACE); + priv->phyaddr = phy_addr; priv->emio = emio; From 22ece0e2e23c5cc5a23a5b8aff3dc75c9832e82f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 20 Sep 2013 16:03:42 +0200 Subject: [PATCH 39/40] net: rtl8169: Improve cache maintenance Instead of directly calling the low-level invalidate_dcache_range() and flush_cache() functions, provide thin wrappers that take into account alignment requirements. While at it, fix a case where the cache was flushed but should have been invalidated, two cases where the buffer data was flushed instead of the descriptor and a missing cache invalidation before reading the packet data that the NIC just wrote to memory. Signed-off-by: Thierry Reding Patch: 276474 --- drivers/net/rtl8169.c | 61 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 290c988..c47485a 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -395,6 +395,50 @@ match: return 0; } +/* + * Cache maintenance functions. These are simple wrappers around the more + * general purpose flush_cache() and invalidate_dcache_range() functions. + */ + +static void rtl_inval_rx_desc(struct RxDesc *desc) +{ + unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); + unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN); + + invalidate_dcache_range(start, end); +} + +static void rtl_flush_rx_desc(struct RxDesc *desc) +{ + flush_cache((unsigned long)desc, sizeof(*desc)); +} + +static void rtl_inval_tx_desc(struct TxDesc *desc) +{ + unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); + unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN); + + invalidate_dcache_range(start, end); +} + +static void rtl_flush_tx_desc(struct TxDesc *desc) +{ + flush_cache((unsigned long)desc, sizeof(*desc)); +} + +static void rtl_inval_buffer(void *buf, size_t size) +{ + unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); + unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); + + invalidate_dcache_range(start, end); +} + +static void rtl_flush_buffer(void *buf, size_t size) +{ + flush_cache((unsigned long)buf, size); +} + /************************************************************************** RECV - Receive a frame ***************************************************************************/ @@ -412,14 +456,16 @@ static int rtl_recv(struct eth_device *dev) ioaddr = dev->iobase; cur_rx = tpc->cur_rx; - flush_cache((unsigned long)&tpc->RxDescArray[cur_rx], - sizeof(struct RxDesc)); + + rtl_inval_rx_desc(&tpc->RxDescArray[cur_rx]); + if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) { if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) { unsigned char rxdata[RX_BUF_LEN]; length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx]. status) & 0x00001FFF) - 4; + rtl_inval_buffer(tpc->RxBufferRing[cur_rx], length); memcpy(rxdata, tpc->RxBufferRing[cur_rx], length); NetReceive(rxdata, length); @@ -431,8 +477,7 @@ static int rtl_recv(struct eth_device *dev) cpu_to_le32(OWNbit + RX_BUF_SIZE); tpc->RxDescArray[cur_rx].buf_addr = cpu_to_le32(bus_to_phys(tpc->RxBufferRing[cur_rx])); - flush_cache((unsigned long)tpc->RxBufferRing[cur_rx], - RX_BUF_SIZE); + rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]); } else { puts("Error Rx"); } @@ -474,7 +519,7 @@ static int rtl_send(struct eth_device *dev, void *packet, int length) /* point to the current txb incase multiple tx_rings are used */ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; memcpy(ptxb, (char *)packet, (int)length); - flush_cache((unsigned long)ptxb, length); + rtl_flush_buffer(ptxb, length); while (len < ETH_ZLEN) ptxb[len++] = '\0'; @@ -490,13 +535,13 @@ static int rtl_send(struct eth_device *dev, void *packet, int length) cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } + rtl_flush_tx_desc(&tpc->TxDescArray[entry]); RTL_W8(TxPoll, 0x40); /* set polling bit */ tpc->cur_tx++; to = currticks() + TX_TIMEOUT; do { - flush_cache((unsigned long)&tpc->TxDescArray[entry], - sizeof(struct TxDesc)); + rtl_inval_tx_desc(&tpc->TxDescArray[entry]); } while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit) && (currticks() < to)); /* wait */ @@ -639,7 +684,7 @@ static void rtl8169_init_ring(struct eth_device *dev) tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; tpc->RxDescArray[i].buf_addr = cpu_to_le32(bus_to_phys(tpc->RxBufferRing[i])); - flush_cache((unsigned long)tpc->RxBufferRing[i], RX_BUF_SIZE); + rtl_flush_rx_desc(&tpc->RxDescArray[i]); } #ifdef DEBUG_RTL8169 From 2287286be4e268d3d4ec3c0347bf31479dbd1f05 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 20 Sep 2013 16:03:43 +0200 Subject: [PATCH 40/40] net: rtl8169: Add support for RTL8168d/8111d This chip is compatible with the existing driver, except that it uses BAR2 instead of BAR1 for the I/O memory region. Using this patch I can use the PCIe ethernet interface on the CompuLab Trimslice to boot from the network. Signed-off-by: Thierry Reding Patch: 276477 --- drivers/net/rtl8169.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index c47485a..d040ab1 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -246,6 +246,7 @@ static struct { {"RTL-8169sc/8110sc", 0x18, 0xff7e1880,}, {"RTL-8168b/8111sb", 0x30, 0xff7e1880,}, {"RTL-8168b/8111sb", 0x38, 0xff7e1880,}, + {"RTL-8168d/8111d", 0x28, 0xff7e1880,}, {"RTL-8168evl/8111evl", 0x2e, 0xff7e1880,}, {"RTL-8101e", 0x34, 0xff7e1880,}, {"RTL-8100e", 0x32, 0xff7e1880,}, @@ -315,6 +316,7 @@ static const unsigned int rtl8169_rx_config = static struct pci_device_id supported[] = { {PCI_VENDOR_ID_REALTEK, 0x8167}, + {PCI_VENDOR_ID_REALTEK, 0x8168}, {PCI_VENDOR_ID_REALTEK, 0x8169}, {} }; @@ -915,11 +917,25 @@ int rtl8169_initialize(bd_t *bis) int idx=0; while(1){ + unsigned int region; + u16 device; + /* Find RTL8169 */ if ((devno = pci_find_devices(supported, idx++)) < 0) break; - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + pci_read_config_word(devno, PCI_DEVICE_ID, &device); + switch (device) { + case 0x8168: + region = 2; + break; + + default: + region = 1; + break; + } + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0 + (region * 4), &iobase); iobase &= ~0xf; debug ("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);