diff options
-rw-r--r-- | drivers/net/ethernet/renesas/sh_eth.c | 197 | ||||
-rw-r--r-- | drivers/net/ethernet/renesas/sh_eth.h | 9 |
2 files changed, 195 insertions, 11 deletions
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 64e72ebdf8c5..5d9e3a77a1eb 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c | |||
@@ -137,9 +137,6 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = { | |||
137 | [TSU_POST3] = 0x0078, | 137 | [TSU_POST3] = 0x0078, |
138 | [TSU_POST4] = 0x007c, | 138 | [TSU_POST4] = 0x007c, |
139 | [TSU_ADRH0] = 0x0100, | 139 | [TSU_ADRH0] = 0x0100, |
140 | [TSU_ADRL0] = 0x0104, | ||
141 | [TSU_ADRH31] = 0x01f8, | ||
142 | [TSU_ADRL31] = 0x01fc, | ||
143 | 140 | ||
144 | [TXNLCR0] = 0x0080, | 141 | [TXNLCR0] = 0x0080, |
145 | [TXALCR0] = 0x0084, | 142 | [TXALCR0] = 0x0084, |
@@ -206,9 +203,6 @@ static const u16 sh_eth_offset_fast_rz[SH_ETH_MAX_REGISTER_OFFSET] = { | |||
206 | [TSU_ADSBSY] = 0x0060, | 203 | [TSU_ADSBSY] = 0x0060, |
207 | [TSU_TEN] = 0x0064, | 204 | [TSU_TEN] = 0x0064, |
208 | [TSU_ADRH0] = 0x0100, | 205 | [TSU_ADRH0] = 0x0100, |
209 | [TSU_ADRL0] = 0x0104, | ||
210 | [TSU_ADRH31] = 0x01f8, | ||
211 | [TSU_ADRL31] = 0x01fc, | ||
212 | 206 | ||
213 | [TXNLCR0] = 0x0080, | 207 | [TXNLCR0] = 0x0080, |
214 | [TXALCR0] = 0x0084, | 208 | [TXALCR0] = 0x0084, |
@@ -405,8 +399,6 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = { | |||
405 | [FWALCR1] = 0x00b4, | 399 | [FWALCR1] = 0x00b4, |
406 | 400 | ||
407 | [TSU_ADRH0] = 0x0100, | 401 | [TSU_ADRH0] = 0x0100, |
408 | [TSU_ADRL0] = 0x0104, | ||
409 | [TSU_ADRL31] = 0x01fc, | ||
410 | }; | 402 | }; |
411 | 403 | ||
412 | static void sh_eth_rcv_snd_disable(struct net_device *ndev); | 404 | static void sh_eth_rcv_snd_disable(struct net_device *ndev); |
@@ -601,6 +593,7 @@ static struct sh_eth_cpu_data sh7757_data = { | |||
601 | .no_ade = 1, | 593 | .no_ade = 1, |
602 | .rpadir = 1, | 594 | .rpadir = 1, |
603 | .rpadir_value = 2 << 16, | 595 | .rpadir_value = 2 << 16, |
596 | .rtrate = 1, | ||
604 | }; | 597 | }; |
605 | 598 | ||
606 | #define SH_GIGA_ETH_BASE 0xfee00000UL | 599 | #define SH_GIGA_ETH_BASE 0xfee00000UL |
@@ -1945,6 +1938,192 @@ error_exit: | |||
1945 | return ret; | 1938 | return ret; |
1946 | } | 1939 | } |
1947 | 1940 | ||
1941 | /* If it is ever necessary to increase SH_ETH_REG_DUMP_MAX_REGS, the | ||
1942 | * version must be bumped as well. Just adding registers up to that | ||
1943 | * limit is fine, as long as the existing register indices don't | ||
1944 | * change. | ||
1945 | */ | ||
1946 | #define SH_ETH_REG_DUMP_VERSION 1 | ||
1947 | #define SH_ETH_REG_DUMP_MAX_REGS 256 | ||
1948 | |||
1949 | static size_t __sh_eth_get_regs(struct net_device *ndev, u32 *buf) | ||
1950 | { | ||
1951 | struct sh_eth_private *mdp = netdev_priv(ndev); | ||
1952 | struct sh_eth_cpu_data *cd = mdp->cd; | ||
1953 | u32 *valid_map; | ||
1954 | size_t len; | ||
1955 | |||
1956 | BUILD_BUG_ON(SH_ETH_MAX_REGISTER_OFFSET > SH_ETH_REG_DUMP_MAX_REGS); | ||
1957 | |||
1958 | /* Dump starts with a bitmap that tells ethtool which | ||
1959 | * registers are defined for this chip. | ||
1960 | */ | ||
1961 | len = DIV_ROUND_UP(SH_ETH_REG_DUMP_MAX_REGS, 32); | ||
1962 | if (buf) { | ||
1963 | valid_map = buf; | ||
1964 | buf += len; | ||
1965 | } else { | ||
1966 | valid_map = NULL; | ||
1967 | } | ||
1968 | |||
1969 | /* Add a register to the dump, if it has a defined offset. | ||
1970 | * This automatically skips most undefined registers, but for | ||
1971 | * some it is also necessary to check a capability flag in | ||
1972 | * struct sh_eth_cpu_data. | ||
1973 | */ | ||
1974 | #define mark_reg_valid(reg) valid_map[reg / 32] |= 1U << (reg % 32) | ||
1975 | #define add_reg_from(reg, read_expr) do { \ | ||
1976 | if (mdp->reg_offset[reg] != SH_ETH_OFFSET_INVALID) { \ | ||
1977 | if (buf) { \ | ||
1978 | mark_reg_valid(reg); \ | ||
1979 | *buf++ = read_expr; \ | ||
1980 | } \ | ||
1981 | ++len; \ | ||
1982 | } \ | ||
1983 | } while (0) | ||
1984 | #define add_reg(reg) add_reg_from(reg, sh_eth_read(ndev, reg)) | ||
1985 | #define add_tsu_reg(reg) add_reg_from(reg, sh_eth_tsu_read(mdp, reg)) | ||
1986 | |||
1987 | add_reg(EDSR); | ||
1988 | add_reg(EDMR); | ||
1989 | add_reg(EDTRR); | ||
1990 | add_reg(EDRRR); | ||
1991 | add_reg(EESR); | ||
1992 | add_reg(EESIPR); | ||
1993 | add_reg(TDLAR); | ||
1994 | add_reg(TDFAR); | ||
1995 | add_reg(TDFXR); | ||
1996 | add_reg(TDFFR); | ||
1997 | add_reg(RDLAR); | ||
1998 | add_reg(RDFAR); | ||
1999 | add_reg(RDFXR); | ||
2000 | add_reg(RDFFR); | ||
2001 | add_reg(TRSCER); | ||
2002 | add_reg(RMFCR); | ||
2003 | add_reg(TFTR); | ||
2004 | add_reg(FDR); | ||
2005 | add_reg(RMCR); | ||
2006 | add_reg(TFUCR); | ||
2007 | add_reg(RFOCR); | ||
2008 | if (cd->rmiimode) | ||
2009 | add_reg(RMIIMODE); | ||
2010 | add_reg(FCFTR); | ||
2011 | if (cd->rpadir) | ||
2012 | add_reg(RPADIR); | ||
2013 | if (!cd->no_trimd) | ||
2014 | add_reg(TRIMD); | ||
2015 | add_reg(ECMR); | ||
2016 | add_reg(ECSR); | ||
2017 | add_reg(ECSIPR); | ||
2018 | add_reg(PIR); | ||
2019 | if (!cd->no_psr) | ||
2020 | add_reg(PSR); | ||
2021 | add_reg(RDMLR); | ||
2022 | add_reg(RFLR); | ||
2023 | add_reg(IPGR); | ||
2024 | if (cd->apr) | ||
2025 | add_reg(APR); | ||
2026 | if (cd->mpr) | ||
2027 | add_reg(MPR); | ||
2028 | add_reg(RFCR); | ||
2029 | add_reg(RFCF); | ||
2030 | if (cd->tpauser) | ||
2031 | add_reg(TPAUSER); | ||
2032 | add_reg(TPAUSECR); | ||
2033 | add_reg(GECMR); | ||
2034 | if (cd->bculr) | ||
2035 | add_reg(BCULR); | ||
2036 | add_reg(MAHR); | ||
2037 | add_reg(MALR); | ||
2038 | add_reg(TROCR); | ||
2039 | add_reg(CDCR); | ||
2040 | add_reg(LCCR); | ||
2041 | add_reg(CNDCR); | ||
2042 | add_reg(CEFCR); | ||
2043 | add_reg(FRECR); | ||
2044 | add_reg(TSFRCR); | ||
2045 | add_reg(TLFRCR); | ||
2046 | add_reg(CERCR); | ||
2047 | add_reg(CEECR); | ||
2048 | add_reg(MAFCR); | ||
2049 | if (cd->rtrate) | ||
2050 | add_reg(RTRATE); | ||
2051 | if (cd->hw_crc) | ||
2052 | add_reg(CSMR); | ||
2053 | if (cd->select_mii) | ||
2054 | add_reg(RMII_MII); | ||
2055 | add_reg(ARSTR); | ||
2056 | if (cd->tsu) { | ||
2057 | add_tsu_reg(TSU_CTRST); | ||
2058 | add_tsu_reg(TSU_FWEN0); | ||
2059 | add_tsu_reg(TSU_FWEN1); | ||
2060 | add_tsu_reg(TSU_FCM); | ||
2061 | add_tsu_reg(TSU_BSYSL0); | ||
2062 | add_tsu_reg(TSU_BSYSL1); | ||
2063 | add_tsu_reg(TSU_PRISL0); | ||
2064 | add_tsu_reg(TSU_PRISL1); | ||
2065 | add_tsu_reg(TSU_FWSL0); | ||
2066 | add_tsu_reg(TSU_FWSL1); | ||
2067 | add_tsu_reg(TSU_FWSLC); | ||
2068 | add_tsu_reg(TSU_QTAG0); | ||
2069 | add_tsu_reg(TSU_QTAG1); | ||
2070 | add_tsu_reg(TSU_QTAGM0); | ||
2071 | add_tsu_reg(TSU_QTAGM1); | ||
2072 | add_tsu_reg(TSU_FWSR); | ||
2073 | add_tsu_reg(TSU_FWINMK); | ||
2074 | add_tsu_reg(TSU_ADQT0); | ||
2075 | add_tsu_reg(TSU_ADQT1); | ||
2076 | add_tsu_reg(TSU_VTAG0); | ||
2077 | add_tsu_reg(TSU_VTAG1); | ||
2078 | add_tsu_reg(TSU_ADSBSY); | ||
2079 | add_tsu_reg(TSU_TEN); | ||
2080 | add_tsu_reg(TSU_POST1); | ||
2081 | add_tsu_reg(TSU_POST2); | ||
2082 | add_tsu_reg(TSU_POST3); | ||
2083 | add_tsu_reg(TSU_POST4); | ||
2084 | if (mdp->reg_offset[TSU_ADRH0] != SH_ETH_OFFSET_INVALID) { | ||
2085 | /* This is the start of a table, not just a single | ||
2086 | * register. | ||
2087 | */ | ||
2088 | if (buf) { | ||
2089 | unsigned int i; | ||
2090 | |||
2091 | mark_reg_valid(TSU_ADRH0); | ||
2092 | for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES * 2; i++) | ||
2093 | *buf++ = ioread32( | ||
2094 | mdp->tsu_addr + | ||
2095 | mdp->reg_offset[TSU_ADRH0] + | ||
2096 | i * 4); | ||
2097 | } | ||
2098 | len += SH_ETH_TSU_CAM_ENTRIES * 2; | ||
2099 | } | ||
2100 | } | ||
2101 | |||
2102 | #undef mark_reg_valid | ||
2103 | #undef add_reg_from | ||
2104 | #undef add_reg | ||
2105 | #undef add_tsu_reg | ||
2106 | |||
2107 | return len * 4; | ||
2108 | } | ||
2109 | |||
2110 | static int sh_eth_get_regs_len(struct net_device *ndev) | ||
2111 | { | ||
2112 | return __sh_eth_get_regs(ndev, NULL); | ||
2113 | } | ||
2114 | |||
2115 | static void sh_eth_get_regs(struct net_device *ndev, struct ethtool_regs *regs, | ||
2116 | void *buf) | ||
2117 | { | ||
2118 | struct sh_eth_private *mdp = netdev_priv(ndev); | ||
2119 | |||
2120 | regs->version = SH_ETH_REG_DUMP_VERSION; | ||
2121 | |||
2122 | pm_runtime_get_sync(&mdp->pdev->dev); | ||
2123 | __sh_eth_get_regs(ndev, buf); | ||
2124 | pm_runtime_put_sync(&mdp->pdev->dev); | ||
2125 | } | ||
2126 | |||
1948 | static int sh_eth_nway_reset(struct net_device *ndev) | 2127 | static int sh_eth_nway_reset(struct net_device *ndev) |
1949 | { | 2128 | { |
1950 | struct sh_eth_private *mdp = netdev_priv(ndev); | 2129 | struct sh_eth_private *mdp = netdev_priv(ndev); |
@@ -2090,6 +2269,8 @@ static int sh_eth_set_ringparam(struct net_device *ndev, | |||
2090 | static const struct ethtool_ops sh_eth_ethtool_ops = { | 2269 | static const struct ethtool_ops sh_eth_ethtool_ops = { |
2091 | .get_settings = sh_eth_get_settings, | 2270 | .get_settings = sh_eth_get_settings, |
2092 | .set_settings = sh_eth_set_settings, | 2271 | .set_settings = sh_eth_set_settings, |
2272 | .get_regs_len = sh_eth_get_regs_len, | ||
2273 | .get_regs = sh_eth_get_regs, | ||
2093 | .nway_reset = sh_eth_nway_reset, | 2274 | .nway_reset = sh_eth_nway_reset, |
2094 | .get_msglevel = sh_eth_get_msglevel, | 2275 | .get_msglevel = sh_eth_get_msglevel, |
2095 | .set_msglevel = sh_eth_set_msglevel, | 2276 | .set_msglevel = sh_eth_set_msglevel, |
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 33a360c4fd10..06dbbe5201cb 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h | |||
@@ -32,6 +32,10 @@ | |||
32 | #define SH_ETH_TSU_CAM_ENTRIES 32 | 32 | #define SH_ETH_TSU_CAM_ENTRIES 32 |
33 | 33 | ||
34 | enum { | 34 | enum { |
35 | /* IMPORTANT: To keep ethtool register dump working, add new | ||
36 | * register names immediately before SH_ETH_MAX_REGISTER_OFFSET. | ||
37 | */ | ||
38 | |||
35 | /* E-DMAC registers */ | 39 | /* E-DMAC registers */ |
36 | EDSR = 0, | 40 | EDSR = 0, |
37 | EDMR, | 41 | EDMR, |
@@ -131,9 +135,7 @@ enum { | |||
131 | TSU_POST3, | 135 | TSU_POST3, |
132 | TSU_POST4, | 136 | TSU_POST4, |
133 | TSU_ADRH0, | 137 | TSU_ADRH0, |
134 | TSU_ADRL0, | 138 | /* TSU_ADR{H,L}{0..31} are assumed to be contiguous */ |
135 | TSU_ADRH31, | ||
136 | TSU_ADRL31, | ||
137 | 139 | ||
138 | TXNLCR0, | 140 | TXNLCR0, |
139 | TXALCR0, | 141 | TXALCR0, |
@@ -491,6 +493,7 @@ struct sh_eth_cpu_data { | |||
491 | unsigned select_mii:1; /* EtherC have RMII_MII (MII select register) */ | 493 | unsigned select_mii:1; /* EtherC have RMII_MII (MII select register) */ |
492 | unsigned shift_rd0:1; /* shift Rx descriptor word 0 right by 16 */ | 494 | unsigned shift_rd0:1; /* shift Rx descriptor word 0 right by 16 */ |
493 | unsigned rmiimode:1; /* EtherC has RMIIMODE register */ | 495 | unsigned rmiimode:1; /* EtherC has RMIIMODE register */ |
496 | unsigned rtrate:1; /* EtherC has RTRATE register */ | ||
494 | }; | 497 | }; |
495 | 498 | ||
496 | struct sh_eth_private { | 499 | struct sh_eth_private { |