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