aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergei Shtylyov <sergei.shtylyov@cogentembedded.com>2013-03-28 07:51:31 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-29 15:31:30 -0400
commita3f109bd793dfe5c611220ca5ab6c72f1aed479e (patch)
treee1e343f8dda30b5e64c92941dd62a529186f8e7c
parentc0013f6f8bbcb7605d591431444780d636dbe223 (diff)
sh_eth: add R-Car support for real
Commit d0418bb7123f44b23d69ac349eec7daf9103472f (net: sh_eth: Add eth support for R8A7779 device) was a failed attempt to add support for one of members of the R-Car SoC family. That's for three reasons: it treated R8A7779 the same as SH7724 except including quite dirty hack adding ECMR_ELB bit to the mask in sh_eth_set_rate() while not removing ECMR_RTM bit (despite it's reserved in R-Car Ether), and it didn't add a new register offset array despite the closest SH_ETH_REG_FAST_SH4 mapping differs by 0x200 to the offsets all the R-Car Ether registers have, and also some of the registers in this old mapping don't exist on R-Car Ether (due to this, SH7724's 'sh_eth_my_cpu_data' structure is not adequeate for R-Car too). Fix all these shortcomings, restoring the SH7724 related section to its pristine state... Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c107
-rw-r--r--include/linux/sh_eth.h1
2 files changed, 100 insertions, 8 deletions
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 13abe917cbdf..da604059b148 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2,7 +2,8 @@
2 * SuperH Ethernet device driver 2 * SuperH Ethernet device driver
3 * 3 *
4 * Copyright (C) 2006-2012 Nobuhiro Iwamatsu 4 * Copyright (C) 2006-2012 Nobuhiro Iwamatsu
5 * Copyright (C) 2008-2012 Renesas Solutions Corp. 5 * Copyright (C) 2008-2013 Renesas Solutions Corp.
6 * Copyright (C) 2013 Cogent Embedded, Inc.
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License, 9 * under the terms and conditions of the GNU General Public License,
@@ -147,6 +148,51 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
147 [FWALCR1] = 0x00b4, 148 [FWALCR1] = 0x00b4,
148}; 149};
149 150
151static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
152 [ECMR] = 0x0300,
153 [RFLR] = 0x0308,
154 [ECSR] = 0x0310,
155 [ECSIPR] = 0x0318,
156 [PIR] = 0x0320,
157 [PSR] = 0x0328,
158 [RDMLR] = 0x0340,
159 [IPGR] = 0x0350,
160 [APR] = 0x0354,
161 [MPR] = 0x0358,
162 [RFCF] = 0x0360,
163 [TPAUSER] = 0x0364,
164 [TPAUSECR] = 0x0368,
165 [MAHR] = 0x03c0,
166 [MALR] = 0x03c8,
167 [TROCR] = 0x03d0,
168 [CDCR] = 0x03d4,
169 [LCCR] = 0x03d8,
170 [CNDCR] = 0x03dc,
171 [CEFCR] = 0x03e4,
172 [FRECR] = 0x03e8,
173 [TSFRCR] = 0x03ec,
174 [TLFRCR] = 0x03f0,
175 [RFCR] = 0x03f4,
176 [MAFCR] = 0x03f8,
177
178 [EDMR] = 0x0200,
179 [EDTRR] = 0x0208,
180 [EDRRR] = 0x0210,
181 [TDLAR] = 0x0218,
182 [RDLAR] = 0x0220,
183 [EESR] = 0x0228,
184 [EESIPR] = 0x0230,
185 [TRSCER] = 0x0238,
186 [RMFCR] = 0x0240,
187 [TFTR] = 0x0248,
188 [FDR] = 0x0250,
189 [RMCR] = 0x0258,
190 [TFUCR] = 0x0264,
191 [RFOCR] = 0x0268,
192 [FCFTR] = 0x0270,
193 [TRIMD] = 0x027c,
194};
195
150static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { 196static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
151 [ECMR] = 0x0100, 197 [ECMR] = 0x0100,
152 [RFLR] = 0x0108, 198 [RFLR] = 0x0108,
@@ -296,7 +342,7 @@ static void sh_eth_select_mii(struct net_device *ndev)
296#endif 342#endif
297 343
298/* There is CPU dependent code */ 344/* There is CPU dependent code */
299#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779) 345#if defined(CONFIG_ARCH_R8A7779)
300#define SH_ETH_RESET_DEFAULT 1 346#define SH_ETH_RESET_DEFAULT 1
301static void sh_eth_set_duplex(struct net_device *ndev) 347static void sh_eth_set_duplex(struct net_device *ndev)
302{ 348{
@@ -311,18 +357,60 @@ static void sh_eth_set_duplex(struct net_device *ndev)
311static void sh_eth_set_rate(struct net_device *ndev) 357static void sh_eth_set_rate(struct net_device *ndev)
312{ 358{
313 struct sh_eth_private *mdp = netdev_priv(ndev); 359 struct sh_eth_private *mdp = netdev_priv(ndev);
314 unsigned int bits = ECMR_RTM;
315 360
316#if defined(CONFIG_ARCH_R8A7779) 361 switch (mdp->speed) {
317 bits |= ECMR_ELB; 362 case 10: /* 10BASE */
318#endif 363 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_ELB, ECMR);
364 break;
365 case 100:/* 100BASE */
366 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_ELB, ECMR);
367 break;
368 default:
369 break;
370 }
371}
372
373/* R8A7779 */
374static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
375 .set_duplex = sh_eth_set_duplex,
376 .set_rate = sh_eth_set_rate,
377
378 .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
379 .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
380 .eesipr_value = 0x01ff009f,
381
382 .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
383 .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
384 EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
385 .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
386
387 .apr = 1,
388 .mpr = 1,
389 .tpauser = 1,
390 .hw_swap = 1,
391};
392#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
393#define SH_ETH_RESET_DEFAULT 1
394static void sh_eth_set_duplex(struct net_device *ndev)
395{
396 struct sh_eth_private *mdp = netdev_priv(ndev);
397
398 if (mdp->duplex) /* Full */
399 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
400 else /* Half */
401 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
402}
403
404static void sh_eth_set_rate(struct net_device *ndev)
405{
406 struct sh_eth_private *mdp = netdev_priv(ndev);
319 407
320 switch (mdp->speed) { 408 switch (mdp->speed) {
321 case 10: /* 10BASE */ 409 case 10: /* 10BASE */
322 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR); 410 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
323 break; 411 break;
324 case 100:/* 100BASE */ 412 case 100:/* 100BASE */
325 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR); 413 sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
326 break; 414 break;
327 default: 415 default:
328 break; 416 break;
@@ -2521,6 +2609,9 @@ static const u16 *sh_eth_get_register_offset(int register_type)
2521 case SH_ETH_REG_GIGABIT: 2609 case SH_ETH_REG_GIGABIT:
2522 reg_offset = sh_eth_offset_gigabit; 2610 reg_offset = sh_eth_offset_gigabit;
2523 break; 2611 break;
2612 case SH_ETH_REG_FAST_RCAR:
2613 reg_offset = sh_eth_offset_fast_rcar;
2614 break;
2524 case SH_ETH_REG_FAST_SH4: 2615 case SH_ETH_REG_FAST_SH4:
2525 reg_offset = sh_eth_offset_fast_sh4; 2616 reg_offset = sh_eth_offset_fast_sh4;
2526 break; 2617 break;
diff --git a/include/linux/sh_eth.h b/include/linux/sh_eth.h
index b17d765ded84..fc305713fc6d 100644
--- a/include/linux/sh_eth.h
+++ b/include/linux/sh_eth.h
@@ -6,6 +6,7 @@
6enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN}; 6enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
7enum { 7enum {
8 SH_ETH_REG_GIGABIT, 8 SH_ETH_REG_GIGABIT,
9 SH_ETH_REG_FAST_RCAR,
9 SH_ETH_REG_FAST_SH4, 10 SH_ETH_REG_FAST_SH4,
10 SH_ETH_REG_FAST_SH3_SH2 11 SH_ETH_REG_FAST_SH3_SH2
11}; 12};