sh_eth.c revision 91c77550000a7d888aaf9f9ac13e3e3485d18560
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
525e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu#if defined(CONFIG_CPU_SUBTYPE_SH7734) || \
535e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7763) || \
545e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	defined(CONFIG_ARCH_R8A7740)
555e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsustatic void sh_eth_select_mii(struct net_device *ndev)
565e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu{
575e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	u32 value = 0x0;
585e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
595e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
605e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	switch (mdp->phy_interface) {
615e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	case PHY_INTERFACE_MODE_GMII:
625e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		value = 0x2;
635e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		break;
645e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	case PHY_INTERFACE_MODE_MII:
655e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		value = 0x1;
665e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		break;
675e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	case PHY_INTERFACE_MODE_RMII:
685e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		value = 0x0;
695e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		break;
705e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	default:
715e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		pr_warn("PHY interface mode was not setup. Set to MII.\n");
725e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		value = 0x1;
735e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		break;
745e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	}
755e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
765e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, value, RMII_MII);
775e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu}
785e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu#endif
795e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
80380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* There is CPU dependent code */
8165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7724)
8265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
8365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
8465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda{
8565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
8665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
8765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	if (mdp->duplex) /* Full */
884a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
8965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	else		/* Half */
904a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
9165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
9265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
9365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
9465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda{
9565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
9665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
9765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	switch (mdp->speed) {
9865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 10: /* 10BASE */
994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
10065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
10165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 100:/* 100BASE */
1024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
10365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
10465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	default:
10565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
10665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	}
10765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
10865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
10965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda/* SH7724 */
11065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
11165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
11265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
11365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
11465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
11565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
11665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f,
11765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
11865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
11965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
12065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
12165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
12265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
12365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.apr		= 1,
12465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.mpr		= 1,
12565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tpauser	= 1,
12665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.hw_swap	= 1,
127503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir		= 1,
128503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
12965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda};
130f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
1318fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_BOTH_MODULES	1
1328fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
1335cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev);
1345cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
135f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
136f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
137f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
138f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
139f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	if (mdp->duplex) /* Full */
1404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
141f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	else		/* Half */
1424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
143f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
144f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
145f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
146f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
147f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
148f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
149f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	switch (mdp->speed) {
150f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 10: /* 10BASE */
1514a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, RTRATE);
152f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
153f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 100:/* 100BASE */
1544a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 1, RTRATE);
155f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
156f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	default:
157f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
158f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	}
159f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
160f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
161f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda/* SH7757 */
162f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
163f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_duplex		= sh_eth_set_duplex,
164f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_rate		= sh_eth_set_rate,
165f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
166f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
167f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.rmcr_value	= 0x00000001,
168f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
169f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
170f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
171f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
172f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
173f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
174f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.apr		= 1,
175f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.mpr		= 1,
176f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tpauser	= 1,
177f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.hw_swap	= 1,
178f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.no_ade		= 1,
1792e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir		= 1,
1802e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir_value   = 2 << 16,
181f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda};
18265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
1838fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_GIGA_ETH_BASE	0xfee00000
1848fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
1858fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
1868fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_chip_reset_giga(struct net_device *ndev)
1878fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
1888fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	int i;
1898fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	unsigned long mahr[2], malr[2];
1908fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1918fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* save MAHR and MALR */
1928fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
193ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		malr[i] = ioread32((void *)GIGA_MALR(i));
194ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		mahr[i] = ioread32((void *)GIGA_MAHR(i));
1958fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
1968fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1978fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* reset device */
198ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ARSTR_ARSTR, (void *)(SH_GIGA_ETH_BASE + 0x1800));
1998fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdelay(1);
2008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2018fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* restore MAHR and MALR */
2028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
203ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(malr[i], (void *)GIGA_MALR(i));
204ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(mahr[i], (void *)GIGA_MAHR(i));
2058fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2068fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2078fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2088fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp);
2095cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_reset(struct net_device *ndev)
2108fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2118fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2125cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
2138fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2148fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
2158fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x03, EDSR);
2168fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
2178fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2185cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
2195cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		ret = sh_eth_check_reset(ndev);
2205cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		if (ret)
2215cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu			goto out;
2228fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2238fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		/* Table Init */
2248fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDLAR);
2258fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFAR);
2268fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFXR);
2278fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFFR);
2288fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDLAR);
2298fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFAR);
2308fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFXR);
2318fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFFR);
2328fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	} else {
2338fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
2348fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2358fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		mdelay(3);
2368fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
2378fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2388fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2395cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
2405cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
2415cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
2428fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2438fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2448fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_duplex_giga(struct net_device *ndev)
2458fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2468fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2478fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2488fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (mdp->duplex) /* Full */
2498fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
2508fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else		/* Half */
2518fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
2528fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2538fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2548fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_rate_giga(struct net_device *ndev)
2558fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2568fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2578fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2588fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	switch (mdp->speed) {
2598fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 10: /* 10BASE */
2608fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000000, GECMR);
2618fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2628fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 100:/* 100BASE */
2638fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000010, GECMR);
2648fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2658fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 1000: /* 1000BASE */
2668fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000020, GECMR);
2678fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2688fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	default:
2698fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2708fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2718fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2728fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2738fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda/* SH7757(GETHERC) */
2748fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
2758fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset_giga,
2768fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex_giga,
2778fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_rate	= sh_eth_set_rate_giga,
2788fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2798fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
2808fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
2818fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
2828fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2838fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
2848fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
2858fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
2868fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_ECI,
2878fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
2888fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_TFE,
2898fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.fdr_value	= 0x0000072f,
2908fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rmcr_value	= 0x00000001,
2918fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2928fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.apr		= 1,
2938fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.mpr		= 1,
2948fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tpauser	= 1,
2958fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.bculr		= 1,
2968fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.hw_swap	= 1,
2978fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir		= 1,
2988fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir_value   = 2 << 16,
2998fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_trimd	= 1,
3008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_ade		= 1,
3013acbc9715a5ac8a2534a69eb3488b63b7c9fb1e2Yoshihiro Shimoda	.tsu		= 1,
3028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda};
3038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
3048fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
3058fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
3068fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp))
3078fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data_giga;
3088fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else
3098fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data;
3108fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
3118fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
312f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
313380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
3145cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev);
315f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsustatic void sh_eth_reset_hw_crc(struct net_device *ndev);
3165e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
317380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
318380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
3194986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
3204986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda
321380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* reset device */
3224986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
323380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(1);
324380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
325380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
326380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
327380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
328380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
329380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
330380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->duplex) /* Full */
3314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
332380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else		/* Half */
3334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
334380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
335380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
336380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
337380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
338380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
339380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
340380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	switch (mdp->speed) {
341380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 10: /* 10BASE */
3424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
343380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
344380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 100:/* 100BASE */
3454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
346380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
347380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 1000: /* 1000BASE */
3484a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
349380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
350380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	default:
351380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
352380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	}
353380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
354380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
355380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* sh7763 */
356380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
357380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
358380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
359380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
360380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
361380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
362380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
363380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
364380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
365380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
366380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
367380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
368380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_ECI,
369380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
370380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_TFE,
371380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
372380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
373380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
374380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
375380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.bculr		= 1,
376380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
377380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_trimd	= 1,
378380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_ade		= 1,
3794986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
380f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#if defined(CONFIG_CPU_SUBTYPE_SH7734)
381f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	.hw_crc     = 1,
3825e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	.select_mii = 1,
383f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#endif
384380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
385380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
3865cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_reset(struct net_device *ndev)
3875e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu{
3885cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
3895e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
3905e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, EDSR_ENALL, EDSR);
3915e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
3925cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
3935cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	ret = sh_eth_check_reset(ndev);
3945cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (ret)
3955cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		goto out;
3965e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
3975e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	/* Table Init */
3985e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDLAR);
3995e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDFAR);
4005e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDFXR);
4015e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDFFR);
4025e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDLAR);
4035e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDFAR);
4045e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDFXR);
4055e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDFFR);
4065e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
4075e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	/* Reset HW CRC register */
4085e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_reset_hw_crc(ndev);
4095e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
4105e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	/* Select MII mode */
4115e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	if (sh_eth_my_cpu_data.select_mii)
4125e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		sh_eth_select_mii(ndev);
4135cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
4145cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
4155e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu}
4165e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
417f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsustatic void sh_eth_reset_hw_crc(struct net_device *ndev)
418f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu{
419f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	if (sh_eth_my_cpu_data.hw_crc)
420f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu		sh_eth_write(ndev, 0x0, CSMR);
421f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu}
422f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu
42373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#elif defined(CONFIG_ARCH_R8A7740)
42473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
4255cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev);
4265cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
42773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
42873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
42973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
43073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
43173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	/* reset device */
43273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
43373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	mdelay(1);
43473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
4355e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_select_mii(ndev);
43673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
43773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
4385cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_reset(struct net_device *ndev)
43973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
4405cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
44173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
44273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, EDSR_ENALL, EDSR);
44373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
4445cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
4455cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	ret = sh_eth_check_reset(ndev);
4465cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (ret)
4475cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		goto out;
44873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
44973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	/* Table Init */
45073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDLAR);
45173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFAR);
45273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFXR);
45373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFFR);
45473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDLAR);
45573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFAR);
45673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFXR);
45773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFFR);
4585cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
4595cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
4605cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
46173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
46273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
46373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
46473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
46573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
46673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
46773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	if (mdp->duplex) /* Full */
46873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
46973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	else		/* Half */
47073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
47173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
47273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
47373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
47473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
47573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
47673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
47773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	switch (mdp->speed) {
47873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 10: /* 10BASE */
47973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
48073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
48173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 100:/* 100BASE */
48273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
48373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
48473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 1000: /* 1000BASE */
48573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
48673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
48773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	default:
48873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
48973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	}
49073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
49173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
49273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda/* R8A7740 */
49373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
49473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
49573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
49673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
49773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
49873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
49973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
50073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
50173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
50273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
50373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
50473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
50573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_ECI,
50673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
50773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_TFE,
50873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
50973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.apr		= 1,
51073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.mpr		= 1,
51173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tpauser	= 1,
51273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.bculr		= 1,
51373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.hw_swap	= 1,
51473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.no_trimd	= 1,
51573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.no_ade		= 1,
51673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tsu		= 1,
5175e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	.select_mii	= 1,
51873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda};
51973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
520380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
521380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
522380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
523380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
524380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
525380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
526380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
527380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
528380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
529380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
530380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
531380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
532380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
533380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
534380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
5354986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
536380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
537380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
538380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
539380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
540380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
541380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsr_value)
542380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsr_value = DEFAULT_ECSR_INIT;
543380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
544380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsipr_value)
545380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
546380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
547380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fcftr_value)
548380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
549380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				  DEFAULT_FIFO_F_D_RFD;
550380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
551380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fdr_value)
552380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fdr_value = DEFAULT_FDR_INIT;
553380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
554380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->rmcr_value)
555380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->rmcr_value = DEFAULT_RMCR_VALUE;
556380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
557380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_check)
558380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_check = DEFAULT_TX_CHECK;
559380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
560380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->eesr_err_check)
561380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK;
562380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
563380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_error_check)
564380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_error_check = DEFAULT_TX_ERROR_CHECK;
565380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
566380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
567380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_RESET_DEFAULT)
568380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* Chip Reset */
5695cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int  sh_eth_reset(struct net_device *ndev)
570380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
571c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
572380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(3);
573c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
5745cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
5755cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return 0;
5765cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu}
5775cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu#else
5785cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev)
5795cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu{
5805cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
5815cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int cnt = 100;
5825cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
5835cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	while (cnt > 0) {
5845cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		if (!(sh_eth_read(ndev, EDMR) & 0x3))
5855cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu			break;
5865cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		mdelay(1);
5875cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		cnt--;
5885cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	}
5895cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (cnt < 0) {
5905cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		printk(KERN_ERR "Device reset fail\n");
5915cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		ret = -ETIMEDOUT;
5925cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	}
5935cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
594380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
595380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
596380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
59773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
598380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
599380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
600380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	int reserve;
601380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
602380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
603380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (reserve)
604380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		skb_reserve(skb, reserve);
605380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
606380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#else
607380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
608380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
609380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
610380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
611380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
612380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
613380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
61471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato/* CPU <-> EDMAC endian convert */
61571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
61671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
61771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
61871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
61971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_le32(x);
62071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
62171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_be32(x);
62271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
62371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
62471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
62571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
62671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
62771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
62871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
62971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
63071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return le32_to_cpu(x);
63171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
63271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return be32_to_cpu(x);
63371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
63471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
63571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
63671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
63786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
63886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Program the hardware MAC address from dev->dev_addr.
63986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
64086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void update_mac_address(struct net_device *ndev)
64186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
6424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
6434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
6444a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
6454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
6464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
64786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
64886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
64986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
65086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Get MAC address from SuperH MAC address register
65186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
65286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
65386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
65486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * When you want use this device, you must set MAC address in bootloader.
65586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
65686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
657748031f9fd2c06b28817d80761a5de97190cfd03Magnus Dammstatic void read_mac_address(struct net_device *ndev, unsigned char *mac)
65886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
659748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
660748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm		memcpy(ndev->dev_addr, mac, 6);
661748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	} else {
6624a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
6634a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
6644a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
6654a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
6664a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
6674a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
668748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	}
66986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
67086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
671c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp)
672c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
673c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (mdp->reg_offset == sh_eth_offset_gigabit)
674c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 1;
675c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
676c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 0;
677c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
678c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
679c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
680c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
681c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp))
682c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_GETHER;
683c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
684c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_ETHER;
685c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
686c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
68786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustruct bb_info {
688ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void (*set_gate)(void *addr);
68986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mdiobb_ctrl ctrl;
690ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void *addr;
69186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mmd_msk;/* MMD */
69286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdo_msk;
69386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdi_msk;
69486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdc_msk;
69586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
69686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
69786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit set */
698ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_set(void *addr, u32 msk)
69986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
700ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ioread32(addr) | msk, addr);
70186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
70286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit clear */
704ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_clr(void *addr, u32 msk)
70586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
706ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32((ioread32(addr) & ~msk), addr);
70786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
70886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit read */
710ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic int bb_read(void *addr, u32 msk)
71186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
712ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	return (ioread32(addr) & msk) != 0;
71386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
71486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
71586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Data I/O pin control */
71686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
71786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
71886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
719b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
720b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
721b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
722b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
72386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
72486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mmd_msk);
72586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
72686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mmd_msk);
72786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
72886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
72986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Set bit data*/
73086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
73186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
73286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
73386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
734b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
735b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
736b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
73786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
73886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdo_msk);
73986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
74086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdo_msk);
74186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
74286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
74386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get bit data*/
74486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_get_mdio(struct mdiobb_ctrl *ctrl)
74586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
74686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
747b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
748b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
749b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
750b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
75186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return bb_read(bitbang->addr, bitbang->mdi_msk);
75286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
75386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
75486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDC pin control */
75586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
75686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
75786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
75886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
759b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
760b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
761b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
76286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
76386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdc_msk);
76486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
76586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdc_msk);
76686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
76786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
76886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* mdio bus control struct */
76986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct mdiobb_ops bb_ops = {
77086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.owner = THIS_MODULE,
77186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdc = sh_mdc_ctrl,
77286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_dir = sh_mmd_ctrl,
77386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_data = sh_set_mdio,
77486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.get_mdio_data = sh_get_mdio,
77586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
77686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free skb and descriptor buffer */
77886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_free(struct net_device *ndev)
77986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
78086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
78186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
78286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
78386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx skb ringbuffer */
78486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->rx_skbuff) {
78586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		for (i = 0; i < RX_RING_SIZE; i++) {
78686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->rx_skbuff[i])
78786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->rx_skbuff[i]);
78886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
78986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
79086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->rx_skbuff);
79191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->rx_skbuff = NULL;
79286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
79386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Tx skb ringbuffer */
79486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->tx_skbuff) {
79586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		for (i = 0; i < TX_RING_SIZE; i++) {
79686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->tx_skbuff[i])
79786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->tx_skbuff[i]);
79886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
79986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
80086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->tx_skbuff);
80191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->tx_skbuff = NULL;
80286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
80386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* format skb and descriptor buffer */
80586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_format(struct net_device *ndev)
80686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
80786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
80886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
80986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
81086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc = NULL;
81186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc = NULL;
81286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE;
81386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE;
81486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
81586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_rx = mdp->cur_tx = 0;
81686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = mdp->dirty_tx = 0;
81786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
81886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->rx_ring, 0, rx_ringsize);
81986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Rx ring buffer */
82186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < RX_RING_SIZE; i++) {
82286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* skb */
82386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
824dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi		skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
82586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = skb;
82686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (skb == NULL)
82786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
828bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
829e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda				DMA_FROM_DEVICE);
830380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_set_receive_align(skb);
831380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
83286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* RX descriptor */
83386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
8340029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
83571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
83686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
83786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
8380029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
839b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* Rx descriptor address set */
840b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
8414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
842c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
843c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
844b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
84586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
84686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
84786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
84886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
84986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Mark the last entry as wrapping the ring. */
85071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
85186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->tx_ring, 0, tx_ringsize);
85386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Tx ring buffer */
85586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < TX_RING_SIZE; i++) {
85686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
85786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[i];
85871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
85986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = 0;
860b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
86171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			/* Tx descriptor address set */
8624a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
863c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
864c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
865b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
86686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
86786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
86871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
86986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
87086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
87186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get skb and descriptor buffer */
87286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_ring_init(struct net_device *ndev)
87386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
87486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
87586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize, tx_ringsize, ret = 0;
87686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
87786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/*
87886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
87986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card needs room to do 8 byte alignment, +2 so we can reserve
88086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * the first 2 bytes, and +16 gets room for the status word from the
88186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card.
88286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 */
88386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ :
88486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			  (((ndev->mtu + 26 + 7) & ~7) + 2 + 16));
885503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	if (mdp->cd->rpadir)
886503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm		mdp->rx_buf_sz += NET_IP_ALIGN;
88786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
88886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate RX and TX skb rings */
88986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
89086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				GFP_KERNEL);
89186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_skbuff) {
892380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx skb\n");
89386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
89486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
89586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
89686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
89886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				GFP_KERNEL);
89986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_skbuff) {
900380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx skb\n");
90186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
90286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto skb_ring_free;
90386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
90486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
90586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Rx descriptors. */
90686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
90786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
90886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
90986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_ring) {
911380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
912380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			rx_ringsize);
91386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
91486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
91586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
91686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = 0;
91886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Tx descriptors. */
92086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
92186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
92286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
92386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_ring) {
924380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
925380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			tx_ringsize);
92686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
92786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
92886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
92986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
93086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
93186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsudesc_ring_free:
93286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
93386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma);
93486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
93586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuskb_ring_free:
93686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx and Tx skb ring buffer */
93786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
93891c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->tx_ring = NULL;
93991c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->rx_ring = NULL;
94086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
94186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
94286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
94386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
94491c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimodastatic void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
94591c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda{
94691c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	int ringsize;
94791c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda
94891c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	if (mdp->rx_ring) {
94991c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
95091c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		dma_free_coherent(NULL, ringsize, mdp->rx_ring,
95191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda				  mdp->rx_desc_dma);
95291c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		mdp->rx_ring = NULL;
95391c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	}
95491c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda
95591c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	if (mdp->tx_ring) {
95691c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
95791c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		dma_free_coherent(NULL, ringsize, mdp->tx_ring,
95891c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda				  mdp->tx_desc_dma);
95991c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		mdp->tx_ring = NULL;
96091c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	}
96191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda}
96291c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda
96386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_dev_init(struct net_device *ndev)
96486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
96586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
96686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
96786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 val;
96886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
96986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Soft Reset */
9705cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	ret = sh_eth_reset(ndev);
9715cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (ret)
9725cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		goto out;
97386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
974b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Descriptor format */
975b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	sh_eth_ring_format(ndev);
976380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->rpadir)
9774a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR);
97886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
97986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* all sh_eth int mask */
9804a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EESIPR);
98186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
98210b9194f959608368ed89df1937f17cfe6bd6d84Yoshihiro Shimoda#if defined(__LITTLE_ENDIAN)
983380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->hw_swap)
9844a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDMR_EL, EDMR);
985380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else
986b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu#endif
9874a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, EDMR);
98886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
989b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* FIFO size set */
9904a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
9914a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TFTR);
99286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
993b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Frame recv control */
9944a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
99586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
9962ecbb783c3bf5a63f555c39deef308dcc1902b7fYoshihiro Shimoda	sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER);
99786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
998380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->bculr)
9994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */
1000b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
10014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fcftr_value, FCFTR);
100286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1003380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->no_trimd)
10044a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, TRIMD);
100586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1006b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Recv frame limit set register */
1007fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda	sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
1008fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda		     RFLR);
100986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
10114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
101286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
101386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PAUSE Prohibition */
10144a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
101586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
101686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, val, ECMR);
1018b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
1019380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->set_rate)
1020380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mdp->cd->set_rate(ndev);
1021380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1022b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Status Register clear */
10234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
1024b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
1025b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Interrupt Enable register */
10264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
102786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
102886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Set MAC address */
102986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	update_mac_address(ndev);
103086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
103186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mask reset */
1032380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->apr)
10334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, APR_AP, APR);
1034380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->mpr)
10354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, MPR_MP, MPR);
1036380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->tpauser)
10374a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
1038b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
103986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Setting the Rx mode will start the Rx process. */
10404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, EDRRR_R, EDRRR);
104186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
104286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_start_queue(ndev);
104386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10445cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
104586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
104686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
104786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
104886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free Tx skb function */
104986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_txfree(struct net_device *ndev)
105086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
105186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
105286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
105386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int freeNum = 0;
105486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = 0;
105586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
105686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
105786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = mdp->dirty_tx % TX_RING_SIZE;
105886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[entry];
105971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
106086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
106186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Free the original skb. */
106286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[entry]) {
106331fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda			dma_unmap_single(&ndev->dev, txdesc->addr,
106431fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda					 txdesc->buffer_length, DMA_TO_DEVICE);
106586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
106686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->tx_skbuff[entry] = NULL;
106786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			freeNum++;
106886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
106971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
107086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (entry >= TX_RING_SIZE - 1)
107171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
107286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1073bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_packets++;
1074bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_bytes += txdesc->buffer_length;
107586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
107686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return freeNum;
107786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
107886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
107986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet receive function */
1080a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimodastatic int sh_eth_rx(struct net_device *ndev, u32 intr_status)
108186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
108286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
108386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
108486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
108586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = mdp->cur_rx % RX_RING_SIZE;
108686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
108786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
108886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u16 pkt_len = 0;
1089380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 desc_status;
109086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
109186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rxdesc = &mdp->rx_ring[entry];
109271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
109371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		desc_status = edmac_to_cpu(mdp, rxdesc->status);
109486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		pkt_len = rxdesc->frame_length;
109586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
109673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#if defined(CONFIG_ARCH_R8A7740)
109773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		desc_status >>= 16;
109873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#endif
109973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
110086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (--boguscnt < 0)
110186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
110286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
110386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!(desc_status & RDFEND))
1104bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_length_errors++;
110586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
110686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
110786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
1108bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_errors++;
110986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS1)
1110bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_crc_errors++;
111186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS2)
1112bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_frame_errors++;
111386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS3)
1114bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
111586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS4)
1116bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
111786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS6)
1118bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_missed_errors++;
111986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS10)
1120bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_over_errors++;
112186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		} else {
1122380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (!mdp->cd->hw_swap)
1123380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				sh_eth_soft_swap(
1124380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					phys_to_virt(ALIGN(rxdesc->addr, 4)),
1125380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					pkt_len + 2);
112686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb = mdp->rx_skbuff[entry];
112786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = NULL;
1128503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm			if (mdp->cd->rpadir)
1129503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm				skb_reserve(skb, NET_IP_ALIGN);
113086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb_put(skb, pkt_len);
113186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb->protocol = eth_type_trans(skb, ndev);
113286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_rx(skb);
1133bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_packets++;
1134bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_bytes += pkt_len;
113586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
113671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
113786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = (++mdp->cur_rx) % RX_RING_SIZE;
1138862df49750e7ca9369c04d8d8105b3cc5d976e0dYoshihiro Shimoda		rxdesc = &mdp->rx_ring[entry];
113986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
114086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
114186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Refill the Rx ring buffers. */
114286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
114386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = mdp->dirty_rx % RX_RING_SIZE;
114486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[entry];
1145b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
11460029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
1147b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
114886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[entry] == NULL) {
1149dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi			skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
115086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = skb;
115186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (skb == NULL)
115286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				break;	/* Better luck next round. */
1153bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
1154e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda					DMA_FROM_DEVICE);
1155380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			sh_eth_set_receive_align(skb);
1156380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1157bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet			skb_checksum_none_assert(skb);
11580029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda			rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
115986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
116086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (entry >= RX_RING_SIZE - 1)
116186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
116271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
116386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		else
116486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
116571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
116686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
116786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
116886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Restart Rx engine if stopped. */
116986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* If we don't need to check status, don't. -KDU */
117079fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
1171a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda		/* fix the values for the next receiving if RDE is set */
1172a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda		if (intr_status & EESR_RDE)
1173a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda			mdp->cur_rx = mdp->dirty_rx =
1174a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda				(sh_eth_read(ndev, RDFAR) -
1175a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda				 sh_eth_read(ndev, RDLAR)) >> 4;
11764a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDRRR_R, EDRRR);
117779fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda	}
117886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
117986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
118086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
118186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
11824a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_disable(struct net_device *ndev)
1183dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1184dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
11854a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) &
11864a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		~(ECMR_RE | ECMR_TE), ECMR);
1187dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1188dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
11894a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_enable(struct net_device *ndev)
1190dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1191dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
11924a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
11934a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ECMR_RE | ECMR_TE), ECMR);
1194dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1195dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
119686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* error control function */
119786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_error(struct net_device *ndev, int intr_status)
119886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
119986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
120086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 felic_stat;
1201380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 link_stat;
1202380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 mask;
120386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
120486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_ECI) {
12054a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		felic_stat = sh_eth_read(ndev, ECSR);
12064a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, felic_stat, ECSR);	/* clear int */
120786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_ICD)
1208bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_carrier_errors++;
120986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_LCHNG) {
121086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Link Changed */
12114923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda			if (mdp->cd->no_psr || mdp->no_ether_link) {
1212380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				if (mdp->link == PHY_DOWN)
1213380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					link_stat = 0;
1214380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				else
1215380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					link_stat = PHY_ST_LINK;
1216380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			} else {
12174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				link_stat = (sh_eth_read(ndev, PSR));
12184923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda				if (mdp->ether_link_active_low)
12194923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda					link_stat = ~link_stat;
1220380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			}
1221dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (!(link_stat & PHY_ST_LINK))
12224a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_disable(ndev);
1223dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			else {
122486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* Link Up */
12254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
12264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ~DMAC_M_ECI, EESIPR);
122786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/*clear int */
12284a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
12294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ECSR);
12304a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
12314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  DMAC_M_ECI, EESIPR);
123286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* enable tx and rx */
12334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_enable(ndev);
123486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			}
123586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
123686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
123786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
123886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_TWB) {
123986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Write buck end. unused write back interrupt */
124086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_TABT)	/* Transmit Abort int */
1241bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_aborted_errors++;
1242dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_err(mdp))
1243dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Transmit Abort\n");
124486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
124586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
124686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RABT) {
124786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Abort int */
124886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_RFRMER) {
124986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Receive Frame Overflow int */
1250bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_frame_errors++;
1251dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_rx_err(mdp))
1252dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Receive Abort\n");
125386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
125486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1255380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1256dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TDE) {
1257dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Transmit Descriptor Empty int */
1258bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1259dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1260dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
1261dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1262dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1263dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TFE) {
1264dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* FIFO under flow */
1265bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1266dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1267dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
126886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
126986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
127086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RDE) {
127186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Descriptor Empty int */
1272bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_over_errors++;
127386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1274dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1275dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive Descriptor Empty\n");
127686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1277dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
127886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RFE) {
127986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive FIFO Overflow int */
1280bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_fifo_errors++;
1281dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1282dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive FIFO Overflow\n");
1283dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1284dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1285dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
1286dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Address Error */
1287bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1288dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1289dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Address Error\n");
129086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1291380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1292380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
1293380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->no_ade)
1294380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mask &= ~EESR_ADE;
1295380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & mask) {
129686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Tx error */
12974a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		u32 edtrr = sh_eth_read(ndev, EDTRR);
129886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dmesg */
1299380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
1300380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				intr_status, mdp->cur_tx);
1301380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
130286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				mdp->dirty_tx, (u32) ndev->state, edtrr);
130386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dirty buffer free */
130486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
130586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
130686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* SH7712 BUG */
1307c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
130886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* tx dma start */
1309c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
131086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
131186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* wakeup */
131286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
131386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
131486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
131586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
131686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic irqreturn_t sh_eth_interrupt(int irq, void *netdev)
131786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
131886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = netdev;
131986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1320380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_cpu_data *cd = mdp->cd;
13210e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	irqreturn_t ret = IRQ_NONE;
13224a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	u32 intr_status = 0;
132386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
132486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock(&mdp->lock);
132586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1326b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Get interrpt stat */
13274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	intr_status = sh_eth_read(ndev, EESR);
132886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Clear interrupt */
13290e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
13300e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
1331380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			cd->tx_check | cd->eesr_err_check)) {
13324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, intr_status, EESR);
13330e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		ret = IRQ_HANDLED;
13340e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	} else
13350e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		goto other_irq;
133686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1337b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	if (intr_status & (EESR_FRC | /* Frame recv*/
1338b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RMAF | /* Multi cast address recv*/
1339b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RRF  | /* Bit frame recv */
1340b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTLF | /* Long frame recv*/
1341b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTSF | /* short frame recv */
1342b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_PRE  | /* PHY-LSI recv error */
1343b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_CERF)){ /* recv frame CRC error */
1344a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda		sh_eth_rx(ndev, intr_status);
1345b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	}
134686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1347b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Tx Check */
1348380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->tx_check) {
134986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
135086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
135186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
135286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1353380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->eesr_err_check)
135486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_error(ndev, intr_status);
135586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
13560e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsuother_irq:
135786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock(&mdp->lock);
135886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
13590e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	return ret;
136086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
136186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
136286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY state control function */
136386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_adjust_link(struct net_device *ndev)
136486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
136586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
136686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
136786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int new_state = 0;
136886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
136986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (phydev->link != PHY_DOWN) {
137086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->duplex != mdp->duplex) {
137186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
137286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->duplex = phydev->duplex;
1373380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_duplex)
1374380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_duplex(ndev);
137586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
137686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
137786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->speed != mdp->speed) {
137886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
137986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->speed = phydev->speed;
1380380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_rate)
1381380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_rate(ndev);
138286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
138386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->link == PHY_DOWN) {
138491a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda			sh_eth_write(ndev,
138591a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda				(sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
138686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
138786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->link = phydev->link;
138886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
138986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else if (mdp->link) {
139086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		new_state = 1;
139186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->link = PHY_DOWN;
139286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->speed = 0;
139386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->duplex = -1;
139486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
139586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1396dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (new_state && netif_msg_link(mdp))
139786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_print_status(phydev);
139886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
139986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
140086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY init function */
140186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_init(struct net_device *ndev)
140286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
140386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
14040a372eb91f9d507701a901c2f62ed31ca67fd66cDavid S. Miller	char phy_id[MII_BUS_ID_SIZE + 3];
140586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = NULL;
140686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1407fb28ad35906af2f042c94e2f9c0f898ef9acfa37Kay Sievers	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
140886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->id , mdp->phy_id);
140986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
141086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->link = PHY_DOWN;
141186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->speed = 0;
141286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->duplex = -1;
141386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
141486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Try connect to PHY */
1415c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
1416e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda				0, mdp->phy_interface);
141786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (IS_ERR(phydev)) {
141886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&ndev->dev, "phy_connect failed\n");
141986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return PTR_ERR(phydev);
142086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1421380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
142286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_info(&ndev->dev, "attached phy %i to driver %s\n",
1423380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		phydev->addr, phydev->drv->name);
142486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->phydev = phydev;
142686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
142886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
142986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
143086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY control start function */
143186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_start(struct net_device *ndev)
143286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
143386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
143486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret;
143586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
143686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_init(ndev);
143786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
143886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
143986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* reset phy - this also wakes it from PDOWN */
144186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
144286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_start(mdp->phydev);
144386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
144586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
144686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1447dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_settings(struct net_device *ndev,
1448dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_cmd *ecmd)
1449dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1450dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1451dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1452dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1453dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1454dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1455dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_gset(mdp->phydev, ecmd);
1456dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1457dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1458dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1459dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1460dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1461dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_set_settings(struct net_device *ndev,
1462dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		struct ethtool_cmd *ecmd)
1463dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1464dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1465dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1466dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1467dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1468dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1469dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1470dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
14714a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_disable(ndev);
1472dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1473dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_sset(mdp->phydev, ecmd);
1474dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ret)
1475dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		goto error_exit;
1476dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1477dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ecmd->duplex == DUPLEX_FULL)
1478dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 1;
1479dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	else
1480dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 0;
1481dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1482dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (mdp->cd->set_duplex)
1483dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->cd->set_duplex(ndev);
1484dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1485dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsuerror_exit:
1486dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdelay(1);
1487dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1488dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
14894a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_enable(ndev);
1490dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1491dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1492dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1493dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1494dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1495dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1496dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_nway_reset(struct net_device *ndev)
1497dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1498dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1499dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1500dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1501dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1502dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1503dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_start_aneg(mdp->phydev);
1504dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1505dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1506dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1507dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1508dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1509dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic u32 sh_eth_get_msglevel(struct net_device *ndev)
1510dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1511dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1512dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return mdp->msg_enable;
1513dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1514dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1515dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_set_msglevel(struct net_device *ndev, u32 value)
1516dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1517dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1518dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = value;
1519dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1520dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1521dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic const char sh_eth_gstrings_stats[][ETH_GSTRING_LEN] = {
1522dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_current", "tx_current",
1523dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_dirty", "tx_dirty",
1524dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1525dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#define SH_ETH_STATS_LEN  ARRAY_SIZE(sh_eth_gstrings_stats)
1526dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1527dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_sset_count(struct net_device *netdev, int sset)
1528dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1529dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (sset) {
1530dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1531dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return SH_ETH_STATS_LEN;
1532dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	default:
1533dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return -EOPNOTSUPP;
1534dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1535dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1536dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1537dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_ethtool_stats(struct net_device *ndev,
1538dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_stats *stats, u64 *data)
1539dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1540dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1541dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int i = 0;
1542dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1543dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* device-specific stats */
1544dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_rx;
1545dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_tx;
1546dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_rx;
1547dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_tx;
1548dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1549dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1550dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
1551dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1552dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (stringset) {
1553dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1554dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		memcpy(data, *sh_eth_gstrings_stats,
1555dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu					sizeof(sh_eth_gstrings_stats));
1556dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		break;
1557dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1558dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1559dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
15609b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemmingerstatic const struct ethtool_ops sh_eth_ethtool_ops = {
1561dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_settings	= sh_eth_get_settings,
1562dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_settings	= sh_eth_set_settings,
15639b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.nway_reset	= sh_eth_nway_reset,
1564dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_msglevel	= sh_eth_get_msglevel,
1565dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_msglevel	= sh_eth_set_msglevel,
15669b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.get_link	= ethtool_op_get_link,
1567dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_strings	= sh_eth_get_strings,
1568dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_ethtool_stats  = sh_eth_get_ethtool_stats,
1569dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_sset_count     = sh_eth_get_sset_count,
1570dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1571dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
157286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* network device open function */
157386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_open(struct net_device *ndev)
157486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
157586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
157686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
157786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1578bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1579bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1580a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches	ret = request_irq(ndev->irq, sh_eth_interrupt,
1581f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
1582dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
1583dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7757)
15840e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				IRQF_SHARED,
15850e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#else
15860e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				0,
15870e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#endif
15880e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				ndev->name, ndev);
158986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret) {
1590380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Can not assign IRQ number\n");
159186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
159286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
159386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
159486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Descriptor set */
159586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_ring_init(ndev);
159686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
159786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
159886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
159986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
160086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_dev_init(ndev);
160186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
160286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
160386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
160486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY control start*/
160586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_start(ndev);
160686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
160786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
160886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
160986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
161086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
161186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
161286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
1613bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
161486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
161586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
161686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
161786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Timeout function */
161886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_tx_timeout(struct net_device *ndev)
161986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
162086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
162186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
162286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
162386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
162486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
162586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1626dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (netif_msg_timer(mdp))
1627dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
16284a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	       " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
162986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
163086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* tx_errors count up */
1631bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_errors++;
163286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
163386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
163486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < RX_RING_SIZE; i++) {
163586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
163686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->status = 0;
163786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->addr = 0xBADF00D0;
163886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[i])
163986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->rx_skbuff[i]);
164086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
164186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
164286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < TX_RING_SIZE; i++) {
164386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[i])
164486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->tx_skbuff[i]);
164586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
164686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
164786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
164886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
164986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_dev_init(ndev);
165086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
165186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet transmit function */
165386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
165486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
165586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
165686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
165786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 entry;
1658fb5e2f9b9410a4362897d12dc1ed4f7cec1b0d45Nobuhiro Iwamatsu	unsigned long flags;
165986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
166086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
166186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
166286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!sh_eth_txfree(ndev)) {
1663dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_queued(mdp))
1664dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_warn(&ndev->dev, "TxFD exhausted.\n");
166586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_stop_queue(ndev);
166686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			spin_unlock_irqrestore(&mdp->lock, flags);
16675b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy			return NETDEV_TX_BUSY;
166886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
166986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
167086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
167186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	entry = mdp->cur_tx % TX_RING_SIZE;
167386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff[entry] = skb;
167486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	txdesc = &mdp->tx_ring[entry];
167586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* soft swap. */
1676380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->hw_swap)
1677380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
1678380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				 skb->len + 2);
167931fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
168031fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda				      DMA_TO_DEVICE);
168186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (skb->len < ETHERSMALL)
168286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = ETHERSMALL;
168386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
168486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = skb->len;
168586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
168686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (entry >= TX_RING_SIZE - 1)
168771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
168886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
168971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
169086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
169186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_tx++;
169286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1693c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDTRR) & sh_eth_get_edtrr_trns(mdp)))
1694c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
1695b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
16966ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
169786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
169886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
169986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* device close function */
170086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_close(struct net_device *ndev)
170186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
170286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
170386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
170486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
170586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
170686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Disable interrupts by clearing the interrupt mask. */
17074a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0000, EESIPR);
170886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
170986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Stop the chip's Tx and Rx processes. */
17104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDTRR);
17114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDRRR);
171286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
171386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY Disconnect */
171486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->phydev) {
171586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_stop(mdp->phydev);
171686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_disconnect(mdp->phydev);
171786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
171886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
171986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
172086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
172286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
172386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
172591c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	sh_eth_free_dma_buffer(mdp);
172686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1727bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1728bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
172986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
173086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
173186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
173386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
173486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
173586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1736bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1737bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1738bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
17394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TROCR);	/* (write clear) */
1740bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.collisions += sh_eth_read(ndev, CDCR);
17414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, CDCR);	/* (write clear) */
1742bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
17434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, LCCR);	/* (write clear) */
1744c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1745bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
1746c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CERCR);	/* (write clear) */
1747bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
1748c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CEECR);	/* (write clear) */
1749c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
1750bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
1751c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CNDCR);	/* (write clear) */
1752c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
1753bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1754bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1755bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	return &ndev->stats;
175686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
175786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1758bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet/* ioctl to device function */
175986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
176086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				int cmd)
176186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
176286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
176386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
176486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
176586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!netif_running(ndev))
176686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -EINVAL;
176786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
176886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!phydev)
176986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -ENODEV;
177086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
177128b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran	return phy_mii_ioctl(phydev, rq, cmd);
177286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
177386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1774380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
17756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda/* For TSU_POSTn. Please refer to the manual about this (strange) bitfields */
17766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void *sh_eth_tsu_get_post_reg_offset(struct sh_eth_private *mdp,
17776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					    int entry)
17786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return sh_eth_tsu_get_offset(mdp, TSU_POST1) + (entry / 8 * 4);
17806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic u32 sh_eth_tsu_get_post_mask(int entry)
17836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0x0f << (28 - ((entry % 8) * 4));
17856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic u32 sh_eth_tsu_get_post_bit(struct sh_eth_private *mdp, int entry)
17886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return (0x08 >> (mdp->port << 1)) << (28 - ((entry % 8) * 4));
17906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
17916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_enable_cam_entry_post(struct net_device *ndev,
17936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					     int entry)
17946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
17956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
17966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 tmp;
17976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset;
17986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
17996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
18006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	tmp = ioread32(reg_offset);
18016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(tmp | sh_eth_tsu_get_post_bit(mdp, entry), reg_offset);
18026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic bool sh_eth_tsu_disable_cam_entry_post(struct net_device *ndev,
18056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					      int entry)
18066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 post_mask, ref_mask, tmp;
18096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset;
18106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
18126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	post_mask = sh_eth_tsu_get_post_mask(entry);
18136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ref_mask = sh_eth_tsu_get_post_bit(mdp, entry) & ~post_mask;
18146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	tmp = ioread32(reg_offset);
18166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(tmp & ~post_mask, reg_offset);
18176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* If other port enables, the function returns "true" */
18196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return tmp & ref_mask;
18206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_busy(struct net_device *ndev)
18236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int timeout = SH_ETH_TSU_TIMEOUT_MS * 100;
18256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	while ((sh_eth_tsu_read(mdp, TSU_ADSBSY) & TSU_ADSBSY_0)) {
18286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		udelay(10);
18296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		timeout--;
18306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (timeout <= 0) {
18316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			dev_err(&ndev->dev, "%s: timeout\n", __func__);
18326743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return -ETIMEDOUT;
18336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		}
18346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
18356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
18376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_write_entry(struct net_device *ndev, void *reg,
18406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				  const u8 *addr)
18416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 val;
18436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
18456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(val, reg);
18466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (sh_eth_tsu_busy(ndev) < 0)
18476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return -EBUSY;
18486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = addr[4] << 8 | addr[5];
18506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(val, reg + 4);
18516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (sh_eth_tsu_busy(ndev) < 0)
18526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return -EBUSY;
18536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
18556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_read_entry(void *reg, u8 *addr)
18586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 val;
18606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = ioread32(reg);
18626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[0] = (val >> 24) & 0xff;
18636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[1] = (val >> 16) & 0xff;
18646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[2] = (val >> 8) & 0xff;
18656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[3] = val & 0xff;
18666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = ioread32(reg + 4);
18676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[4] = (val >> 8) & 0xff;
18686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[5] = val & 0xff;
18696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_find_entry(struct net_device *ndev, const u8 *addr)
18736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
18766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i;
18776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 c_addr[ETH_ALEN];
18786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
18806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_read_entry(reg_offset, c_addr);
18816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (memcmp(addr, c_addr, ETH_ALEN) == 0)
18826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return i;
18836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
18846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return -ENOENT;
18866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_find_empty(struct net_device *ndev)
18896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 blank[ETH_ALEN];
18916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int entry;
18926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	memset(blank, 0, sizeof(blank));
18946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	entry = sh_eth_tsu_find_entry(ndev, blank);
18956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return (entry < 0) ? -ENOMEM : entry;
18966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_disable_cam_entry_table(struct net_device *ndev,
18996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					      int entry)
19006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
19036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int ret;
19046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 blank[ETH_ALEN];
19056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) &
19076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			 ~(1 << (31 - entry)), TSU_TEN);
19086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	memset(blank, 0, sizeof(blank));
19106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ret = sh_eth_tsu_write_entry(ndev, reg_offset + entry * 8, blank);
19116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (ret < 0)
19126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return ret;
19136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_add_entry(struct net_device *ndev, const u8 *addr)
19176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
19206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
19216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!mdp->cd->tsu)
19236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
19246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	i = sh_eth_tsu_find_entry(ndev, addr);
19266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (i < 0) {
19276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* No entry found, create one */
19286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		i = sh_eth_tsu_find_empty(ndev);
19296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (i < 0)
19306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return -ENOMEM;
19316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_write_entry(ndev, reg_offset + i * 8, addr);
19326743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
19336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
19346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Enable the entry */
19366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) |
19376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				 (1 << (31 - i)), TSU_TEN);
19386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* Entry found or created, enable POST */
19416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_tsu_enable_cam_entry_post(ndev, i);
19426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_del_entry(struct net_device *ndev, const u8 *addr)
19476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
19506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!mdp->cd->tsu)
19526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
19536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	i = sh_eth_tsu_find_entry(ndev, addr);
19556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (i) {
19566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Entry found */
19576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
19586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			goto done;
19596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Disable the entry if both ports was disabled */
19616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
19626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
19636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
19646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodadone:
19666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_purge_all(struct net_device *ndev)
19706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
19736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
19756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
19766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) {
19786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
19796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			continue;
19806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Disable the entry if both ports was disabled */
19826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
19836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
19846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
19856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_purge_mcast(struct net_device *ndev)
19916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 addr[ETH_ALEN];
19946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
19956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i;
19966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
19986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return;
19996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
20016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_read_entry(reg_offset, addr);
20026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (is_multicast_ether_addr(addr))
20036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			sh_eth_tsu_del_entry(ndev, addr);
20046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
20066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
200786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Multicast reception directions set */
200886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_set_multicast_list(struct net_device *ndev)
200986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
20106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
20116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 ecmr_bits;
20126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int mcast_all = 0;
20136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	unsigned long flags;
20146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	spin_lock_irqsave(&mdp->lock, flags);
20166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/*
20176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 * Initial condition is MCT = 1, PRM = 0.
20186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 * Depending on ndev->flags, set PRM or clear MCT
20196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 */
20206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
20216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!(ndev->flags & IFF_MULTICAST)) {
20236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_mcast(ndev);
20246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mcast_all = 1;
20256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (ndev->flags & IFF_ALLMULTI) {
20276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_mcast(ndev);
20286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits &= ~ECMR_MCT;
20296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mcast_all = 1;
20306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
203286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev->flags & IFF_PROMISC) {
20336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_all(ndev);
20346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits = (ecmr_bits & ~ECMR_MCT) | ECMR_PRM;
20356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	} else if (mdp->cd->tsu) {
20366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		struct netdev_hw_addr *ha;
20376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		netdev_for_each_mc_addr(ha, ndev) {
20386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			if (mcast_all && is_multicast_ether_addr(ha->addr))
20396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				continue;
20406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			if (sh_eth_tsu_add_entry(ndev, ha->addr) < 0) {
20426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				if (!mcast_all) {
20436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					sh_eth_tsu_purge_mcast(ndev);
20446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					ecmr_bits &= ~ECMR_MCT;
20456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					mcast_all = 1;
20466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				}
20476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			}
20486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		}
204986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else {
205086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Normal, unicast/broadcast-only mode. */
20516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits = (ecmr_bits & ~ECMR_PRM) | ECMR_MCT;
205286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
20536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* update the ethernet mode */
20556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_write(ndev, ecmr_bits, ECMR);
20566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	spin_unlock_irqrestore(&mdp->lock, flags);
205886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
205971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
206071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
206171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
206271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!mdp->port)
206371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return TSU_VTAG0;
206471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	else
206571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return TSU_VTAG1;
206671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
206771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
206871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
206971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
207071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
207171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	int vtag_reg_index = sh_eth_get_vtag_index(mdp);
207271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
207371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
207471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return -EPERM;
207571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
207671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/* No filtering if vid = 0 */
207771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!vid)
207871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
207971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
208071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	mdp->vlan_num_ids++;
208171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
208271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/*
208371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 * The controller has one VLAN tag HW filter. So, if the filter is
208471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 * already enabled, the driver disables it and the filte
208571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 */
208671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (mdp->vlan_num_ids > 1) {
208771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		/* disable VLAN filter */
208871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, vtag_reg_index);
208971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
209071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	}
209171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
209271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_VTAG_ENABLE | (vid & TSU_VTAG_VID_MASK),
209371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda			 vtag_reg_index);
209471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
209571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	return 0;
209671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
209771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
209871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
209971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
210071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
210171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	int vtag_reg_index = sh_eth_get_vtag_index(mdp);
210271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
210371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
210471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return -EPERM;
210571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
210671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/* No filtering if vid = 0 */
210771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!vid)
210871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
210971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
211071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	mdp->vlan_num_ids--;
211171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, vtag_reg_index);
211271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
211371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	return 0;
211471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
21154986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda#endif /* SH_ETH_HAS_TSU */
211686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
211786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* SuperH's TSU register init function */
21184a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_tsu_init(struct sh_eth_private *mdp)
211986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
21204a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
21214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
21224a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
21234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL0);
21244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL1);
21254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL0);
21264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL1);
21274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL0);
21284a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL1);
21294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, TSU_FWSLC);
2130c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
2131c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG0);	/* Disable QTAG(0->1) */
2132c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG1);	/* Disable QTAG(1->0) */
2133c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
2134c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM0);	/* Disable QTAG(0->1) */
2135c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM1);	/* Disable QTAG(1->0) */
2136c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
21374a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSR);	/* all interrupt status clear */
21384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWINMK);	/* Disable all interrupt */
21394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_TEN);	/* Disable all CAM entry */
21404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST1);	/* Disable CAM entry [ 0- 7] */
21414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST2);	/* Disable CAM entry [ 8-15] */
21424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST3);	/* Disable CAM entry [16-23] */
21434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST4);	/* Disable CAM entry [24-31] */
214486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
214586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
214686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus release function */
214786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_mdio_release(struct net_device *ndev)
214886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
214986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
215086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
215186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* unregister mdio bus */
215286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdiobus_unregister(bus);
215386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
215486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* remove mdio bus info from net_device */
215586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, NULL);
215686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
21570f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	/* free interrupts memory */
21580f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	kfree(bus->irq);
21590f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov
216086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free bitbang info */
216186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_mdio_bitbang(bus);
216286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
216386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
216486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
216586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
216686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus init function */
2167b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimodastatic int sh_mdio_init(struct net_device *ndev, int id,
2168b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda			struct sh_eth_plat_data *pd)
216986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
217086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret, i;
217186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang;
217286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
217386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
217486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* create bit control struct for PHY */
217586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
217686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!bitbang) {
217786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
217886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
217986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
218086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
218186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* bitbang init */
2182ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
2183b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	bitbang->set_gate = pd->set_mdio_gate;
218486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdi_msk = 0x08;
218586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdo_msk = 0x04;
218686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mmd_msk = 0x02;/* MMD */
218786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdc_msk = 0x01;
218886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->ctrl.ops = &bb_ops;
218986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2190c2e07b3a9ced33dd92597201be3931be8ea57ed6Stefan Weil	/* MII controller setting */
219186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
219286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus) {
219386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
219486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bitbang;
219586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
219686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
219786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Hook up MII support for ethtool */
219886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->name = "sh_mii";
219918ee49ddb0d242ed1d0e273038d5e4f6de7379d3Lennert Buytenhek	mdp->mii_bus->parent = &ndev->dev;
22005278fb547076ad6768d16c8b4df45c086470c163Florian Fainelli	snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
220134aa6f1400810890636ba0b170effbfa71eacec7Nobuhiro Iwamatsu		mdp->pdev->name, id);
220286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
220386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY IRQ */
220486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
220586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus->irq) {
220686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
220786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bus;
220886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
220986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
221086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < PHY_MAX_ADDR; i++)
221186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->irq[i] = PHY_POLL;
221286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
221386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* regist mdio bus */
221486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = mdiobus_register(mdp->mii_bus);
221586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
221686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
221786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
221886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, mdp->mii_bus);
221986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
222086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
222186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
222286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
222386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->mii_bus->irq);
222486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
222586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bus:
2226298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek	free_mdio_bitbang(mdp->mii_bus);
222786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
222886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bitbang:
222986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(bitbang);
223086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
223186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
223286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
223386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
223486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
22354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic const u16 *sh_eth_get_register_offset(int register_type)
22364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda{
22374a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	const u16 *reg_offset = NULL;
22384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
22394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	switch (register_type) {
22404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_GIGABIT:
22414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_gigabit;
22424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH4:
22444a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh4;
22454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH3_SH2:
22474a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh3_sh2;
22484a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22494a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	default:
22504a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
22514a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
22524a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	}
22534a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
22544a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	return reg_offset;
22554a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda}
22564a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
2257ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalovstatic const struct net_device_ops sh_eth_netdev_ops = {
2258ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_open		= sh_eth_open,
2259ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_stop		= sh_eth_close,
2260ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_start_xmit		= sh_eth_start_xmit,
2261ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_get_stats		= sh_eth_get_stats,
2262380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
2263afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= sh_eth_set_multicast_list,
226471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	.ndo_vlan_rx_add_vid	= sh_eth_vlan_rx_add_vid,
226571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	.ndo_vlan_rx_kill_vid	= sh_eth_vlan_rx_kill_vid,
2266380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
2267ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_tx_timeout		= sh_eth_tx_timeout,
2268ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_do_ioctl		= sh_eth_do_ioctl,
2269ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_validate_addr	= eth_validate_addr,
2270ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_set_mac_address	= eth_mac_addr,
2271ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_change_mtu		= eth_change_mtu,
2272ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov};
2273ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov
227486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_probe(struct platform_device *pdev)
227586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
22769c38657cfcb739b7dc4ce9065a85b4f0c195bef8Kuninori Morimoto	int ret, devno = 0;
227786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct resource *res;
227886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = NULL;
2279ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	struct sh_eth_private *mdp = NULL;
228071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	struct sh_eth_plat_data *pd;
228186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
228286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get base addr */
228386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
228486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (unlikely(res == NULL)) {
228586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&pdev->dev, "invalid resource\n");
228686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -EINVAL;
228786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
228886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
228986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
229086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev = alloc_etherdev(sizeof(struct sh_eth_private));
229186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!ndev) {
229286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
229386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
229486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
229586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
229686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* The sh Ether-specific entries in the device structure. */
229786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->base_addr = res->start;
229886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	devno = pdev->id;
229986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (devno < 0)
230086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		devno = 0;
230186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
230286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->dma = -1;
2303cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ret = platform_get_irq(pdev, 0);
2304cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	if (ret < 0) {
230586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENODEV;
230686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
230786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
2308cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ndev->irq = ret;
230986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	SET_NETDEV_DEV(ndev, &pdev->dev);
231186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Fill in the fields of the device structure with ethernet values. */
231386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ether_setup(ndev);
231486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp = netdev_priv(ndev);
2316ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	mdp->addr = ioremap(res->start, resource_size(res));
2317ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp->addr == NULL) {
2318ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		ret = -ENOMEM;
2319ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		dev_err(&pdev->dev, "ioremap failed.\n");
2320ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		goto out_release;
2321ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	}
2322ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda
232386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_init(&mdp->lock);
2324bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	mdp->pdev = pdev;
2325bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_enable(&pdev->dev);
2326bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_resume(&pdev->dev);
232786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
232871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
232986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get PHY ID */
233071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->phy_id = pd->phy;
2331e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda	mdp->phy_interface = pd->phy_interface;
233271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	/* EDMAC endian */
233371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->edmac_endian = pd->edmac_endian;
23344923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->no_ether_link = pd->no_ether_link;
23354923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->ether_link_active_low = pd->ether_link_active_low;
23364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);
233786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2338380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* set cpu data */
23398fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#if defined(SH_ETH_HAS_BOTH_MODULES)
23408fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdp->cd = sh_eth_get_cpu_data(mdp);
23418fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#else
2342380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdp->cd = &sh_eth_my_cpu_data;
23438fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#endif
2344380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	sh_eth_set_default_cpu_data(mdp->cd);
2345380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
234686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* set function */
2347ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	ndev->netdev_ops = &sh_eth_netdev_ops;
2348dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
234986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->watchdog_timeo = TX_TIMEOUT;
235086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2351dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* debug message level */
2352dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
235386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
235486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* read and set MAC address */
2355748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	read_mac_address(ndev, pd->mac_addr);
235686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23576ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	/* ioremap the TSU registers */
23586ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	if (mdp->cd->tsu) {
23596ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		struct resource *rtsu;
23606ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
23616ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		if (!rtsu) {
23626ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda			dev_err(&pdev->dev, "Not found TSU resource\n");
23636ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda			goto out_release;
23646ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		}
23656ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		mdp->tsu_addr = ioremap(rtsu->start,
23666ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda					resource_size(rtsu));
23676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mdp->port = devno % 2;
236871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		ndev->features = NETIF_F_HW_VLAN_FILTER;
23696ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	}
23706ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda
2371150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	/* initialize first or needed device */
2372150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	if (!devno || pd->needs_init) {
2373380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		if (mdp->cd->chip_reset)
2374380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			mdp->cd->chip_reset(ndev);
237586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23764986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		if (mdp->cd->tsu) {
23774986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			/* TSU init (Init only)*/
23784986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			sh_eth_tsu_init(mdp);
23794986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		}
238086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
238186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
238286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* network device register */
238386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = register_netdev(ndev);
238486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
238586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
238686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
238786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mdio bus init */
2388b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	ret = sh_mdio_init(ndev, pdev->id, pd);
238986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
239086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_unregister;
239186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
239225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* print device information */
23936cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
23946cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	       (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
239586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
239686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, ndev);
239786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
239886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
239986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
240086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_unregister:
240186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
240286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
240386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_release:
240486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* net_dev free */
2405ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp && mdp->addr)
2406ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iounmap(mdp->addr);
2407ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	if (mdp && mdp->tsu_addr)
24084986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		iounmap(mdp->tsu_addr);
240986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev)
241086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		free_netdev(ndev);
241186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
241286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
241386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
241486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
241586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
241686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_remove(struct platform_device *pdev)
241786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
241886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = platform_get_drvdata(pdev);
24194986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
242086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
24216ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	if (mdp->cd->tsu)
24226ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		iounmap(mdp->tsu_addr);
242386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_mdio_release(ndev);
242486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
2425bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_disable(&pdev->dev);
2426ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iounmap(mdp->addr);
242786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_netdev(ndev);
242886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, NULL);
242986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
243086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
243186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
243286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2433bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic int sh_eth_runtime_nop(struct device *dev)
2434bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm{
2435bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	/*
2436bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * Runtime PM callback shared between ->runtime_suspend()
2437bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * and ->runtime_resume(). Simply returns success.
2438bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 *
2439bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * This driver re-initializes all registers after
2440bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * pm_runtime_get_sync() anyway so there is no need
2441bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * to save and restore registers here.
2442bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 */
2443bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	return 0;
2444bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm}
2445bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
2446bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic struct dev_pm_ops sh_eth_dev_pm_ops = {
2447bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_suspend = sh_eth_runtime_nop,
2448bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_resume = sh_eth_runtime_nop,
2449bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm};
2450bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
245186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct platform_driver sh_eth_driver = {
245286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.probe = sh_eth_drv_probe,
245386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.remove = sh_eth_drv_remove,
245486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.driver = {
245586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		   .name = CARDNAME,
2456bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm		   .pm = &sh_eth_dev_pm_ops,
245786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	},
245886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
245986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2460db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(sh_eth_driver);
246186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
246286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_AUTHOR("Nobuhiro Iwamatsu, Yoshihiro Shimoda");
246386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_DESCRIPTION("Renesas SuperH Ethernet driver");
246486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_LICENSE("GPL v2");
2465