From patchwork Thu Sep 8 20:37:18 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 113942 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id D5557B70B7 for ; Fri, 9 Sep 2011 06:39:51 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3297928238; Thu, 8 Sep 2011 22:38:26 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id JlP2lwFAXo2f; Thu, 8 Sep 2011 22:38:25 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 40209281FD; Thu, 8 Sep 2011 22:37:58 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CB0EC2818B for ; Thu, 8 Sep 2011 22:37:55 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pOk6-+lREeOB for ; Thu, 8 Sep 2011 22:37:55 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-fx0-f44.google.com (mail-fx0-f44.google.com [209.85.161.44]) by theia.denx.de (Postfix) with ESMTPS id 271E1281D2 for ; Thu, 8 Sep 2011 22:37:44 +0200 (CEST) Received: by mail-fx0-f44.google.com with SMTP id 6so1771828fxe.3 for ; Thu, 08 Sep 2011 13:37:44 -0700 (PDT) Received: by 10.223.36.207 with SMTP id u15mr829640fad.57.1315514263960; Thu, 08 Sep 2011 13:37:43 -0700 (PDT) Received: from mashiro.kolej.mff.cuni.cz (vasut.kolej.mff.cuni.cz [78.128.198.52]) by mx.google.com with ESMTPS id h5sm1884647fae.13.2011.09.08.13.37.41 (version=SSLv3 cipher=OTHER); Thu, 08 Sep 2011 13:37:42 -0700 (PDT) From: Marek Vasut To: u-boot@lists.denx.de Date: Thu, 8 Sep 2011 22:37:18 +0200 Message-Id: <1315514242-18998-8-git-send-email-marek.vasut@gmail.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1315514242-18998-1-git-send-email-marek.vasut@gmail.com> References: <1315514242-18998-1-git-send-email-marek.vasut@gmail.com> Cc: Ben Warren Subject: [U-Boot] [PATCH 07/11] FEC: Allow multiple FECes X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This patch allows user to register multiple FEC controllers. To preserve compatibility with older boards, the mxcfec_register() call is still in place. To use multiple controllers, new macro is in place, the mxcfec_register_multi(), which takes more arguments. The syntax is: mxcfec_register_multi(bd, FEC ID, FEC PHY ID on the MII bus, base address); To disable the fecmxc_register() compatibility stuff, define the macro CONFIG_FEC_MXC_MULTI. This will remove the requirement for defining IMX_FEC_BASE and CONFIG_FEC_MXC_PHYADDR. Signed-off-by: Marek Vasut Cc: Ben Warren Cc: Stefano Babic Cc: Wolfgang Denk Cc: Detlev Zundel --- drivers/net/fec_mxc.c | 79 ++++++++++++++++++++++++++++++------------------ drivers/net/fec_mxc.h | 2 + include/netdev.h | 2 +- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 6f56a7a..44b7919 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -51,18 +51,6 @@ struct nbuf { uint8_t head[16]; /**< MAC header(6 + 6 + 2) + 2(aligned) */ }; -struct fec_priv gfec = { - .eth = (struct ethernet_regs *)IMX_FEC_BASE, - .xcv_type = MII100, - .rbd_base = NULL, - .rbd_index = 0, - .tbd_base = NULL, - .tbd_index = 0, - .bd = NULL, - .rdb_ptr = NULL, - .base_ptr = NULL, -}; - /* * MII-interface related functions */ @@ -164,26 +152,27 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, static int miiphy_restart_aneg(struct eth_device *dev) { + struct fec_priv *fec = (struct fec_priv *)dev->priv; + /* * Wake up from sleep if necessary * Reset PHY, then delay 300ns */ #ifdef CONFIG_MX27 - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_DCOUNTER, 0x00FF); + miiphy_write(dev->name, fec->phy_id, MII_DCOUNTER, 0x00FF); #endif - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR, + miiphy_write(dev->name, fec->phy_id, MII_BMCR, BMCR_RESET); udelay(1000); /* * Set the auto-negotiation advertisement register bits */ - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_ADVERTISE, + miiphy_write(dev->name, fec->phy_id, MII_ADVERTISE, LPA_100FULL | LPA_100HALF | LPA_10FULL | LPA_10HALF | PHY_ANLPAR_PSB_802_3); - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR, + miiphy_write(dev->name, fec->phy_id, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; } @@ -191,6 +180,7 @@ static int miiphy_wait_aneg(struct eth_device *dev) { uint32_t start; uint16_t status; + struct fec_priv *fec = (struct fec_priv *)dev->priv; /* * Wait for AN completion @@ -202,7 +192,7 @@ static int miiphy_wait_aneg(struct eth_device *dev) return -1; } - if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR, + if (miiphy_read(dev->name, fec->phy_id, MII_BMSR, &status)) { printf("%s: Autonegotiation failed. status: 0x%04x\n", dev->name, status); @@ -390,8 +380,8 @@ static int fec_open(struct eth_device *edev) #endif miiphy_wait_aneg(edev); - miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); - miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR); + miiphy_speed(edev->name, fec->phy_id); + miiphy_duplex(edev->name, fec->phy_id); /* * Enable SmartDMA receive task @@ -406,7 +396,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd) { uint32_t base; struct fec_priv *fec = (struct fec_priv *)dev->priv; + uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; uint32_t rcntrl; + int i; /* Initialize MAC address */ fec_set_hwaddr(dev); @@ -477,9 +469,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd) /* clear MIB RAM */ - long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200); - while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC)) - *mib_ptr++ = 0; + for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) + writel(0, i); /* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); @@ -513,7 +504,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) */ static void fec_halt(struct eth_device *dev) { - struct fec_priv *fec = &gfec; + struct fec_priv *fec = (struct fec_priv *)dev->priv; int counter = 0xffff; /* @@ -694,19 +685,28 @@ static int fec_recv(struct eth_device *dev) return len; } -static int fec_probe(bd_t *bd) +static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) { struct eth_device *edev; - struct fec_priv *fec = &gfec; + struct fec_priv *fec; unsigned char ethaddr[6]; /* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) { - puts("fec_mxc: not enough malloc memory\n"); + puts("fec_mxc: not enough malloc memory for eth_device\n"); + return -ENOMEM; + } + + fec = (struct fec_priv *)malloc(sizeof(struct fec_priv)); + if (!fec) { + puts("fec_mxc: not enough malloc memory for fec_priv\n"); return -ENOMEM; } + memset(edev, 0, sizeof(*edev)); + memset(fec, 0, sizeof(*fec)); + edev->priv = fec; edev->init = fec_init; edev->send = fec_send; @@ -714,7 +714,7 @@ static int fec_probe(bd_t *bd) edev->halt = fec_halt; edev->write_hwaddr = fec_set_hwaddr; - fec->eth = (struct ethernet_regs *)IMX_FEC_BASE; + fec->eth = (struct ethernet_regs *)base_addr; fec->bd = bd; fec->xcv_type = CONFIG_FEC_XCV_TYPE; @@ -744,7 +744,14 @@ static int fec_probe(bd_t *bd) FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl); fec_mii_setspeed(fec); - sprintf(edev->name, "FEC"); + if (dev_id == -1) { + sprintf(edev->name, "FEC"); + fec->dev_id = 0; + } else { + sprintf(edev->name, "FEC%i", dev_id); + fec->dev_id = dev_id; + } + fec->phy_id = phy_id; miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write); @@ -758,12 +765,24 @@ static int fec_probe(bd_t *bd) return 0; } +#ifndef CONFIG_FEC_MXC_MULTI int fecmxc_initialize(bd_t *bd) { int lout = 1; debug("eth_init: fec_probe(bd)\n"); - lout = fec_probe(bd); + lout = fec_probe(bd, -1, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE); + + return lout; +} +#endif + +int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr) +{ + int lout = 1; + + debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr); + lout = fec_probe(bd, dev_id, phy_id, addr); return lout; } diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index f16f9db..e436c22 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -275,6 +275,8 @@ struct fec_priv { bd_t *bd; void *rdb_ptr; void *base_ptr; + int dev_id; + int phy_id; }; /** diff --git a/include/netdev.h b/include/netdev.h index 6f0a971..6e70341 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -61,6 +61,7 @@ int ethoc_initialize(u8 dev_num, int base_addr); int eth_3com_initialize (bd_t * bis); int fec_initialize (bd_t *bis); int fecmxc_initialize (bd_t *bis); +int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr); int ftgmac100_initialize(bd_t *bits); int ftmac100_initialize(bd_t *bits); int greth_initialize(bd_t *bis); @@ -93,7 +94,6 @@ int uli526x_initialize(bd_t *bis); int xilinx_emaclite_initialize (bd_t *bis, int base_addr); int sh_eth_initialize(bd_t *bis); int dm9000_initialize(bd_t *bis); -int fecmxc_initialize(bd_t *bis); /* Boards with PCI network controllers can call this from their board_eth_init() * function to initialize whatever's on board.