From patchwork Fri May 4 10:58:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brilliantov Kirill Vladimirovich X-Patchwork-Id: 156877 X-Patchwork-Delegate: trini@ti.com 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 4D3B4B6FC5 for ; Fri, 4 May 2012 21:45:21 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 57232280A7; Fri, 4 May 2012 13:45:19 +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 njb3x3cz52VW; Fri, 4 May 2012 13:45:19 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CE80F28095; Fri, 4 May 2012 13:45:16 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 692EF28096 for ; Fri, 4 May 2012 13:29:51 +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 bhxd5Ks-Usii for ; Fri, 4 May 2012 13:29:50 +0200 (CEST) X-Greylist: delayed 1942 seconds by postgrey-1.27 at theia; Fri, 04 May 2012 13:29:49 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.byterg.ru (mail.byterg.ru [62.205.171.178]) by theia.denx.de (Postfix) with ESMTPS id A5E8728095 for ; Fri, 4 May 2012 13:29:49 +0200 (CEST) Received: from [192.168.10.42] (helo=kirill.byterg.ru) by mail.byterg.ru with esmtp (envelope-from ) id 1SQGMQ-00047X-MY ; Fri, 04 May 2012 15:07:42 +0400 From: Brilliantov Kirill Vladimirovich To: u-boot@lists.denx.de Date: Fri, 4 May 2012 14:58:14 +0400 Message-Id: <1336129094-396-1-git-send-email-brilliantov@byterg.ru> X-Mailer: git-send-email 1.7.9 X-Mailman-Approved-At: Fri, 04 May 2012 13:45:14 +0200 Cc: Tom Rini , Brilliantov Kirill Vladimirovich , Sandeep Paulraj Subject: [U-Boot] [PATCH] davinci: added Marvell 88E1111 PHY support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 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 added Marvell 88E1111 PHY support for Davinchi DM36x tested on DM368ZCEF Signed-off-by: Brilliantov Kirill Vladimirovich --- arch/arm/cpu/arm926ejs/davinci/Makefile | 1 + arch/arm/cpu/arm926ejs/davinci/marvell.c | 232 +++++++++++++++++++++++++ arch/arm/include/asm/arch-davinci/emac_defs.h | 6 + drivers/net/davinci_emac.c | 18 ++ 4 files changed, 257 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/davinci/marvell.c diff --git a/arch/arm/cpu/arm926ejs/davinci/Makefile b/arch/arm/cpu/arm926ejs/davinci/Makefile index da7efac..687c58b 100644 --- a/arch/arm/cpu/arm926ejs/davinci/Makefile +++ b/arch/arm/cpu/arm926ejs/davinci/Makefile @@ -35,6 +35,7 @@ COBJS-$(CONFIG_SOC_DM644X) += dm644x.o COBJS-$(CONFIG_SOC_DM646X) += dm646x.o COBJS-$(CONFIG_SOC_DA850) += da850_pinmux.o COBJS-$(CONFIG_DRIVER_TI_EMAC) += lxt972.o dp83848.o et1011c.o ksz8873.o +COBJS-$(CONFIG_DRIVER_TI_EMAC) += marvell.o ifdef CONFIG_SPL_BUILD COBJS-y += spl.o diff --git a/arch/arm/cpu/arm926ejs/davinci/marvell.c b/arch/arm/cpu/arm926ejs/davinci/marvell.c new file mode 100644 index 0000000..00e896a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/davinci/marvell.c @@ -0,0 +1,232 @@ +/* + * Marvel 88E1111 Driver for TI DaVinci (TMS320DM635) based boards. + * + * Copyright (C) 2011 Brilliantov Kirill Vladimirovich + * References: 88E1111 Datasheet Integrated 10/100/1000 + * Ultra Gigabit Ethernet Transceiver + * Doc. No. MV-S100649-00, Rev. F + * December, 3, 2004 + * -------------------------------------------------------- + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "../../../../../drivers/net/davinci_emac.h" + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +#define DEBUG 0 +#define DBG(f, a...) \ + do { \ + if (DEBUG) \ + printf("Marvell: " f "\n", ##a);\ + } while (0) +#define ERR(f, a...) printf("Marvell: " f "\n", ##a) + +#define EXTENDED_PHY_SPECIFIC_STATUS_REGISTER 27 + +int m88e1111_is_phy_connected(int phy_addr) +{ + u_int16_t id1 = 0, id2 = 0; + + DBG("starting %s", __func__); + + if (!davinci_eth_phy_read(phy_addr, MII_PHYSID1, &id1)) { + ERR("can't read register %d (MII_PHYSID1)", MII_PHYSID1); + return (0); + } + + if (!davinci_eth_phy_read(phy_addr, MII_PHYSID2, &id2)) { + ERR("can't read register %d (MII_PHYSID2)", MII_PHYSID2); + return (0); + } + + DBG("ID1 %#x, ID2 %#x", id1, id2); + + if ((id1 == 0x141) && ((id2 & 0xFFF0) == 0x0CC0)) + return (1); + + ERR("ID1 or ID2 not corrected"); + + return (0); +} + +int m88e1111_get_link_speed(int phy_addr) +{ + u_int16_t val = 0; + volatile emac_regs *emac = (emac_regs *) EMAC_BASE_ADDR; + + DBG("starting %s", __func__); + + if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &val)) { + ERR("can't read register %d (MII_BMSR)", MII_BMSR); + return (0); + } + + if (!(val & BMSR_LSTATUS)) { + ERR("link down"); + return (0); + } + DBG("link up"); + + if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &val)) { + ERR("can't read register %d (MII_BMCR)", MII_BMCR); + return (0); + } + + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; + if (val & BMCR_FULLDPLX) + emac->MACCONTROL |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE; + DBG("set emac in %s duplex mode", + val & BMCR_FULLDPLX ? "full" : "half"); + + return (1); +} + +int m88e1111_auto_negotiate(int phy_addr) +{ + u_int16_t val = 0; + + DBG("starting %s", __func__); + +#if defined(CONFIG_SOC_DM365) + /* disable 1000Mb/s auto-negotination */ + if (!davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val)) { + ERR("can't read register %d (MII_CTRL1000)", MII_CTRL1000); + return (0); + } + + if (!davinci_eth_phy_write(phy_addr, MII_CTRL1000, + val & (~(ADVERTISE_1000FULL | ADVERTISE_1000HALF)))) { + ERR("can't disable 1000Mb/s autonegotiation"); + return (0); + } + DBG("1000Mb/s autonegotiation disabled"); +#endif + + if (!davinci_eth_phy_read(phy_addr, MII_ADVERTISE, &val)) { + ERR("can't read register %d (MII_ADVERTISE)", MII_ADVERTISE); + return (0); + } + + val |= (ADVERTISE_100FULL | ADVERTISE_100HALF | + ADVERTISE_10FULL | ADVERTISE_10HALF); + if (!davinci_eth_phy_write(phy_addr, MII_ADVERTISE, val)) { + ERR("can't set 100Mb/s autonegotiation"); + return (0); + } + + if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &val)) { + ERR("can't read register %d (MII_BMCR)", MII_BMCR); + return (0); + } + + davinci_eth_phy_write(phy_addr, MII_BMCR, val | BMCR_RESET); + + /* TODO: very long time on auto-negotiation */ + udelay(2000000); + if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &val)) { + ERR("can't read register %d (MII_BMSR)", MII_BMSR); + return (0); + } + + if (DEBUG) { + u_int8_t i; + u_int16_t v = 0; + + for (i = 0; i < 32; i++) { + davinci_eth_phy_read(phy_addr, i, &v); + printf("Register %d: value %#x\n", i, v); + } + } + + if (!(val & BMSR_ANEGCOMPLETE)) { + ERR("autonegotiation not completed"); + return (0); + } + DBG("autonegotiation completed"); + + return (m88e1111_get_link_speed(phy_addr)); +} + +int m88e1111_init_phy(int phy_addr) +{ + int ret = 1; + u_int16_t val = 0; + + DBG("starting %s", __func__); + + if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &val)) { + ERR("can't read register %d (MII_BMCR)", MII_BMCR); + return(0); + } + + if (!davinci_eth_phy_write(phy_addr, MII_BMCR, val | BMCR_RESET)) { + ERR("can't set soft reset"); + return(0); + } + + udelay(20000); + if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &val)) { + ERR("can't read register %d (MII_BMCR)", MII_BMCR); + return(0); + } + while (val & BMCR_RESET) { + udelay(10000); + davinci_eth_phy_read(phy_addr, MII_BMCR, &val); + } + +#if defined(CONFIG_SOC_DM365) + if (!davinci_eth_phy_read(phy_addr, + EXTENDED_PHY_SPECIFIC_STATUS_REGISTER, &val)) { + ERR("can't read register %d (Extended PHY Status)", + EXTENDED_PHY_SPECIFIC_STATUS_REGISTER); + return (0); + } + if (!davinci_eth_phy_write(phy_addr, + EXTENDED_PHY_SPECIFIC_STATUS_REGISTER, + val | 0xF)) { + ERR("can't set GMII to cooper mode"); + return (0); + } + DBG("hardware configred set in GMII to cooper mode"); + + if (!m88e1111_auto_negotiate(phy_addr)) + ret = m88e1111_auto_negotiate(phy_addr); +#else + if (!m88e1111_get_link_speed(phy_addr)) + ret = m88e1111_get_link_speed(phy_addr); +#endif + + return (ret); +} + + + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ + +/* vim: set noet sw=8 ts=8: */ diff --git a/arch/arm/include/asm/arch-davinci/emac_defs.h b/arch/arm/include/asm/arch-davinci/emac_defs.h index 8a17de9..5f27600 100644 --- a/arch/arm/include/asm/arch-davinci/emac_defs.h +++ b/arch/arm/include/asm/arch-davinci/emac_defs.h @@ -105,4 +105,10 @@ int dp83848_auto_negotiate(int phy_addr); #define PHY_ET1011C (0x282f013) int et1011c_get_link_speed(int phy_addr); +#define PHY_M88E1111 (0x1410CC2) +int m88e1111_is_phy_connected(int phy_addr); +int m88e1111_get_link_speed(int phy_addr); +int m88e1111_init_phy(int phy_addr); +int m88e1111_auto_negotiate(int phy_addr); + #endif /* _DM644X_EMAC_H_ */ diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index fbd0f1b..fdca1ae 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -881,6 +881,16 @@ int davinci_emac_initialize(void) phy[i].auto_negotiate = gen_auto_negotiate; break; #endif +#ifdef PHY_M88E1111 + case PHY_M88E1111: + sprintf(phy[i].name, "MARVELL88E1111 @ 0x%02x", + active_phy_addr[i]); + phy[i].init = m88e1111_init_phy; + phy[i].is_phy_connected = m88e1111_is_phy_connected; + phy[i].get_link_speed = m88e1111_get_link_speed; + phy[i].auto_negotiate = m88e1111_auto_negotiate; + break; +#endif default: sprintf(phy[i].name, "GENERIC @ 0x%02x", active_phy_addr[i]); @@ -892,6 +902,14 @@ int davinci_emac_initialize(void) debug("Ethernet PHY: %s\n", phy[i].name); +#if defined(PHY_M88E1111) && defined(CONFIG_SOC_DM365) + /* I always get 1000Mb/s without this */ + if (PHY_M88E1111 == phy_id) { + if (!phy[i].init(active_phy_addr[i])) + return(0); + } +#endif + miiphy_register(phy[i].name, davinci_mii_phy_read, davinci_mii_phy_write); }