From patchwork Mon Apr 22 11:16:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dirk Eibach X-Patchwork-Id: 238459 X-Patchwork-Delegate: sr@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 A37092C009B for ; Mon, 22 Apr 2013 21:17:57 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 032DD4A494; Mon, 22 Apr 2013 13:17:44 +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 FzTtD6q2RUHQ; Mon, 22 Apr 2013 13:17:43 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3414B4A2DC; Mon, 22 Apr 2013 13:17:10 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A870A4A29C for ; Mon, 22 Apr 2013 13:17:01 +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 ZjCvzhYB2q+o for ; Mon, 22 Apr 2013 13:16:58 +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 sputnik.urmx.de (sputnik.urmx.de [88.198.51.18]) by theia.denx.de (Postfix) with ESMTP id 8A9CE4A2FD for ; Mon, 22 Apr 2013 13:16:54 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by sputnik.urmx.de (Postfix) with ESMTP id 22CE660222D4 for ; Mon, 22 Apr 2013 13:16:54 +0200 (CEST) X-Virus-Scanned: amavisd-new at urmx.de Received: from sputnik.urmx.de ([127.0.0.1]) by localhost (sputnik.urmx.de [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id Jz51tNUuZG4A for ; Mon, 22 Apr 2013 13:16:53 +0200 (CEST) Received: from utm1.gdsys.de (unknown [195.243.218.178]) by mforward1.urmx.de (Postfix) with ESMTPS id AC2B860222D5 for ; Mon, 22 Apr 2013 13:16:53 +0200 (CEST) Received: from [172.16.100.239] (port=55421 helo=smgw1.gd.local) by utm1.gdsys.de with esmtp (Exim 4.76) (envelope-from ) id 1UUEjq-0000nS-18 for u-boot@lists.denx.de; Mon, 22 Apr 2013 13:16:50 +0200 Received: from smgw1.gd.local (localhost [127.0.0.1]) by smgw1.gd.local (Postfix) with ESMTP id 450591A30FB for ; Mon, 22 Apr 2013 13:16:50 +0200 (CEST) From: Dirk Eibach To: u-boot@lists.denx.de, Stefan Roese Date: Mon, 22 Apr 2013 13:16:09 +0200 Message-Id: <1366629372-32022-9-git-send-email-eibach@gdsys.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1366629372-32022-1-git-send-email-eibach@gdsys.de> References: <1366629372-32022-1-git-send-email-eibach@gdsys.de> X-SafeGuard_MailGateway: Version: 5.80.2.12968 SGMG_SOPHOS Date: 20130422111650Z Subject: [U-Boot] [PATCH 08/11] powerpc/ppc4xx: Fixup phy erratum on gdsys iocon hardware 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 Marvell 88E1518 has an erratum that requires fixing up. This patch checks for presence of this phy and adds code for fixup. Signed-off-by: Dirk Eibach --- board/gdsys/405ep/iocon.c | 214 +++++++++++++++++++++++++++++++++++++++++++++ include/configs/iocon.h | 3 + 2 files changed, 217 insertions(+) diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c index ece45d6..45c5b36 100644 --- a/board/gdsys/405ep/iocon.c +++ b/board/gdsys/405ep/iocon.c @@ -38,6 +38,8 @@ #include #include +#include + DECLARE_GLOBAL_DATA_PTR; #define LATCH0_BASE (CONFIG_SYS_LATCH_BASE) @@ -95,8 +97,16 @@ enum { MCFPGA_RESET_N = 1 << 4, }; +enum { + GPIO_MDC = 1 << 14, + GPIO_MDIO = 1 << 15, +}; + unsigned int mclink_fpgacount; +static int setup_88e1518(const char *bus, unsigned char addr); +static int verify_88e1518(const char *bus, unsigned char addr); + void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) { int res; @@ -339,6 +349,7 @@ int last_stage_init(void) int slaves; unsigned int k; unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 }; + int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM; print_fpga_info(0); osd_probe(0); @@ -360,6 +371,16 @@ int last_stage_init(void) } } + if (!legacy) { + miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read, + bb_miiphy_write); + if (!verify_88e1518(bb_miiphy_buses[0].name, 0)) { + printf("Fixup 88e1518 erratum on %s\n", + bb_miiphy_buses[0].name); + setup_88e1518(bb_miiphy_buses[0].name, 0); + } + } + /* wait for slave-PLLs to be up and running */ udelay(500000); @@ -375,6 +396,13 @@ int last_stage_init(void) for (k = 1; k <= slaves; ++k) { print_fpga_info(k); osd_probe(k); + miiphy_register(bb_miiphy_buses[k].name, + bb_miiphy_read, bb_miiphy_write); + if (!verify_88e1518(bb_miiphy_buses[k].name, 0)) { + printf("Fixup 88e1518 erratum on %s\n", + bb_miiphy_buses[k].name); + setup_88e1518(bb_miiphy_buses[k].name, 0); + } } return 0; @@ -446,3 +474,189 @@ int gd405ep_get_fpga_done(unsigned fpga) else return pca9698_get_value(0x20, 20); } + +/* + * FPGA MII bitbang implementation + */ + +struct fpga_mii { + unsigned fpga; + int mdio; +} fpga_mii[] = { + { 0, 1}, + { 1, 1}, + { 2, 1}, + { 3, 1}, +}; + +static int mii_dummy_init(struct bb_miiphy_bus *bus) +{ + return 0; +} + +static int mii_mdio_active(struct bb_miiphy_bus *bus) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (fpga_mii->mdio) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDIO); + + return 0; +} + +static int mii_mdio_tristate(struct bb_miiphy_bus *bus) +{ + struct fpga_mii *fpga_mii = bus->priv; + + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + + return 0; +} + +static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (v) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDIO); + + fpga_mii->mdio = v; + + return 0; +} + +static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + *v = ((fpga_get_reg(fpga_mii->fpga, REG(gpio.read)) & GPIO_MDIO) != 0); + + return 0; +} + +static int mii_set_mdc(struct bb_miiphy_bus *bus, int v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (v) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDC); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDC); + + return 0; +} + +static int mii_delay(struct bb_miiphy_bus *bus) +{ + udelay(1); + + return 0; +} + +struct bb_miiphy_bus bb_miiphy_buses[] = { + { + .name = "trans1", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[0], + }, + { + .name = "trans2", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[1], + }, + { + .name = "trans3", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[2], + }, + { + .name = "trans4", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[3], + }, +}; + +int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / + sizeof(bb_miiphy_buses[0]); + +/* + * Workaround for erratum mentioned in 88E1518 release notes + */ + +static int verify_88e1518(const char *bus, unsigned char addr) +{ + u16 phy_id1, phy_id2; + + if (miiphy_read(bus, addr, 2, &phy_id1) || + miiphy_read(bus, addr, 3, &phy_id2)) { + printf("Error reading from the PHY addr=%02x\n", addr); + return -EIO; + } + + if ((phy_id1 != 0x0141) || ((phy_id2 & 0xfff0) != 0x0dd0)) + return -EINVAL; + + return 0; +} + +struct regfix_88e1518 { + u8 reg; + u16 data; +} regfix_88e1518[] = { + { 22, 0x00ff }, + { 17, 0x214b }, + { 16, 0x2144 }, + { 17, 0x0c28 }, + { 16, 0x2146 }, + { 17, 0xb233 }, + { 16, 0x214d }, + { 17, 0xcc0c }, + { 16, 0x2159 }, + { 22, 0x00fb }, + { 7, 0xc00d }, + { 22, 0x0000 }, +}; + +static int setup_88e1518(const char *bus, unsigned char addr) +{ + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(regfix_88e1518); ++k) { + if (miiphy_write(bus, addr, + regfix_88e1518[k].reg, + regfix_88e1518[k].data)) { + printf("Error writing to the PHY addr=%02x\n", addr); + return -1; + } + } + + return 0; +} diff --git a/include/configs/iocon.h b/include/configs/iocon.h index e99efa6..441b37b 100644 --- a/include/configs/iocon.h +++ b/include/configs/iocon.h @@ -274,4 +274,7 @@ int fpga_gpio_get(unsigned int bus, int pin); #define CONFIG_SYS_CH7301 #define CONFIG_SYS_OSD_SCREENS 1 +#define CONFIG_BITBANGMII /* bit-bang MII PHY management */ +#define CONFIG_BITBANGMII_MULTI + #endif /* __CONFIG_H */