Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73a0d907 authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by David S. Miller
Browse files

net: sh_eth: add support R8A7740



The R8A7740 has a Gigabit Ethernet MAC. This patch supports it.

Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8b1467a3
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -4,11 +4,11 @@

config SH_ETH
	tristate "Renesas SuperH Ethernet support"
	depends on SUPERH && \
	depends on (SUPERH || ARCH_SHMOBILE) && \
		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
		 CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
		 CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
		 CPU_SUBTYPE_SH7757)
		 CPU_SUBTYPE_SH7757 || ARCH_R8A7740)
	select CRC32
	select NET_CORE
	select MII
@@ -17,4 +17,5 @@ config SH_ETH
	---help---
	  Renesas SuperH Ethernet device driver.
	  This driver supporting CPUs are:
		- SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757.
		- SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
		  and R8A7740.
+113 −1
Original line number Diff line number Diff line
@@ -386,6 +386,114 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
		sh_eth_write(ndev, 0x0, CSMR);
}

#elif defined(CONFIG_ARCH_R8A7740)
#define SH_ETH_HAS_TSU	1
static void sh_eth_chip_reset(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);
	unsigned long mii;

	/* reset device */
	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
	mdelay(1);

	switch (mdp->phy_interface) {
	case PHY_INTERFACE_MODE_GMII:
		mii = 2;
		break;
	case PHY_INTERFACE_MODE_MII:
		mii = 1;
		break;
	case PHY_INTERFACE_MODE_RMII:
	default:
		mii = 0;
		break;
	}
	sh_eth_write(ndev, mii, RMII_MII);
}

static void sh_eth_reset(struct net_device *ndev)
{
	int cnt = 100;

	sh_eth_write(ndev, EDSR_ENALL, EDSR);
	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
	while (cnt > 0) {
		if (!(sh_eth_read(ndev, EDMR) & 0x3))
			break;
		mdelay(1);
		cnt--;
	}
	if (cnt == 0)
		printk(KERN_ERR "Device reset fail\n");

	/* Table Init */
	sh_eth_write(ndev, 0x0, TDLAR);
	sh_eth_write(ndev, 0x0, TDFAR);
	sh_eth_write(ndev, 0x0, TDFXR);
	sh_eth_write(ndev, 0x0, TDFFR);
	sh_eth_write(ndev, 0x0, RDLAR);
	sh_eth_write(ndev, 0x0, RDFAR);
	sh_eth_write(ndev, 0x0, RDFXR);
	sh_eth_write(ndev, 0x0, RDFFR);
}

static void sh_eth_set_duplex(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);

	if (mdp->duplex) /* Full */
		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
	else		/* Half */
		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
}

static void sh_eth_set_rate(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);

	switch (mdp->speed) {
	case 10: /* 10BASE */
		sh_eth_write(ndev, GECMR_10, GECMR);
		break;
	case 100:/* 100BASE */
		sh_eth_write(ndev, GECMR_100, GECMR);
		break;
	case 1000: /* 1000BASE */
		sh_eth_write(ndev, GECMR_1000, GECMR);
		break;
	default:
		break;
	}
}

/* R8A7740 */
static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
	.chip_reset	= sh_eth_chip_reset,
	.set_duplex	= sh_eth_set_duplex,
	.set_rate	= sh_eth_set_rate,

	.ecsr_value	= ECSR_ICD | ECSR_MPD,
	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,

	.tx_check	= EESR_TC1 | EESR_FTC,
	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
			  EESR_ECI,
	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
			  EESR_TFE,

	.apr		= 1,
	.mpr		= 1,
	.tpauser	= 1,
	.bculr		= 1,
	.hw_swap	= 1,
	.no_trimd	= 1,
	.no_ade		= 1,
	.tsu		= 1,
};

#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
#define SH_ETH_RESET_DEFAULT	1
static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
@@ -443,7 +551,7 @@ static void sh_eth_reset(struct net_device *ndev)
}
#endif

#if defined(CONFIG_CPU_SH4)
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
static void sh_eth_set_receive_align(struct sk_buff *skb)
{
	int reserve;
@@ -919,6 +1027,10 @@ static int sh_eth_rx(struct net_device *ndev)
		desc_status = edmac_to_cpu(mdp, rxdesc->status);
		pkt_len = rxdesc->frame_length;

#if defined(CONFIG_ARCH_R8A7740)
		desc_status >>= 16;
#endif

		if (--boguscnt < 0)
			break;

+3 −2
Original line number Diff line number Diff line
@@ -372,7 +372,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
};

/* Driver's parameters */
#if defined(CONFIG_CPU_SH4)
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
#define SH4_SKB_RX_ALIGN	32
#else
#define SH2_SH3_SKB_RX_ALIGN	2
@@ -381,7 +381,8 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
/*
 * Register's bits
 */
#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ||\
    defined(CONFIG_ARCH_R8A7740)
/* EDSR */
enum EDSR_BIT {
	EDSR_ENT = 0x01, EDSR_ENR = 0x02,