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