Commit 8fcd4961 authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by David S. Miller
Browse files

net: sh_eth: add support for SH7757's GETHER



The SH7757 have GETHER and ETHER both. This patch supports them.

Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e47c9052
Loading
Loading
Loading
Loading
+135 −1
Original line number Diff line number Diff line
@@ -94,7 +94,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
};
#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
#define SH_ETH_RESET_DEFAULT	1
#define SH_ETH_HAS_BOTH_MODULES	1
#define SH_ETH_HAS_TSU	1
static void sh_eth_set_duplex(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -141,6 +142,135 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
	.no_ade		= 1,
};

#define SH_GIGA_ETH_BASE	0xfee00000
#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
static void sh_eth_chip_reset_giga(struct net_device *ndev)
{
	int i;
	unsigned long mahr[2], malr[2];

	/* save MAHR and MALR */
	for (i = 0; i < 2; i++) {
		malr[i] = readl(GIGA_MALR(i));
		mahr[i] = readl(GIGA_MAHR(i));
	}

	/* reset device */
	writel(ARSTR_ARSTR, SH_GIGA_ETH_BASE + 0x1800);
	mdelay(1);

	/* restore MAHR and MALR */
	for (i = 0; i < 2; i++) {
		writel(malr[i], GIGA_MALR(i));
		writel(mahr[i], GIGA_MAHR(i));
	}
}

static int sh_eth_is_gether(struct sh_eth_private *mdp);
static void sh_eth_reset(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);
	int cnt = 100;

	if (sh_eth_is_gether(mdp)) {
		sh_eth_write(ndev, 0x03, 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);
	} else {
		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
				EDMR);
		mdelay(3);
		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
				EDMR);
	}
}

static void sh_eth_set_duplex_giga(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_giga(struct net_device *ndev)
{
	struct sh_eth_private *mdp = netdev_priv(ndev);

	switch (mdp->speed) {
	case 10: /* 10BASE */
		sh_eth_write(ndev, 0x00000000, GECMR);
		break;
	case 100:/* 100BASE */
		sh_eth_write(ndev, 0x00000010, GECMR);
		break;
	case 1000: /* 1000BASE */
		sh_eth_write(ndev, 0x00000020, GECMR);
		break;
	default:
		break;
	}
}

/* SH7757(GETHERC) */
static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
	.chip_reset	= sh_eth_chip_reset_giga,
	.set_duplex	= sh_eth_set_duplex_giga,
	.set_rate	= sh_eth_set_rate_giga,

	.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,
	.fdr_value	= 0x0000072f,
	.rmcr_value	= 0x00000001,

	.apr		= 1,
	.mpr		= 1,
	.tpauser	= 1,
	.bculr		= 1,
	.hw_swap	= 1,
	.rpadir		= 1,
	.rpadir_value   = 2 << 16,
	.no_trimd	= 1,
	.no_ade		= 1,
};

static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
{
	if (sh_eth_is_gether(mdp))
		return &sh_eth_my_cpu_data_giga;
	else
		return &sh_eth_my_cpu_data;
}

#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
#define SH_ETH_HAS_TSU	1
static void sh_eth_chip_reset(struct net_device *ndev)
@@ -1677,7 +1807,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);

	/* set cpu data */
#if defined(SH_ETH_HAS_BOTH_MODULES)
	mdp->cd = sh_eth_get_cpu_data(mdp);
#else
	mdp->cd = &sh_eth_my_cpu_data;
#endif
	sh_eth_set_default_cpu_data(mdp->cd);

	/* set function */