sh_eth.c revision 79fba9f51755c704c0a7d7b7f0df10874dc0a744
186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  SuperH Ethernet device driver
386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
4f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
5f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu *  Copyright (C) 2008-2012 Renesas Solutions Corp.
686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  This program is free software; you can redistribute it and/or modify it
886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  under the terms and conditions of the GNU General Public License,
986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  version 2, as published by the Free Software Foundation.
1086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
1186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  This program is distributed in the hope it will be useful, but WITHOUT
1286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  more details.
1586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  You should have received a copy of the GNU General Public License along with
1686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  this program; if not, write to the Free Software Foundation, Inc.,
1786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
1886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
1986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  The full GNU General Public License is included in this distribution in
2086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  the file called "COPYING".
2186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
2286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/init.h>
240654011d900670884197d9a06ad17b378dfde831Yoshihiro Shimoda#include <linux/module.h>
250654011d900670884197d9a06ad17b378dfde831Yoshihiro Shimoda#include <linux/kernel.h>
260654011d900670884197d9a06ad17b378dfde831Yoshihiro Shimoda#include <linux/spinlock.h>
276a27cdeddf48858089e3672f844615cbf0877ebfNobuhiro Iwamatsu#include <linux/interrupt.h>
2886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/dma-mapping.h>
2986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/etherdevice.h>
3086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/delay.h>
3186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/platform_device.h>
3286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/mdio-bitbang.h>
3386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/netdevice.h>
3486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/phy.h>
3586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/cache.h>
3686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include <linux/io.h>
37bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm#include <linux/pm_runtime.h>
385a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
39dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#include <linux/ethtool.h>
40fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda#include <linux/if_vlan.h>
41f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#include <linux/clk.h>
42d4fa0e35fdbd54acf791fa3793d6d17f7795f7aeYoshihiro Shimoda#include <linux/sh_eth.h>
4386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
4486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include "sh_eth.h"
4586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
46dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#define SH_ETH_DEF_MSG_ENABLE \
47dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		(NETIF_MSG_LINK	| \
48dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		NETIF_MSG_TIMER	| \
49dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		NETIF_MSG_RX_ERR| \
50dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		NETIF_MSG_TX_ERR)
51dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
52380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* There is CPU dependent code */
5365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7724)
5465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
5565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
5665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda{
5765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
5865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
5965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	if (mdp->duplex) /* Full */
604a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
6165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	else		/* Half */
624a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
6365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
6465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
6565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
6665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda{
6765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
6865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
6965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	switch (mdp->speed) {
7065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 10: /* 10BASE */
714a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
7265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
7365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 100:/* 100BASE */
744a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
7565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
7665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	default:
7765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
7865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	}
7965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
8065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
8165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda/* SH7724 */
8265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
8365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
8465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
8565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
8665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
8765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
8865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f,
8965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
9065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
9165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
9265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
9365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
9465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
9565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.apr		= 1,
9665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.mpr		= 1,
9765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tpauser	= 1,
9865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.hw_swap	= 1,
99503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir		= 1,
100503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
10165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda};
102f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
1038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_BOTH_MODULES	1
1048fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
105f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
106f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
107f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
108f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
109f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	if (mdp->duplex) /* Full */
1104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
111f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	else		/* Half */
1124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
113f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
114f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
115f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
116f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
117f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
118f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
119f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	switch (mdp->speed) {
120f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 10: /* 10BASE */
1214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, RTRATE);
122f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
123f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 100:/* 100BASE */
1244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 1, RTRATE);
125f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
126f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	default:
127f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
128f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	}
129f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
130f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
131f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda/* SH7757 */
132f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
133f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_duplex		= sh_eth_set_duplex,
134f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_rate		= sh_eth_set_rate,
135f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
136f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
137f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.rmcr_value	= 0x00000001,
138f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
139f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
140f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
141f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
142f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
143f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
144f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.apr		= 1,
145f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.mpr		= 1,
146f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tpauser	= 1,
147f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.hw_swap	= 1,
148f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.no_ade		= 1,
1492e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir		= 1,
1502e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir_value   = 2 << 16,
151f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda};
15265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
1538fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_GIGA_ETH_BASE	0xfee00000
1548fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
1558fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
1568fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_chip_reset_giga(struct net_device *ndev)
1578fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
1588fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	int i;
1598fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	unsigned long mahr[2], malr[2];
1608fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1618fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* save MAHR and MALR */
1628fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
163ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		malr[i] = ioread32((void *)GIGA_MALR(i));
164ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		mahr[i] = ioread32((void *)GIGA_MAHR(i));
1658fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
1668fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1678fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* reset device */
168ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ARSTR_ARSTR, (void *)(SH_GIGA_ETH_BASE + 0x1800));
1698fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdelay(1);
1708fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1718fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* restore MAHR and MALR */
1728fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
173ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(malr[i], (void *)GIGA_MALR(i));
174ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(mahr[i], (void *)GIGA_MAHR(i));
1758fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
1768fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
1778fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1788fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp);
1798fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
1808fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
1818fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
1828fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	int cnt = 100;
1838fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1848fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1858fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x03, EDSR);
1868fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
1878fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
1888fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		while (cnt > 0) {
1898fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			if (!(sh_eth_read(ndev, EDMR) & 0x3))
1908fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				break;
1918fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			mdelay(1);
1928fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			cnt--;
1938fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		}
1948fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		if (cnt < 0)
1958fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			printk(KERN_ERR "Device reset fail\n");
1968fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1978fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		/* Table Init */
1988fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDLAR);
1998fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFAR);
2008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFXR);
2018fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFFR);
2028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDLAR);
2038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFAR);
2048fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFXR);
2058fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFFR);
2068fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	} else {
2078fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
2088fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2098fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		mdelay(3);
2108fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
2118fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2128fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2138fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2148fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2158fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_duplex_giga(struct net_device *ndev)
2168fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2178fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2188fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2198fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (mdp->duplex) /* Full */
2208fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
2218fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else		/* Half */
2228fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
2238fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2248fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2258fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_rate_giga(struct net_device *ndev)
2268fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2278fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2288fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2298fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	switch (mdp->speed) {
2308fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 10: /* 10BASE */
2318fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000000, GECMR);
2328fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2338fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 100:/* 100BASE */
2348fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000010, GECMR);
2358fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2368fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 1000: /* 1000BASE */
2378fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000020, GECMR);
2388fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2398fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	default:
2408fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2418fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2428fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2438fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2448fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda/* SH7757(GETHERC) */
2458fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
2468fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset_giga,
2478fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex_giga,
2488fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_rate	= sh_eth_set_rate_giga,
2498fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2508fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
2518fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
2528fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
2538fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2548fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
2558fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
2568fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
2578fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_ECI,
2588fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
2598fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_TFE,
2608fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.fdr_value	= 0x0000072f,
2618fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rmcr_value	= 0x00000001,
2628fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2638fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.apr		= 1,
2648fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.mpr		= 1,
2658fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tpauser	= 1,
2668fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.bculr		= 1,
2678fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.hw_swap	= 1,
2688fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir		= 1,
2698fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir_value   = 2 << 16,
2708fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_trimd	= 1,
2718fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_ade		= 1,
2723acbc9715a5ac8a2534a69eb3488b63b7c9fb1e2Yoshihiro Shimoda	.tsu		= 1,
2738fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda};
2748fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2758fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
2768fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2778fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp))
2788fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data_giga;
2798fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else
2808fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data;
2818fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2828fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
283f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
284380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
285f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsustatic void sh_eth_reset_hw_crc(struct net_device *ndev);
286380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
287380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
2884986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2894986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda
290380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* reset device */
2914986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
292380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(1);
293380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
294380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
295380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
296380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
297380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	int cnt = 100;
298380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
2994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, EDSR_ENALL, EDSR);
300c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
301380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	while (cnt > 0) {
3024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		if (!(sh_eth_read(ndev, EDMR) & 0x3))
303380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			break;
304380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mdelay(1);
305380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cnt--;
306380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	}
307890c8c18986eb975a76aa8359a712596bc70e61croel kluin	if (cnt == 0)
308380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		printk(KERN_ERR "Device reset fail\n");
309380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
310380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* Table Init */
3114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDLAR);
3124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFAR);
3134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFXR);
3144a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFFR);
3154a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDLAR);
3164a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFAR);
3174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFXR);
3184a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFFR);
319f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu
320f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	/* Reset HW CRC register */
321f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	sh_eth_reset_hw_crc(ndev);
322380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
323380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
324380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
325380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
326380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
327380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
328380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->duplex) /* Full */
3294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
330380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else		/* Half */
3314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
332380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
333380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
334380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
335380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
336380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
337380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
338380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	switch (mdp->speed) {
339380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 10: /* 10BASE */
3404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
341380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
342380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 100:/* 100BASE */
3434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
344380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
345380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 1000: /* 1000BASE */
3464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
347380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
348380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	default:
349380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
350380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	}
351380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
352380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
353380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* sh7763 */
354380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
355380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
356380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
357380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
358380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
359380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
360380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
361380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
362380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
363380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
364380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
365380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
366380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_ECI,
367380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
368380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_TFE,
369380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
370380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
371380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
372380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
373380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.bculr		= 1,
374380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
375380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_trimd	= 1,
376380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_ade		= 1,
3774986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
378f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#if defined(CONFIG_CPU_SUBTYPE_SH7734)
379f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	.hw_crc     = 1,
380f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#endif
381380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
382380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
383f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsustatic void sh_eth_reset_hw_crc(struct net_device *ndev)
384f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu{
385f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	if (sh_eth_my_cpu_data.hw_crc)
386f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu		sh_eth_write(ndev, 0x0, CSMR);
387f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu}
388f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu
38973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#elif defined(CONFIG_ARCH_R8A7740)
39073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
39173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
39273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
39373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
39473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	unsigned long mii;
39573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
39673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	/* reset device */
39773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
39873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	mdelay(1);
39973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
40073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	switch (mdp->phy_interface) {
40173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case PHY_INTERFACE_MODE_GMII:
40273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		mii = 2;
40373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
40473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case PHY_INTERFACE_MODE_MII:
40573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		mii = 1;
40673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
40773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case PHY_INTERFACE_MODE_RMII:
40873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	default:
40973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		mii = 0;
41073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
41173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	}
41273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, mii, RMII_MII);
41373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
41473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
41573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
41673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
41773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	int cnt = 100;
41873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
41973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, EDSR_ENALL, EDSR);
42073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
42173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	while (cnt > 0) {
42273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		if (!(sh_eth_read(ndev, EDMR) & 0x3))
42373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			break;
42473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		mdelay(1);
42573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		cnt--;
42673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	}
42773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	if (cnt == 0)
42873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		printk(KERN_ERR "Device reset fail\n");
42973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
43073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	/* Table Init */
43173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDLAR);
43273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFAR);
43373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFXR);
43473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFFR);
43573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDLAR);
43673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFAR);
43773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFXR);
43873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFFR);
43973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
44073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
44173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
44273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
44373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
44473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
44573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	if (mdp->duplex) /* Full */
44673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
44773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	else		/* Half */
44873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
44973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
45073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
45173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
45273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
45373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
45473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
45573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	switch (mdp->speed) {
45673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 10: /* 10BASE */
45773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
45873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
45973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 100:/* 100BASE */
46073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
46173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
46273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 1000: /* 1000BASE */
46373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
46473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
46573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	default:
46673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
46773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	}
46873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
46973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
47073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda/* R8A7740 */
47173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
47273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
47373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
47473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
47573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
47673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
47773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
47873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
47973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
48073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
48173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
48273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
48373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_ECI,
48473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
48573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_TFE,
48673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
48773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.apr		= 1,
48873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.mpr		= 1,
48973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tpauser	= 1,
49073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.bculr		= 1,
49173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.hw_swap	= 1,
49273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.no_trimd	= 1,
49373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.no_ade		= 1,
49473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tsu		= 1,
49573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda};
49673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
497380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
498380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
499380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
500380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
501380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
502380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
503380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
504380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
505380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
506380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
507380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
508380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
509380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
510380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
511380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
5124986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
513380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
514380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
515380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
516380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
517380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
518380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsr_value)
519380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsr_value = DEFAULT_ECSR_INIT;
520380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
521380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsipr_value)
522380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
523380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
524380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fcftr_value)
525380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
526380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				  DEFAULT_FIFO_F_D_RFD;
527380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
528380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fdr_value)
529380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fdr_value = DEFAULT_FDR_INIT;
530380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
531380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->rmcr_value)
532380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->rmcr_value = DEFAULT_RMCR_VALUE;
533380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
534380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_check)
535380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_check = DEFAULT_TX_CHECK;
536380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
537380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->eesr_err_check)
538380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK;
539380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
540380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_error_check)
541380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_error_check = DEFAULT_TX_ERROR_CHECK;
542380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
543380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
544380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_RESET_DEFAULT)
545380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* Chip Reset */
546380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
547380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
548c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
549380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(3);
550c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
551380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
552380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
553380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
55473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
555380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
556380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
557380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	int reserve;
558380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
559380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
560380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (reserve)
561380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		skb_reserve(skb, reserve);
562380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
563380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#else
564380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
565380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
566380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
567380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
568380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
569380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
570380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
57171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato/* CPU <-> EDMAC endian convert */
57271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
57371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
57471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
57571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
57671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_le32(x);
57771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
57871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_be32(x);
57971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
58071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
58171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
58271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
58371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
58471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
58571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
58671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
58771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return le32_to_cpu(x);
58871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
58971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return be32_to_cpu(x);
59071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
59171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
59271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
59371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
59486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
59586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Program the hardware MAC address from dev->dev_addr.
59686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
59786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void update_mac_address(struct net_device *ndev)
59886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
5994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
6004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
6014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
6024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
6034a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
60486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
60586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
60686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
60786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Get MAC address from SuperH MAC address register
60886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
60986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
61086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
61186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * When you want use this device, you must set MAC address in bootloader.
61286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
61386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
614748031f9fd2c06b28817d80761a5de97190cfd03Magnus Dammstatic void read_mac_address(struct net_device *ndev, unsigned char *mac)
61586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
616748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
617748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm		memcpy(ndev->dev_addr, mac, 6);
618748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	} else {
6194a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
6204a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
6214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
6224a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
6234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
6244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
625748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	}
62686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
62786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
628c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp)
629c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
630c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (mdp->reg_offset == sh_eth_offset_gigabit)
631c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 1;
632c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
633c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 0;
634c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
635c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
636c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
637c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
638c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp))
639c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_GETHER;
640c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
641c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_ETHER;
642c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
643c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
64486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustruct bb_info {
645ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void (*set_gate)(void *addr);
64686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mdiobb_ctrl ctrl;
647ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void *addr;
64886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mmd_msk;/* MMD */
64986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdo_msk;
65086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdi_msk;
65186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdc_msk;
65286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
65386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
65486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit set */
655ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_set(void *addr, u32 msk)
65686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
657ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ioread32(addr) | msk, addr);
65886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
65986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
66086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit clear */
661ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_clr(void *addr, u32 msk)
66286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
663ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32((ioread32(addr) & ~msk), addr);
66486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
66586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
66686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit read */
667ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic int bb_read(void *addr, u32 msk)
66886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
669ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	return (ioread32(addr) & msk) != 0;
67086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
67186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
67286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Data I/O pin control */
67386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
67486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
67586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
676b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
677b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
678b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
679b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
68086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
68186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mmd_msk);
68286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
68386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mmd_msk);
68486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
68586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
68686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Set bit data*/
68786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
68886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
68986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
69086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
691b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
692b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
693b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
69486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
69586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdo_msk);
69686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
69786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdo_msk);
69886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
69986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get bit data*/
70186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_get_mdio(struct mdiobb_ctrl *ctrl)
70286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
70386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
704b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
705b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
706b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
707b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
70886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return bb_read(bitbang->addr, bitbang->mdi_msk);
70986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
71086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
71186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDC pin control */
71286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
71386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
71486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
71586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
716b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
717b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
718b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
71986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
72086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdc_msk);
72186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
72286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdc_msk);
72386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
72486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
72586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* mdio bus control struct */
72686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct mdiobb_ops bb_ops = {
72786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.owner = THIS_MODULE,
72886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdc = sh_mdc_ctrl,
72986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_dir = sh_mmd_ctrl,
73086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_data = sh_set_mdio,
73186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.get_mdio_data = sh_get_mdio,
73286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
73386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
73486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free skb and descriptor buffer */
73586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_free(struct net_device *ndev)
73686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
73786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
73886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
73986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
74086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx skb ringbuffer */
74186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->rx_skbuff) {
74286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		for (i = 0; i < RX_RING_SIZE; i++) {
74386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->rx_skbuff[i])
74486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->rx_skbuff[i]);
74586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
74686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
74786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->rx_skbuff);
74886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
74986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Tx skb ringbuffer */
75086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->tx_skbuff) {
75186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		for (i = 0; i < TX_RING_SIZE; i++) {
75286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->tx_skbuff[i])
75386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->tx_skbuff[i]);
75486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
75586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
75686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->tx_skbuff);
75786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
75886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
75986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* format skb and descriptor buffer */
76086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_format(struct net_device *ndev)
76186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
76286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
76386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
76486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
76586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc = NULL;
76686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc = NULL;
76786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE;
76886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE;
76986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_rx = mdp->cur_tx = 0;
77186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = mdp->dirty_tx = 0;
77286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->rx_ring, 0, rx_ringsize);
77486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Rx ring buffer */
77686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < RX_RING_SIZE; i++) {
77786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* skb */
77886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
779dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi		skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
78086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = skb;
78186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (skb == NULL)
78286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
783bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
784e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda				DMA_FROM_DEVICE);
785380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_set_receive_align(skb);
786380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
78786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* RX descriptor */
78886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
7890029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
79071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
79186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
79286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
7930029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
794b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* Rx descriptor address set */
795b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
7964a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
797c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
798c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
799b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
80086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
80186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
80386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Mark the last entry as wrapping the ring. */
80571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
80686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->tx_ring, 0, tx_ringsize);
80886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Tx ring buffer */
81086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < TX_RING_SIZE; i++) {
81186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
81286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[i];
81371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
81486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = 0;
815b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
81671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			/* Tx descriptor address set */
8174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
818c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
819c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
820b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
82186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
82286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
82486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
82586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get skb and descriptor buffer */
82786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_ring_init(struct net_device *ndev)
82886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
82986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
83086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize, tx_ringsize, ret = 0;
83186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
83286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/*
83386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
83486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card needs room to do 8 byte alignment, +2 so we can reserve
83586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * the first 2 bytes, and +16 gets room for the status word from the
83686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card.
83786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 */
83886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ :
83986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			  (((ndev->mtu + 26 + 7) & ~7) + 2 + 16));
840503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	if (mdp->cd->rpadir)
841503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm		mdp->rx_buf_sz += NET_IP_ALIGN;
84286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
84386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate RX and TX skb rings */
84486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
84586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				GFP_KERNEL);
84686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_skbuff) {
847380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx skb\n");
84886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
84986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
85086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
85186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
85386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				GFP_KERNEL);
85486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_skbuff) {
855380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx skb\n");
85686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
85786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto skb_ring_free;
85886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
85986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
86086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Rx descriptors. */
86186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
86286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
86386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
86486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
86586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_ring) {
866380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
867380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			rx_ringsize);
86886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
86986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
87086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
87186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
87286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = 0;
87386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
87486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Tx descriptors. */
87586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
87686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
87786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
87886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_ring) {
879380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
880380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			tx_ringsize);
88186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
88286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
88386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
88486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
88586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
88686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsudesc_ring_free:
88786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
88886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma);
88986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuskb_ring_free:
89186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx and Tx skb ring buffer */
89286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
89386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
89586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
89686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_dev_init(struct net_device *ndev)
89886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
89986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
90086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
90186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u_int32_t rx_int_var, tx_int_var;
90286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 val;
90386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
90486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Soft Reset */
90586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_reset(ndev);
90686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
907b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Descriptor format */
908b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	sh_eth_ring_format(ndev);
909380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->rpadir)
9104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR);
91186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* all sh_eth int mask */
9134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EESIPR);
91486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91510b9194f959608368ed89df1937f17cfe6bd6d84Yoshihiro Shimoda#if defined(__LITTLE_ENDIAN)
916380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->hw_swap)
9174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDMR_EL, EDMR);
918380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else
919b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu#endif
9204a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, EDMR);
92186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
922b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* FIFO size set */
9234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
9244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TFTR);
92586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
926b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Frame recv control */
9274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
92886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
92986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
93086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
9314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER);
93286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
933380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->bculr)
9344a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */
935b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
9364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fcftr_value, FCFTR);
93786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
938380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->no_trimd)
9394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, TRIMD);
94086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
941b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Recv frame limit set register */
942fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda	sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
943fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda		     RFLR);
94486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
9454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
9464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
94786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
94886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PAUSE Prohibition */
9494a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
95086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
95186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
9524a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, val, ECMR);
953b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
954380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->set_rate)
955380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mdp->cd->set_rate(ndev);
956380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
957b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Status Register clear */
9584a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
959b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
960b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Interrupt Enable register */
9614a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
96286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
96386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Set MAC address */
96486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	update_mac_address(ndev);
96586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
96686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mask reset */
967380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->apr)
9684a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, APR_AP, APR);
969380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->mpr)
9704a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, MPR_MP, MPR);
971380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->tpauser)
9724a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
973b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
97486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Setting the Rx mode will start the Rx process. */
9754a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, EDRRR_R, EDRRR);
97686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
97786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_start_queue(ndev);
97886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
97986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
98086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
98186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
98286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free Tx skb function */
98386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_txfree(struct net_device *ndev)
98486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
98586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
98686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
98786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int freeNum = 0;
98886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = 0;
98986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
99086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
99186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = mdp->dirty_tx % TX_RING_SIZE;
99286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[entry];
99371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
99486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
99586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Free the original skb. */
99686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[entry]) {
99731fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda			dma_unmap_single(&ndev->dev, txdesc->addr,
99831fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda					 txdesc->buffer_length, DMA_TO_DEVICE);
99986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
100086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->tx_skbuff[entry] = NULL;
100186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			freeNum++;
100286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
100371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
100486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (entry >= TX_RING_SIZE - 1)
100571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
100686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1007bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_packets++;
1008bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_bytes += txdesc->buffer_length;
100986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
101086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return freeNum;
101186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
101286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
101386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet receive function */
101486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_rx(struct net_device *ndev)
101586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
101686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
101786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
101886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
101986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = mdp->cur_rx % RX_RING_SIZE;
102086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
102186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
102286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u16 pkt_len = 0;
1023380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 desc_status;
102486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
102586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rxdesc = &mdp->rx_ring[entry];
102671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
102771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		desc_status = edmac_to_cpu(mdp, rxdesc->status);
102886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		pkt_len = rxdesc->frame_length;
102986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
103073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#if defined(CONFIG_ARCH_R8A7740)
103173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		desc_status >>= 16;
103273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#endif
103373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
103486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (--boguscnt < 0)
103586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
103686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
103786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!(desc_status & RDFEND))
1038bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_length_errors++;
103986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
104086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
104186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
1042bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_errors++;
104386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS1)
1044bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_crc_errors++;
104586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS2)
1046bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_frame_errors++;
104786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS3)
1048bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
104986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS4)
1050bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
105186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS6)
1052bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_missed_errors++;
105386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS10)
1054bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_over_errors++;
105586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		} else {
1056380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (!mdp->cd->hw_swap)
1057380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				sh_eth_soft_swap(
1058380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					phys_to_virt(ALIGN(rxdesc->addr, 4)),
1059380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					pkt_len + 2);
106086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb = mdp->rx_skbuff[entry];
106186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = NULL;
1062503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm			if (mdp->cd->rpadir)
1063503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm				skb_reserve(skb, NET_IP_ALIGN);
106486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb_put(skb, pkt_len);
106586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb->protocol = eth_type_trans(skb, ndev);
106686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_rx(skb);
1067bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_packets++;
1068bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_bytes += pkt_len;
106986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
107071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
107186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = (++mdp->cur_rx) % RX_RING_SIZE;
1072862df49750e7ca9369c04d8d8105b3cc5d976e0dYoshihiro Shimoda		rxdesc = &mdp->rx_ring[entry];
107386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
107486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
107586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Refill the Rx ring buffers. */
107686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
107786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = mdp->dirty_rx % RX_RING_SIZE;
107886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[entry];
1079b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
10800029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
1081b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
108286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[entry] == NULL) {
1083dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi			skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
108486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = skb;
108586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (skb == NULL)
108686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				break;	/* Better luck next round. */
1087bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
1088e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda					DMA_FROM_DEVICE);
1089380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			sh_eth_set_receive_align(skb);
1090380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1091bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet			skb_checksum_none_assert(skb);
10920029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda			rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
109386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
109486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (entry >= RX_RING_SIZE - 1)
109586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
109671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
109786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		else
109886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
109971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
110086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
110186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
110286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Restart Rx engine if stopped. */
110386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* If we don't need to check status, don't. -KDU */
110479fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
110579fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda		/* fix the values for the next receiving */
110679fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda		mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) -
110779fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda					       sh_eth_read(ndev, RDLAR)) >> 4;
11084a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDRRR_R, EDRRR);
110979fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda	}
111086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
111186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
111286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
111386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
11144a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_disable(struct net_device *ndev)
1115dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1116dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
11174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) &
11184a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		~(ECMR_RE | ECMR_TE), ECMR);
1119dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1120dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
11214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_enable(struct net_device *ndev)
1122dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1123dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
11244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
11254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ECMR_RE | ECMR_TE), ECMR);
1126dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1127dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
112886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* error control function */
112986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_error(struct net_device *ndev, int intr_status)
113086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
113186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
113286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 felic_stat;
1133380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 link_stat;
1134380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 mask;
113586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
113686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_ECI) {
11374a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		felic_stat = sh_eth_read(ndev, ECSR);
11384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, felic_stat, ECSR);	/* clear int */
113986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_ICD)
1140bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_carrier_errors++;
114186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_LCHNG) {
114286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Link Changed */
11434923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda			if (mdp->cd->no_psr || mdp->no_ether_link) {
1144380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				if (mdp->link == PHY_DOWN)
1145380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					link_stat = 0;
1146380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				else
1147380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					link_stat = PHY_ST_LINK;
1148380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			} else {
11494a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				link_stat = (sh_eth_read(ndev, PSR));
11504923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda				if (mdp->ether_link_active_low)
11514923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda					link_stat = ~link_stat;
1152380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			}
1153dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (!(link_stat & PHY_ST_LINK))
11544a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_disable(ndev);
1155dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			else {
115686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* Link Up */
11574a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
11584a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ~DMAC_M_ECI, EESIPR);
115986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/*clear int */
11604a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
11614a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ECSR);
11624a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
11634a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  DMAC_M_ECI, EESIPR);
116486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* enable tx and rx */
11654a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_enable(ndev);
116686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			}
116786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
116886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
116986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
117086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_TWB) {
117186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Write buck end. unused write back interrupt */
117286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_TABT)	/* Transmit Abort int */
1173bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_aborted_errors++;
1174dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_err(mdp))
1175dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Transmit Abort\n");
117686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
117786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
117886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RABT) {
117986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Abort int */
118086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_RFRMER) {
118186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Receive Frame Overflow int */
1182bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_frame_errors++;
1183dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_rx_err(mdp))
1184dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Receive Abort\n");
118586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
118686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1187380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1188dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TDE) {
1189dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Transmit Descriptor Empty int */
1190bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1191dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1192dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
1193dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1194dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1195dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TFE) {
1196dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* FIFO under flow */
1197bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1198dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1199dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
120086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
120186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
120286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RDE) {
120386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Descriptor Empty int */
1204bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_over_errors++;
120586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1206dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1207dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive Descriptor Empty\n");
120886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1209dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
121086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RFE) {
121186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive FIFO Overflow int */
1212bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_fifo_errors++;
1213dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1214dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive FIFO Overflow\n");
1215dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1216dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1217dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
1218dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Address Error */
1219bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1220dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1221dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Address Error\n");
122286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1223380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1224380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
1225380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->no_ade)
1226380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mask &= ~EESR_ADE;
1227380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & mask) {
122886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Tx error */
12294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		u32 edtrr = sh_eth_read(ndev, EDTRR);
123086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dmesg */
1231380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
1232380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				intr_status, mdp->cur_tx);
1233380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
123486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				mdp->dirty_tx, (u32) ndev->state, edtrr);
123586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dirty buffer free */
123686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
123786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
123886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* SH7712 BUG */
1239c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
124086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* tx dma start */
1241c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
124286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
124386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* wakeup */
124486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
124586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
124686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
124786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
124886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic irqreturn_t sh_eth_interrupt(int irq, void *netdev)
124986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
125086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = netdev;
125186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1252380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_cpu_data *cd = mdp->cd;
12530e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	irqreturn_t ret = IRQ_NONE;
12544a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	u32 intr_status = 0;
125586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
125686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock(&mdp->lock);
125786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1258b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Get interrpt stat */
12594a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	intr_status = sh_eth_read(ndev, EESR);
126086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Clear interrupt */
12610e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
12620e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
1263380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			cd->tx_check | cd->eesr_err_check)) {
12644a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, intr_status, EESR);
12650e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		ret = IRQ_HANDLED;
12660e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	} else
12670e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		goto other_irq;
126886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1269b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	if (intr_status & (EESR_FRC | /* Frame recv*/
1270b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RMAF | /* Multi cast address recv*/
1271b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RRF  | /* Bit frame recv */
1272b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTLF | /* Long frame recv*/
1273b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTSF | /* short frame recv */
1274b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_PRE  | /* PHY-LSI recv error */
1275b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_CERF)){ /* recv frame CRC error */
127686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_rx(ndev);
1277b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	}
127886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1279b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Tx Check */
1280380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->tx_check) {
128186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
128286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
128386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
128486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1285380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->eesr_err_check)
128686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_error(ndev, intr_status);
128786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
12880e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsuother_irq:
128986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock(&mdp->lock);
129086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
12910e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	return ret;
129286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
129386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
129486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_timer(unsigned long data)
129586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
129686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = (struct net_device *)data;
129786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
129886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
129986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mod_timer(&mdp->timer, jiffies + (10 * HZ));
130086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
130186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
130286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY state control function */
130386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_adjust_link(struct net_device *ndev)
130486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
130586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
130686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
130786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int new_state = 0;
130886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
130986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (phydev->link != PHY_DOWN) {
131086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->duplex != mdp->duplex) {
131186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
131286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->duplex = phydev->duplex;
1313380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_duplex)
1314380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_duplex(ndev);
131586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
131686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
131786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->speed != mdp->speed) {
131886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
131986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->speed = phydev->speed;
1320380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_rate)
1321380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_rate(ndev);
132286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
132386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->link == PHY_DOWN) {
132491a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda			sh_eth_write(ndev,
132591a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda				(sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
132686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
132786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->link = phydev->link;
132886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
132986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else if (mdp->link) {
133086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		new_state = 1;
133186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->link = PHY_DOWN;
133286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->speed = 0;
133386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->duplex = -1;
133486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
133586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1336dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (new_state && netif_msg_link(mdp))
133786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_print_status(phydev);
133886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
133986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
134086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY init function */
134186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_init(struct net_device *ndev)
134286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
134386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
13440a372eb91f9d507701a901c2f62ed31ca67fd66cDavid S. Miller	char phy_id[MII_BUS_ID_SIZE + 3];
134586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = NULL;
134686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1347fb28ad35906af2f042c94e2f9c0f898ef9acfa37Kay Sievers	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
134886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->id , mdp->phy_id);
134986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
135086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->link = PHY_DOWN;
135186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->speed = 0;
135286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->duplex = -1;
135386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
135486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Try connect to PHY */
1355c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
1356e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda				0, mdp->phy_interface);
135786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (IS_ERR(phydev)) {
135886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&ndev->dev, "phy_connect failed\n");
135986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return PTR_ERR(phydev);
136086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1361380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
136286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_info(&ndev->dev, "attached phy %i to driver %s\n",
1363380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		phydev->addr, phydev->drv->name);
136486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
136586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->phydev = phydev;
136686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
136786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
136886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
136986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
137086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY control start function */
137186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_start(struct net_device *ndev)
137286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
137386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
137486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret;
137586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
137686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_init(ndev);
137786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
137886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
137986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
138086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* reset phy - this also wakes it from PDOWN */
138186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
138286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_start(mdp->phydev);
138386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
138486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
138586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
138686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1387dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_settings(struct net_device *ndev,
1388dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_cmd *ecmd)
1389dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1390dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1391dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1392dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1393dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1394dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1395dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_gset(mdp->phydev, ecmd);
1396dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1397dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1398dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1399dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1400dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1401dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_set_settings(struct net_device *ndev,
1402dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		struct ethtool_cmd *ecmd)
1403dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1404dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1405dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1406dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1407dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1408dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1409dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1410dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
14114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_disable(ndev);
1412dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1413dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_sset(mdp->phydev, ecmd);
1414dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ret)
1415dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		goto error_exit;
1416dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1417dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ecmd->duplex == DUPLEX_FULL)
1418dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 1;
1419dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	else
1420dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 0;
1421dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1422dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (mdp->cd->set_duplex)
1423dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->cd->set_duplex(ndev);
1424dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1425dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsuerror_exit:
1426dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdelay(1);
1427dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1428dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
14294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_enable(ndev);
1430dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1431dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1432dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1433dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1434dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1435dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1436dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_nway_reset(struct net_device *ndev)
1437dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1438dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1439dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1440dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1441dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1442dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1443dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_start_aneg(mdp->phydev);
1444dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1445dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1446dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1447dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1448dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1449dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic u32 sh_eth_get_msglevel(struct net_device *ndev)
1450dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1451dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1452dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return mdp->msg_enable;
1453dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1454dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1455dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_set_msglevel(struct net_device *ndev, u32 value)
1456dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1457dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1458dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = value;
1459dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1460dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1461dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic const char sh_eth_gstrings_stats[][ETH_GSTRING_LEN] = {
1462dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_current", "tx_current",
1463dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_dirty", "tx_dirty",
1464dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1465dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#define SH_ETH_STATS_LEN  ARRAY_SIZE(sh_eth_gstrings_stats)
1466dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1467dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_sset_count(struct net_device *netdev, int sset)
1468dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1469dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (sset) {
1470dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1471dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return SH_ETH_STATS_LEN;
1472dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	default:
1473dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return -EOPNOTSUPP;
1474dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1475dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1476dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1477dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_ethtool_stats(struct net_device *ndev,
1478dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_stats *stats, u64 *data)
1479dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1480dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1481dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int i = 0;
1482dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1483dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* device-specific stats */
1484dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_rx;
1485dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_tx;
1486dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_rx;
1487dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_tx;
1488dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1489dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1490dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
1491dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1492dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (stringset) {
1493dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1494dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		memcpy(data, *sh_eth_gstrings_stats,
1495dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu					sizeof(sh_eth_gstrings_stats));
1496dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		break;
1497dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1498dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1499dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
15009b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemmingerstatic const struct ethtool_ops sh_eth_ethtool_ops = {
1501dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_settings	= sh_eth_get_settings,
1502dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_settings	= sh_eth_set_settings,
15039b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.nway_reset	= sh_eth_nway_reset,
1504dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_msglevel	= sh_eth_get_msglevel,
1505dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_msglevel	= sh_eth_set_msglevel,
15069b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.get_link	= ethtool_op_get_link,
1507dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_strings	= sh_eth_get_strings,
1508dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_ethtool_stats  = sh_eth_get_ethtool_stats,
1509dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_sset_count     = sh_eth_get_sset_count,
1510dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1511dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
151286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* network device open function */
151386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_open(struct net_device *ndev)
151486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
151586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
151686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
151786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1518bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1519bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1520a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches	ret = request_irq(ndev->irq, sh_eth_interrupt,
1521f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
1522dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
1523dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7757)
15240e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				IRQF_SHARED,
15250e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#else
15260e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				0,
15270e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#endif
15280e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				ndev->name, ndev);
152986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret) {
1530380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Can not assign IRQ number\n");
153186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
153286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
153386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
153486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Descriptor set */
153586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_ring_init(ndev);
153686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
153786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
153886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
153986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
154086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_dev_init(ndev);
154186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
154286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
154386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
154486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY control start*/
154586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_start(ndev);
154686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
154786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
154886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
154986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Set the timer to check for link beat. */
155086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	init_timer(&mdp->timer);
155186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
1552b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	setup_timer(&mdp->timer, sh_eth_timer, (unsigned long)ndev);
155386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
155486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
155586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
155686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
155786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
1558bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
155986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
156086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
156186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
156286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Timeout function */
156386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_tx_timeout(struct net_device *ndev)
156486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
156586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
156686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
156786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
156886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
156986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
157086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1571dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (netif_msg_timer(mdp))
1572dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
15734a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	       " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
157486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
157586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* tx_errors count up */
1576bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_errors++;
157786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
157886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* timer off */
157986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	del_timer_sync(&mdp->timer);
158086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
158186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
158286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < RX_RING_SIZE; i++) {
158386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
158486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->status = 0;
158586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->addr = 0xBADF00D0;
158686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[i])
158786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->rx_skbuff[i]);
158886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
158986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
159086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < TX_RING_SIZE; i++) {
159186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[i])
159286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->tx_skbuff[i]);
159386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
159486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
159586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
159686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
159786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_dev_init(ndev);
159886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
159986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* timer on */
160086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
160186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	add_timer(&mdp->timer);
160286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
160386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
160486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet transmit function */
160586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
160686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
160786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
160886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
160986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 entry;
1610fb5e2f9b9410a4362897d12dc1ed4f7cec1b0d45Nobuhiro Iwamatsu	unsigned long flags;
161186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
161286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
161386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
161486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!sh_eth_txfree(ndev)) {
1615dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_queued(mdp))
1616dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_warn(&ndev->dev, "TxFD exhausted.\n");
161786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_stop_queue(ndev);
161886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			spin_unlock_irqrestore(&mdp->lock, flags);
16195b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy			return NETDEV_TX_BUSY;
162086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
162186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
162286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
162386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
162486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	entry = mdp->cur_tx % TX_RING_SIZE;
162586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff[entry] = skb;
162686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	txdesc = &mdp->tx_ring[entry];
162786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* soft swap. */
1628380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->hw_swap)
1629380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
1630380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				 skb->len + 2);
163131fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
163231fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda				      DMA_TO_DEVICE);
163386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (skb->len < ETHERSMALL)
163486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = ETHERSMALL;
163586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
163686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = skb->len;
163786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
163886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (entry >= TX_RING_SIZE - 1)
163971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
164086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
164171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
164286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
164386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_tx++;
164486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1645c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDTRR) & sh_eth_get_edtrr_trns(mdp)))
1646c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
1647b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
16486ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
164986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
165086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* device close function */
165286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_close(struct net_device *ndev)
165386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
165486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
165586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ringsize;
165686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
165886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Disable interrupts by clearing the interrupt mask. */
16604a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0000, EESIPR);
166186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
166286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Stop the chip's Tx and Rx processes. */
16634a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDTRR);
16644a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDRRR);
166586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
166686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY Disconnect */
166786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->phydev) {
166886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_stop(mdp->phydev);
166986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_disconnect(mdp->phydev);
167086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
167186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
167386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	del_timer_sync(&mdp->timer);
167586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
167786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
167886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
168086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
168186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma);
168286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
168386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
168486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
168586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma);
168686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1687bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1688bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
168986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
169086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
169186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
169286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
169386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
169486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
169586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1696bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1697bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1698bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
16994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TROCR);	/* (write clear) */
1700bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.collisions += sh_eth_read(ndev, CDCR);
17014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, CDCR);	/* (write clear) */
1702bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
17034a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, LCCR);	/* (write clear) */
1704c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1705bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
1706c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CERCR);	/* (write clear) */
1707bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
1708c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CEECR);	/* (write clear) */
1709c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
1710bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
1711c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CNDCR);	/* (write clear) */
1712c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
1713bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1714bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1715bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	return &ndev->stats;
171686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
171786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1718bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet/* ioctl to device function */
171986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
172086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				int cmd)
172186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
172286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
172386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
172486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!netif_running(ndev))
172686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -EINVAL;
172786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!phydev)
172986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -ENODEV;
173086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173128b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran	return phy_mii_ioctl(phydev, rq, cmd);
173286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
173386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1734380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
17356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda/* For TSU_POSTn. Please refer to the manual about this (strange) bitfields */
17366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void *sh_eth_tsu_get_post_reg_offset(struct sh_eth_private *mdp,
17376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					    int entry)
17386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return sh_eth_tsu_get_offset(mdp, TSU_POST1) + (entry / 8 * 4);
17406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic u32 sh_eth_tsu_get_post_mask(int entry)
17436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0x0f << (28 - ((entry % 8) * 4));
17456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic u32 sh_eth_tsu_get_post_bit(struct sh_eth_private *mdp, int entry)
17486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return (0x08 >> (mdp->port << 1)) << (28 - ((entry % 8) * 4));
17506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_enable_cam_entry_post(struct net_device *ndev,
17536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					     int entry)
17546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
17566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 tmp;
17576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset;
17586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
17606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	tmp = ioread32(reg_offset);
17616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(tmp | sh_eth_tsu_get_post_bit(mdp, entry), reg_offset);
17626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic bool sh_eth_tsu_disable_cam_entry_post(struct net_device *ndev,
17656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					      int entry)
17666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
17686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 post_mask, ref_mask, tmp;
17696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset;
17706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
17726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	post_mask = sh_eth_tsu_get_post_mask(entry);
17736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ref_mask = sh_eth_tsu_get_post_bit(mdp, entry) & ~post_mask;
17746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	tmp = ioread32(reg_offset);
17766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(tmp & ~post_mask, reg_offset);
17776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* If other port enables, the function returns "true" */
17796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return tmp & ref_mask;
17806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_busy(struct net_device *ndev)
17836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int timeout = SH_ETH_TSU_TIMEOUT_MS * 100;
17856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
17866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	while ((sh_eth_tsu_read(mdp, TSU_ADSBSY) & TSU_ADSBSY_0)) {
17886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		udelay(10);
17896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		timeout--;
17906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (timeout <= 0) {
17916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			dev_err(&ndev->dev, "%s: timeout\n", __func__);
17926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return -ETIMEDOUT;
17936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		}
17946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
17956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
17976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_write_entry(struct net_device *ndev, void *reg,
18006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				  const u8 *addr)
18016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 val;
18036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
18056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(val, reg);
18066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (sh_eth_tsu_busy(ndev) < 0)
18076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return -EBUSY;
18086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = addr[4] << 8 | addr[5];
18106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(val, reg + 4);
18116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (sh_eth_tsu_busy(ndev) < 0)
18126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return -EBUSY;
18136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
18156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_read_entry(void *reg, u8 *addr)
18186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 val;
18206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = ioread32(reg);
18226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[0] = (val >> 24) & 0xff;
18236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[1] = (val >> 16) & 0xff;
18246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[2] = (val >> 8) & 0xff;
18256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[3] = val & 0xff;
18266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = ioread32(reg + 4);
18276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[4] = (val >> 8) & 0xff;
18286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[5] = val & 0xff;
18296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18326743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_find_entry(struct net_device *ndev, const u8 *addr)
18336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
18366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i;
18376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 c_addr[ETH_ALEN];
18386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
18406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_read_entry(reg_offset, c_addr);
18416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (memcmp(addr, c_addr, ETH_ALEN) == 0)
18426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return i;
18436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
18446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return -ENOENT;
18466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_find_empty(struct net_device *ndev)
18496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 blank[ETH_ALEN];
18516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int entry;
18526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	memset(blank, 0, sizeof(blank));
18546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	entry = sh_eth_tsu_find_entry(ndev, blank);
18556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return (entry < 0) ? -ENOMEM : entry;
18566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_disable_cam_entry_table(struct net_device *ndev,
18596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					      int entry)
18606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
18636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int ret;
18646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 blank[ETH_ALEN];
18656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) &
18676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			 ~(1 << (31 - entry)), TSU_TEN);
18686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	memset(blank, 0, sizeof(blank));
18706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ret = sh_eth_tsu_write_entry(ndev, reg_offset + entry * 8, blank);
18716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (ret < 0)
18726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return ret;
18736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
18746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_add_entry(struct net_device *ndev, const u8 *addr)
18776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
18806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
18816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!mdp->cd->tsu)
18836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
18846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	i = sh_eth_tsu_find_entry(ndev, addr);
18866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (i < 0) {
18876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* No entry found, create one */
18886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		i = sh_eth_tsu_find_empty(ndev);
18896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (i < 0)
18906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return -ENOMEM;
18916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_write_entry(ndev, reg_offset + i * 8, addr);
18926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
18936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
18946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Enable the entry */
18966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) |
18976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				 (1 << (31 - i)), TSU_TEN);
18986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
18996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* Entry found or created, enable POST */
19016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_tsu_enable_cam_entry_post(ndev, i);
19026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_del_entry(struct net_device *ndev, const u8 *addr)
19076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
19106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!mdp->cd->tsu)
19126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
19136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	i = sh_eth_tsu_find_entry(ndev, addr);
19156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (i) {
19166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Entry found */
19176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
19186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			goto done;
19196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Disable the entry if both ports was disabled */
19216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
19226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
19236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
19246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodadone:
19266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_purge_all(struct net_device *ndev)
19306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19326743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
19336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
19356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
19366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) {
19386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
19396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			continue;
19406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Disable the entry if both ports was disabled */
19426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
19436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
19446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
19456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_purge_mcast(struct net_device *ndev)
19516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 addr[ETH_ALEN];
19546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
19556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i;
19566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
19586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return;
19596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
19616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_read_entry(reg_offset, addr);
19626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (is_multicast_ether_addr(addr))
19636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			sh_eth_tsu_del_entry(ndev, addr);
19646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
196786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Multicast reception directions set */
196886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_set_multicast_list(struct net_device *ndev)
196986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
19706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 ecmr_bits;
19726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int mcast_all = 0;
19736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	unsigned long flags;
19746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	spin_lock_irqsave(&mdp->lock, flags);
19766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/*
19776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 * Initial condition is MCT = 1, PRM = 0.
19786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 * Depending on ndev->flags, set PRM or clear MCT
19796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 */
19806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
19816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!(ndev->flags & IFF_MULTICAST)) {
19836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_mcast(ndev);
19846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mcast_all = 1;
19856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (ndev->flags & IFF_ALLMULTI) {
19876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_mcast(ndev);
19886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits &= ~ECMR_MCT;
19896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mcast_all = 1;
19906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
199286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev->flags & IFF_PROMISC) {
19936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_all(ndev);
19946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits = (ecmr_bits & ~ECMR_MCT) | ECMR_PRM;
19956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	} else if (mdp->cd->tsu) {
19966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		struct netdev_hw_addr *ha;
19976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		netdev_for_each_mc_addr(ha, ndev) {
19986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			if (mcast_all && is_multicast_ether_addr(ha->addr))
19996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				continue;
20006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			if (sh_eth_tsu_add_entry(ndev, ha->addr) < 0) {
20026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				if (!mcast_all) {
20036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					sh_eth_tsu_purge_mcast(ndev);
20046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					ecmr_bits &= ~ECMR_MCT;
20056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					mcast_all = 1;
20066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				}
20076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			}
20086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		}
200986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else {
201086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Normal, unicast/broadcast-only mode. */
20116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits = (ecmr_bits & ~ECMR_PRM) | ECMR_MCT;
201286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
20136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* update the ethernet mode */
20156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_write(ndev, ecmr_bits, ECMR);
20166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	spin_unlock_irqrestore(&mdp->lock, flags);
201886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
201971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
202071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
202171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
202271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!mdp->port)
202371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return TSU_VTAG0;
202471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	else
202571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return TSU_VTAG1;
202671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
202771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
202871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
202971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
203071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
203171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	int vtag_reg_index = sh_eth_get_vtag_index(mdp);
203271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
203371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
203471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return -EPERM;
203571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
203671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/* No filtering if vid = 0 */
203771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!vid)
203871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
203971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
204071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	mdp->vlan_num_ids++;
204171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
204271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/*
204371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 * The controller has one VLAN tag HW filter. So, if the filter is
204471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 * already enabled, the driver disables it and the filte
204571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 */
204671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (mdp->vlan_num_ids > 1) {
204771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		/* disable VLAN filter */
204871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, vtag_reg_index);
204971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
205071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	}
205171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
205271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_VTAG_ENABLE | (vid & TSU_VTAG_VID_MASK),
205371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda			 vtag_reg_index);
205471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
205571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	return 0;
205671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
205771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
205871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
205971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
206071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
206171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	int vtag_reg_index = sh_eth_get_vtag_index(mdp);
206271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
206371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
206471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return -EPERM;
206571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
206671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/* No filtering if vid = 0 */
206771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!vid)
206871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
206971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
207071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	mdp->vlan_num_ids--;
207171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, vtag_reg_index);
207271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
207371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	return 0;
207471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
20754986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda#endif /* SH_ETH_HAS_TSU */
207686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
207786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* SuperH's TSU register init function */
20784a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_tsu_init(struct sh_eth_private *mdp)
207986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
20804a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
20814a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
20824a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
20834a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL0);
20844a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL1);
20854a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL0);
20864a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL1);
20874a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL0);
20884a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL1);
20894a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, TSU_FWSLC);
2090c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
2091c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG0);	/* Disable QTAG(0->1) */
2092c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG1);	/* Disable QTAG(1->0) */
2093c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
2094c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM0);	/* Disable QTAG(0->1) */
2095c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM1);	/* Disable QTAG(1->0) */
2096c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
20974a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSR);	/* all interrupt status clear */
20984a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWINMK);	/* Disable all interrupt */
20994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_TEN);	/* Disable all CAM entry */
21004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST1);	/* Disable CAM entry [ 0- 7] */
21014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST2);	/* Disable CAM entry [ 8-15] */
21024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST3);	/* Disable CAM entry [16-23] */
21034a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST4);	/* Disable CAM entry [24-31] */
210486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
210586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
210686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus release function */
210786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_mdio_release(struct net_device *ndev)
210886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
210986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
211086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
211186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* unregister mdio bus */
211286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdiobus_unregister(bus);
211386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
211486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* remove mdio bus info from net_device */
211586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, NULL);
211686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
21170f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	/* free interrupts memory */
21180f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	kfree(bus->irq);
21190f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov
212086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free bitbang info */
212186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_mdio_bitbang(bus);
212286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
212386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
212486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
212586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
212686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus init function */
2127b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimodastatic int sh_mdio_init(struct net_device *ndev, int id,
2128b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda			struct sh_eth_plat_data *pd)
212986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
213086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret, i;
213186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang;
213286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
213386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
213486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* create bit control struct for PHY */
213586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
213686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!bitbang) {
213786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
213886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
213986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
214086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
214186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* bitbang init */
2142ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
2143b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	bitbang->set_gate = pd->set_mdio_gate;
214486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdi_msk = 0x08;
214586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdo_msk = 0x04;
214686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mmd_msk = 0x02;/* MMD */
214786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdc_msk = 0x01;
214886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->ctrl.ops = &bb_ops;
214986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2150c2e07b3a9ced33dd92597201be3931be8ea57ed6Stefan Weil	/* MII controller setting */
215186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
215286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus) {
215386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
215486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bitbang;
215586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
215686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
215786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Hook up MII support for ethtool */
215886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->name = "sh_mii";
215918ee49ddb0d242ed1d0e273038d5e4f6de7379d3Lennert Buytenhek	mdp->mii_bus->parent = &ndev->dev;
21605278fb547076ad6768d16c8b4df45c086470c163Florian Fainelli	snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
216134aa6f1400810890636ba0b170effbfa71eacec7Nobuhiro Iwamatsu		mdp->pdev->name, id);
216286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
216386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY IRQ */
216486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
216586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus->irq) {
216686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
216786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bus;
216886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
216986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
217086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < PHY_MAX_ADDR; i++)
217186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->irq[i] = PHY_POLL;
217286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
217386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* regist mdio bus */
217486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = mdiobus_register(mdp->mii_bus);
217586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
217686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
217786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
217886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, mdp->mii_bus);
217986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
218086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
218186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
218286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
218386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->mii_bus->irq);
218486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
218586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bus:
2186298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek	free_mdio_bitbang(mdp->mii_bus);
218786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
218886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bitbang:
218986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(bitbang);
219086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
219186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
219286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
219386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
219486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
21954a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic const u16 *sh_eth_get_register_offset(int register_type)
21964a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda{
21974a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	const u16 *reg_offset = NULL;
21984a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
21994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	switch (register_type) {
22004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_GIGABIT:
22014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_gigabit;
22024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22034a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH4:
22044a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh4;
22054a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22064a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH3_SH2:
22074a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh3_sh2;
22084a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22094a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	default:
22104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
22114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	}
22134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
22144a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	return reg_offset;
22154a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda}
22164a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
2217ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalovstatic const struct net_device_ops sh_eth_netdev_ops = {
2218ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_open		= sh_eth_open,
2219ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_stop		= sh_eth_close,
2220ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_start_xmit		= sh_eth_start_xmit,
2221ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_get_stats		= sh_eth_get_stats,
2222380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
2223afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= sh_eth_set_multicast_list,
222471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	.ndo_vlan_rx_add_vid	= sh_eth_vlan_rx_add_vid,
222571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	.ndo_vlan_rx_kill_vid	= sh_eth_vlan_rx_kill_vid,
2226380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
2227ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_tx_timeout		= sh_eth_tx_timeout,
2228ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_do_ioctl		= sh_eth_do_ioctl,
2229ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_validate_addr	= eth_validate_addr,
2230ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_set_mac_address	= eth_mac_addr,
2231ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_change_mtu		= eth_change_mtu,
2232ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov};
2233ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov
223486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_probe(struct platform_device *pdev)
223586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
22369c38657cfcb739b7dc4ce9065a85b4f0c195bef8Kuninori Morimoto	int ret, devno = 0;
223786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct resource *res;
223886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = NULL;
2239ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	struct sh_eth_private *mdp = NULL;
224071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	struct sh_eth_plat_data *pd;
224186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
224286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get base addr */
224386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
224486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (unlikely(res == NULL)) {
224586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&pdev->dev, "invalid resource\n");
224686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -EINVAL;
224786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
224886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
224986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
225086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev = alloc_etherdev(sizeof(struct sh_eth_private));
225186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!ndev) {
225286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
225386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
225486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
225586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
225686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* The sh Ether-specific entries in the device structure. */
225786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->base_addr = res->start;
225886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	devno = pdev->id;
225986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (devno < 0)
226086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		devno = 0;
226186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
226286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->dma = -1;
2263cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ret = platform_get_irq(pdev, 0);
2264cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	if (ret < 0) {
226586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENODEV;
226686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
226786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
2268cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ndev->irq = ret;
226986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
227086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	SET_NETDEV_DEV(ndev, &pdev->dev);
227186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
227286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Fill in the fields of the device structure with ethernet values. */
227386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ether_setup(ndev);
227486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
227586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp = netdev_priv(ndev);
2276ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	mdp->addr = ioremap(res->start, resource_size(res));
2277ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp->addr == NULL) {
2278ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		ret = -ENOMEM;
2279ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		dev_err(&pdev->dev, "ioremap failed.\n");
2280ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		goto out_release;
2281ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	}
2282ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda
228386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_init(&mdp->lock);
2284bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	mdp->pdev = pdev;
2285bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_enable(&pdev->dev);
2286bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_resume(&pdev->dev);
228786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
228871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
228986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get PHY ID */
229071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->phy_id = pd->phy;
2291e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda	mdp->phy_interface = pd->phy_interface;
229271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	/* EDMAC endian */
229371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->edmac_endian = pd->edmac_endian;
22944923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->no_ether_link = pd->no_ether_link;
22954923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->ether_link_active_low = pd->ether_link_active_low;
22964a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);
229786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2298380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* set cpu data */
22998fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#if defined(SH_ETH_HAS_BOTH_MODULES)
23008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdp->cd = sh_eth_get_cpu_data(mdp);
23018fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#else
2302380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdp->cd = &sh_eth_my_cpu_data;
23038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#endif
2304380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	sh_eth_set_default_cpu_data(mdp->cd);
2305380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
230686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* set function */
2307ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	ndev->netdev_ops = &sh_eth_netdev_ops;
2308dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
230986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->watchdog_timeo = TX_TIMEOUT;
231086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2311dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* debug message level */
2312dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
231386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->post_rx = POST_RX >> (devno << 1);
231486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->post_fw = POST_FW >> (devno << 1);
231586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* read and set MAC address */
2317748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	read_mac_address(ndev, pd->mac_addr);
231886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23196ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	/* ioremap the TSU registers */
23206ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	if (mdp->cd->tsu) {
23216ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		struct resource *rtsu;
23226ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
23236ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		if (!rtsu) {
23246ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda			dev_err(&pdev->dev, "Not found TSU resource\n");
23256ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda			goto out_release;
23266ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		}
23276ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		mdp->tsu_addr = ioremap(rtsu->start,
23286ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda					resource_size(rtsu));
23296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mdp->port = devno % 2;
233071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		ndev->features = NETIF_F_HW_VLAN_FILTER;
23316ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	}
23326ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda
2333150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	/* initialize first or needed device */
2334150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	if (!devno || pd->needs_init) {
2335380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		if (mdp->cd->chip_reset)
2336380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			mdp->cd->chip_reset(ndev);
233786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23384986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		if (mdp->cd->tsu) {
23394986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			/* TSU init (Init only)*/
23404986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			sh_eth_tsu_init(mdp);
23414986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		}
234286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
234386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
234486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* network device register */
234586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = register_netdev(ndev);
234686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
234786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
234886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
234986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mdio bus init */
2350b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	ret = sh_mdio_init(ndev, pdev->id, pd);
235186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
235286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_unregister;
235386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
235425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* print device information */
23556cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
23566cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	       (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
235786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
235886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, ndev);
235986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
236086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
236186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
236286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_unregister:
236386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
236486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
236586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_release:
236686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* net_dev free */
2367ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp && mdp->addr)
2368ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iounmap(mdp->addr);
2369ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	if (mdp && mdp->tsu_addr)
23704986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		iounmap(mdp->tsu_addr);
237186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev)
237286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		free_netdev(ndev);
237386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
237486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
237586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
237686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
237786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
237886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_remove(struct platform_device *pdev)
237986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
238086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = platform_get_drvdata(pdev);
23814986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
238286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23836ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	if (mdp->cd->tsu)
23846ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		iounmap(mdp->tsu_addr);
238586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_mdio_release(ndev);
238686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
2387bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_disable(&pdev->dev);
2388ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iounmap(mdp->addr);
238986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_netdev(ndev);
239086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, NULL);
239186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
239286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
239386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
239486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2395bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic int sh_eth_runtime_nop(struct device *dev)
2396bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm{
2397bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	/*
2398bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * Runtime PM callback shared between ->runtime_suspend()
2399bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * and ->runtime_resume(). Simply returns success.
2400bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 *
2401bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * This driver re-initializes all registers after
2402bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * pm_runtime_get_sync() anyway so there is no need
2403bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * to save and restore registers here.
2404bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 */
2405bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	return 0;
2406bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm}
2407bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
2408bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic struct dev_pm_ops sh_eth_dev_pm_ops = {
2409bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_suspend = sh_eth_runtime_nop,
2410bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_resume = sh_eth_runtime_nop,
2411bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm};
2412bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
241386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct platform_driver sh_eth_driver = {
241486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.probe = sh_eth_drv_probe,
241586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.remove = sh_eth_drv_remove,
241686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.driver = {
241786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		   .name = CARDNAME,
2418bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm		   .pm = &sh_eth_dev_pm_ops,
241986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	},
242086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
242186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2422db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(sh_eth_driver);
242386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
242486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_AUTHOR("Nobuhiro Iwamatsu, Yoshihiro Shimoda");
242586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_DESCRIPTION("Renesas SuperH Ethernet driver");
242686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_LICENSE("GPL v2");
2427