sh_eth.c revision 3893b27345ac0ff13c1b9ec20ad50966b810997e
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 */
81d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779)
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);
96d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy	unsigned int bits = ECMR_RTM;
97d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy
98d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy#if defined(CONFIG_ARCH_R8A7779)
99d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy	bits |= ECMR_ELB;
100d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy#endif
10165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
10265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	switch (mdp->speed) {
10365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 10: /* 10BASE */
104d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR);
10565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
10665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 100:/* 100BASE */
107d0418bb7123f44b23d69ac349eec7daf9103472fPhil Edworthy		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR);
10865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
10965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	default:
11065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
11165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	}
11265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
11365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
11465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda/* SH7724 */
11565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
11665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
11765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
11865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
11965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
12065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
12165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f,
12265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
12365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
12465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
12565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
12665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
12765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
12865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.apr		= 1,
12965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.mpr		= 1,
13065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tpauser	= 1,
13165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.hw_swap	= 1,
132503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir		= 1,
133503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
13465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda};
135f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
1368fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_BOTH_MODULES	1
1378fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
1385cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev);
1395cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
140f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
141f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
142f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
143f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
144f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	if (mdp->duplex) /* Full */
1454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
146f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	else		/* Half */
1474a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
148f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
149f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
150f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
151f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
152f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
153f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
154f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	switch (mdp->speed) {
155f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 10: /* 10BASE */
1564a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, RTRATE);
157f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
158f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 100:/* 100BASE */
1594a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 1, RTRATE);
160f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
161f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	default:
162f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
163f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	}
164f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
165f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
166f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda/* SH7757 */
167f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
168f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_duplex		= sh_eth_set_duplex,
169f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_rate		= sh_eth_set_rate,
170f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
171f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
172f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.rmcr_value	= 0x00000001,
173f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
174f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
175f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
176f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
177f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
178f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
179f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.apr		= 1,
180f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.mpr		= 1,
181f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tpauser	= 1,
182f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.hw_swap	= 1,
183f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.no_ade		= 1,
1842e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir		= 1,
1852e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir_value   = 2 << 16,
186f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda};
18765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
1888fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_GIGA_ETH_BASE	0xfee00000
1898fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
1908fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
1918fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_chip_reset_giga(struct net_device *ndev)
1928fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
1938fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	int i;
1948fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	unsigned long mahr[2], malr[2];
1958fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1968fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* save MAHR and MALR */
1978fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
198ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		malr[i] = ioread32((void *)GIGA_MALR(i));
199ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		mahr[i] = ioread32((void *)GIGA_MAHR(i));
2008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2018fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* reset device */
203ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ARSTR_ARSTR, (void *)(SH_GIGA_ETH_BASE + 0x1800));
2048fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdelay(1);
2058fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2068fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* restore MAHR and MALR */
2078fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
208ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(malr[i], (void *)GIGA_MALR(i));
209ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(mahr[i], (void *)GIGA_MAHR(i));
2108fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2118fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2128fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2138fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp);
2145cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_reset(struct net_device *ndev)
2158fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2168fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2175cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
2188fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2198fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
2208fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x03, EDSR);
2218fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
2228fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2235cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
2245cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		ret = sh_eth_check_reset(ndev);
2255cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		if (ret)
2265cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu			goto out;
2278fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2288fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		/* Table Init */
2298fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDLAR);
2308fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFAR);
2318fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFXR);
2328fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFFR);
2338fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDLAR);
2348fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFAR);
2358fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFXR);
2368fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFFR);
2378fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	} else {
2388fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
2398fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2408fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		mdelay(3);
2418fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
2428fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2438fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2445cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
2455cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
2465cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
2478fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2488fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2498fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_duplex_giga(struct net_device *ndev)
2508fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2518fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2528fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2538fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (mdp->duplex) /* Full */
2548fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
2558fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else		/* Half */
2568fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
2578fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2588fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2598fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_rate_giga(struct net_device *ndev)
2608fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2618fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2628fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2638fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	switch (mdp->speed) {
2648fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 10: /* 10BASE */
2658fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000000, GECMR);
2668fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2678fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 100:/* 100BASE */
2688fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000010, GECMR);
2698fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2708fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 1000: /* 1000BASE */
2718fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000020, GECMR);
2728fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2738fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	default:
2748fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2758fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2768fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2778fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2788fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda/* SH7757(GETHERC) */
2798fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
2808fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset_giga,
2818fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex_giga,
2828fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_rate	= sh_eth_set_rate_giga,
2838fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2848fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
2858fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
2868fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
2878fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2888fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
2898fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
2908fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
2918fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_ECI,
2928fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
2938fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_TFE,
2948fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.fdr_value	= 0x0000072f,
2958fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rmcr_value	= 0x00000001,
2968fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2978fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.apr		= 1,
2988fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.mpr		= 1,
2998fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tpauser	= 1,
3008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.bculr		= 1,
3018fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.hw_swap	= 1,
3028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir		= 1,
3038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir_value   = 2 << 16,
3048fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_trimd	= 1,
3058fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_ade		= 1,
3063acbc9715a5ac8a2534a69eb3488b63b7c9fb1e2Yoshihiro Shimoda	.tsu		= 1,
3078fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda};
3088fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
3098fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
3108fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
3118fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp))
3128fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data_giga;
3138fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else
3148fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data;
3158fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
3168fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
317f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
318380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
3195cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev);
320f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsustatic void sh_eth_reset_hw_crc(struct net_device *ndev);
3215e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
322380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
323380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
3244986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
3254986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda
326380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* reset device */
3274986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
328380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(1);
329380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
330380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
331380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
332380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
333380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
334380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
335380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->duplex) /* Full */
3364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
337380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else		/* Half */
3384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
339380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
340380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
341380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
342380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
343380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
344380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
345380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	switch (mdp->speed) {
346380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 10: /* 10BASE */
3474a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
348380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
349380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 100:/* 100BASE */
3504a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
351380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
352380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 1000: /* 1000BASE */
3534a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
354380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
355380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	default:
356380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
357380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	}
358380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
359380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
360380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* sh7763 */
361380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
362380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
363380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
364380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
365380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
366380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
367380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
368380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
369380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
370380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
371380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
372380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
373380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_ECI,
374380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
375380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_TFE,
376380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
377380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
378380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
379380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
380380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.bculr		= 1,
381380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
382380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_trimd	= 1,
383380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_ade		= 1,
3844986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
385f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#if defined(CONFIG_CPU_SUBTYPE_SH7734)
386f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	.hw_crc     = 1,
3875e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	.select_mii = 1,
388f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu#endif
389380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
390380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
3915cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_reset(struct net_device *ndev)
3925e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu{
3935cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
3945e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
3955e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, EDSR_ENALL, EDSR);
3965e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
3975cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
3985cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	ret = sh_eth_check_reset(ndev);
3995cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (ret)
4005cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		goto out;
4015e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
4025e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	/* Table Init */
4035e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDLAR);
4045e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDFAR);
4055e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDFXR);
4065e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, TDFFR);
4075e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDLAR);
4085e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDFAR);
4095e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDFXR);
4105e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_write(ndev, 0x0, RDFFR);
4115e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
4125e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	/* Reset HW CRC register */
4135e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_reset_hw_crc(ndev);
4145e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
4155e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	/* Select MII mode */
4165e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	if (sh_eth_my_cpu_data.select_mii)
4175e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu		sh_eth_select_mii(ndev);
4185cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
4195cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
4205e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu}
4215e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu
422f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsustatic void sh_eth_reset_hw_crc(struct net_device *ndev)
423f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu{
424f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu	if (sh_eth_my_cpu_data.hw_crc)
425f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu		sh_eth_write(ndev, 0x0, CSMR);
426f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu}
427f0e81fecd4f83de7854262c8a6b3af19dfa99bf9Nobuhiro Iwamatsu
42873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#elif defined(CONFIG_ARCH_R8A7740)
42973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
4305cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev);
4315cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
43273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
43373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
43473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
43573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
43673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	/* reset device */
43773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
43873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	mdelay(1);
43973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
4405e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	sh_eth_select_mii(ndev);
44173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
44273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
4435cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_reset(struct net_device *ndev)
44473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
4455cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
44673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
44773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, EDSR_ENALL, EDSR);
44873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
4495cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
4505cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	ret = sh_eth_check_reset(ndev);
4515cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (ret)
4525cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		goto out;
45373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
45473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	/* Table Init */
45573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDLAR);
45673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFAR);
45773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFXR);
45873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFFR);
45973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDLAR);
46073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFAR);
46173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFXR);
46273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFFR);
4635cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
4645cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
4655cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
46673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
46773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
46873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
46973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
47073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
47173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
47273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	if (mdp->duplex) /* Full */
47373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
47473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	else		/* Half */
47573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
47673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
47773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
47873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
47973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda{
48073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
48173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
48273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	switch (mdp->speed) {
48373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 10: /* 10BASE */
48473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
48573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
48673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 100:/* 100BASE */
48773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
48873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
48973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	case 1000: /* 1000BASE */
49073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
49173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
49273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	default:
49373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		break;
49473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	}
49573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda}
49673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
49773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda/* R8A7740 */
49873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
49973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
50073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
50173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
50273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
50373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
50473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
50573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
50673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
50773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
50873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
50973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
51073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_ECI,
51173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
51273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda			  EESR_TFE,
51373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
51473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.apr		= 1,
51573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.mpr		= 1,
51673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tpauser	= 1,
51773a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.bculr		= 1,
51873a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.hw_swap	= 1,
51973a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.no_trimd	= 1,
52073a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.no_ade		= 1,
52173a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda	.tsu		= 1,
5225e7a76be0e48217aff6b6f34bdcce4725db999e2Nobuhiro Iwamatsu	.select_mii	= 1,
52373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda};
52473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
525380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
526380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
527380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
528380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
529380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
530380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
531380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
532380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
533380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
534380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
535380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
536380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
537380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
538380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
539380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
5404986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
541380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
542380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
543380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
544380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
545380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
546380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsr_value)
547380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsr_value = DEFAULT_ECSR_INIT;
548380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
549380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsipr_value)
550380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
551380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
552380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fcftr_value)
553380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
554380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				  DEFAULT_FIFO_F_D_RFD;
555380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
556380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fdr_value)
557380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fdr_value = DEFAULT_FDR_INIT;
558380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
559380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->rmcr_value)
560380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->rmcr_value = DEFAULT_RMCR_VALUE;
561380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
562380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_check)
563380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_check = DEFAULT_TX_CHECK;
564380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
565380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->eesr_err_check)
566380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK;
567380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
568380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_error_check)
569380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_error_check = DEFAULT_TX_ERROR_CHECK;
570380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
571380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
572380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_RESET_DEFAULT)
573380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* Chip Reset */
5745cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int  sh_eth_reset(struct net_device *ndev)
575380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
576c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
577380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(3);
578c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
5795cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
5805cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return 0;
5815cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu}
5825cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu#else
5835cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsustatic int sh_eth_check_reset(struct net_device *ndev)
5845cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu{
5855cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int ret = 0;
5865cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	int cnt = 100;
5875cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu
5885cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	while (cnt > 0) {
5895cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		if (!(sh_eth_read(ndev, EDMR) & 0x3))
5905cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu			break;
5915cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		mdelay(1);
5925cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		cnt--;
5935cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	}
5945cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (cnt < 0) {
5955cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		printk(KERN_ERR "Device reset fail\n");
5965cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		ret = -ETIMEDOUT;
5975cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	}
5985cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	return ret;
599380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
600380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
601380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
60273a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
603380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
604380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
605380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	int reserve;
606380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
607380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
608380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (reserve)
609380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		skb_reserve(skb, reserve);
610380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
611380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#else
612380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
613380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
614380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
615380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
616380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
617380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
618380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
61971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato/* CPU <-> EDMAC endian convert */
62071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
62171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
62271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
62371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
62471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_le32(x);
62571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
62671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_be32(x);
62771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
62871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
62971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
63071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
63171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
63271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
63371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
63471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
63571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return le32_to_cpu(x);
63671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
63771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return be32_to_cpu(x);
63871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
63971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
64071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
64171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
64286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
64386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Program the hardware MAC address from dev->dev_addr.
64486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
64586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void update_mac_address(struct net_device *ndev)
64686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
6474a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
6484a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
6494a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
6504a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
6514a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
65286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
65386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
65486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
65586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Get MAC address from SuperH MAC address register
65686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
65786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
65886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
65986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * When you want use this device, you must set MAC address in bootloader.
66086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
66186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
662748031f9fd2c06b28817d80761a5de97190cfd03Magnus Dammstatic void read_mac_address(struct net_device *ndev, unsigned char *mac)
66386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
664748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
665748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm		memcpy(ndev->dev_addr, mac, 6);
666748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	} else {
6674a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
6684a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
6694a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
6704a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
6714a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
6724a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
673748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	}
67486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
67586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
676c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp)
677c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
678c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (mdp->reg_offset == sh_eth_offset_gigabit)
679c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 1;
680c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
681c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 0;
682c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
683c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
684c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
685c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
686c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp))
687c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_GETHER;
688c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
689c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_ETHER;
690c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
691c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
69286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustruct bb_info {
693ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void (*set_gate)(void *addr);
69486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mdiobb_ctrl ctrl;
695ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void *addr;
69686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mmd_msk;/* MMD */
69786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdo_msk;
69886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdi_msk;
69986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdc_msk;
70086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
70186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit set */
703ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_set(void *addr, u32 msk)
70486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
705ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ioread32(addr) | msk, addr);
70686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
70786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit clear */
709ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_clr(void *addr, u32 msk)
71086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
711ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32((ioread32(addr) & ~msk), addr);
71286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
71386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
71486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit read */
715ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic int bb_read(void *addr, u32 msk)
71686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
717ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	return (ioread32(addr) & msk) != 0;
71886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
71986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
72086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Data I/O pin control */
72186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
72286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
72386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
724b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
725b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
726b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
727b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
72886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
72986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mmd_msk);
73086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
73186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mmd_msk);
73286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
73386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
73486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Set bit data*/
73586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
73686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
73786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
73886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
739b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
740b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
741b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
74286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
74386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdo_msk);
74486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
74586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdo_msk);
74686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
74786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
74886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get bit data*/
74986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_get_mdio(struct mdiobb_ctrl *ctrl)
75086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
75186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
752b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
753b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
754b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
755b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
75686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return bb_read(bitbang->addr, bitbang->mdi_msk);
75786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
75886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
75986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDC pin control */
76086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
76186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
76286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
76386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
764b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
765b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
766b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
76786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
76886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdc_msk);
76986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
77086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdc_msk);
77186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
77286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* mdio bus control struct */
77486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct mdiobb_ops bb_ops = {
77586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.owner = THIS_MODULE,
77686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdc = sh_mdc_ctrl,
77786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_dir = sh_mmd_ctrl,
77886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_data = sh_set_mdio,
77986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.get_mdio_data = sh_get_mdio,
78086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
78186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
78286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free skb and descriptor buffer */
78386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_free(struct net_device *ndev)
78486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
78586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
78686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
78786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
78886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx skb ringbuffer */
78986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->rx_skbuff) {
790525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		for (i = 0; i < mdp->num_rx_ring; i++) {
79186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->rx_skbuff[i])
79286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->rx_skbuff[i]);
79386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
79486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
79586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->rx_skbuff);
79691c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->rx_skbuff = NULL;
79786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
79886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Tx skb ringbuffer */
79986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->tx_skbuff) {
800525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		for (i = 0; i < mdp->num_tx_ring; i++) {
80186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->tx_skbuff[i])
80286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->tx_skbuff[i]);
80386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
80486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
80586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->tx_skbuff);
80691c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->tx_skbuff = NULL;
80786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
80886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* format skb and descriptor buffer */
81086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_format(struct net_device *ndev)
81186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
81286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
81386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
81486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
81586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc = NULL;
81686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc = NULL;
817525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
818525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
81986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_rx = mdp->cur_tx = 0;
82186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = mdp->dirty_tx = 0;
82286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->rx_ring, 0, rx_ringsize);
82486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Rx ring buffer */
826525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	for (i = 0; i < mdp->num_rx_ring; i++) {
82786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* skb */
82886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
829dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi		skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
83086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = skb;
83186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (skb == NULL)
83286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
833bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
834e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda				DMA_FROM_DEVICE);
835380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_set_receive_align(skb);
836380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
83786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* RX descriptor */
83886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
8390029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
84071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
84186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
84286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
8430029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
844b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* Rx descriptor address set */
845b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
8464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
847c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
848c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
849b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
85086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
85186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
852525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	mdp->dirty_rx = (u32) (i - mdp->num_rx_ring);
85386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Mark the last entry as wrapping the ring. */
85571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
85686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->tx_ring, 0, tx_ringsize);
85886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Tx ring buffer */
860525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	for (i = 0; i < mdp->num_tx_ring; i++) {
86186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
86286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[i];
86371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
86486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = 0;
865b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
86671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			/* Tx descriptor address set */
8674a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
868c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
869c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
870b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
87186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
87286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
87371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
87486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
87586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
87686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get skb and descriptor buffer */
87786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_ring_init(struct net_device *ndev)
87886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
87986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
88086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize, tx_ringsize, ret = 0;
88186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
88286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/*
88386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
88486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card needs room to do 8 byte alignment, +2 so we can reserve
88586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * the first 2 bytes, and +16 gets room for the status word from the
88686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card.
88786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 */
88886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ :
88986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			  (((ndev->mtu + 26 + 7) & ~7) + 2 + 16));
890503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	if (mdp->cd->rpadir)
891503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm		mdp->rx_buf_sz += NET_IP_ALIGN;
89286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate RX and TX skb rings */
894b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches	mdp->rx_skbuff = kmalloc_array(mdp->num_rx_ring,
895b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches				       sizeof(*mdp->rx_skbuff), GFP_KERNEL);
89686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_skbuff) {
89786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
89886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
89986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
90086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
901b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches	mdp->tx_skbuff = kmalloc_array(mdp->num_tx_ring,
902b2adaca92c63b9bb8beb021d554f656e387a7648Joe Perches				       sizeof(*mdp->tx_skbuff), GFP_KERNEL);
90386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_skbuff) {
90486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
90586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto skb_ring_free;
90686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
90786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
90886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Rx descriptors. */
909525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
91086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
91186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
91286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_ring) {
914380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
915380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			rx_ringsize);
91686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
91786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
91886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
91986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
92086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = 0;
92186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
92286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Tx descriptors. */
923525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
92486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
92586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
92686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_ring) {
927380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
928380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			tx_ringsize);
92986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
93086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
93186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
93286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
93386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
93486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsudesc_ring_free:
93586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
93686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma);
93786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
93886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuskb_ring_free:
93986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx and Tx skb ring buffer */
94086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
94191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->tx_ring = NULL;
94291c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	mdp->rx_ring = NULL;
94386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
94486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
94586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
94686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
94791c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimodastatic void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
94891c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda{
94991c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	int ringsize;
95091c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda
95191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	if (mdp->rx_ring) {
952525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
95391c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		dma_free_coherent(NULL, ringsize, mdp->rx_ring,
95491c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda				  mdp->rx_desc_dma);
95591c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		mdp->rx_ring = NULL;
95691c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	}
95791c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda
95891c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	if (mdp->tx_ring) {
959525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
96091c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		dma_free_coherent(NULL, ringsize, mdp->tx_ring,
96191c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda				  mdp->tx_desc_dma);
96291c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda		mdp->tx_ring = NULL;
96391c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	}
96491c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda}
96591c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda
966525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimodastatic int sh_eth_dev_init(struct net_device *ndev, bool start)
96786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
96886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
96986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
97086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 val;
97186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
97286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Soft Reset */
9735cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	ret = sh_eth_reset(ndev);
9745cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu	if (ret)
9755cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsu		goto out;
97686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
977b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Descriptor format */
978b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	sh_eth_ring_format(ndev);
979380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->rpadir)
9804a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR);
98186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
98286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* all sh_eth int mask */
9834a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EESIPR);
98486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
98510b9194f959608368ed89df1937f17cfe6bd6d84Yoshihiro Shimoda#if defined(__LITTLE_ENDIAN)
986380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->hw_swap)
9874a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDMR_EL, EDMR);
988380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else
989b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu#endif
9904a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, EDMR);
99186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
992b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* FIFO size set */
9934a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
9944a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TFTR);
99586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
996b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Frame recv control */
9974a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
99886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
9992ecbb783c3bf5a63f555c39deef308dcc1902b7fYoshihiro Shimoda	sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER);
100086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1001380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->bculr)
10024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */
1003b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
10044a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fcftr_value, FCFTR);
100586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1006380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->no_trimd)
10074a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, TRIMD);
100886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1009b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Recv frame limit set register */
1010fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda	sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
1011fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda		     RFLR);
101286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
1014525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (start)
1015525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
101686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
101786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PAUSE Prohibition */
10184a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
101986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
102086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, val, ECMR);
1022b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
1023380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->set_rate)
1024380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mdp->cd->set_rate(ndev);
1025380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1026b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Status Register clear */
10274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
1028b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
1029b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Interrupt Enable register */
1030525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (start)
1031525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
103286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
103386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Set MAC address */
103486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	update_mac_address(ndev);
103586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
103686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mask reset */
1037380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->apr)
10384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, APR_AP, APR);
1039380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->mpr)
10404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, MPR_MP, MPR);
1041380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->tpauser)
10424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
1043b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
1044525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (start) {
1045525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		/* Setting the Rx mode will start the Rx process. */
1046525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, EDRRR_R, EDRRR);
104786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1048525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		netif_start_queue(ndev);
1049525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	}
105086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10515cee1d37c9f565f1aa515408863dbb13db67dab9Nobuhiro Iwamatsuout:
105286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
105386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
105486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
105586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free Tx skb function */
105686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_txfree(struct net_device *ndev)
105786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
105886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
105986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
106086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int freeNum = 0;
106186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = 0;
106286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
106386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
1064525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		entry = mdp->dirty_tx % mdp->num_tx_ring;
106586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[entry];
106671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
106786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
106886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Free the original skb. */
106986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[entry]) {
107031fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda			dma_unmap_single(&ndev->dev, txdesc->addr,
107131fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda					 txdesc->buffer_length, DMA_TO_DEVICE);
107286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
107386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->tx_skbuff[entry] = NULL;
107486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			freeNum++;
107586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
107671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
1077525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		if (entry >= mdp->num_tx_ring - 1)
107871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
107986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1080bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_packets++;
1081bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_bytes += txdesc->buffer_length;
108286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
108386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return freeNum;
108486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
108586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
108686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet receive function */
1087a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimodastatic int sh_eth_rx(struct net_device *ndev, u32 intr_status)
108886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
108986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
109086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
109186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1092525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	int entry = mdp->cur_rx % mdp->num_rx_ring;
1093525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx;
109486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
109586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u16 pkt_len = 0;
1096380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 desc_status;
109786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
109886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rxdesc = &mdp->rx_ring[entry];
109971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
110071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		desc_status = edmac_to_cpu(mdp, rxdesc->status);
110186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		pkt_len = rxdesc->frame_length;
110286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
110373a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#if defined(CONFIG_ARCH_R8A7740)
110473a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda		desc_status >>= 16;
110573a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda#endif
110673a0d907301ece200d32b4e8ba2da2ca296b507fYoshihiro Shimoda
110786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (--boguscnt < 0)
110886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
110986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
111086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!(desc_status & RDFEND))
1111bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_length_errors++;
111286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
111386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
111486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
1115bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_errors++;
111686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS1)
1117bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_crc_errors++;
111886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS2)
1119bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_frame_errors++;
112086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS3)
1121bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
112286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS4)
1123bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
112486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS6)
1125bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_missed_errors++;
112686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS10)
1127bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_over_errors++;
112886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		} else {
1129380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (!mdp->cd->hw_swap)
1130380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				sh_eth_soft_swap(
1131380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					phys_to_virt(ALIGN(rxdesc->addr, 4)),
1132380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					pkt_len + 2);
113386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb = mdp->rx_skbuff[entry];
113486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = NULL;
1135503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm			if (mdp->cd->rpadir)
1136503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm				skb_reserve(skb, NET_IP_ALIGN);
113786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb_put(skb, pkt_len);
113886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb->protocol = eth_type_trans(skb, ndev);
113986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_rx(skb);
1140bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_packets++;
1141bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_bytes += pkt_len;
114286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
114371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
1144525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		entry = (++mdp->cur_rx) % mdp->num_rx_ring;
1145862df49750e7ca9369c04d8d8105b3cc5d976e0dYoshihiro Shimoda		rxdesc = &mdp->rx_ring[entry];
114686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
114786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
114886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Refill the Rx ring buffers. */
114986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
1150525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		entry = mdp->dirty_rx % mdp->num_rx_ring;
115186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[entry];
1152b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
11530029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
1154b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
115586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[entry] == NULL) {
1156dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi			skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
115786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = skb;
115886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (skb == NULL)
115986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				break;	/* Better luck next round. */
1160bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
1161e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda					DMA_FROM_DEVICE);
1162380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			sh_eth_set_receive_align(skb);
1163380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1164bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet			skb_checksum_none_assert(skb);
11650029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda			rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
116686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
1167525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		if (entry >= mdp->num_rx_ring - 1)
116886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
116971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
117086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		else
117186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
117271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
117386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
117486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
117586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Restart Rx engine if stopped. */
117686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* If we don't need to check status, don't. -KDU */
117779fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
1178a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda		/* fix the values for the next receiving if RDE is set */
1179a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda		if (intr_status & EESR_RDE)
1180a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda			mdp->cur_rx = mdp->dirty_rx =
1181a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda				(sh_eth_read(ndev, RDFAR) -
1182a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda				 sh_eth_read(ndev, RDLAR)) >> 4;
11834a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDRRR_R, EDRRR);
118479fba9f51755c704c0a7d7b7f0df10874dc0a744Yoshihiro Shimoda	}
118586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
118686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
118786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
118886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
11894a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_disable(struct net_device *ndev)
1190dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1191dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable 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
11964a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_enable(struct net_device *ndev)
1197dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1198dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
11994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
12004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ECMR_RE | ECMR_TE), ECMR);
1201dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1202dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
120386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* error control function */
120486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_error(struct net_device *ndev, int intr_status)
120586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
120686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
120786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 felic_stat;
1208380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 link_stat;
1209380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 mask;
121086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
121186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_ECI) {
12124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		felic_stat = sh_eth_read(ndev, ECSR);
12134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, felic_stat, ECSR);	/* clear int */
121486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_ICD)
1215bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_carrier_errors++;
121686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_LCHNG) {
121786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Link Changed */
12184923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda			if (mdp->cd->no_psr || mdp->no_ether_link) {
12191e1b812bbe1069fc8e2e372dca7d5f541c7a8cebSergei Shtylyov				goto ignore_link;
1220380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			} else {
12214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				link_stat = (sh_eth_read(ndev, PSR));
12224923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda				if (mdp->ether_link_active_low)
12234923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda					link_stat = ~link_stat;
1224380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			}
1225dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (!(link_stat & PHY_ST_LINK))
12264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_disable(ndev);
1227dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			else {
122886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* Link Up */
12294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
12304a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ~DMAC_M_ECI, EESIPR);
123186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/*clear int */
12324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
12334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ECSR);
12344a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
12354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  DMAC_M_ECI, EESIPR);
123686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* enable tx and rx */
12374a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_enable(ndev);
123886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			}
123986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
124086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
124186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
12421e1b812bbe1069fc8e2e372dca7d5f541c7a8cebSergei Shtylyovignore_link:
124386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_TWB) {
124486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Write buck end. unused write back interrupt */
124586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_TABT)	/* Transmit Abort int */
1246bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_aborted_errors++;
1247dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_err(mdp))
1248dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Transmit Abort\n");
124986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
125086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
125186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RABT) {
125286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Abort int */
125386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_RFRMER) {
125486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Receive Frame Overflow int */
1255bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_frame_errors++;
1256dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_rx_err(mdp))
1257dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Receive Abort\n");
125886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
125986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1260380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1261dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TDE) {
1262dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Transmit Descriptor Empty int */
1263bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1264dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1265dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
1266dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1267dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1268dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TFE) {
1269dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* FIFO under flow */
1270bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1271dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1272dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
127386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
127486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
127586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RDE) {
127686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Descriptor Empty int */
1277bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_over_errors++;
127886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1279dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1280dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive Descriptor Empty\n");
128186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1282dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
128386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RFE) {
128486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive FIFO Overflow int */
1285bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_fifo_errors++;
1286dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1287dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive FIFO Overflow\n");
1288dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1289dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1290dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
1291dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Address Error */
1292bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1293dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1294dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Address Error\n");
129586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1296380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1297380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
1298380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->no_ade)
1299380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mask &= ~EESR_ADE;
1300380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & mask) {
130186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Tx error */
13024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		u32 edtrr = sh_eth_read(ndev, EDTRR);
130386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dmesg */
1304380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
1305380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				intr_status, mdp->cur_tx);
1306380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
130786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				mdp->dirty_tx, (u32) ndev->state, edtrr);
130886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dirty buffer free */
130986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
131086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
131186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* SH7712 BUG */
1312c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
131386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* tx dma start */
1314c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
131586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
131686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* wakeup */
131786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
131886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
131986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
132086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
132186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic irqreturn_t sh_eth_interrupt(int irq, void *netdev)
132286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
132386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = netdev;
132486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1325380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_cpu_data *cd = mdp->cd;
13260e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	irqreturn_t ret = IRQ_NONE;
13273893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	unsigned long intr_status;
132886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
132986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock(&mdp->lock);
133086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
13313893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	/* Get interrupt status */
13324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	intr_status = sh_eth_read(ndev, EESR);
13333893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	/* Mask it with the interrupt mask, forcing ECI interrupt to be always
13343893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	 * enabled since it's the one that  comes thru regardless of the mask,
13353893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	 * and we need to fully handle it in sh_eth_error() in order to quench
13363893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	 * it as it doesn't get cleared by just writing 1 to the ECI bit...
13373893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	 */
13383893b27345ac0ff13c1b9ec20ad50966b810997eSergei Shtylyov	intr_status &= sh_eth_read(ndev, EESIPR) | DMAC_M_ECI;
133986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Clear interrupt */
13400e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
13410e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
1342380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			cd->tx_check | cd->eesr_err_check)) {
13434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, intr_status, EESR);
13440e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		ret = IRQ_HANDLED;
13450e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	} else
13460e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		goto other_irq;
134786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1348b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	if (intr_status & (EESR_FRC | /* Frame recv*/
1349b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RMAF | /* Multi cast address recv*/
1350b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RRF  | /* Bit frame recv */
1351b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTLF | /* Long frame recv*/
1352b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTSF | /* short frame recv */
1353b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_PRE  | /* PHY-LSI recv error */
1354b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_CERF)){ /* recv frame CRC error */
1355a18e08bdcf845efb7344cea146e683df746bbfb4Yoshihiro Shimoda		sh_eth_rx(ndev, intr_status);
1356b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	}
135786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1358b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Tx Check */
1359380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->tx_check) {
136086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
136186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
136286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
136386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1364380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->eesr_err_check)
136586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_error(ndev, intr_status);
136686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
13670e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsuother_irq:
136886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock(&mdp->lock);
136986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
13700e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	return ret;
137186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
137286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
137386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY state control function */
137486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_adjust_link(struct net_device *ndev)
137586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
137686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
137786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
137886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int new_state = 0;
137986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
138086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (phydev->link != PHY_DOWN) {
138186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->duplex != mdp->duplex) {
138286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
138386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->duplex = phydev->duplex;
1384380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_duplex)
1385380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_duplex(ndev);
138686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
138786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
138886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->speed != mdp->speed) {
138986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
139086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->speed = phydev->speed;
1391380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_rate)
1392380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_rate(ndev);
139386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
139486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->link == PHY_DOWN) {
139591a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda			sh_eth_write(ndev,
139691a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda				(sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
139786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
139886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->link = phydev->link;
13991e1b812bbe1069fc8e2e372dca7d5f541c7a8cebSergei Shtylyov			if (mdp->cd->no_psr || mdp->no_ether_link)
14001e1b812bbe1069fc8e2e372dca7d5f541c7a8cebSergei Shtylyov				sh_eth_rcv_snd_enable(ndev);
140186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
140286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else if (mdp->link) {
140386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		new_state = 1;
140486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->link = PHY_DOWN;
140586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->speed = 0;
140686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->duplex = -1;
14071e1b812bbe1069fc8e2e372dca7d5f541c7a8cebSergei Shtylyov		if (mdp->cd->no_psr || mdp->no_ether_link)
14081e1b812bbe1069fc8e2e372dca7d5f541c7a8cebSergei Shtylyov			sh_eth_rcv_snd_disable(ndev);
140986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
141086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1411dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (new_state && netif_msg_link(mdp))
141286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_print_status(phydev);
141386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
141486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
141586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY init function */
141686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_init(struct net_device *ndev)
141786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
141886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
14190a372eb91f9d507701a901c2f62ed31ca67fd66cDavid S. Miller	char phy_id[MII_BUS_ID_SIZE + 3];
142086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = NULL;
142186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1422fb28ad35906af2f042c94e2f9c0f898ef9acfa37Kay Sievers	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
142386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->id , mdp->phy_id);
142486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->link = PHY_DOWN;
142686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->speed = 0;
142786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->duplex = -1;
142886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Try connect to PHY */
1430c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
1431f9a8f83b04e0c362a2fc660dbad980d24af209fcFlorian Fainelli			     mdp->phy_interface);
143286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (IS_ERR(phydev)) {
143386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&ndev->dev, "phy_connect failed\n");
143486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return PTR_ERR(phydev);
143586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1436380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
143786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_info(&ndev->dev, "attached phy %i to driver %s\n",
1438380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		phydev->addr, phydev->drv->name);
143986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->phydev = phydev;
144186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
144386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
144486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY control start function */
144686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_start(struct net_device *ndev)
144786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
144886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
144986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret;
145086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
145186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_init(ndev);
145286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
145386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
145486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
145586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* reset phy - this also wakes it from PDOWN */
145686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
145786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_start(mdp->phydev);
145886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
145986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
146086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
146186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1462dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_settings(struct net_device *ndev,
1463dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_cmd *ecmd)
1464dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1465dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1466dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1467dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1468dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1469dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1470dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_gset(mdp->phydev, ecmd);
1471dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1472dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1473dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1474dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1475dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1476dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_set_settings(struct net_device *ndev,
1477dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		struct ethtool_cmd *ecmd)
1478dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1479dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1480dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1481dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1482dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1483dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1484dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1485dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
14864a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_disable(ndev);
1487dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1488dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_sset(mdp->phydev, ecmd);
1489dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ret)
1490dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		goto error_exit;
1491dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1492dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ecmd->duplex == DUPLEX_FULL)
1493dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 1;
1494dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	else
1495dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 0;
1496dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1497dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (mdp->cd->set_duplex)
1498dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->cd->set_duplex(ndev);
1499dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1500dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsuerror_exit:
1501dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdelay(1);
1502dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1503dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
15044a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_enable(ndev);
1505dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1506dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1507dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1508dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1509dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1510dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1511dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_nway_reset(struct net_device *ndev)
1512dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1513dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1514dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1515dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1516dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1517dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1518dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_start_aneg(mdp->phydev);
1519dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1520dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1521dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1522dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1523dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1524dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic u32 sh_eth_get_msglevel(struct net_device *ndev)
1525dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1526dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1527dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return mdp->msg_enable;
1528dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1529dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1530dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_set_msglevel(struct net_device *ndev, u32 value)
1531dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1532dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1533dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = value;
1534dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1535dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1536dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic const char sh_eth_gstrings_stats[][ETH_GSTRING_LEN] = {
1537dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_current", "tx_current",
1538dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_dirty", "tx_dirty",
1539dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1540dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#define SH_ETH_STATS_LEN  ARRAY_SIZE(sh_eth_gstrings_stats)
1541dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1542dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_sset_count(struct net_device *netdev, int sset)
1543dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1544dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (sset) {
1545dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1546dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return SH_ETH_STATS_LEN;
1547dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	default:
1548dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return -EOPNOTSUPP;
1549dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1550dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1551dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1552dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_ethtool_stats(struct net_device *ndev,
1553dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_stats *stats, u64 *data)
1554dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1555dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1556dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int i = 0;
1557dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1558dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* device-specific stats */
1559dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_rx;
1560dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_tx;
1561dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_rx;
1562dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_tx;
1563dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1564dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1565dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
1566dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1567dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (stringset) {
1568dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1569dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		memcpy(data, *sh_eth_gstrings_stats,
1570dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu					sizeof(sh_eth_gstrings_stats));
1571dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		break;
1572dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1573dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1574dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1575525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimodastatic void sh_eth_get_ringparam(struct net_device *ndev,
1576525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda				 struct ethtool_ringparam *ring)
1577525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda{
1578525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
1579525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1580525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ring->rx_max_pending = RX_RING_MAX;
1581525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ring->tx_max_pending = TX_RING_MAX;
1582525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ring->rx_pending = mdp->num_rx_ring;
1583525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ring->tx_pending = mdp->num_tx_ring;
1584525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda}
1585525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1586525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimodastatic int sh_eth_set_ringparam(struct net_device *ndev,
1587525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda				struct ethtool_ringparam *ring)
1588525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda{
1589525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
1590525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	int ret;
1591525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1592525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (ring->tx_pending > TX_RING_MAX ||
1593525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	    ring->rx_pending > RX_RING_MAX ||
1594525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	    ring->tx_pending < TX_RING_MIN ||
1595525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	    ring->rx_pending < RX_RING_MIN)
1596525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		return -EINVAL;
1597525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
1598525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		return -EINVAL;
1599525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1600525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (netif_running(ndev)) {
1601525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		netif_tx_disable(ndev);
1602525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		/* Disable interrupts by clearing the interrupt mask. */
1603525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, 0x0000, EESIPR);
1604525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		/* Stop the chip's Tx and Rx processes. */
1605525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, 0, EDTRR);
1606525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, 0, EDRRR);
1607525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		synchronize_irq(ndev->irq);
1608525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	}
1609525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1610525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	/* Free all the skbuffs in the Rx queue. */
1611525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	sh_eth_ring_free(ndev);
1612525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	/* Free DMA buffer */
1613525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	sh_eth_free_dma_buffer(mdp);
1614525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1615525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	/* Set new parameters */
1616525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	mdp->num_rx_ring = ring->rx_pending;
1617525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	mdp->num_tx_ring = ring->tx_pending;
1618525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1619525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ret = sh_eth_ring_init(ndev);
1620525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (ret < 0) {
1621525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		dev_err(&ndev->dev, "%s: sh_eth_ring_init failed.\n", __func__);
1622525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		return ret;
1623525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	}
1624525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ret = sh_eth_dev_init(ndev, false);
1625525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (ret < 0) {
1626525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		dev_err(&ndev->dev, "%s: sh_eth_dev_init failed.\n", __func__);
1627525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		return ret;
1628525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	}
1629525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1630525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (netif_running(ndev)) {
1631525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
1632525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		/* Setting the Rx mode will start the Rx process. */
1633525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		sh_eth_write(ndev, EDRRR_R, EDRRR);
1634525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda		netif_wake_queue(ndev);
1635525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	}
1636525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
1637525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	return 0;
1638525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda}
1639525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda
16409b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemmingerstatic const struct ethtool_ops sh_eth_ethtool_ops = {
1641dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_settings	= sh_eth_get_settings,
1642dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_settings	= sh_eth_set_settings,
16439b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.nway_reset	= sh_eth_nway_reset,
1644dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_msglevel	= sh_eth_get_msglevel,
1645dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_msglevel	= sh_eth_set_msglevel,
16469b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.get_link	= ethtool_op_get_link,
1647dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_strings	= sh_eth_get_strings,
1648dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_ethtool_stats  = sh_eth_get_ethtool_stats,
1649dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_sset_count     = sh_eth_get_sset_count,
1650525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	.get_ringparam	= sh_eth_get_ringparam,
1651525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	.set_ringparam	= sh_eth_set_ringparam,
1652dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1653dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
165486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* network device open function */
165586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_open(struct net_device *ndev)
165686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
165786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
165886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
165986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1660bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1661bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1662a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches	ret = request_irq(ndev->irq, sh_eth_interrupt,
1663f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
1664dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
1665dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7757)
16660e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				IRQF_SHARED,
16670e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#else
16680e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				0,
16690e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#endif
16700e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				ndev->name, ndev);
167186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret) {
1672380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Can not assign IRQ number\n");
167386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
167486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
167586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Descriptor set */
167786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_ring_init(ndev);
167886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
167986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
168086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
168186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
1682525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	ret = sh_eth_dev_init(ndev, true);
168386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
168486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
168586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
168686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY control start*/
168786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_start(ndev);
168886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
168986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
169086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
169186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
169286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
169386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
169486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
1695bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
169686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
169786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
169886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
169986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Timeout function */
170086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_tx_timeout(struct net_device *ndev)
170186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
170286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
170386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
170486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
170586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
170686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
170786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1708dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (netif_msg_timer(mdp))
1709dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
17104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	       " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
171186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
171286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* tx_errors count up */
1713bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_errors++;
171486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
171586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
1716525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	for (i = 0; i < mdp->num_rx_ring; i++) {
171786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
171886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->status = 0;
171986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->addr = 0xBADF00D0;
172086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[i])
172186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->rx_skbuff[i]);
172286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
172386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1724525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	for (i = 0; i < mdp->num_tx_ring; i++) {
172586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[i])
172686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->tx_skbuff[i]);
172786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
172886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
172986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
1731525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	sh_eth_dev_init(ndev, true);
173286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
173386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet transmit function */
173586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
173686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
173786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
173886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
173986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 entry;
1740fb5e2f9b9410a4362897d12dc1ed4f7cec1b0d45Nobuhiro Iwamatsu	unsigned long flags;
174186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
174286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1743525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) {
174486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!sh_eth_txfree(ndev)) {
1745dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_queued(mdp))
1746dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_warn(&ndev->dev, "TxFD exhausted.\n");
174786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_stop_queue(ndev);
174886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			spin_unlock_irqrestore(&mdp->lock, flags);
17495b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy			return NETDEV_TX_BUSY;
175086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
175186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
175286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
175386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1754525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	entry = mdp->cur_tx % mdp->num_tx_ring;
175586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff[entry] = skb;
175686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	txdesc = &mdp->tx_ring[entry];
175786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* soft swap. */
1758380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->hw_swap)
1759380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
1760380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				 skb->len + 2);
176131fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
176231fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda				      DMA_TO_DEVICE);
176386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (skb->len < ETHERSMALL)
176486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = ETHERSMALL;
176586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
176686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = skb->len;
176786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1768525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	if (entry >= mdp->num_tx_ring - 1)
176971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
177086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
177171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
177286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
177386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_tx++;
177486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1775c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDTRR) & sh_eth_get_edtrr_trns(mdp)))
1776c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
1777b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
17786ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
177986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
178086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
178186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* device close function */
178286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_close(struct net_device *ndev)
178386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
178486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
178586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
178686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
178786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
178886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Disable interrupts by clearing the interrupt mask. */
17894a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0000, EESIPR);
179086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
179186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Stop the chip's Tx and Rx processes. */
17924a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDTRR);
17934a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDRRR);
179486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
179586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY Disconnect */
179686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->phydev) {
179786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_stop(mdp->phydev);
179886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_disconnect(mdp->phydev);
179986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
180086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
180186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
180286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
180386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
180486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
180586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
180686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
180791c77550000a7d888aaf9f9ac13e3e3485d18560Yoshihiro Shimoda	sh_eth_free_dma_buffer(mdp);
180886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1809bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1810bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
181186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
181286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
181386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
181486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
181586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
181686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
181786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1818bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1819bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1820bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
18214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TROCR);	/* (write clear) */
1822bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.collisions += sh_eth_read(ndev, CDCR);
18234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, CDCR);	/* (write clear) */
1824bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
18254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, LCCR);	/* (write clear) */
1826c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1827bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
1828c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CERCR);	/* (write clear) */
1829bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
1830c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CEECR);	/* (write clear) */
1831c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
1832bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
1833c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CNDCR);	/* (write clear) */
1834c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
1835bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1836bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1837bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	return &ndev->stats;
183886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
183986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1840bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet/* ioctl to device function */
184186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
184286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				int cmd)
184386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
184486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
184586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
184686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
184786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!netif_running(ndev))
184886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -EINVAL;
184986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
185086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!phydev)
185186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -ENODEV;
185286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
185328b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran	return phy_mii_ioctl(phydev, rq, cmd);
185486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
185586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1856380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
18576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda/* For TSU_POSTn. Please refer to the manual about this (strange) bitfields */
18586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void *sh_eth_tsu_get_post_reg_offset(struct sh_eth_private *mdp,
18596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					    int entry)
18606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return sh_eth_tsu_get_offset(mdp, TSU_POST1) + (entry / 8 * 4);
18626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic u32 sh_eth_tsu_get_post_mask(int entry)
18656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0x0f << (28 - ((entry % 8) * 4));
18676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic u32 sh_eth_tsu_get_post_bit(struct sh_eth_private *mdp, int entry)
18706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return (0x08 >> (mdp->port << 1)) << (28 - ((entry % 8) * 4));
18726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_enable_cam_entry_post(struct net_device *ndev,
18756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					     int entry)
18766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 tmp;
18796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset;
18806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
18826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	tmp = ioread32(reg_offset);
18836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(tmp | sh_eth_tsu_get_post_bit(mdp, entry), reg_offset);
18846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
18856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic bool sh_eth_tsu_disable_cam_entry_post(struct net_device *ndev,
18876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					      int entry)
18886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
18896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
18906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 post_mask, ref_mask, tmp;
18916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset;
18926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
18946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	post_mask = sh_eth_tsu_get_post_mask(entry);
18956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ref_mask = sh_eth_tsu_get_post_bit(mdp, entry) & ~post_mask;
18966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
18976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	tmp = ioread32(reg_offset);
18986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(tmp & ~post_mask, reg_offset);
18996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* If other port enables, the function returns "true" */
19016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return tmp & ref_mask;
19026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_busy(struct net_device *ndev)
19056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int timeout = SH_ETH_TSU_TIMEOUT_MS * 100;
19076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	while ((sh_eth_tsu_read(mdp, TSU_ADSBSY) & TSU_ADSBSY_0)) {
19106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		udelay(10);
19116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		timeout--;
19126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (timeout <= 0) {
19136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			dev_err(&ndev->dev, "%s: timeout\n", __func__);
19146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return -ETIMEDOUT;
19156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		}
19166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_write_entry(struct net_device *ndev, void *reg,
19226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				  const u8 *addr)
19236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 val;
19256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
19276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(val, reg);
19286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (sh_eth_tsu_busy(ndev) < 0)
19296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return -EBUSY;
19306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = addr[4] << 8 | addr[5];
19326743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	iowrite32(val, reg + 4);
19336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (sh_eth_tsu_busy(ndev) < 0)
19346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return -EBUSY;
19356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_read_entry(void *reg, u8 *addr)
19406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 val;
19426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = ioread32(reg);
19446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[0] = (val >> 24) & 0xff;
19456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[1] = (val >> 16) & 0xff;
19466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[2] = (val >> 8) & 0xff;
19476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[3] = val & 0xff;
19486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	val = ioread32(reg + 4);
19496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[4] = (val >> 8) & 0xff;
19506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	addr[5] = val & 0xff;
19516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_find_entry(struct net_device *ndev, const u8 *addr)
19556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
19586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i;
19596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 c_addr[ETH_ALEN];
19606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
19626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_read_entry(reg_offset, c_addr);
19636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (memcmp(addr, c_addr, ETH_ALEN) == 0)
19646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return i;
19656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
19666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return -ENOENT;
19686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_find_empty(struct net_device *ndev)
19716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 blank[ETH_ALEN];
19736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int entry;
19746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	memset(blank, 0, sizeof(blank));
19766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	entry = sh_eth_tsu_find_entry(ndev, blank);
19776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return (entry < 0) ? -ENOMEM : entry;
19786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_disable_cam_entry_table(struct net_device *ndev,
19816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					      int entry)
19826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
19836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
19846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
19856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int ret;
19866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 blank[ETH_ALEN];
19876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) &
19896743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			 ~(1 << (31 - entry)), TSU_TEN);
19906743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19916743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	memset(blank, 0, sizeof(blank));
19926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ret = sh_eth_tsu_write_entry(ndev, reg_offset + entry * 8, blank);
19936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (ret < 0)
19946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return ret;
19956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
19966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
19976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
19986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_add_entry(struct net_device *ndev, const u8 *addr)
19996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
20006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
20016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
20026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
20036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!mdp->cd->tsu)
20056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
20066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	i = sh_eth_tsu_find_entry(ndev, addr);
20086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (i < 0) {
20096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* No entry found, create one */
20106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		i = sh_eth_tsu_find_empty(ndev);
20116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (i < 0)
20126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return -ENOMEM;
20136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_write_entry(ndev, reg_offset + i * 8, addr);
20146743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
20156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
20166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Enable the entry */
20186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) |
20196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				 (1 << (31 - i)), TSU_TEN);
20206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* Entry found or created, enable POST */
20236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_tsu_enable_cam_entry_post(ndev, i);
20246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
20266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
20276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_del_entry(struct net_device *ndev, const u8 *addr)
20296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
20306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
20316743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
20326743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!mdp->cd->tsu)
20346743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
20356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	i = sh_eth_tsu_find_entry(ndev, addr);
20376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (i) {
20386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Entry found */
20396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
20406743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			goto done;
20416743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20426743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Disable the entry if both ports was disabled */
20436743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
20446743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
20456743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
20466743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20476743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodadone:
20486743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
20496743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
20506743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20516743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic int sh_eth_tsu_purge_all(struct net_device *ndev)
20526743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
20536743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
20546743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i, ret;
20556743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20566743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
20576743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return 0;
20586743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20596743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) {
20606743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
20616743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			continue;
20626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20636743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		/* Disable the entry if both ports was disabled */
20646743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
20656743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (ret < 0)
20666743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			return ret;
20676743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20686743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20696743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	return 0;
20706743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
20716743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20726743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimodastatic void sh_eth_tsu_purge_mcast(struct net_device *ndev)
20736743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda{
20746743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
20756743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u8 addr[ETH_ALEN];
20766743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
20776743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int i;
20786743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20796743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
20806743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		return;
20816743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20826743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
20836743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_read_entry(reg_offset, addr);
20846743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		if (is_multicast_ether_addr(addr))
20856743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			sh_eth_tsu_del_entry(ndev, addr);
20866743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
20876743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda}
20886743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
208986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Multicast reception directions set */
209086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_set_multicast_list(struct net_device *ndev)
209186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
20926743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
20936743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	u32 ecmr_bits;
20946743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	int mcast_all = 0;
20956743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	unsigned long flags;
20966743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
20976743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	spin_lock_irqsave(&mdp->lock, flags);
20986743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/*
20996743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 * Initial condition is MCT = 1, PRM = 0.
21006743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 * Depending on ndev->flags, set PRM or clear MCT
21016743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	 */
21026743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
21036743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
21046743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (!(ndev->flags & IFF_MULTICAST)) {
21056743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_mcast(ndev);
21066743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mcast_all = 1;
21076743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
21086743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	if (ndev->flags & IFF_ALLMULTI) {
21096743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_mcast(ndev);
21106743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits &= ~ECMR_MCT;
21116743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mcast_all = 1;
21126743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	}
21136743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
211486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev->flags & IFF_PROMISC) {
21156743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		sh_eth_tsu_purge_all(ndev);
21166743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits = (ecmr_bits & ~ECMR_MCT) | ECMR_PRM;
21176743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	} else if (mdp->cd->tsu) {
21186743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		struct netdev_hw_addr *ha;
21196743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		netdev_for_each_mc_addr(ha, ndev) {
21206743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			if (mcast_all && is_multicast_ether_addr(ha->addr))
21216743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				continue;
21226743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
21236743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			if (sh_eth_tsu_add_entry(ndev, ha->addr) < 0) {
21246743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				if (!mcast_all) {
21256743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					sh_eth_tsu_purge_mcast(ndev);
21266743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					ecmr_bits &= ~ECMR_MCT;
21276743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda					mcast_all = 1;
21286743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda				}
21296743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda			}
21306743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		}
213186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else {
213286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Normal, unicast/broadcast-only mode. */
21336743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		ecmr_bits = (ecmr_bits & ~ECMR_PRM) | ECMR_MCT;
213486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
21356743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
21366743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	/* update the ethernet mode */
21376743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	sh_eth_write(ndev, ecmr_bits, ECMR);
21386743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda
21396743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda	spin_unlock_irqrestore(&mdp->lock, flags);
214086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
214171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
214271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
214371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
214471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!mdp->port)
214571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return TSU_VTAG0;
214671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	else
214771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return TSU_VTAG1;
214871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
214971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
215071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
215171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
215271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
215371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	int vtag_reg_index = sh_eth_get_vtag_index(mdp);
215471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
215571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
215671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return -EPERM;
215771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
215871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/* No filtering if vid = 0 */
215971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!vid)
216071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
216171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
216271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	mdp->vlan_num_ids++;
216371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
216471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/*
216571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 * The controller has one VLAN tag HW filter. So, if the filter is
216671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 * already enabled, the driver disables it and the filte
216771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	 */
216871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (mdp->vlan_num_ids > 1) {
216971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		/* disable VLAN filter */
217071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, vtag_reg_index);
217171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
217271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	}
217371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
217471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_VTAG_ENABLE | (vid & TSU_VTAG_VID_MASK),
217571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda			 vtag_reg_index);
217671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
217771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	return 0;
217871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
217971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
218071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimodastatic int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
218171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda{
218271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
218371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	int vtag_reg_index = sh_eth_get_vtag_index(mdp);
218471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
218571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (unlikely(!mdp->cd->tsu))
218671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return -EPERM;
218771cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
218871cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	/* No filtering if vid = 0 */
218971cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	if (!vid)
219071cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		return 0;
219171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
219271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	mdp->vlan_num_ids--;
219371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, vtag_reg_index);
219471cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda
219571cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	return 0;
219671cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda}
21974986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda#endif /* SH_ETH_HAS_TSU */
219886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
219986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* SuperH's TSU register init function */
22004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_tsu_init(struct sh_eth_private *mdp)
220186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
22024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
22034a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
22044a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
22054a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL0);
22064a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL1);
22074a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL0);
22084a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL1);
22094a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL0);
22104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL1);
22114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, TSU_FWSLC);
2212c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
2213c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG0);	/* Disable QTAG(0->1) */
2214c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG1);	/* Disable QTAG(1->0) */
2215c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
2216c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM0);	/* Disable QTAG(0->1) */
2217c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM1);	/* Disable QTAG(1->0) */
2218c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
22194a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSR);	/* all interrupt status clear */
22204a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWINMK);	/* Disable all interrupt */
22214a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_TEN);	/* Disable all CAM entry */
22224a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST1);	/* Disable CAM entry [ 0- 7] */
22234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST2);	/* Disable CAM entry [ 8-15] */
22244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST3);	/* Disable CAM entry [16-23] */
22254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST4);	/* Disable CAM entry [24-31] */
222686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
222786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
222886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus release function */
222986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_mdio_release(struct net_device *ndev)
223086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
22310582b7d15f8a7ae53dd2128b8eb01567b3fd2277Sergei Shtylyov	struct sh_eth_private *mdp = netdev_priv(ndev);
223286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
223386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
223486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* unregister mdio bus */
223586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdiobus_unregister(bus);
223686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
223786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* remove mdio bus info from net_device */
223886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, NULL);
223986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
22400f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	/* free interrupts memory */
22410f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	kfree(bus->irq);
22420f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov
224386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free bitbang info */
224486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_mdio_bitbang(bus);
224586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
22460582b7d15f8a7ae53dd2128b8eb01567b3fd2277Sergei Shtylyov	/* free bitbang memory */
22470582b7d15f8a7ae53dd2128b8eb01567b3fd2277Sergei Shtylyov	kfree(mdp->bitbang);
22480582b7d15f8a7ae53dd2128b8eb01567b3fd2277Sergei Shtylyov
224986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
225086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
225186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
225286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus init function */
2253b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimodastatic int sh_mdio_init(struct net_device *ndev, int id,
2254b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda			struct sh_eth_plat_data *pd)
225586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
225686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret, i;
225786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang;
225886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
225986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
226086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* create bit control struct for PHY */
226186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
226286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!bitbang) {
226386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
226486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
226586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
226686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
226786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* bitbang init */
2268ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
2269b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	bitbang->set_gate = pd->set_mdio_gate;
227086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdi_msk = 0x08;
227186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdo_msk = 0x04;
227286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mmd_msk = 0x02;/* MMD */
227386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdc_msk = 0x01;
227486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->ctrl.ops = &bb_ops;
227586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2276c2e07b3a9ced33dd92597201be3931be8ea57ed6Stefan Weil	/* MII controller setting */
22770582b7d15f8a7ae53dd2128b8eb01567b3fd2277Sergei Shtylyov	mdp->bitbang = bitbang;
227886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
227986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus) {
228086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
228186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bitbang;
228286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
228386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
228486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Hook up MII support for ethtool */
228586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->name = "sh_mii";
228618ee49ddb0d242ed1d0e273038d5e4f6de7379d3Lennert Buytenhek	mdp->mii_bus->parent = &ndev->dev;
22875278fb547076ad6768d16c8b4df45c086470c163Florian Fainelli	snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
228834aa6f1400810890636ba0b170effbfa71eacec7Nobuhiro Iwamatsu		mdp->pdev->name, id);
228986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
229086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY IRQ */
229186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
229286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus->irq) {
229386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
229486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bus;
229586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
229686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
229786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < PHY_MAX_ADDR; i++)
229886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->irq[i] = PHY_POLL;
229986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23008f6352f2b5aecd4b0af5ef31361af1146f9528d6YOSHIFUJI Hideaki / 吉藤英明	/* register mdio bus */
230186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = mdiobus_register(mdp->mii_bus);
230286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
230386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
230486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
230586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, mdp->mii_bus);
230686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
230786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
230886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
230986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
231086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->mii_bus->irq);
231186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bus:
2313298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek	free_mdio_bitbang(mdp->mii_bus);
231486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bitbang:
231686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(bitbang);
231786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
231886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
231986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
232086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
232186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
23224a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic const u16 *sh_eth_get_register_offset(int register_type)
23234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda{
23244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	const u16 *reg_offset = NULL;
23254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
23264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	switch (register_type) {
23274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_GIGABIT:
23284a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_gigabit;
23294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
23304a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH4:
23314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh4;
23324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
23334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH3_SH2:
23344a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh3_sh2;
23354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
23364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	default:
23374a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
23384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
23394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	}
23404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
23414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	return reg_offset;
23424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda}
23434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
2344ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalovstatic const struct net_device_ops sh_eth_netdev_ops = {
2345ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_open		= sh_eth_open,
2346ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_stop		= sh_eth_close,
2347ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_start_xmit		= sh_eth_start_xmit,
2348ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_get_stats		= sh_eth_get_stats,
2349380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
2350afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= sh_eth_set_multicast_list,
235171cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	.ndo_vlan_rx_add_vid	= sh_eth_vlan_rx_add_vid,
235271cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda	.ndo_vlan_rx_kill_vid	= sh_eth_vlan_rx_kill_vid,
2353380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
2354ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_tx_timeout		= sh_eth_tx_timeout,
2355ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_do_ioctl		= sh_eth_do_ioctl,
2356ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_validate_addr	= eth_validate_addr,
2357ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_set_mac_address	= eth_mac_addr,
2358ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_change_mtu		= eth_change_mtu,
2359ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov};
2360ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov
236186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_probe(struct platform_device *pdev)
236286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
23639c38657cfcb739b7dc4ce9065a85b4f0c195bef8Kuninori Morimoto	int ret, devno = 0;
236486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct resource *res;
236586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = NULL;
2366ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	struct sh_eth_private *mdp = NULL;
236771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	struct sh_eth_plat_data *pd;
236886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
236986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get base addr */
237086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
237186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (unlikely(res == NULL)) {
237286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&pdev->dev, "invalid resource\n");
237386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -EINVAL;
237486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
237586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
237686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
237786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev = alloc_etherdev(sizeof(struct sh_eth_private));
237886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!ndev) {
237986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
238086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
238186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
238286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
238386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* The sh Ether-specific entries in the device structure. */
238486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->base_addr = res->start;
238586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	devno = pdev->id;
238686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (devno < 0)
238786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		devno = 0;
238886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
238986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->dma = -1;
2390cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ret = platform_get_irq(pdev, 0);
2391cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	if (ret < 0) {
239286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENODEV;
239386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
239486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
2395cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ndev->irq = ret;
239686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
239786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	SET_NETDEV_DEV(ndev, &pdev->dev);
239886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
239986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Fill in the fields of the device structure with ethernet values. */
240086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ether_setup(ndev);
240186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
240286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp = netdev_priv(ndev);
2403525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	mdp->num_tx_ring = TX_RING_SIZE;
2404525b8075edda9c2ab4b81e210505bd7487ea6e56Yoshihiro Shimoda	mdp->num_rx_ring = RX_RING_SIZE;
2405ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	mdp->addr = ioremap(res->start, resource_size(res));
2406ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp->addr == NULL) {
2407ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		ret = -ENOMEM;
2408ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		dev_err(&pdev->dev, "ioremap failed.\n");
2409ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		goto out_release;
2410ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	}
2411ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda
241286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_init(&mdp->lock);
2413bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	mdp->pdev = pdev;
2414bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_enable(&pdev->dev);
2415bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_resume(&pdev->dev);
241686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
241771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
241886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get PHY ID */
241971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->phy_id = pd->phy;
2420e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda	mdp->phy_interface = pd->phy_interface;
242171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	/* EDMAC endian */
242271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->edmac_endian = pd->edmac_endian;
24234923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->no_ether_link = pd->no_ether_link;
24244923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->ether_link_active_low = pd->ether_link_active_low;
24254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);
242686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2427380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* set cpu data */
24288fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#if defined(SH_ETH_HAS_BOTH_MODULES)
24298fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdp->cd = sh_eth_get_cpu_data(mdp);
24308fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#else
2431380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdp->cd = &sh_eth_my_cpu_data;
24328fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#endif
2433380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	sh_eth_set_default_cpu_data(mdp->cd);
2434380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
243586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* set function */
2436ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	ndev->netdev_ops = &sh_eth_netdev_ops;
2437dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
243886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->watchdog_timeo = TX_TIMEOUT;
243986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2440dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* debug message level */
2441dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
244286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
244386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* read and set MAC address */
2444748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	read_mac_address(ndev, pd->mac_addr);
244586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
24466ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	/* ioremap the TSU registers */
24476ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	if (mdp->cd->tsu) {
24486ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		struct resource *rtsu;
24496ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
24506ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		if (!rtsu) {
24516ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda			dev_err(&pdev->dev, "Not found TSU resource\n");
2452043c4789726e6abb5be6115cb054af4926481952Peter Senna Tschudin			ret = -ENODEV;
24536ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda			goto out_release;
24546ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		}
24556ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		mdp->tsu_addr = ioremap(rtsu->start,
24566ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda					resource_size(rtsu));
2457fc0c0900408e05758a0df17c1924ca837fafca5eSergei Shtylyov		if (mdp->tsu_addr == NULL) {
2458fc0c0900408e05758a0df17c1924ca837fafca5eSergei Shtylyov			ret = -ENOMEM;
2459fc0c0900408e05758a0df17c1924ca837fafca5eSergei Shtylyov			dev_err(&pdev->dev, "TSU ioremap failed.\n");
2460fc0c0900408e05758a0df17c1924ca837fafca5eSergei Shtylyov			goto out_release;
2461fc0c0900408e05758a0df17c1924ca837fafca5eSergei Shtylyov		}
24626743fe6df43b4dc5950f605edfeee086d0a80f06Yoshihiro Shimoda		mdp->port = devno % 2;
246371cc7c37af71b497698f7f8a68e46a458071fcefYoshihiro Shimoda		ndev->features = NETIF_F_HW_VLAN_FILTER;
24646ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	}
24656ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda
2466150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	/* initialize first or needed device */
2467150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	if (!devno || pd->needs_init) {
2468380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		if (mdp->cd->chip_reset)
2469380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			mdp->cd->chip_reset(ndev);
247086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
24714986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		if (mdp->cd->tsu) {
24724986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			/* TSU init (Init only)*/
24734986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			sh_eth_tsu_init(mdp);
24744986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		}
247586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
247686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
247786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* network device register */
247886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = register_netdev(ndev);
247986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
248086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
248186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
248286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mdio bus init */
2483b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	ret = sh_mdio_init(ndev, pdev->id, pd);
248486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
248586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_unregister;
248686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
248725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* print device information */
24886cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
24896cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	       (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
249086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
249186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, ndev);
249286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
249386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
249486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
249586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_unregister:
249686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
249786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
249886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_release:
249986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* net_dev free */
2500ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp && mdp->addr)
2501ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iounmap(mdp->addr);
2502ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	if (mdp && mdp->tsu_addr)
25034986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		iounmap(mdp->tsu_addr);
250486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev)
250586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		free_netdev(ndev);
250686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
250786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
250886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
250986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
251086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
251186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_remove(struct platform_device *pdev)
251286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
251386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = platform_get_drvdata(pdev);
25144986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
251586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
25166ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda	if (mdp->cd->tsu)
25176ba88021c36516c26c11eff8c6d7d9a045faecd3Yoshihiro Shimoda		iounmap(mdp->tsu_addr);
251886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_mdio_release(ndev);
251986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
2520bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_disable(&pdev->dev);
2521ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iounmap(mdp->addr);
252286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_netdev(ndev);
252386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, NULL);
252486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
252586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
252686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
252786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2528bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic int sh_eth_runtime_nop(struct device *dev)
2529bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm{
2530bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	/*
2531bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * Runtime PM callback shared between ->runtime_suspend()
2532bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * and ->runtime_resume(). Simply returns success.
2533bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 *
2534bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * This driver re-initializes all registers after
2535bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * pm_runtime_get_sync() anyway so there is no need
2536bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * to save and restore registers here.
2537bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 */
2538bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	return 0;
2539bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm}
2540bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
2541bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic struct dev_pm_ops sh_eth_dev_pm_ops = {
2542bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_suspend = sh_eth_runtime_nop,
2543bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_resume = sh_eth_runtime_nop,
2544bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm};
2545bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
254686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct platform_driver sh_eth_driver = {
254786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.probe = sh_eth_drv_probe,
254886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.remove = sh_eth_drv_remove,
254986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.driver = {
255086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		   .name = CARDNAME,
2551bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm		   .pm = &sh_eth_dev_pm_ops,
255286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	},
255386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
255486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
2555db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(sh_eth_driver);
255686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
255786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_AUTHOR("Nobuhiro Iwamatsu, Yoshihiro Shimoda");
255886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_DESCRIPTION("Renesas SuperH Ethernet driver");
255986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_LICENSE("GPL v2");
2560