From patchwork Tue Feb 15 11:47:32 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Shimoda X-Patchwork-Id: 558651 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p1FBm6ZN006719 for ; Tue, 15 Feb 2011 11:48:07 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754732Ab1BOLrh (ORCPT ); Tue, 15 Feb 2011 06:47:37 -0500 Received: from relmlor2.renesas.com ([210.160.252.172]:44565 "EHLO relmlor2.renesas.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754726Ab1BOLre (ORCPT ); Tue, 15 Feb 2011 06:47:34 -0500 Received: from relmlir1.idc.renesas.com ([10.200.68.151]) by relmlor2.idc.renesas.com ( SJSMS) with ESMTP id <0LGN00K2OQ38P0F0@relmlor2.idc.renesas.com>; Tue, 15 Feb 2011 20:47:32 +0900 (JST) Received: from relmlac1.idc.renesas.com ([10.200.69.21]) by relmlir1.idc.renesas.com (SJSMS) with ESMTP id <0LGN00C20Q389N10@relmlir1.idc.renesas.com>; Tue, 15 Feb 2011 20:47:32 +0900 (JST) Received: by relmlac1.idc.renesas.com (Postfix, from userid 0) id C530380088; Tue, 15 Feb 2011 20:47:32 +0900 (JST) Received: from relmlac1.idc.renesas.com (localhost [127.0.0.1]) by relmlac1.idc.renesas.com (Postfix) with ESMTP id BE76480030; Tue, 15 Feb 2011 20:47:32 +0900 (JST) Received: from relmlii1.idc.renesas.com [10.200.68.65] by relmlac1.idc.renesas.com with ESMTP id WAJ07104; Tue, 15 Feb 2011 20:47:32 +0900 X-IronPort-AV: E=Sophos; i="4.60,473,1291561200"; d="scan'208"; a="11531369" Received: from unknown (HELO [172.30.8.157]) ([172.30.8.157]) by relmlii1.idc.renesas.com with ESMTP; Tue, 15 Feb 2011 20:47:32 +0900 Message-id: <4D5A67D4.2000408@renesas.com> Date: Tue, 15 Feb 2011 20:47:32 +0900 From: Yoshihiro Shimoda User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2.13) Gecko/20101207 Thunderbird/3.1.7 MIME-version: 1.0 To: netdev@vger.kernel.org Cc: SH-Linux Subject: [RFC, PATCH 4/4] net: sh_eth: add support for SH7757's GETHER Content-type: text/plain; charset=ISO-8859-1 Content-transfer-encoding: 7bit Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 15 Feb 2011 11:48:07 +0000 (UTC) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index ca7ff4e..330f608 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -87,7 +87,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .rpadir_value = 0x00020000, /* NET_IP_ALIGN assumed to be 2 */ }; #elif defined(CONFIG_CPU_SUBTYPE_SH7757) -#define SH_ETH_RESET_DEFAULT 1 +#define SH_ETH_HAS_BOTH_MODULES 1 +#define SH_ETH_HAS_TSU 1 static void sh_eth_set_duplex(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -134,6 +135,135 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .no_ade = 1, }; +#define SH_GIGA_ETH_BASE 0xfee00000 +#define GIGA_MALR(port) (SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8) +#define GIGA_MAHR(port) (SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0) +static void sh_eth_chip_reset_giga(struct net_device *ndev) +{ + int i; + unsigned long mahr[2], malr[2]; + + /* save MAHR and MALR */ + for (i = 0; i < 2; i++) { + malr[i] = readl(GIGA_MALR(i)); + mahr[i] = readl(GIGA_MAHR(i)); + } + + /* reset device */ + writel(ARSTR_ARSTR, SH_GIGA_ETH_BASE + 0x1800); + mdelay(1); + + /* restore MAHR and MALR */ + for (i = 0; i < 2; i++) { + writel(malr[i], GIGA_MALR(i)); + writel(mahr[i], GIGA_MAHR(i)); + } +} + +static int sh_eth_is_gether(struct sh_eth_private *mdp); +static void sh_eth_reset(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + int cnt = 100; + + if (sh_eth_is_gether(mdp)) { + sh_eth_write(ndev, 0x03, EDSR); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, + EDMR); + while (cnt > 0) { + if (!(sh_eth_read(ndev, EDMR) & 0x3)) + break; + mdelay(1); + cnt--; + } + if (cnt < 0) + printk(KERN_ERR "Device reset fail\n"); + + /* Table Init */ + sh_eth_write(ndev, 0x0, TDLAR); + sh_eth_write(ndev, 0x0, TDFAR); + sh_eth_write(ndev, 0x0, TDFXR); + sh_eth_write(ndev, 0x0, TDFFR); + sh_eth_write(ndev, 0x0, RDLAR); + sh_eth_write(ndev, 0x0, RDFAR); + sh_eth_write(ndev, 0x0, RDFXR); + sh_eth_write(ndev, 0x0, RDFFR); + } else { + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, + EDMR); + mdelay(3); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, + EDMR); + } +} + +static void sh_eth_set_duplex_giga(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + + if (mdp->duplex) /* Full */ + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); + else /* Half */ + sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); +} + +static void sh_eth_set_rate_giga(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + + switch (mdp->speed) { + case 10: /* 10BASE */ + sh_eth_write(ndev, 0x00000000, GECMR); + break; + case 100:/* 100BASE */ + sh_eth_write(ndev, 0x00000010, GECMR); + break; + case 1000: /* 1000BASE */ + sh_eth_write(ndev, 0x00000020, GECMR); + break; + default: + break; + } +} + +/* SH7757(GETHERC) */ +static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = { + .chip_reset = sh_eth_chip_reset_giga, + .set_duplex = sh_eth_set_duplex_giga, + .set_rate = sh_eth_set_rate_giga, + + .ecsr_value = ECSR_ICD | ECSR_MPD, + .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP, + .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, + + .tx_check = EESR_TC1 | EESR_FTC, + .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ + EESR_ECI, + .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ + EESR_TFE, + .fdr_value = 0x0000072f, + .rmcr_value = 0x00000001, + + .apr = 1, + .mpr = 1, + .tpauser = 1, + .bculr = 1, + .hw_swap = 1, + .rpadir = 1, + .rpadir_value = 2 << 16, + .no_trimd = 1, + .no_ade = 1, +}; + +static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) +{ + if (sh_eth_is_gether(mdp)) + return &sh_eth_my_cpu_data_giga; + else + return &sh_eth_my_cpu_data; +} + #elif defined(CONFIG_CPU_SUBTYPE_SH7763) #define SH_ETH_HAS_TSU 1 static void sh_eth_chip_reset(struct net_device *ndev) @@ -1515,7 +1645,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev) mdp->reg_offset = sh_eth_get_register_offset(pd->register_type); /* set cpu data */ +#if defined(SH_ETH_HAS_BOTH_MODULES) + mdp->cd = sh_eth_get_cpu_data(mdp); +#else mdp->cd = &sh_eth_my_cpu_data; +#endif sh_eth_set_default_cpu_data(mdp->cd); /* set function */