From patchwork Tue Oct 4 06:30:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brilliantov Kirill Vladimirovich X-Patchwork-Id: 117567 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 13CF8B6F70 for ; Tue, 4 Oct 2011 17:30:24 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 8D905281ED; Tue, 4 Oct 2011 08:30:22 +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 qZgqgYDe5hQx; Tue, 4 Oct 2011 08:30:22 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 17180281A4; Tue, 4 Oct 2011 08:30:20 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C23CE281A4 for ; Tue, 4 Oct 2011 08:30:16 +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 2GNs7YT6MJ6K for ; Tue, 4 Oct 2011 08:30:15 +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.byterg.ru (mail.byterg.ru [62.205.171.178]) by theia.denx.de (Postfix) with ESMTPS id 2E4242819C for ; Tue, 4 Oct 2011 08:30:15 +0200 (CEST) Received: from [192.168.10.42] by mail.byterg.ru with esmtp (envelope-from ) id 1RAyW6-0001dw-FD ; Tue, 04 Oct 2011 10:30:14 +0400 Message-ID: <4E8AA7F5.1090108@byterg.ru> Date: Tue, 04 Oct 2011 10:30:13 +0400 From: Brilliantov Kirill Vladimirovich Organization: LLC Byterg User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.20) Gecko/20110822 Icedove/3.1.12 MIME-Version: 1.0 To: u-boot@lists.denx.de Subject: [U-Boot] [PATCH 3/3] add new PHY chips support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list Reply-To: brilliantov@byterg.ru List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add Marvell 88E1111 PHY support, tested on U-Boot 1.3.4. Signed-off-by: Brilliantov Kirill Vladimirovich --- cpu/arm926ejs/davinci/Makefile | 1 + cpu/arm926ejs/davinci/ether.c | 14 +++ cpu/arm926ejs/davinci/marvell.c | 189 ++++++++++++++++++++++++++++++ include/asm-arm/arch-davinci/emac_defs.h | 6 + 4 files changed, 210 insertions(+), 0 deletions(-) create mode 100644 cpu/arm926ejs/davinci/marvell.c diff --git a/cpu/arm926ejs/davinci/Makefile b/cpu/arm926ejs/davinci/Makefile index 0b6cbd2..f39a2ad 100644 --- a/cpu/arm926ejs/davinci/Makefile +++ b/cpu/arm926ejs/davinci/Makefile @@ -29,6 +29,7 @@ LIB = $(obj)lib$(SOC).a COBJS = timer.o ether.o lxt972.o dp83848.o i2c.o nand.o COBJS += realtek.o +COBJS += marvell.o SOBJS = lowlevel_init.o reset.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/cpu/arm926ejs/davinci/ether.c b/cpu/arm926ejs/davinci/ether.c index 09fe24e..4e4a606 100644 --- a/cpu/arm926ejs/davinci/ether.c +++ b/cpu/arm926ejs/davinci/ether.c @@ -406,6 +406,14 @@ static int davinci_eth_hw_init(void) phy.get_link_speed = rtl8201_get_link_speed; phy.auto_negotiate = rtl8201_auto_negotiate; break; + case PHY_MARVEL88E1111: + sprintf(phy.name, "MARVELL88E1111 @ 0x%02x", + active_phy_addr); + phy.init = marvell88e1111_init_phy; + phy.is_phy_connected = marvell88e1111_is_phy_connected; + phy.get_link_speed = marvell88e1111_get_link_speed; + phy.auto_negotiate = marvell88e1111_auto_negotiate; + break; default: sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr); phy.init = gen_init_phy; @@ -416,6 +424,12 @@ static int davinci_eth_hw_init(void) printf("Ethernet PHY: %s\n", phy.name); + /* disable 1000Mb/s autonegotiation */ + if (PHY_MARVEL88E1111 == phy_id) { + if (!phy.init(active_phy_addr)) + return(0); + } + return(1); } diff --git a/cpu/arm926ejs/davinci/marvell.c b/cpu/arm926ejs/davinci/marvell.c new file mode 100644 index 0000000..6918bef --- /dev/null +++ b/cpu/arm926ejs/davinci/marvell.c @@ -0,0 +1,189 @@ +/* + * 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 + +#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: %s: " f "\n", __func__, ##a) + +#define LINK_DOWN (0 << 2) +#define EXTENDED_PHY_SPECIFIC_STATUS_REGISTER 27 + +int marvell88e1111_is_phy_connected(int phy_addr) +{ + u_int16_t id1, id2; + + DBG("starting %s", __func__); + + if (!davinci_eth_phy_read(phy_addr, PHY_PHYIDR1, &id1)) { + ERR("can't read PHY_PHYIDR1 register %#x", PHY_PHYIDR1); + return (0); + } + + if (!davinci_eth_phy_read(phy_addr, PHY_PHYIDR2, &id2)) { + ERR("can't read PHY_PHYIDR2 register %#x", PHY_PHYIDR2); + return (0); + } + + DBG("ID1 %#x, ID2 %#x\n", id1, id2); + + if ((id1 == 0x141) && ((id2 & 0xFFF0) == 0x0CC0)) + return (1); + + ERR("ID1 or ID2 not corrected"); + + return (0); +} + +int marvell88e1111_get_link_speed(int phy_addr) +{ + u_int16_t val; + volatile emac_regs *emac = (emac_regs *) EMAC_BASE_ADDR; + + DBG("starting %s", __func__); + + if (!davinci_eth_phy_read(phy_addr, PHY_BMSR, &val)) { + ERR("can't read PHY_BMSR register %#x", PHY_BMSR); + return (0); + } + + if (val & LINK_DOWN) { + ERR("link down"); + return (0); + } + DBG("link up"); + + if (!davinci_eth_phy_read(phy_addr, PHY_BMCR, &val)) { + ERR("can't read PHY_BMCR register %#x", PHY_BMCR); + return (0); + } + + if (val & PHY_BMCR_DPLX) { + DBG("set emac full duplex mode"); + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | + EMAC_MACCONTROL_FULLDUPLEX_ENABLE; + } else { + DBG("set emac half duplex mode"); + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; + } + + return (1); +} + +int marvell88e1111_init_phy(int phy_addr) +{ + int ret = 1; + + DBG("starting %s\n", __func__); + +#if defined(CFG_DM365_EVM) || defined(CFG_DM365_IPNC) || defined(CFG_DM368_IPNC) + u_int16_t tmp; + + if (!davinci_eth_phy_read(phy_addr, + EXTENDED_PHY_SPECIFIC_STATUS_REGISTER, &tmp)) { + ERR("can't read Extended PHY Status register %#x", + EXTENDED_PHY_SPECIFIC_STATUS_REGISTER); + return (0); + } + if (!davinci_eth_phy_write(phy_addr, + EXTENDED_PHY_SPECIFIC_STATUS_REGISTER, tmp | 0xF)) { + ERR("can't set GMII to cooper mode"); + return (0); + } + DBG("hardware configred set in GMII to cooper mode"); + + if (!marvell88e1111_auto_negotiate(phy_addr)) + ret = marvell88e1111_auto_negotiate(phy_addr); +#else + if (!marvell88e1111_get_link_speed(phy_addr)) + ret = marvell88e1111_get_link_speed(phy_addr); +#endif + + return (ret); +} + +int marvell88e1111_auto_negotiate(int phy_addr) +{ + u_int16_t tmp; + + DBG("starting %s", __func__); + +#if defined(CFG_DM365_EVM) || defined(CFG_DM365_IPNC) || defined(CFG_DM368_IPNC) + /* disable autonegotiation 1000Mb/s */ + if (!davinci_eth_phy_read(phy_addr, PHY_1000BTCR, &tmp)) { + ERR("can't read PHY_1000BTCR register %#x", PHY_1000BTCR); + return (0); + } + if (!davinci_eth_phy_write(phy_addr, PHY_1000BTCR, + tmp & (~(PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD)))) { + ERR("can't disable 1000Mb/s autonegotiation"); + return (0); + } + DBG("1000Mb/s autonegotiation disabled"); +#endif + + if (!davinci_eth_phy_read(phy_addr, PHY_BMCR, &tmp)) { + ERR("can't read PHY_BMCR register %#x", PHY_BMCR); + return (0); + } + + tmp |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG | PHY_BMCR_RESET); + davinci_eth_phy_write(phy_addr, PHY_BMCR, tmp); + + udelay(10000); + if (!davinci_eth_phy_read(phy_addr, PHY_BMSR, &tmp)) { + ERR("can't read PHY_BMSR register %#x", PHY_BMSR); + return (0); + } + + if (tmp & PHY_BMSR_AUTN_COMP) + DBG("autonegotiation completed"); + else { + ERR("autonegotiation not completed"); + return (0); + } + + return (marvell88e1111_get_link_speed(phy_addr)); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ diff --git a/include/asm-arm/arch-davinci/emac_defs.h b/include/asm-arm/arch-davinci/emac_defs.h index fafbce4..b0aca7c 100644 --- a/include/asm-arm/arch-davinci/emac_defs.h +++ b/include/asm-arm/arch-davinci/emac_defs.h @@ -349,4 +349,10 @@ int rtl8201_get_link_speed(int phy_addr); int rtl8201_init_phy(int phy_addr); int rtl8201_auto_negotiate(int phy_addr); +#define PHY_MARVEL88E1111 (0x1410CC2) +int marvell88e1111_is_phy_connected(int phy_addr); +int marvell88e1111_get_link_speed(int phy_addr); +int marvell88e1111_init_phy(int phy_addr); +int marvell88e1111_auto_negotiate(int phy_addr); + #endif /* _DM644X_EMAC_H_ */