From patchwork Sun Jan 2 23:37:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francois Romieu X-Patchwork-Id: 77212 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id AEC24B6F14 for ; Mon, 3 Jan 2011 10:37:44 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752886Ab1ABXhk (ORCPT ); Sun, 2 Jan 2011 18:37:40 -0500 Received: from violet.fr.zoreil.com ([92.243.8.30]:51704 "EHLO violet.fr.zoreil.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752611Ab1ABXhk (ORCPT ); Sun, 2 Jan 2011 18:37:40 -0500 Received: from violet.fr.zoreil.com (localhost [127.0.0.1]) by violet.fr.zoreil.com (8.13.8/8.13.8) with ESMTP id p02NbTVY005831; Mon, 3 Jan 2011 00:37:29 +0100 Received: (from romieu@localhost) by violet.fr.zoreil.com (8.13.8/8.13.8/Submit) id p02NbTko005830; Mon, 3 Jan 2011 00:37:29 +0100 Date: Mon, 3 Jan 2011 00:37:29 +0100 From: Francois Romieu To: davem@davemloft.net Cc: netdev@vger.kernel.org, Hayes Wang , Ben Hutchings Subject: [net-next-2.6 06/08] r8169: magic. Message-ID: <20110102233729.GG5780@electric-eye.fr.zoreil.com> Mime-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.4.2.2i X-Organisation: Land of Sunshine Inc. Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Adapted from version 8.019.00 of Realtek's r8168 driver. Signed-off-by: Francois Romieu Cc: Hayes --- drivers/net/r8169.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 93 insertions(+), 0 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index fd7e40a..ab1741d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -278,6 +278,18 @@ enum rtl8168_8101_registers { }; enum rtl8168_registers { + ERIDR = 0x70, + ERIAR = 0x74, +#define ERIAR_FLAG 0x80000000 +#define ERIAR_WRITE_CMD 0x80000000 +#define ERIAR_READ_CMD 0x00000000 +#define ERIAR_ADDR_BYTE_ALIGN 4 +#define ERIAR_EXGMAC 0 +#define ERIAR_MSIX 1 +#define ERIAR_ASF 2 +#define ERIAR_TYPE_SHIFT 16 +#define ERIAR_BYTEEN 0x0f +#define ERIAR_BYTEEN_SHIFT 12 EPHY_RXER_NUM = 0x7c, OCPDR = 0xb0, /* OCP GPHY access */ #define OCPDR_WRITE_CMD 0x80000000 @@ -572,6 +584,81 @@ static int rtl8169_poll(struct napi_struct *napi, int budget); static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); +static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) +{ + void __iomem *ioaddr = tp->mmio_addr; + int i; + + RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); + for (i = 0; i < 20; i++) { + udelay(100); + if (RTL_R32(OCPAR) & OCPAR_FLAG) + break; + } + return RTL_R32(OCPDR); +} + +static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data) +{ + void __iomem *ioaddr = tp->mmio_addr; + int i; + + RTL_W32(OCPDR, data); + RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); + for (i = 0; i < 20; i++) { + udelay(100); + if ((RTL_R32(OCPAR) & OCPAR_FLAG) == 0) + break; + } +} + +static void rtl8168_oob_notify(void __iomem *ioaddr, u8 cmd) +{ + int i; + + RTL_W8(ERIDR, cmd); + RTL_W32(ERIAR, 0x800010e8); + msleep(2); + for (i = 0; i < 5; i++) { + udelay(100); + if (!(RTL_R32(ERIDR) & ERIAR_FLAG)) + break; + } + + ocp_write(ioaddr, 0x1, 0x30, 0x00000001); +} + +#define OOB_CMD_RESET 0x00 +#define OOB_CMD_DRIVER_START 0x05 +#define OOB_CMD_DRIVER_STOP 0x06 + +static void rtl8168_driver_start(struct rtl8169_private *tp) +{ + int i; + + rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); + + for (i = 0; i < 10; i++) { + msleep(10); + if (ocp_read(tp, 0x0f, 0x0010) & 0x00000800) + break; + } +} + +static void rtl8168_driver_stop(struct rtl8169_private *tp) +{ + int i; + + rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); + + for (i = 0; i < 10; i++) { + msleep(10); + if ((ocp_read(tp, 0x0f, 0x0010) & 0x00000800) == 0) + break; + } +} + + static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value) { int i; @@ -2913,6 +3000,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); + if (tp->mac_version == RTL_GIGA_MAC_VER_27) + rtl8168_driver_start(tp); + rtl8169_init_phy(dev, tp); /* @@ -2948,6 +3038,9 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); + if (tp->mac_version == RTL_GIGA_MAC_VER_27) + rtl8168_driver_stop(tp); + cancel_delayed_work_sync(&tp->task); unregister_netdev(dev);