155195773SJean-Christophe PLAGNIOL-VILLARD /* 24ba31ab3SLuigi 'Comio' Mantellini * (C) Copyright 2009 Industrie Dial Face S.p.A. 34ba31ab3SLuigi 'Comio' Mantellini * Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com> 44ba31ab3SLuigi 'Comio' Mantellini * 555195773SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2001 655195773SJean-Christophe PLAGNIOL-VILLARD * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 755195773SJean-Christophe PLAGNIOL-VILLARD * 855195773SJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 955195773SJean-Christophe PLAGNIOL-VILLARD * project. 1055195773SJean-Christophe PLAGNIOL-VILLARD * 1155195773SJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 1255195773SJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 1355195773SJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 1455195773SJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 1555195773SJean-Christophe PLAGNIOL-VILLARD * 1655195773SJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 1755195773SJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 1855195773SJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1955195773SJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 2055195773SJean-Christophe PLAGNIOL-VILLARD * 2155195773SJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 2255195773SJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 2355195773SJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2455195773SJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 2555195773SJean-Christophe PLAGNIOL-VILLARD */ 2655195773SJean-Christophe PLAGNIOL-VILLARD 2755195773SJean-Christophe PLAGNIOL-VILLARD /* 2855195773SJean-Christophe PLAGNIOL-VILLARD * This provides a bit-banged interface to the ethernet MII management 2955195773SJean-Christophe PLAGNIOL-VILLARD * channel. 3055195773SJean-Christophe PLAGNIOL-VILLARD */ 3155195773SJean-Christophe PLAGNIOL-VILLARD 3255195773SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 3355195773SJean-Christophe PLAGNIOL-VILLARD #include <ioports.h> 3455195773SJean-Christophe PLAGNIOL-VILLARD #include <ppc_asm.tmpl> 354ba31ab3SLuigi 'Comio' Mantellini #include <miiphy.h> 364ba31ab3SLuigi 'Comio' Mantellini 374ba31ab3SLuigi 'Comio' Mantellini #define BB_MII_RELOCATE(v,off) (v += (v?off:0)) 384ba31ab3SLuigi 'Comio' Mantellini 394ba31ab3SLuigi 'Comio' Mantellini DECLARE_GLOBAL_DATA_PTR; 404ba31ab3SLuigi 'Comio' Mantellini 414ba31ab3SLuigi 'Comio' Mantellini #ifndef CONFIG_BITBANGMII_MULTI 424ba31ab3SLuigi 'Comio' Mantellini 434ba31ab3SLuigi 'Comio' Mantellini /* 444ba31ab3SLuigi 'Comio' Mantellini * If CONFIG_BITBANGMII_MULTI is not defined we use a 454ba31ab3SLuigi 'Comio' Mantellini * compatibility layer with the previous miiphybb implementation 464ba31ab3SLuigi 'Comio' Mantellini * based on macros usage. 474ba31ab3SLuigi 'Comio' Mantellini * 484ba31ab3SLuigi 'Comio' Mantellini */ 494ba31ab3SLuigi 'Comio' Mantellini static int bb_mii_init_wrap(struct bb_miiphy_bus *bus) 504ba31ab3SLuigi 'Comio' Mantellini { 514ba31ab3SLuigi 'Comio' Mantellini #ifdef MII_INIT 524ba31ab3SLuigi 'Comio' Mantellini MII_INIT; 534ba31ab3SLuigi 'Comio' Mantellini #endif 544ba31ab3SLuigi 'Comio' Mantellini return 0; 554ba31ab3SLuigi 'Comio' Mantellini } 564ba31ab3SLuigi 'Comio' Mantellini 574ba31ab3SLuigi 'Comio' Mantellini static int bb_mdio_active_wrap(struct bb_miiphy_bus *bus) 584ba31ab3SLuigi 'Comio' Mantellini { 594ba31ab3SLuigi 'Comio' Mantellini #ifdef MDIO_DECLARE 604ba31ab3SLuigi 'Comio' Mantellini MDIO_DECLARE; 614ba31ab3SLuigi 'Comio' Mantellini #endif 624ba31ab3SLuigi 'Comio' Mantellini MDIO_ACTIVE; 634ba31ab3SLuigi 'Comio' Mantellini return 0; 644ba31ab3SLuigi 'Comio' Mantellini } 654ba31ab3SLuigi 'Comio' Mantellini 664ba31ab3SLuigi 'Comio' Mantellini static int bb_mdio_tristate_wrap(struct bb_miiphy_bus *bus) 674ba31ab3SLuigi 'Comio' Mantellini { 684ba31ab3SLuigi 'Comio' Mantellini #ifdef MDIO_DECLARE 694ba31ab3SLuigi 'Comio' Mantellini MDIO_DECLARE; 704ba31ab3SLuigi 'Comio' Mantellini #endif 714ba31ab3SLuigi 'Comio' Mantellini MDIO_TRISTATE; 724ba31ab3SLuigi 'Comio' Mantellini return 0; 734ba31ab3SLuigi 'Comio' Mantellini } 744ba31ab3SLuigi 'Comio' Mantellini 754ba31ab3SLuigi 'Comio' Mantellini static int bb_set_mdio_wrap(struct bb_miiphy_bus *bus, int v) 764ba31ab3SLuigi 'Comio' Mantellini { 774ba31ab3SLuigi 'Comio' Mantellini #ifdef MDIO_DECLARE 784ba31ab3SLuigi 'Comio' Mantellini MDIO_DECLARE; 794ba31ab3SLuigi 'Comio' Mantellini #endif 804ba31ab3SLuigi 'Comio' Mantellini MDIO(v); 814ba31ab3SLuigi 'Comio' Mantellini return 0; 824ba31ab3SLuigi 'Comio' Mantellini } 834ba31ab3SLuigi 'Comio' Mantellini 844ba31ab3SLuigi 'Comio' Mantellini static int bb_get_mdio_wrap(struct bb_miiphy_bus *bus, int *v) 854ba31ab3SLuigi 'Comio' Mantellini { 864ba31ab3SLuigi 'Comio' Mantellini #ifdef MDIO_DECLARE 874ba31ab3SLuigi 'Comio' Mantellini MDIO_DECLARE; 884ba31ab3SLuigi 'Comio' Mantellini #endif 894ba31ab3SLuigi 'Comio' Mantellini *v = MDIO_READ; 904ba31ab3SLuigi 'Comio' Mantellini return 0; 914ba31ab3SLuigi 'Comio' Mantellini } 924ba31ab3SLuigi 'Comio' Mantellini 934ba31ab3SLuigi 'Comio' Mantellini static int bb_set_mdc_wrap(struct bb_miiphy_bus *bus, int v) 944ba31ab3SLuigi 'Comio' Mantellini { 954ba31ab3SLuigi 'Comio' Mantellini #ifdef MDC_DECLARE 964ba31ab3SLuigi 'Comio' Mantellini MDC_DECLARE; 974ba31ab3SLuigi 'Comio' Mantellini #endif 984ba31ab3SLuigi 'Comio' Mantellini MDC(v); 994ba31ab3SLuigi 'Comio' Mantellini return 0; 1004ba31ab3SLuigi 'Comio' Mantellini } 1014ba31ab3SLuigi 'Comio' Mantellini 1024ba31ab3SLuigi 'Comio' Mantellini static int bb_delay_wrap(struct bb_miiphy_bus *bus) 1034ba31ab3SLuigi 'Comio' Mantellini { 1044ba31ab3SLuigi 'Comio' Mantellini MIIDELAY; 1054ba31ab3SLuigi 'Comio' Mantellini return 0; 1064ba31ab3SLuigi 'Comio' Mantellini } 1074ba31ab3SLuigi 'Comio' Mantellini 1084ba31ab3SLuigi 'Comio' Mantellini struct bb_miiphy_bus bb_miiphy_buses[] = { 1094ba31ab3SLuigi 'Comio' Mantellini { 1104ba31ab3SLuigi 'Comio' Mantellini .name = BB_MII_DEVNAME, 1114ba31ab3SLuigi 'Comio' Mantellini .init = bb_mii_init_wrap, 1124ba31ab3SLuigi 'Comio' Mantellini .mdio_active = bb_mdio_active_wrap, 1134ba31ab3SLuigi 'Comio' Mantellini .mdio_tristate = bb_mdio_tristate_wrap, 1144ba31ab3SLuigi 'Comio' Mantellini .set_mdio = bb_set_mdio_wrap, 1154ba31ab3SLuigi 'Comio' Mantellini .get_mdio = bb_get_mdio_wrap, 1164ba31ab3SLuigi 'Comio' Mantellini .set_mdc = bb_set_mdc_wrap, 1174ba31ab3SLuigi 'Comio' Mantellini .delay = bb_delay_wrap, 1184ba31ab3SLuigi 'Comio' Mantellini } 1194ba31ab3SLuigi 'Comio' Mantellini }; 1204ba31ab3SLuigi 'Comio' Mantellini 1214ba31ab3SLuigi 'Comio' Mantellini int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / 1224ba31ab3SLuigi 'Comio' Mantellini sizeof(bb_miiphy_buses[0]); 1234ba31ab3SLuigi 'Comio' Mantellini #endif 1244ba31ab3SLuigi 'Comio' Mantellini 1254ba31ab3SLuigi 'Comio' Mantellini void bb_miiphy_init(void) 1264ba31ab3SLuigi 'Comio' Mantellini { 1274ba31ab3SLuigi 'Comio' Mantellini int i; 1284ba31ab3SLuigi 'Comio' Mantellini 1294ba31ab3SLuigi 'Comio' Mantellini for (i = 0; i < bb_miiphy_buses_num; i++) { 1304ba31ab3SLuigi 'Comio' Mantellini #if !defined(CONFIG_RELOC_FIXUP_WORKS) 1314ba31ab3SLuigi 'Comio' Mantellini /* Relocate the hook pointers*/ 1324ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].init, gd->reloc_off); 1334ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].mdio_active, gd->reloc_off); 1344ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].mdio_tristate, gd->reloc_off); 1354ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].set_mdio, gd->reloc_off); 1364ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].get_mdio, gd->reloc_off); 1374ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].set_mdc, gd->reloc_off); 1384ba31ab3SLuigi 'Comio' Mantellini BB_MII_RELOCATE(bb_miiphy_buses[i].delay, gd->reloc_off); 1394ba31ab3SLuigi 'Comio' Mantellini #endif 1404ba31ab3SLuigi 'Comio' Mantellini if (bb_miiphy_buses[i].init != NULL) { 1414ba31ab3SLuigi 'Comio' Mantellini bb_miiphy_buses[i].init(&bb_miiphy_buses[i]); 1424ba31ab3SLuigi 'Comio' Mantellini } 1434ba31ab3SLuigi 'Comio' Mantellini } 1444ba31ab3SLuigi 'Comio' Mantellini } 1454ba31ab3SLuigi 'Comio' Mantellini 146*d7fb9bcfSBen Warren static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname) 1474ba31ab3SLuigi 'Comio' Mantellini { 1484ba31ab3SLuigi 'Comio' Mantellini #ifdef CONFIG_BITBANGMII_MULTI 1494ba31ab3SLuigi 'Comio' Mantellini int i; 1504ba31ab3SLuigi 'Comio' Mantellini 1514ba31ab3SLuigi 'Comio' Mantellini /* Search the correct bus */ 1524ba31ab3SLuigi 'Comio' Mantellini for (i = 0; i < bb_miiphy_buses_num; i++) { 1534ba31ab3SLuigi 'Comio' Mantellini if (!strcmp(bb_miiphy_buses[i].name, devname)) { 1544ba31ab3SLuigi 'Comio' Mantellini return &bb_miiphy_buses[i]; 1554ba31ab3SLuigi 'Comio' Mantellini } 1564ba31ab3SLuigi 'Comio' Mantellini } 1574ba31ab3SLuigi 'Comio' Mantellini return NULL; 1584ba31ab3SLuigi 'Comio' Mantellini #else 1594ba31ab3SLuigi 'Comio' Mantellini /* We have just one bitbanging bus */ 1604ba31ab3SLuigi 'Comio' Mantellini return &bb_miiphy_buses[0]; 1614ba31ab3SLuigi 'Comio' Mantellini #endif 1624ba31ab3SLuigi 'Comio' Mantellini } 16355195773SJean-Christophe PLAGNIOL-VILLARD 16455195773SJean-Christophe PLAGNIOL-VILLARD /***************************************************************************** 16555195773SJean-Christophe PLAGNIOL-VILLARD * 16655195773SJean-Christophe PLAGNIOL-VILLARD * Utility to send the preamble, address, and register (common to read 16755195773SJean-Christophe PLAGNIOL-VILLARD * and write). 16855195773SJean-Christophe PLAGNIOL-VILLARD */ 1694ba31ab3SLuigi 'Comio' Mantellini static void miiphy_pre(struct bb_miiphy_bus *bus, char read, 1704ba31ab3SLuigi 'Comio' Mantellini unsigned char addr, unsigned char reg) 17155195773SJean-Christophe PLAGNIOL-VILLARD { 1724ba31ab3SLuigi 'Comio' Mantellini int j; 17355195773SJean-Christophe PLAGNIOL-VILLARD 17455195773SJean-Christophe PLAGNIOL-VILLARD /* 17555195773SJean-Christophe PLAGNIOL-VILLARD * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure. 17655195773SJean-Christophe PLAGNIOL-VILLARD * The IEEE spec says this is a PHY optional requirement. The AMD 17755195773SJean-Christophe PLAGNIOL-VILLARD * 79C874 requires one after power up and one after a MII communications 17855195773SJean-Christophe PLAGNIOL-VILLARD * error. This means that we are doing more preambles than we need, 17955195773SJean-Christophe PLAGNIOL-VILLARD * but it is safer and will be much more robust. 18055195773SJean-Christophe PLAGNIOL-VILLARD */ 18155195773SJean-Christophe PLAGNIOL-VILLARD 1824ba31ab3SLuigi 'Comio' Mantellini bus->mdio_active(bus); 1834ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 1); 18455195773SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 32; j++) { 1854ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 1864ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 1874ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 1884ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 18955195773SJean-Christophe PLAGNIOL-VILLARD } 19055195773SJean-Christophe PLAGNIOL-VILLARD 19155195773SJean-Christophe PLAGNIOL-VILLARD /* send the start bit (01) and the read opcode (10) or write (10) */ 1924ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 1934ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 0); 1944ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 1954ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 1964ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 1974ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 1984ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 1); 1994ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2004ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2014ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2024ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 2034ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, read); 2044ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2054ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2064ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2074ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 2084ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, !read); 2094ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2104ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2114ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 21255195773SJean-Christophe PLAGNIOL-VILLARD 21355195773SJean-Christophe PLAGNIOL-VILLARD /* send the PHY address */ 21455195773SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 5; j++) { 2154ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 21655195773SJean-Christophe PLAGNIOL-VILLARD if ((addr & 0x10) == 0) { 2174ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 0); 21855195773SJean-Christophe PLAGNIOL-VILLARD } else { 2194ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 1); 22055195773SJean-Christophe PLAGNIOL-VILLARD } 2214ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2224ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2234ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 22455195773SJean-Christophe PLAGNIOL-VILLARD addr <<= 1; 22555195773SJean-Christophe PLAGNIOL-VILLARD } 22655195773SJean-Christophe PLAGNIOL-VILLARD 22755195773SJean-Christophe PLAGNIOL-VILLARD /* send the register address */ 22855195773SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 5; j++) { 2294ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 23055195773SJean-Christophe PLAGNIOL-VILLARD if ((reg & 0x10) == 0) { 2314ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 0); 23255195773SJean-Christophe PLAGNIOL-VILLARD } else { 2334ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 1); 23455195773SJean-Christophe PLAGNIOL-VILLARD } 2354ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2364ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2374ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 23855195773SJean-Christophe PLAGNIOL-VILLARD reg <<= 1; 23955195773SJean-Christophe PLAGNIOL-VILLARD } 24055195773SJean-Christophe PLAGNIOL-VILLARD } 24155195773SJean-Christophe PLAGNIOL-VILLARD 24255195773SJean-Christophe PLAGNIOL-VILLARD /***************************************************************************** 24355195773SJean-Christophe PLAGNIOL-VILLARD * 24455195773SJean-Christophe PLAGNIOL-VILLARD * Read a MII PHY register. 24555195773SJean-Christophe PLAGNIOL-VILLARD * 24655195773SJean-Christophe PLAGNIOL-VILLARD * Returns: 24755195773SJean-Christophe PLAGNIOL-VILLARD * 0 on success 24855195773SJean-Christophe PLAGNIOL-VILLARD */ 249*d7fb9bcfSBen Warren int bb_miiphy_read(const char *devname, unsigned char addr, 25055195773SJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short *value) 25155195773SJean-Christophe PLAGNIOL-VILLARD { 25255195773SJean-Christophe PLAGNIOL-VILLARD short rdreg; /* register working value */ 2534ba31ab3SLuigi 'Comio' Mantellini int v; 25455195773SJean-Christophe PLAGNIOL-VILLARD int j; /* counter */ 2554ba31ab3SLuigi 'Comio' Mantellini struct bb_miiphy_bus *bus; 2564ba31ab3SLuigi 'Comio' Mantellini 2574ba31ab3SLuigi 'Comio' Mantellini bus = bb_miiphy_getbus(devname); 2584ba31ab3SLuigi 'Comio' Mantellini if (bus == NULL) { 2594ba31ab3SLuigi 'Comio' Mantellini return -1; 2604ba31ab3SLuigi 'Comio' Mantellini } 26155195773SJean-Christophe PLAGNIOL-VILLARD 2623f6b18ffSRichard Retanubun if (value == NULL) { 2633f6b18ffSRichard Retanubun puts("NULL value pointer\n"); 2644ba31ab3SLuigi 'Comio' Mantellini return -1; 2653f6b18ffSRichard Retanubun } 2663f6b18ffSRichard Retanubun 2674ba31ab3SLuigi 'Comio' Mantellini miiphy_pre (bus, 1, addr, reg); 26855195773SJean-Christophe PLAGNIOL-VILLARD 26955195773SJean-Christophe PLAGNIOL-VILLARD /* tri-state our MDIO I/O pin so we can read */ 2704ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 2714ba31ab3SLuigi 'Comio' Mantellini bus->mdio_tristate(bus); 2724ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2734ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2744ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 27555195773SJean-Christophe PLAGNIOL-VILLARD 27655195773SJean-Christophe PLAGNIOL-VILLARD /* check the turnaround bit: the PHY should be driving it to zero */ 2774ba31ab3SLuigi 'Comio' Mantellini bus->get_mdio(bus, &v); 2784ba31ab3SLuigi 'Comio' Mantellini if (v != 0) { 27955195773SJean-Christophe PLAGNIOL-VILLARD /* puts ("PHY didn't drive TA low\n"); */ 28055195773SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 32; j++) { 2814ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 2824ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 2834ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2844ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 28555195773SJean-Christophe PLAGNIOL-VILLARD } 2863f6b18ffSRichard Retanubun /* There is no PHY, set value to 0xFFFF and return */ 2873f6b18ffSRichard Retanubun *value = 0xFFFF; 2884ba31ab3SLuigi 'Comio' Mantellini return -1; 28955195773SJean-Christophe PLAGNIOL-VILLARD } 29055195773SJean-Christophe PLAGNIOL-VILLARD 2914ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 2924ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 29355195773SJean-Christophe PLAGNIOL-VILLARD 29455195773SJean-Christophe PLAGNIOL-VILLARD /* read 16 bits of register data, MSB first */ 29555195773SJean-Christophe PLAGNIOL-VILLARD rdreg = 0; 29655195773SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 16; j++) { 2974ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 2984ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 29955195773SJean-Christophe PLAGNIOL-VILLARD rdreg <<= 1; 3004ba31ab3SLuigi 'Comio' Mantellini bus->get_mdio(bus, &v); 3014ba31ab3SLuigi 'Comio' Mantellini rdreg |= (v & 0x1); 3024ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 3034ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 30455195773SJean-Christophe PLAGNIOL-VILLARD } 30555195773SJean-Christophe PLAGNIOL-VILLARD 3064ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 3074ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3084ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 3094ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3104ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 3114ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 31255195773SJean-Christophe PLAGNIOL-VILLARD 31355195773SJean-Christophe PLAGNIOL-VILLARD *value = rdreg; 31455195773SJean-Christophe PLAGNIOL-VILLARD 31555195773SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 31655195773SJean-Christophe PLAGNIOL-VILLARD printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value); 31755195773SJean-Christophe PLAGNIOL-VILLARD #endif 31855195773SJean-Christophe PLAGNIOL-VILLARD 31955195773SJean-Christophe PLAGNIOL-VILLARD return 0; 32055195773SJean-Christophe PLAGNIOL-VILLARD } 32155195773SJean-Christophe PLAGNIOL-VILLARD 32255195773SJean-Christophe PLAGNIOL-VILLARD 32355195773SJean-Christophe PLAGNIOL-VILLARD /***************************************************************************** 32455195773SJean-Christophe PLAGNIOL-VILLARD * 32555195773SJean-Christophe PLAGNIOL-VILLARD * Write a MII PHY register. 32655195773SJean-Christophe PLAGNIOL-VILLARD * 32755195773SJean-Christophe PLAGNIOL-VILLARD * Returns: 32855195773SJean-Christophe PLAGNIOL-VILLARD * 0 on success 32955195773SJean-Christophe PLAGNIOL-VILLARD */ 330*d7fb9bcfSBen Warren int bb_miiphy_write (const char *devname, unsigned char addr, 33155195773SJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short value) 33255195773SJean-Christophe PLAGNIOL-VILLARD { 3334ba31ab3SLuigi 'Comio' Mantellini struct bb_miiphy_bus *bus; 33455195773SJean-Christophe PLAGNIOL-VILLARD int j; /* counter */ 33555195773SJean-Christophe PLAGNIOL-VILLARD 3364ba31ab3SLuigi 'Comio' Mantellini bus = bb_miiphy_getbus(devname); 3374ba31ab3SLuigi 'Comio' Mantellini if (bus == NULL) { 3384ba31ab3SLuigi 'Comio' Mantellini /* Bus not found! */ 3394ba31ab3SLuigi 'Comio' Mantellini return -1; 3404ba31ab3SLuigi 'Comio' Mantellini } 3414ba31ab3SLuigi 'Comio' Mantellini 3424ba31ab3SLuigi 'Comio' Mantellini miiphy_pre (bus, 0, addr, reg); 34355195773SJean-Christophe PLAGNIOL-VILLARD 34455195773SJean-Christophe PLAGNIOL-VILLARD /* send the turnaround (10) */ 3454ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 3464ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 1); 3474ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3484ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 3494ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3504ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 3514ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 0); 3524ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3534ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 3544ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 35555195773SJean-Christophe PLAGNIOL-VILLARD 35655195773SJean-Christophe PLAGNIOL-VILLARD /* write 16 bits of register data, MSB first */ 35755195773SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 16; j++) { 3584ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 35955195773SJean-Christophe PLAGNIOL-VILLARD if ((value & 0x00008000) == 0) { 3604ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 0); 36155195773SJean-Christophe PLAGNIOL-VILLARD } else { 3624ba31ab3SLuigi 'Comio' Mantellini bus->set_mdio(bus, 1); 36355195773SJean-Christophe PLAGNIOL-VILLARD } 3644ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3654ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 3664ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 36755195773SJean-Christophe PLAGNIOL-VILLARD value <<= 1; 36855195773SJean-Christophe PLAGNIOL-VILLARD } 36955195773SJean-Christophe PLAGNIOL-VILLARD 37055195773SJean-Christophe PLAGNIOL-VILLARD /* 37155195773SJean-Christophe PLAGNIOL-VILLARD * Tri-state the MDIO line. 37255195773SJean-Christophe PLAGNIOL-VILLARD */ 3734ba31ab3SLuigi 'Comio' Mantellini bus->mdio_tristate(bus); 3744ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 0); 3754ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 3764ba31ab3SLuigi 'Comio' Mantellini bus->set_mdc(bus, 1); 3774ba31ab3SLuigi 'Comio' Mantellini bus->delay(bus); 37855195773SJean-Christophe PLAGNIOL-VILLARD 37955195773SJean-Christophe PLAGNIOL-VILLARD return 0; 38055195773SJean-Christophe PLAGNIOL-VILLARD } 381