sh_eth.c revision 150647fb2c313d7c5184fca3fa0829a4a7d6f7bc
186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *  SuperH Ethernet device driver
386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
4b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
5380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda *  Copyright (C) 2008-2009 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>
41d4fa0e35fdbd54acf791fa3793d6d17f7795f7aeYoshihiro Shimoda#include <linux/sh_eth.h>
4286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
4386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu#include "sh_eth.h"
4486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
45dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#define SH_ETH_DEF_MSG_ENABLE \
46dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		(NETIF_MSG_LINK	| \
47dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		NETIF_MSG_TIMER	| \
48dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		NETIF_MSG_RX_ERR| \
49dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		NETIF_MSG_TX_ERR)
50dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
51380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* There is CPU dependent code */
5265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7724)
5365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
5465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
5565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda{
5665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
5765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
5865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	if (mdp->duplex) /* Full */
594a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
6065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	else		/* Half */
614a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
6265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
6365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
6465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
6565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda{
6665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
6765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
6865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	switch (mdp->speed) {
6965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 10: /* 10BASE */
704a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
7165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
7265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	case 100:/* 100BASE */
734a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
7465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
7565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	default:
7665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda		break;
7765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	}
7865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda}
7965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
8065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda/* SH7724 */
8165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
8265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
8365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
8465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
8565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
8665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
8765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f,
8865ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
8965ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
9065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
9165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
9265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
9365ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
9465ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.apr		= 1,
9565ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.mpr		= 1,
9665ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.tpauser	= 1,
9765ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda	.hw_swap	= 1,
98503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir		= 1,
99503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
10065ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda};
101f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
1028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_BOTH_MODULES	1
1038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
104f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
105f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
106f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
107f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
108f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	if (mdp->duplex) /* Full */
1094a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
110f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	else		/* Half */
1114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
112f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
113f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
114f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
115f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda{
116f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
117f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
118f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	switch (mdp->speed) {
119f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 10: /* 10BASE */
1204a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, RTRATE);
121f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
122f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	case 100:/* 100BASE */
1234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 1, RTRATE);
124f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
125f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	default:
126f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda		break;
127f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	}
128f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda}
129f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
130f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda/* SH7757 */
131f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
132f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_duplex		= sh_eth_set_duplex,
133f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.set_rate		= sh_eth_set_rate,
134f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
135f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
136f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.rmcr_value	= 0x00000001,
137f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
138f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
139f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
140f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
141f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
142f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda
143f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.apr		= 1,
144f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.mpr		= 1,
145f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.tpauser	= 1,
146f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.hw_swap	= 1,
147f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda	.no_ade		= 1,
1482e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir		= 1,
1492e98e7974de208de0dab9e9969bd47576d07ff10Yoshihiro Shimoda	.rpadir_value   = 2 << 16,
150f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda};
15165ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda
1528fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define SH_GIGA_ETH_BASE	0xfee00000
1538fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
1548fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
1558fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_chip_reset_giga(struct net_device *ndev)
1568fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
1578fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	int i;
1588fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	unsigned long mahr[2], malr[2];
1598fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1608fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* save MAHR and MALR */
1618fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
162ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		malr[i] = ioread32((void *)GIGA_MALR(i));
163ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		mahr[i] = ioread32((void *)GIGA_MAHR(i));
1648fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
1658fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1668fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* reset device */
167ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ARSTR_ARSTR, (void *)(SH_GIGA_ETH_BASE + 0x1800));
1688fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdelay(1);
1698fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1708fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	/* restore MAHR and MALR */
1718fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	for (i = 0; i < 2; i++) {
172ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(malr[i], (void *)GIGA_MALR(i));
173ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iowrite32(mahr[i], (void *)GIGA_MAHR(i));
1748fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
1758fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
1768fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1778fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp);
1788fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
1798fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
1808fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
1818fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	int cnt = 100;
1828fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1838fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1848fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x03, EDSR);
1858fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
1868fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
1878fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		while (cnt > 0) {
1888fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			if (!(sh_eth_read(ndev, EDMR) & 0x3))
1898fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				break;
1908fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			mdelay(1);
1918fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			cnt--;
1928fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		}
1938fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		if (cnt < 0)
1948fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			printk(KERN_ERR "Device reset fail\n");
1958fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
1968fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		/* Table Init */
1978fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDLAR);
1988fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFAR);
1998fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFXR);
2008fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, TDFFR);
2018fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDLAR);
2028fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFAR);
2038fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFXR);
2048fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x0, RDFFR);
2058fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	} else {
2068fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
2078fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2088fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		mdelay(3);
2098fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
2108fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda				EDMR);
2118fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2128fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2138fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2148fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_duplex_giga(struct net_device *ndev)
2158fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2168fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2178fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2188fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (mdp->duplex) /* Full */
2198fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
2208fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else		/* Half */
2218fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
2228fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2238fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2248fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic void sh_eth_set_rate_giga(struct net_device *ndev)
2258fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2268fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2278fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2288fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	switch (mdp->speed) {
2298fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 10: /* 10BASE */
2308fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000000, GECMR);
2318fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2328fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 100:/* 100BASE */
2338fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000010, GECMR);
2348fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2358fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	case 1000: /* 1000BASE */
2368fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		sh_eth_write(ndev, 0x00000020, GECMR);
2378fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2388fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	default:
2398fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		break;
2408fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	}
2418fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2428fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2438fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda/* SH7757(GETHERC) */
2448fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
2458fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset_giga,
2468fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex_giga,
2478fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.set_rate	= sh_eth_set_rate_giga,
2488fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2498fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
2508fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
2518fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
2528fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2538fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
2548fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
2558fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
2568fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_ECI,
2578fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
2588fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda			  EESR_TFE,
2598fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.fdr_value	= 0x0000072f,
2608fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rmcr_value	= 0x00000001,
2618fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2628fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.apr		= 1,
2638fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.mpr		= 1,
2648fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.tpauser	= 1,
2658fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.bculr		= 1,
2668fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.hw_swap	= 1,
2678fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir		= 1,
2688fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.rpadir_value   = 2 << 16,
2698fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_trimd	= 1,
2708fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	.no_ade		= 1,
2713acbc9715a5ac8a2534a69eb3488b63b7c9fb1e2Yoshihiro Shimoda	.tsu		= 1,
2728fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda};
2738fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
2748fcd496151b4354569283056076339239b86fabeYoshihiro Shimodastatic struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
2758fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda{
2768fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	if (sh_eth_is_gether(mdp))
2778fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data_giga;
2788fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	else
2798fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda		return &sh_eth_my_cpu_data;
2808fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda}
2818fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda
28265ac8851490ec97a96759af729132c96f925a795Yoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
283380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
284380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_chip_reset(struct net_device *ndev)
285380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
2864986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
2874986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda
288380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* reset device */
2894986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
290380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(1);
291380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
292380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
293380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
294380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
295380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	int cnt = 100;
296380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
2974a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, EDSR_ENALL, EDSR);
298c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
299380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	while (cnt > 0) {
3004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		if (!(sh_eth_read(ndev, EDMR) & 0x3))
301380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			break;
302380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mdelay(1);
303380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cnt--;
304380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	}
305890c8c18986eb975a76aa8359a712596bc70e61croel kluin	if (cnt == 0)
306380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		printk(KERN_ERR "Device reset fail\n");
307380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
308380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* Table Init */
3094a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDLAR);
3104a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFAR);
3114a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFXR);
3124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, TDFFR);
3134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDLAR);
3144a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFAR);
3154a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFXR);
3164a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0, RDFFR);
317380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
318380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
319380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_duplex(struct net_device *ndev)
320380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
321380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
322380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
323380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->duplex) /* Full */
3244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
325380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else		/* Half */
3264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
327380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
328380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
329380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_rate(struct net_device *ndev)
330380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
331380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
332380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
333380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	switch (mdp->speed) {
334380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 10: /* 10BASE */
3354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_10, GECMR);
336380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
337380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 100:/* 100BASE */
3384a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_100, GECMR);
339380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
340380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	case 1000: /* 1000BASE */
3414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, GECMR_1000, GECMR);
342380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
343380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	default:
344380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		break;
345380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	}
346380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
347380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
348380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* sh7763 */
349380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
350380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.chip_reset	= sh_eth_chip_reset,
351380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_duplex	= sh_eth_set_duplex,
352380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.set_rate	= sh_eth_set_rate,
353380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
354380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsr_value	= ECSR_ICD | ECSR_MPD,
355380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
356380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
357380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
358380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_check	= EESR_TC1 | EESR_FTC,
359380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
360380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
361380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_ECI,
362380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
363380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			  EESR_TFE,
364380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
365380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
366380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
367380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
368380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.bculr		= 1,
369380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
370380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_trimd	= 1,
371380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.no_ade		= 1,
3724986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
373380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
374380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
375380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
376380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
377380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
378380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
379380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
380380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.apr		= 1,
381380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.mpr		= 1,
382380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.tpauser	= 1,
383380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.hw_swap	= 1,
384380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
385380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
386380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_RESET_DEFAULT	1
387380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#define SH_ETH_HAS_TSU	1
388380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic struct sh_eth_cpu_data sh_eth_my_cpu_data = {
389380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
3904986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	.tsu		= 1,
391380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda};
392380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
393380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
394380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
395380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
396380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsr_value)
397380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsr_value = DEFAULT_ECSR_INIT;
398380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
399380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->ecsipr_value)
400380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
401380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
402380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fcftr_value)
403380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
404380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				  DEFAULT_FIFO_F_D_RFD;
405380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
406380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->fdr_value)
407380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->fdr_value = DEFAULT_FDR_INIT;
408380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
409380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->rmcr_value)
410380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->rmcr_value = DEFAULT_RMCR_VALUE;
411380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
412380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_check)
413380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_check = DEFAULT_TX_CHECK;
414380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
415380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->eesr_err_check)
416380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK;
417380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
418380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!cd->tx_error_check)
419380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		cd->tx_error_check = DEFAULT_TX_ERROR_CHECK;
420380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
421380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
422380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_RESET_DEFAULT)
423380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda/* Chip Reset */
424380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_reset(struct net_device *ndev)
425380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
426c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
427380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdelay(3);
428c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
429380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
430380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
431380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
432380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(CONFIG_CPU_SH4)
433380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
434380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
435380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	int reserve;
436380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
437380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
438380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (reserve)
439380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		skb_reserve(skb, reserve);
440380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
441380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#else
442380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimodastatic void sh_eth_set_receive_align(struct sk_buff *skb)
443380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda{
444380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
445380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda}
446380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
447380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
448380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
44971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato/* CPU <-> EDMAC endian convert */
45071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
45171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
45271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
45371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
45471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_le32(x);
45571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
45671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return cpu_to_be32(x);
45771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
45871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
45971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
46071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
46171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Satostatic inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
46271557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato{
46371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	switch (mdp->edmac_endian) {
46471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_LITTLE_ENDIAN:
46571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return le32_to_cpu(x);
46671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	case EDMAC_BIG_ENDIAN:
46771557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		return be32_to_cpu(x);
46871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	}
46971557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	return x;
47071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato}
47171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato
47286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
47386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Program the hardware MAC address from dev->dev_addr.
47486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
47586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void update_mac_address(struct net_device *ndev)
47686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
4774a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
4784a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
4794a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
4804a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev,
4814a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
48286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
48386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
48486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/*
48586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * Get MAC address from SuperH MAC address register
48686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
48786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
48886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
48986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu * When you want use this device, you must set MAC address in bootloader.
49086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu *
49186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu */
492748031f9fd2c06b28817d80761a5de97190cfd03Magnus Dammstatic void read_mac_address(struct net_device *ndev, unsigned char *mac)
49386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
494748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
495748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm		memcpy(ndev->dev_addr, mac, 6);
496748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	} else {
4974a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
4984a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
4994a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
5004a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
5014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
5024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
503748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	}
50486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
50586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
506c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic int sh_eth_is_gether(struct sh_eth_private *mdp)
507c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
508c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (mdp->reg_offset == sh_eth_offset_gigabit)
509c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 1;
510c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
511c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return 0;
512c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
513c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
514c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimodastatic unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
515c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda{
516c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp))
517c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_GETHER;
518c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	else
519c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		return EDTRR_TRNS_ETHER;
520c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda}
521c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda
52286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustruct bb_info {
523ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void (*set_gate)(void *addr);
52486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mdiobb_ctrl ctrl;
525ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	void *addr;
52686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mmd_msk;/* MMD */
52786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdo_msk;
52886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdi_msk;
52986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 mdc_msk;
53086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
53186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
53286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit set */
533ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_set(void *addr, u32 msk)
53486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
535ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32(ioread32(addr) | msk, addr);
53686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
53786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
53886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit clear */
539ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic void bb_clr(void *addr, u32 msk)
54086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
541ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iowrite32((ioread32(addr) & ~msk), addr);
54286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
54386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
54486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY bit read */
545ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimodastatic int bb_read(void *addr, u32 msk)
54686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
547ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	return (ioread32(addr) & msk) != 0;
54886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
54986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
55086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Data I/O pin control */
55186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
55286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
55386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
554b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
555b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
556b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
557b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
55886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
55986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mmd_msk);
56086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
56186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mmd_msk);
56286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
56386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
56486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Set bit data*/
56586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
56686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
56786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
56886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
569b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
570b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
571b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
57286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
57386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdo_msk);
57486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
57586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdo_msk);
57686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
57786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
57886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get bit data*/
57986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_get_mdio(struct mdiobb_ctrl *ctrl)
58086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
58186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
582b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
583b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
584b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
585b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
58686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return bb_read(bitbang->addr, bitbang->mdi_msk);
58786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
58886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
58986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDC pin control */
59086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
59186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
59286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
59386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
594b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	if (bitbang->set_gate)
595b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda		bitbang->set_gate(bitbang->addr);
596b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda
59786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (bit)
59886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_set(bitbang->addr, bitbang->mdc_msk);
59986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
60086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		bb_clr(bitbang->addr, bitbang->mdc_msk);
60186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
60286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
60386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* mdio bus control struct */
60486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct mdiobb_ops bb_ops = {
60586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.owner = THIS_MODULE,
60686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdc = sh_mdc_ctrl,
60786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_dir = sh_mmd_ctrl,
60886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.set_mdio_data = sh_set_mdio,
60986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.get_mdio_data = sh_get_mdio,
61086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
61186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
61286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free skb and descriptor buffer */
61386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_free(struct net_device *ndev)
61486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
61586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
61686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
61786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
61886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx skb ringbuffer */
61986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->rx_skbuff) {
62086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		for (i = 0; i < RX_RING_SIZE; i++) {
62186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->rx_skbuff[i])
62286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->rx_skbuff[i]);
62386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
62486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
62586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->rx_skbuff);
62686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
62786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Tx skb ringbuffer */
62886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->tx_skbuff) {
62986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		for (i = 0; i < TX_RING_SIZE; i++) {
63086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (mdp->tx_skbuff[i])
63186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				dev_kfree_skb(mdp->tx_skbuff[i]);
63286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
63386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
63486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->tx_skbuff);
63586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
63686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
63786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* format skb and descriptor buffer */
63886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_ring_format(struct net_device *ndev)
63986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
64086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
64186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
64286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
64386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc = NULL;
64486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc = NULL;
64586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE;
64686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE;
64786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
64886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_rx = mdp->cur_tx = 0;
64986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = mdp->dirty_tx = 0;
65086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
65186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->rx_ring, 0, rx_ringsize);
65286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
65386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Rx ring buffer */
65486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < RX_RING_SIZE; i++) {
65586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* skb */
65686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
657dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi		skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
65886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = skb;
65986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (skb == NULL)
66086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
661bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
662e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda				DMA_FROM_DEVICE);
663380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_set_receive_align(skb);
664380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
66586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* RX descriptor */
66686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
6670029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
66871557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
66986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
67086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
6710029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
672b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* Rx descriptor address set */
673b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
6744a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
675c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
676c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
677b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
67886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
67986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
68086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
68186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
68286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Mark the last entry as wrapping the ring. */
68371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
68486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
68586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	memset(mdp->tx_ring, 0, tx_ringsize);
68686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
68786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* build Tx ring buffer */
68886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < TX_RING_SIZE; i++) {
68986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
69086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[i];
69171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
69286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = 0;
693b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		if (i == 0) {
69471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			/* Tx descriptor address set */
6954a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
696c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			if (sh_eth_is_gether(mdp))
697c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
698b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		}
69986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
70086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
70286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
70386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
70486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Get skb and descriptor buffer */
70586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_ring_init(struct net_device *ndev)
70686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
70786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
70886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int rx_ringsize, tx_ringsize, ret = 0;
70986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
71086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/*
71186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
71286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card needs room to do 8 byte alignment, +2 so we can reserve
71386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * the first 2 bytes, and +16 gets room for the status word from the
71486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 * card.
71586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	 */
71686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ :
71786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			  (((ndev->mtu + 26 + 7) & ~7) + 2 + 16));
718503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm	if (mdp->cd->rpadir)
719503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm		mdp->rx_buf_sz += NET_IP_ALIGN;
72086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
72186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate RX and TX skb rings */
72286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
72386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				GFP_KERNEL);
72486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_skbuff) {
725380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx skb\n");
72686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
72786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
72886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
72986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
73086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
73186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				GFP_KERNEL);
73286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_skbuff) {
733380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx skb\n");
73486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
73586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto skb_ring_free;
73686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
73786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
73886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Rx descriptors. */
73986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
74086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
74186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
74286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
74386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->rx_ring) {
744380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
745380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			rx_ringsize);
74686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
74786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
74886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
74986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
75086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->dirty_rx = 0;
75186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
75286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Allocate all Tx descriptors. */
75386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
75486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
75586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			GFP_KERNEL);
75686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->tx_ring) {
757380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
758380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			tx_ringsize);
75986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
76086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto desc_ring_free;
76186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
76286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
76386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
76486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsudesc_ring_free:
76586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
76686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma);
76786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
76886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuskb_ring_free:
76986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free Rx and Tx skb ring buffer */
77086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
77186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
77386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
77486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
77586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_dev_init(struct net_device *ndev)
77686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
77786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
77886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
77986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u_int32_t rx_int_var, tx_int_var;
78086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 val;
78186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
78286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Soft Reset */
78386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_reset(ndev);
78486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
785b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Descriptor format */
786b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	sh_eth_ring_format(ndev);
787380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->rpadir)
7884a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR);
78986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
79086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* all sh_eth int mask */
7914a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EESIPR);
79286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
793380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(__LITTLE_ENDIAN__)
794380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->hw_swap)
7954a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDMR_EL, EDMR);
796380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	else
797b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu#endif
7984a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, EDMR);
79986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
800b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* FIFO size set */
8014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
8024a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TFTR);
80386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
804b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Frame recv control */
8054a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
80686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
80786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
80886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
8094a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER);
81086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
811380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->bculr)
8124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */
813b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
8144a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->fcftr_value, FCFTR);
81586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
816380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->no_trimd)
8174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, 0, TRIMD);
81886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
819b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Recv frame limit set register */
820fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda	sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
821fdb37a7f84a58ccad24abffd54ad46d23b763e13Yoshihiro Shimoda		     RFLR);
82286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
8234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
8244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
82586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
82686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PAUSE Prohibition */
8274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
82886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
82986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
8304a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, val, ECMR);
831b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
832380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->set_rate)
833380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mdp->cd->set_rate(ndev);
834380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
835b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Status Register clear */
8364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
837b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
838b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* E-MAC Interrupt Enable register */
8394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
84086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
84186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Set MAC address */
84286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	update_mac_address(ndev);
84386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
84486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mask reset */
845380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->apr)
8464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, APR_AP, APR);
847380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->mpr)
8484a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, MPR_MP, MPR);
849380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->tpauser)
8504a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
851b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
85286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Setting the Rx mode will start the Rx process. */
8534a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, EDRRR_R, EDRRR);
85486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_start_queue(ndev);
85686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
85786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
85886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
85986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
86086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* free Tx skb function */
86186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_txfree(struct net_device *ndev)
86286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
86386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
86486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
86586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int freeNum = 0;
86686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = 0;
86786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
86886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
86986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = mdp->dirty_tx % TX_RING_SIZE;
87086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc = &mdp->tx_ring[entry];
87171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
87286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
87386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Free the original skb. */
87486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[entry]) {
87531fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda			dma_unmap_single(&ndev->dev, txdesc->addr,
87631fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda					 txdesc->buffer_length, DMA_TO_DEVICE);
87786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
87886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->tx_skbuff[entry] = NULL;
87986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			freeNum++;
88086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
88171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
88286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (entry >= TX_RING_SIZE - 1)
88371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato			txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
88486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
885bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_packets++;
886bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_bytes += txdesc->buffer_length;
88786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
88886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return freeNum;
88986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
89086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet receive function */
89286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_rx(struct net_device *ndev)
89386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
89486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
89586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
89686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
89786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int entry = mdp->cur_rx % RX_RING_SIZE;
89886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
89986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sk_buff *skb;
90086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u16 pkt_len = 0;
901380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 desc_status;
90286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
90386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	rxdesc = &mdp->rx_ring[entry];
90471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
90571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		desc_status = edmac_to_cpu(mdp, rxdesc->status);
90686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		pkt_len = rxdesc->frame_length;
90786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
90886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (--boguscnt < 0)
90986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			break;
91086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!(desc_status & RDFEND))
912bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_length_errors++;
91386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
91486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
91586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
916bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_errors++;
91786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS1)
918bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_crc_errors++;
91986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS2)
920bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_frame_errors++;
92186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS3)
922bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
92386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS4)
924bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_length_errors++;
92586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS6)
926bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_missed_errors++;
92786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (desc_status & RD_RFS10)
928bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet				ndev->stats.rx_over_errors++;
92986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		} else {
930380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (!mdp->cd->hw_swap)
931380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				sh_eth_soft_swap(
932380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					phys_to_virt(ALIGN(rxdesc->addr, 4)),
933380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					pkt_len + 2);
93486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb = mdp->rx_skbuff[entry];
93586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = NULL;
936503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm			if (mdp->cd->rpadir)
937503914cf4a4b5dbe3f844e0a92f412ae99fde70eMagnus Damm				skb_reserve(skb, NET_IP_ALIGN);
93886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb_put(skb, pkt_len);
93986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			skb->protocol = eth_type_trans(skb, ndev);
94086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_rx(skb);
941bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_packets++;
942bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_bytes += pkt_len;
94386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
94471557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
94586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = (++mdp->cur_rx) % RX_RING_SIZE;
946862df49750e7ca9369c04d8d8105b3cc5d976e0dYoshihiro Shimoda		rxdesc = &mdp->rx_ring[entry];
94786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
94886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
94986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Refill the Rx ring buffers. */
95086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
95186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		entry = mdp->dirty_rx % RX_RING_SIZE;
95286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[entry];
953b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu		/* The size of the buffer is 16 byte boundary. */
9540029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
955b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
95686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[entry] == NULL) {
957dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi			skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
95886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->rx_skbuff[entry] = skb;
95986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			if (skb == NULL)
96086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				break;	/* Better luck next round. */
961bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
962e88aae7bb1dc50457489d1d7c81dcf4db23ccf94Yoshihiro Shimoda					DMA_FROM_DEVICE);
963380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			sh_eth_set_receive_align(skb);
964380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
965bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet			skb_checksum_none_assert(skb);
9660029d64af5d72049e2170e4609fa83bd1f3f07cdYoshihiro Shimoda			rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
96786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
96886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (entry >= RX_RING_SIZE - 1)
96986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
97071557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
97186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		else
97286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			rxdesc->status |=
97371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
97486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
97586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
97686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Restart Rx engine if stopped. */
97786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* If we don't need to check status, don't. -KDU */
9784a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R))
9794a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, EDRRR_R, EDRRR);
98086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
98186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
98286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
98386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
9844a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_disable(struct net_device *ndev)
985dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
986dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
9874a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) &
9884a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		~(ECMR_RE | ECMR_TE), ECMR);
989dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
990dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
9914a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_rcv_snd_enable(struct net_device *ndev)
992dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
993dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
9944a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
9954a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		(ECMR_RE | ECMR_TE), ECMR);
996dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
997dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
99886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* error control function */
99986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_error(struct net_device *ndev, int intr_status)
100086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
100186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
100286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 felic_stat;
1003380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 link_stat;
1004380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	u32 mask;
100586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
100686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_ECI) {
10074a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		felic_stat = sh_eth_read(ndev, ECSR);
10084a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, felic_stat, ECSR);	/* clear int */
100986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_ICD)
1010bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_carrier_errors++;
101186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (felic_stat & ECSR_LCHNG) {
101286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Link Changed */
10134923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda			if (mdp->cd->no_psr || mdp->no_ether_link) {
1014380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				if (mdp->link == PHY_DOWN)
1015380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					link_stat = 0;
1016380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				else
1017380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda					link_stat = PHY_ST_LINK;
1018380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			} else {
10194a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				link_stat = (sh_eth_read(ndev, PSR));
10204923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda				if (mdp->ether_link_active_low)
10214923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda					link_stat = ~link_stat;
1022380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			}
1023dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (!(link_stat & PHY_ST_LINK))
10244a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_disable(ndev);
1025dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			else {
102686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* Link Up */
10274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
10284a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ~DMAC_M_ECI, EESIPR);
102986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/*clear int */
10304a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
10314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  ECSR);
10324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
10334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda					  DMAC_M_ECI, EESIPR);
103486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				/* enable tx and rx */
10354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				sh_eth_rcv_snd_enable(ndev);
103686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			}
103786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
103886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
103986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
104086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_TWB) {
104186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Write buck end. unused write back interrupt */
104286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_TABT)	/* Transmit Abort int */
1043bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.tx_aborted_errors++;
1044dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_err(mdp))
1045dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Transmit Abort\n");
104686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
104786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
104886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RABT) {
104986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Abort int */
105086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (intr_status & EESR_RFRMER) {
105186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* Receive Frame Overflow int */
1052bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet			ndev->stats.rx_frame_errors++;
1053dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_rx_err(mdp))
1054dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_err(&ndev->dev, "Receive Abort\n");
105586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
105686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1057380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1058dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TDE) {
1059dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Transmit Descriptor Empty int */
1060bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1061dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1062dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
1063dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1064dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1065dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (intr_status & EESR_TFE) {
1066dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* FIFO under flow */
1067bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1068dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1069dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
107086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
107186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
107286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RDE) {
107386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive Descriptor Empty int */
1074bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_over_errors++;
107586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
10764a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R)
10774a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda			sh_eth_write(ndev, EDRRR_R, EDRRR);
1078dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1079dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive Descriptor Empty\n");
108086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1081dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
108286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (intr_status & EESR_RFE) {
108386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Receive FIFO Overflow int */
1084bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.rx_fifo_errors++;
1085dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_rx_err(mdp))
1086dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Receive FIFO Overflow\n");
1087dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1088dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1089dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
1090dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		/* Address Error */
1091bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_fifo_errors++;
1092dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		if (netif_msg_tx_err(mdp))
1093dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			dev_err(&ndev->dev, "Address Error\n");
109486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1095380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
1096380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
1097380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (mdp->cd->no_ade)
1098380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		mask &= ~EESR_ADE;
1099380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & mask) {
110086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Tx error */
11014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		u32 edtrr = sh_eth_read(ndev, EDTRR);
110286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dmesg */
1103380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
1104380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				intr_status, mdp->cur_tx);
1105380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
110686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				mdp->dirty_tx, (u32) ndev->state, edtrr);
110786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* dirty buffer free */
110886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
110986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
111086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* SH7712 BUG */
1111c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
111286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			/* tx dma start */
1113c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda			sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
111486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
111586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* wakeup */
111686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
111786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
111886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
111986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
112086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic irqreturn_t sh_eth_interrupt(int irq, void *netdev)
112186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
112286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = netdev;
112386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1124380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	struct sh_eth_cpu_data *cd = mdp->cd;
11250e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	irqreturn_t ret = IRQ_NONE;
11264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	u32 intr_status = 0;
112786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
112886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock(&mdp->lock);
112986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1130b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Get interrpt stat */
11314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	intr_status = sh_eth_read(ndev, EESR);
113286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Clear interrupt */
11330e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
11340e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
1135380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			cd->tx_check | cd->eesr_err_check)) {
11364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, intr_status, EESR);
11370e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		ret = IRQ_HANDLED;
11380e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	} else
11390e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu		goto other_irq;
114086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1141b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	if (intr_status & (EESR_FRC | /* Frame recv*/
1142b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RMAF | /* Multi cast address recv*/
1143b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RRF  | /* Bit frame recv */
1144b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTLF | /* Long frame recv*/
1145b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_RTSF | /* short frame recv */
1146b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_PRE  | /* PHY-LSI recv error */
1147b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu			EESR_CERF)){ /* recv frame CRC error */
114886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_rx(ndev);
1149b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	}
115086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1151b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	/* Tx Check */
1152380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->tx_check) {
115386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_txfree(ndev);
115486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		netif_wake_queue(ndev);
115586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
115686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1157380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (intr_status & cd->eesr_err_check)
115886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		sh_eth_error(ndev, intr_status);
115986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
11600e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsuother_irq:
116186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock(&mdp->lock);
116286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
11630e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu	return ret;
116486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
116586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
116686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_timer(unsigned long data)
116786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
116886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = (struct net_device *)data;
116986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
117086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
117186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mod_timer(&mdp->timer, jiffies + (10 * HZ));
117286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
117386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
117486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY state control function */
117586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_adjust_link(struct net_device *ndev)
117686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
117786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
117886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
117986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int new_state = 0;
118086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
118186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (phydev->link != PHY_DOWN) {
118286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->duplex != mdp->duplex) {
118386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
118486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->duplex = phydev->duplex;
1185380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_duplex)
1186380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_duplex(ndev);
118786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
118886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
118986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (phydev->speed != mdp->speed) {
119086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
119186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->speed = phydev->speed;
1192380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			if (mdp->cd->set_rate)
1193380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				mdp->cd->set_rate(ndev);
119486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
119586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->link == PHY_DOWN) {
119691a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda			sh_eth_write(ndev,
119791a5615203355bb34e0b9e68e94f27f24719a74cYoshihiro Shimoda				(sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
119886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			new_state = 1;
119986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			mdp->link = phydev->link;
120086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
120186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else if (mdp->link) {
120286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		new_state = 1;
120386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->link = PHY_DOWN;
120486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->speed = 0;
120586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->duplex = -1;
120686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
120786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1208dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (new_state && netif_msg_link(mdp))
120986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_print_status(phydev);
121086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
121186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
121286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY init function */
121386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_init(struct net_device *ndev)
121486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
121586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
12160a372eb91f9d507701a901c2f62ed31ca67fd66cDavid S. Miller	char phy_id[MII_BUS_ID_SIZE + 3];
121786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = NULL;
121886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1219fb28ad35906af2f042c94e2f9c0f898ef9acfa37Kay Sievers	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
122086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->id , mdp->phy_id);
122186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
122286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->link = PHY_DOWN;
122386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->speed = 0;
122486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->duplex = -1;
122586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
122686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Try connect to PHY */
1227c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
1228e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda				0, mdp->phy_interface);
122986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (IS_ERR(phydev)) {
123086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&ndev->dev, "phy_connect failed\n");
123186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return PTR_ERR(phydev);
123286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1233380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
123486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_info(&ndev->dev, "attached phy %i to driver %s\n",
1235380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		phydev->addr, phydev->drv->name);
123686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
123786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->phydev = phydev;
123886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
123986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
124086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
124186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
124286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* PHY control start function */
124386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_phy_start(struct net_device *ndev)
124486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
124586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
124686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret;
124786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
124886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_init(ndev);
124986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
125086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
125186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
125286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* reset phy - this also wakes it from PDOWN */
125386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
125486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	phy_start(mdp->phydev);
125586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
125686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
125786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
125886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1259dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_settings(struct net_device *ndev,
1260dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_cmd *ecmd)
1261dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1262dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1263dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1264dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1265dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1266dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1267dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_gset(mdp->phydev, ecmd);
1268dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1269dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1270dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1271dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1272dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1273dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_set_settings(struct net_device *ndev,
1274dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		struct ethtool_cmd *ecmd)
1275dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1276dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1277dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1278dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1279dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1280dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1281dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1282dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* disable tx and rx */
12834a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_disable(ndev);
1284dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1285dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_ethtool_sset(mdp->phydev, ecmd);
1286dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ret)
1287dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		goto error_exit;
1288dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1289dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (ecmd->duplex == DUPLEX_FULL)
1290dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 1;
1291dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	else
1292dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->duplex = 0;
1293dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1294dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (mdp->cd->set_duplex)
1295dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		mdp->cd->set_duplex(ndev);
1296dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1297dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsuerror_exit:
1298dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdelay(1);
1299dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1300dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* enable tx and rx */
13014a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_rcv_snd_enable(ndev);
1302dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1303dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1304dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1305dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1306dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1307dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1308dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_nway_reset(struct net_device *ndev)
1309dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1310dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1311dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	unsigned long flags;
1312dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int ret;
1313dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1314dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
1315dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	ret = phy_start_aneg(mdp->phydev);
1316dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
1317dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1318dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return ret;
1319dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1320dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1321dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic u32 sh_eth_get_msglevel(struct net_device *ndev)
1322dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1323dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1324dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	return mdp->msg_enable;
1325dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1326dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1327dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_set_msglevel(struct net_device *ndev, u32 value)
1328dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1329dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1330dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = value;
1331dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1332dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1333dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic const char sh_eth_gstrings_stats[][ETH_GSTRING_LEN] = {
1334dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_current", "tx_current",
1335dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	"rx_dirty", "tx_dirty",
1336dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1337dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu#define SH_ETH_STATS_LEN  ARRAY_SIZE(sh_eth_gstrings_stats)
1338dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1339dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic int sh_eth_get_sset_count(struct net_device *netdev, int sset)
1340dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1341dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (sset) {
1342dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1343dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return SH_ETH_STATS_LEN;
1344dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	default:
1345dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		return -EOPNOTSUPP;
1346dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1347dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1348dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1349dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_ethtool_stats(struct net_device *ndev,
1350dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			struct ethtool_stats *stats, u64 *data)
1351dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1352dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
1353dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	int i = 0;
1354dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1355dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* device-specific stats */
1356dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_rx;
1357dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->cur_tx;
1358dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_rx;
1359dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	data[i++] = mdp->dirty_tx;
1360dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1361dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
1362dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsustatic void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
1363dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu{
1364dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	switch (stringset) {
1365dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	case ETH_SS_STATS:
1366dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		memcpy(data, *sh_eth_gstrings_stats,
1367dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu					sizeof(sh_eth_gstrings_stats));
1368dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		break;
1369dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	}
1370dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu}
1371dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
13729b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemmingerstatic const struct ethtool_ops sh_eth_ethtool_ops = {
1373dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_settings	= sh_eth_get_settings,
1374dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_settings	= sh_eth_set_settings,
13759b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.nway_reset	= sh_eth_nway_reset,
1376dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_msglevel	= sh_eth_get_msglevel,
1377dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.set_msglevel	= sh_eth_set_msglevel,
13789b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemminger	.get_link	= ethtool_op_get_link,
1379dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_strings	= sh_eth_get_strings,
1380dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_ethtool_stats  = sh_eth_get_ethtool_stats,
1381dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	.get_sset_count     = sh_eth_get_sset_count,
1382dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu};
1383dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu
138486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* network device open function */
138586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_open(struct net_device *ndev)
138686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
138786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret = 0;
138886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
138986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1390bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1391bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1392a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches	ret = request_irq(ndev->irq, sh_eth_interrupt,
1393f29a3d040727a80c3307a2bea057206be049c305Yoshihiro Shimoda#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
1394dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
1395dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	defined(CONFIG_CPU_SUBTYPE_SH7757)
13960e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				IRQF_SHARED,
13970e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#else
13980e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				0,
13990e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu#endif
14000e0fde3c8d65524b8dfd834332d6e4a92711a66aNobuhiro Iwamatsu				ndev->name, ndev);
140186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret) {
1402380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		dev_err(&ndev->dev, "Can not assign IRQ number\n");
140386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return ret;
140486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
140586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
140686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Descriptor set */
140786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_ring_init(ndev);
140886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
140986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
141086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
141186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
141286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_dev_init(ndev);
141386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
141486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
141586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
141686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY control start*/
141786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = sh_eth_phy_start(ndev);
141886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
141986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
142086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Set the timer to check for link beat. */
142286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	init_timer(&mdp->timer);
142386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
1424b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu	setup_timer(&mdp->timer, sh_eth_timer, (unsigned long)ndev);
142586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
142786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
142886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
142986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
1430bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
143186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
143286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
143386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
143486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Timeout function */
143586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_tx_timeout(struct net_device *ndev)
143686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
143786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
143886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_rxdesc *rxdesc;
143986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int i;
144086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
144286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1443dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	if (netif_msg_timer(mdp))
1444dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu		dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
14454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	       " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
144686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
144786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* tx_errors count up */
1448bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_errors++;
144986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
145086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* timer off */
145186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	del_timer_sync(&mdp->timer);
145286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
145386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
145486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < RX_RING_SIZE; i++) {
145586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc = &mdp->rx_ring[i];
145686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->status = 0;
145786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		rxdesc->addr = 0xBADF00D0;
145886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->rx_skbuff[i])
145986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->rx_skbuff[i]);
146086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->rx_skbuff[i] = NULL;
146186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
146286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < TX_RING_SIZE; i++) {
146386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (mdp->tx_skbuff[i])
146486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			dev_kfree_skb(mdp->tx_skbuff[i]);
146586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->tx_skbuff[i] = NULL;
146686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
146786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
146886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* device init */
146986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_dev_init(ndev);
147086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
147186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* timer on */
147286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
147386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	add_timer(&mdp->timer);
147486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
147586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
147686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Packet transmit function */
147786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
147886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
147986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
148086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_txdesc *txdesc;
148186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	u32 entry;
1482fb5e2f9b9410a4362897d12dc1ed4f7cec1b0d45Nobuhiro Iwamatsu	unsigned long flags;
148386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
148486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_irqsave(&mdp->lock, flags);
148586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
148686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		if (!sh_eth_txfree(ndev)) {
1487dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu			if (netif_msg_tx_queued(mdp))
1488dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu				dev_warn(&ndev->dev, "TxFD exhausted.\n");
148986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			netif_stop_queue(ndev);
149086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu			spin_unlock_irqrestore(&mdp->lock, flags);
14915b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy			return NETDEV_TX_BUSY;
149286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		}
149386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
149486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_unlock_irqrestore(&mdp->lock, flags);
149586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
149686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	entry = mdp->cur_tx % TX_RING_SIZE;
149786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->tx_skbuff[entry] = skb;
149886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	txdesc = &mdp->tx_ring[entry];
149986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* soft swap. */
1500380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	if (!mdp->cd->hw_swap)
1501380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
1502380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda				 skb->len + 2);
150331fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
150431fcb99d9958bdf04e84224e202f69e6cdac893bYoshihiro Shimoda				      DMA_TO_DEVICE);
150586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (skb->len < ETHERSMALL)
150686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = ETHERSMALL;
150786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
150886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		txdesc->buffer_length = skb->len;
150986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
151086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (entry >= TX_RING_SIZE - 1)
151171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
151286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	else
151371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
151486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
151586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->cur_tx++;
151686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1517c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (!(sh_eth_read(ndev, EDTRR) & sh_eth_get_edtrr_trns(mdp)))
1518c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
1519b0ca2a21f769ae255bd6821cbc5af8af797f1da7Nobuhiro Iwamatsu
15206ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
152186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
152286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
152386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* device close function */
152486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_close(struct net_device *ndev)
152586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
152686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
152786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ringsize;
152886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
152986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	netif_stop_queue(ndev);
153086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
153186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Disable interrupts by clearing the interrupt mask. */
15324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0x0000, EESIPR);
153386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
153486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Stop the chip's Tx and Rx processes. */
15354a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDTRR);
15364a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, EDRRR);
153786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
153886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY Disconnect */
153986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (mdp->phydev) {
154086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_stop(mdp->phydev);
154186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		phy_disconnect(mdp->phydev);
154286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
154386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
154486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_irq(ndev->irq, ndev);
154586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
154686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	del_timer_sync(&mdp->timer);
154786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
154886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Free all the skbuffs in the Rx queue. */
154986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_eth_ring_free(ndev);
155086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
155186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
155286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
155386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma);
155486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
155586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free DMA buffer */
155686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
155786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma);
155886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1559bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1560bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
156186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
156286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
156386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
156486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
156586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
156686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
156786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1568bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_get_sync(&mdp->pdev->dev);
1569bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1570bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
15714a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, TROCR);	/* (write clear) */
1572bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.collisions += sh_eth_read(ndev, CDCR);
15734a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, CDCR);	/* (write clear) */
1574bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
15754a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_write(ndev, 0, LCCR);	/* (write clear) */
1576c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1577bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
1578c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CERCR);	/* (write clear) */
1579bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
1580c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CEECR);	/* (write clear) */
1581c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
1582bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet		ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
1583c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_write(ndev, 0, CNDCR);	/* (write clear) */
1584c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
1585bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_put_sync(&mdp->pdev->dev);
1586bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1587bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet	return &ndev->stats;
158886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
158986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1590bb7d92e3e3049e22b5807ac559a72b38fad5f499Eric Dumazet/* ioctl to device function */
159186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
159286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu				int cmd)
159386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
159486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
159586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct phy_device *phydev = mdp->phydev;
159686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
159786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!netif_running(ndev))
159886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -EINVAL;
159986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
160086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!phydev)
160186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		return -ENODEV;
160286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
160328b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran	return phy_mii_ioctl(phydev, rq, cmd);
160486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
160586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1606380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
160786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* Multicast reception directions set */
160886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic void sh_eth_set_multicast_list(struct net_device *ndev)
160986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
161086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev->flags & IFF_PROMISC) {
161186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Set promiscuous. */
16124a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_MCT) |
16134a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				ECMR_PRM, ECMR);
161486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	} else {
161586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		/* Normal, unicast/broadcast-only mode. */
16164a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) |
16174a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda				ECMR_MCT, ECMR);
161886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
161986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
16204986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda#endif /* SH_ETH_HAS_TSU */
162186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
162286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* SuperH's TSU register init function */
16234a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic void sh_eth_tsu_init(struct sh_eth_private *mdp)
162486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
16254a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
16264a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
16274a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
16284a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL0);
16294a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL1);
16304a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL0);
16314a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_PRISL1);
16324a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL0);
16334a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSL1);
16344a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, TSU_FWSLC);
1635c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	if (sh_eth_is_gether(mdp)) {
1636c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG0);	/* Disable QTAG(0->1) */
1637c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAG1);	/* Disable QTAG(1->0) */
1638c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	} else {
1639c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM0);	/* Disable QTAG(0->1) */
1640c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda		sh_eth_tsu_write(mdp, 0, TSU_QTAGM1);	/* Disable QTAG(1->0) */
1641c5ed53687b39c195b4730de8c0355c1b78054ba6Yoshihiro Shimoda	}
16424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWSR);	/* all interrupt status clear */
16434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_FWINMK);	/* Disable all interrupt */
16444a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_TEN);	/* Disable all CAM entry */
16454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST1);	/* Disable CAM entry [ 0- 7] */
16464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST2);	/* Disable CAM entry [ 8-15] */
16474a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST3);	/* Disable CAM entry [16-23] */
16484a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	sh_eth_tsu_write(mdp, 0, TSU_POST4);	/* Disable CAM entry [24-31] */
164986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
165086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus release function */
165286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_mdio_release(struct net_device *ndev)
165386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
165486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
165586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* unregister mdio bus */
165786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdiobus_unregister(bus);
165886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
165986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* remove mdio bus info from net_device */
166086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, NULL);
166186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
16620f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	/* free interrupts memory */
16630f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov	kfree(bus->irq);
16640f0b405cd16f7aaff84a935984cae421897d725dDenis Kirjanov
166586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* free bitbang info */
166686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_mdio_bitbang(bus);
166786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
166886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
166986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
167086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu/* MDIO bus init function */
1672b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimodastatic int sh_mdio_init(struct net_device *ndev, int id,
1673b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda			struct sh_eth_plat_data *pd)
167486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
167586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	int ret, i;
167686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct bb_info *bitbang;
167786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct sh_eth_private *mdp = netdev_priv(ndev);
167886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
167986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* create bit control struct for PHY */
168086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
168186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!bitbang) {
168286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
168386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
168486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
168586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
168686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* bitbang init */
1687ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
1688b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	bitbang->set_gate = pd->set_mdio_gate;
168986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdi_msk = 0x08;
169086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdo_msk = 0x04;
169186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mmd_msk = 0x02;/* MMD */
169286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->mdc_msk = 0x01;
169386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	bitbang->ctrl.ops = &bb_ops;
169486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1695c2e07b3a9ced33dd92597201be3931be8ea57ed6Stefan Weil	/* MII controller setting */
169686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
169786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus) {
169886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
169986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bitbang;
170086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
170186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
170286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Hook up MII support for ethtool */
170386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->name = "sh_mii";
170418ee49ddb0d242ed1d0e273038d5e4f6de7379d3Lennert Buytenhek	mdp->mii_bus->parent = &ndev->dev;
17055278fb547076ad6768d16c8b4df45c086470c163Florian Fainelli	snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
170634aa6f1400810890636ba0b170effbfa71eacec7Nobuhiro Iwamatsu		mdp->pdev->name, id);
170786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
170886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* PHY IRQ */
170986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
171086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!mdp->mii_bus->irq) {
171186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
171286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_bus;
171386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
171486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
171586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	for (i = 0; i < PHY_MAX_ADDR; i++)
171686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		mdp->mii_bus->irq[i] = PHY_POLL;
171786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
171886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* regist mdio bus */
171986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = mdiobus_register(mdp->mii_bus);
172086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
172186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_free_irq;
172286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	dev_set_drvdata(&ndev->dev, mdp->mii_bus);
172486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
172686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
172786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_irq:
172886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(mdp->mii_bus->irq);
172986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bus:
1731298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek	free_mdio_bitbang(mdp->mii_bus);
173286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_free_bitbang:
173486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	kfree(bitbang);
173586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
173686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
173786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
173886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
173986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
17404a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimodastatic const u16 *sh_eth_get_register_offset(int register_type)
17414a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda{
17424a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	const u16 *reg_offset = NULL;
17434a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
17444a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	switch (register_type) {
17454a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_GIGABIT:
17464a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_gigabit;
17474a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
17484a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH4:
17494a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh4;
17504a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
17514a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	case SH_ETH_REG_FAST_SH3_SH2:
17524a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		reg_offset = sh_eth_offset_fast_sh3_sh2;
17534a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
17544a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	default:
17554a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
17564a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda		break;
17574a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	}
17584a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
17594a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	return reg_offset;
17604a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda}
17614a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda
1762ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalovstatic const struct net_device_ops sh_eth_netdev_ops = {
1763ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_open		= sh_eth_open,
1764ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_stop		= sh_eth_close,
1765ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_start_xmit		= sh_eth_start_xmit,
1766ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_get_stats		= sh_eth_get_stats,
1767380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#if defined(SH_ETH_HAS_TSU)
1768afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= sh_eth_set_multicast_list,
1769380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda#endif
1770ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_tx_timeout		= sh_eth_tx_timeout,
1771ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_do_ioctl		= sh_eth_do_ioctl,
1772ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_validate_addr	= eth_validate_addr,
1773ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_set_mac_address	= eth_mac_addr,
1774ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	.ndo_change_mtu		= eth_change_mtu,
1775ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov};
1776ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov
177786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_probe(struct platform_device *pdev)
177886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
17799c38657cfcb739b7dc4ce9065a85b4f0c195bef8Kuninori Morimoto	int ret, devno = 0;
178086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct resource *res;
178186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = NULL;
1782ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	struct sh_eth_private *mdp = NULL;
178371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	struct sh_eth_plat_data *pd;
178486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
178586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get base addr */
178686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
178786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (unlikely(res == NULL)) {
178886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		dev_err(&pdev->dev, "invalid resource\n");
178986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -EINVAL;
179086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
179186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
179286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
179386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev = alloc_etherdev(sizeof(struct sh_eth_private));
179486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (!ndev) {
179586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENOMEM;
179686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out;
179786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
179886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
179986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* The sh Ether-specific entries in the device structure. */
180086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->base_addr = res->start;
180186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	devno = pdev->id;
180286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (devno < 0)
180386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		devno = 0;
180486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
180586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->dma = -1;
1806cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ret = platform_get_irq(pdev, 0);
1807cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	if (ret < 0) {
180886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		ret = -ENODEV;
180986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
181086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
1811cc3c080d9f4484021e7b14f99de94a8c85a668d5roel kluin	ndev->irq = ret;
181286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
181386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	SET_NETDEV_DEV(ndev, &pdev->dev);
181486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
181586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* Fill in the fields of the device structure with ethernet values. */
181686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ether_setup(ndev);
181786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
181886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp = netdev_priv(ndev);
1819ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	mdp->addr = ioremap(res->start, resource_size(res));
1820ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp->addr == NULL) {
1821ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		ret = -ENOMEM;
1822ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		dev_err(&pdev->dev, "ioremap failed.\n");
1823ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		goto out_release;
1824ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	}
1825ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda
182686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	spin_lock_init(&mdp->lock);
1827bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	mdp->pdev = pdev;
1828bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_enable(&pdev->dev);
1829bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_resume(&pdev->dev);
183086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
183171557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
183286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* get PHY ID */
183371557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->phy_id = pd->phy;
1834e47c90523484518aac30498150e427d824ace705Yoshihiro Shimoda	mdp->phy_interface = pd->phy_interface;
183571557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	/* EDMAC endian */
183671557a37adb5df17631c493b3b7d912938c720b2Yoshinori Sato	mdp->edmac_endian = pd->edmac_endian;
18374923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->no_ether_link = pd->no_ether_link;
18384923576b8ac5bfd36ab2beb176aeb747aaab7e41Yoshihiro Shimoda	mdp->ether_link_active_low = pd->ether_link_active_low;
18394a55530f38e4eeee3afb06093e81309138fe8360Yoshihiro Shimoda	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);
184086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1841380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	/* set cpu data */
18428fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#if defined(SH_ETH_HAS_BOTH_MODULES)
18438fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda	mdp->cd = sh_eth_get_cpu_data(mdp);
18448fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#else
1845380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	mdp->cd = &sh_eth_my_cpu_data;
18468fcd496151b4354569283056076339239b86fabeYoshihiro Shimoda#endif
1847380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda	sh_eth_set_default_cpu_data(mdp->cd);
1848380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda
184986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* set function */
1850ebf84eaa927be41a440fd4c8f81e1844922bc0b2Alexander Beregalov	ndev->netdev_ops = &sh_eth_netdev_ops;
1851dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
185286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ndev->watchdog_timeo = TX_TIMEOUT;
185386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1854dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	/* debug message level */
1855dc19e4e5e02fb6b46cccb08b2735e38b997a6ddfNobuhiro Iwamatsu	mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
185686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->post_rx = POST_RX >> (devno << 1);
185786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	mdp->post_fw = POST_FW >> (devno << 1);
185886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
185986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* read and set MAC address */
1860748031f9fd2c06b28817d80761a5de97190cfd03Magnus Damm	read_mac_address(ndev, pd->mac_addr);
186186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1862150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	/* initialize first or needed device */
1863150647fb2c313d7c5184fca3fa0829a4a7d6f7bcYoshihiro Shimoda	if (!devno || pd->needs_init) {
18644986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		if (mdp->cd->tsu) {
18654986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			struct resource *rtsu;
18664986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
18674986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			if (!rtsu) {
18684986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda				dev_err(&pdev->dev, "Not found TSU resource\n");
18694986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda				goto out_release;
18704986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			}
18714986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			mdp->tsu_addr = ioremap(rtsu->start,
18724986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda						resource_size(rtsu));
18734986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		}
1874380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda		if (mdp->cd->chip_reset)
1875380af9e390ec81e74a2fd7fad948a8b12eeec7daYoshihiro Shimoda			mdp->cd->chip_reset(ndev);
187686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
18774986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		if (mdp->cd->tsu) {
18784986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			/* TSU init (Init only)*/
18794986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda			sh_eth_tsu_init(mdp);
18804986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		}
188186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	}
188286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
188386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* network device register */
188486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	ret = register_netdev(ndev);
188586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
188686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_release;
188786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
188886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* mdio bus init */
1889b3017e6a03d261778ad9450b5510460c4d462203Yoshihiro Shimoda	ret = sh_mdio_init(ndev, pdev->id, pd);
189086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ret)
189186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		goto out_unregister;
189286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
189325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* print device information */
18946cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
18956cd9b49d7328c4656bfc17fcb47fb814955d40d2H Hartley Sweeten	       (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
189686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
189786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, ndev);
189886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
189986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
190086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
190186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_unregister:
190286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
190386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
190486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout_release:
190586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	/* net_dev free */
1906ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	if (mdp && mdp->addr)
1907ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda		iounmap(mdp->addr);
1908ec0d75518cb06261f1823fa2713fe52b9b26455eKuninori Morimoto	if (mdp && mdp->tsu_addr)
19094986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda		iounmap(mdp->tsu_addr);
191086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	if (ndev)
191186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		free_netdev(ndev);
191286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
191386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsuout:
191486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return ret;
191586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
191686a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
191786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic int sh_eth_drv_remove(struct platform_device *pdev)
191886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu{
191986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	struct net_device *ndev = platform_get_drvdata(pdev);
19204986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	struct sh_eth_private *mdp = netdev_priv(ndev);
192186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
19224986b996882d82c68ab54b822d7cfdd7dd35f19aYoshihiro Shimoda	iounmap(mdp->tsu_addr);
192386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	sh_mdio_release(ndev);
192486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	unregister_netdev(ndev);
1925bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	pm_runtime_disable(&pdev->dev);
1926ae70644df780c0e87f1705fda932e7cb1bdb2074Yoshihiro Shimoda	iounmap(mdp->addr);
192786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	free_netdev(ndev);
192886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	platform_set_drvdata(pdev, NULL);
192986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
193086a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	return 0;
193186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu}
193286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1933bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic int sh_eth_runtime_nop(struct device *dev)
1934bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm{
1935bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	/*
1936bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * Runtime PM callback shared between ->runtime_suspend()
1937bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * and ->runtime_resume(). Simply returns success.
1938bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 *
1939bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * This driver re-initializes all registers after
1940bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * pm_runtime_get_sync() anyway so there is no need
1941bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 * to save and restore registers here.
1942bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	 */
1943bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	return 0;
1944bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm}
1945bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
1946bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Dammstatic struct dev_pm_ops sh_eth_dev_pm_ops = {
1947bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_suspend = sh_eth_runtime_nop,
1948bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm	.runtime_resume = sh_eth_runtime_nop,
1949bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm};
1950bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm
195186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsustatic struct platform_driver sh_eth_driver = {
195286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.probe = sh_eth_drv_probe,
195386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.remove = sh_eth_drv_remove,
195486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	.driver = {
195586a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu		   .name = CARDNAME,
1956bcd5149ded6b2edbf3732fa1483600a716b1cba6Magnus Damm		   .pm = &sh_eth_dev_pm_ops,
195786a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu	},
195886a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu};
195986a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
1960db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(sh_eth_driver);
196186a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro Iwamatsu
196286a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_AUTHOR("Nobuhiro Iwamatsu, Yoshihiro Shimoda");
196386a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_DESCRIPTION("Renesas SuperH Ethernet driver");
196486a74ff21a7ac4bc06b18076ddb0347712b46cfdNobuhiro IwamatsuMODULE_LICENSE("GPL v2");
1965