Modifications for 1.0.6:
======================================================================
+* Patch by Jerry Van Baren, 19 Sep 2001:
+- tweaks to SBC8260 configuration
+- added "mii" command to read and write MII PHY registers; it will
+ also do a simple "info" where it finds all MII PHYs and prints some
+ info from their registers.
+
* Patch by David Updegraff, 05 Oct 2001:
- Added "reginfo" command for 405GP
- Added DHCP vendor extensions
cmd_nvedit.o cmd_pcmcia.o cmd_reginfo.o \
cmd_fdc.o cmd_scsi.o cmd_autoscript.o \
cmd_bedbug.o bedbug.o s_record.o dlmalloc.o \
- kgdb.o console.o lists.o devices.o flash.o cmd_i2c.o cmd_immap.o
+ kgdb.o console.o lists.o devices.o flash.o cmd_i2c.o \
+ cmd_immap.o miiphyutil.o miiphybb.o cmd_mii.o
OBJS = $(AOBJS) $(COBJS)
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ *
+ * 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
+ */
+
+/*
+ * MII Utilities
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <cmd_mii.h>
+#include <miiphy.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+
+/*
+ * Display values from last command.
+ */
+uint last_op;
+uint last_addr;
+uint last_data;
+uint last_reg;
+
+/*
+ * MII read/write
+ *
+ * Syntax:
+ * mii read {addr} {reg}
+ * mii write {addr} {reg} {data}
+ */
+
+void do_mii (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ char op;
+ unsigned char addr, reg;
+ unsigned short data;
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ op = last_op;
+ addr = last_addr;
+ data = last_data;
+ reg = last_reg;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0)
+ {
+ op = argv[1][0];
+ if (argc >= 3)
+ addr = simple_strtoul(argv[2], NULL, 16);
+ if (argc >= 4)
+ reg = simple_strtoul(argv[3], NULL, 16);
+ if (argc >= 5)
+ data = simple_strtoul(argv[4], NULL, 16);
+ }
+
+ /*
+ * check info/read/write.
+ */
+ if(op == 'i')
+ {
+ int j;
+ unsigned int oui;
+ unsigned char model;
+ unsigned char rev;
+
+ /*
+ * Look for any and all PHYs. Valid addresses are 0..31.
+ */
+ for(j = 0; j < 32; j++)
+ {
+ if(miiphy_info(j, &oui, &model, &rev) == 0)
+ {
+ printf("PHY 0x%02X: OUI = 0x%04X, Model = 0x%02X, Rev = 0x%02X, %3dbaseT, %s\n",
+ j, oui, model, rev,
+ miiphy_speed(j) == _100BASET ? 100 : 10,
+ miiphy_duplex(j) == FULL ? "FDX" : "HDX");
+ }
+ }
+ }
+ else if(op == 'r')
+ {
+ if(miiphy_read(addr, reg, &data) != 0)
+ printf("Error reading from the PHY\n");
+ printf("%04X\n", data & 0x0000FFFF);
+ }
+ else if(op == 'w')
+ {
+ if(miiphy_write(addr, reg, data) != 0)
+ printf("Error writing to the PHY\n");
+ }
+ else
+ {
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return;
+ }
+
+ /*
+ * Save the parameters for repeats.
+ */
+ last_op = op;
+ last_addr = addr;
+ last_data = data;
+}
+
+#endif /* CFG_CMD_MII */
#include <cmd_bsp.h> /* board special functions */
#include <cmd_fdc.h> /* Floppy support */
#include <cmd_scsi.h>
+#include <cmd_mii.h>
#include <cmd_bedbug.h>
CMD_TBL_STEP
CMD_TBL_NEXT
CMD_TBL_RDUMP
+ CMD_TBL_MII
/* the following entry terminates this table */
MK_CMD_TBL_ENTRY( NULL, 0, 0, 0, NULL, NULL, NULL )
};
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ *
+ * 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
+ */
+
+/*
+ * This provides a bit-banged interface to the ethernet MII management
+ * channel.
+ */
+
+#include <ppcboot.h>
+#include <ioports.h>
+#include <ppc_asm.tmpl>
+
+#ifdef CONFIG_BITBANGMII
+
+
+/*****************************************************************************
+ *
+ * Utility to send the preamble, address, and register (common to read
+ * and write).
+ */
+static void miiphy_pre(char read,
+ unsigned char addr,
+ unsigned char reg)
+{
+ int j; /* counter */
+ volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT);
+
+ /*
+ * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
+ * The IEEE spec says this is a PHY optional requirement. The AMD
+ * 79C874 requires one after power up and one after a MII communications
+ * error. This means that we are doing more preambles than we need,
+ * but it is safer and will be much more robust.
+ */
+ MDIO_ACTIVE;
+ MDIO(1);
+ for(j = 0; j < 32; j++)
+ {
+ MDC(0);
+ MIIDELAY;
+ MDC(1);
+ MIIDELAY;
+ }
+
+ /* send the start bit (01) and the read opcode (10) or write (10) */
+ MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY;
+ MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY;
+ MDC(0); MDIO(read); MIIDELAY; MDC(1); MIIDELAY;
+ MDC(0); MDIO(!read); MIIDELAY; MDC(1); MIIDELAY;
+
+ /* send the PHY address */
+ for(j = 0; j < 5; j++)
+ {
+ MDC(0);
+ if((addr & 0x10) == 0)
+ {
+ MDIO(0);
+ }
+ else
+ {
+ MDIO(1);
+ }
+ MIIDELAY;
+ MDC(1);
+ MIIDELAY;
+ addr <<= 1;
+ }
+
+ /* send the register address */
+ for(j = 0; j < 5; j++)
+ {
+ MDC(0);
+ if((reg & 0x10) == 0)
+ {
+ MDIO(0);
+ }
+ else
+ {
+ MDIO(1);
+ }
+ MIIDELAY;
+ MDC(1);
+ MIIDELAY;
+ reg <<= 1;
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * Read a MII PHY register.
+ *
+ * Returns:
+ * 0 on success
+ */
+int miiphy_read(unsigned char addr,
+ unsigned char reg,
+ unsigned short *value)
+{
+ short rdreg; /* register working value */
+ int j; /* counter */
+ volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT);
+
+ miiphy_pre(1, addr, reg);
+
+ /* tri-state our MDIO I/O pin so we can read */
+ MDC(0);
+ MDIO_TRISTATE;
+ MIIDELAY;
+ MDC(1);
+ MIIDELAY;
+
+ /* check the turnaround bit: the PHY should be driving it to zero */
+ if(MDIO_READ != 0)
+ {
+ /* printf("PHY didn't drive TA low\n"); */
+ return(-1);
+ }
+
+ MDC(0);
+ MIIDELAY;
+
+ /* read 16 bits of register data, MSB first */
+ rdreg = 0;
+ for(j = 0; j < 16; j++)
+ {
+ MDC(1);
+ MIIDELAY;
+ rdreg <<= 1;
+ rdreg |= MDIO_READ;
+ MDC(0);
+ MIIDELAY;
+ }
+
+ *value = rdreg;
+ return 0;
+}
+
+
+/*****************************************************************************
+ *
+ * Write a MII PHY register.
+ *
+ * Returns:
+ * 0 on success
+ */
+int miiphy_write(unsigned char addr,
+ unsigned char reg,
+ unsigned short value)
+{
+ int j; /* counter */
+ volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT);
+
+ miiphy_pre(0, addr, reg);
+
+ /* send the turnaround (10) */
+ MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY;
+ MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY;
+
+ /* write 16 bits of register data, MSB first */
+ for(j = 0; j < 16; j++)
+ {
+ MDC(0);
+ if((value & 0x00008000) == 0)
+ {
+ MDIO(0);
+ }
+ else
+ {
+ MDIO(1);
+ }
+ MIIDELAY;
+ MDC(1);
+ MIIDELAY;
+ value <<= 1;
+ }
+
+ /*
+ * Tri-state the MDIO line.
+ */
+ MDIO_TRISTATE;
+
+ return 0;
+}
+
+#endif /* CONFIG_BITBANGMII */
+
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ *
+ * 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
+ */
+
+/*
+ * This provides a bit-banged interface to the ethernet MII management
+ * channel.
+ */
+
+#include <ppcboot.h>
+#include <miiphy.h>
+
+#ifdef CONFIG_MII
+
+#undef DEBUG /* define for more debug messages */
+
+
+/*****************************************************************************
+ *
+ * Read the OUI, manufacture's model number, and revision number.
+ *
+ * OUI: 22 bits (unsigned int)
+ * Model: 6 bits (unsigned char)
+ * Revision: 4 bits (unsigned char)
+ *
+ * Returns:
+ * 0 on success
+ */
+int miiphy_info(unsigned char addr,
+ unsigned int *oui,
+ unsigned char *model,
+ unsigned char *rev)
+{
+ unsigned int reg;
+
+ /*
+ * Trick: we are reading two 16 registers into a 32 bit variable
+ * so we do a 16 read into the high order bits of the variable (big
+ * endian, you know), shift it down 16 bits, and the read the rest.
+ */
+ if(miiphy_read(addr, PHY_PHYIDR2, (unsigned short *)®) != 0)
+ {
+# ifdef DEBUG
+ printf("PHY ID register 2 read failed\n");
+# endif
+ return(-1);
+ }
+ reg >>= 16;
+ if(miiphy_read(addr, PHY_PHYIDR1, (unsigned short *)®) != 0)
+ {
+# ifdef DEBUG
+ printf("PHY ID register 1 read failed\n");
+# endif
+ return(-1);
+ }
+ *oui = (reg >> 10);
+ *model = (unsigned char)((reg >> 4) & 0x0000003F);
+ *rev = (unsigned char)( reg & 0x0000000F);
+ return(0);
+}
+
+
+/*****************************************************************************
+ *
+ * Reset the PHY.
+ * Returns:
+ * 0 on success
+ */
+int miiphy_reset(unsigned char addr)
+{
+ unsigned short reg;
+ int loop_cnt;
+
+ if(miiphy_write(addr, PHY_BMCR, 0x8000) != 0)
+ {
+# ifdef DEBUG
+ printf("PHY reset failed\n");
+# endif
+ return(-1);
+ }
+
+ /*
+ * Poll the control register for the reset bit to go to 0 (it is
+ * auto-clearing). This should happen within 0.5 seconds per the
+ * IEEE spec.
+ */
+ loop_cnt = 0;
+ reg = 0x8000;
+ while(((reg & 0x8000) != 0) && (loop_cnt++ < 1000000))
+ {
+ if(miiphy_read(addr, PHY_BMCR, ®) != 0)
+ {
+# ifdef DEBUG
+ printf("PHY status read failed\n");
+# endif
+ return(-1);
+ }
+ }
+ if((reg & 0x8000) == 0)
+ {
+ return(0);
+ }
+ else
+ {
+ printf("PHY reset timed out\n");
+ return(-1);
+ }
+ return(0);
+}
+
+
+/*****************************************************************************
+ *
+ * Determine the ethernet speed (10/100).
+ */
+int miiphy_speed(unsigned char addr)
+{
+ unsigned short reg;
+
+ if(miiphy_read(addr, PHY_ANLPAR, ®))
+ {
+ printf("PHY speed1 read failed, assuming 10bT\n");
+ return(_10BASET);
+ }
+
+ if((reg & PHY_ANLPAR_100) != 0)
+ {
+ return(_100BASET);
+ }
+ else
+ {
+ return(_10BASET);
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * Determine full/half duplex.
+ */
+int miiphy_duplex(unsigned char addr)
+{
+ unsigned short reg;
+
+ if(miiphy_read(addr, PHY_ANLPAR, ®))
+ {
+ printf("PHY duplex read failed, assuming half duplex\n");
+ return(HALF);
+ }
+
+ if((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0)
+ {
+ return(FULL);
+ }
+ else
+ {
+ return(HALF);
+ }
+}
+
+#endif /* CONFIG_MII */
+
for(i=0; i<0x1A; i++)
{
- if(miiphy_read(i, &data))
+ if(miiphy_read(0, i, &data))
{
printf("read error for reg %lx\n",i);
return;
/* read a phy reg and return the value with a rc */
/***********************************************************/
-int miiphy_read(unsigned char reg, unsigned short * value)
+int miiphy_read(unsigned char addr, unsigned char reg, unsigned short * value)
{
unsigned long sta_reg; /* STA scratch area */
unsigned long i;
/* write a phy reg and return the value with a rc */
/***********************************************************/
-int miiphy_write(unsigned char reg, unsigned short value)
+int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
{
unsigned long sta_reg; /* STA scratch area */
unsigned long i;
int speed = _10BASET; /* Assume 10Mbs */
unsigned short bmcr = 0x0;
- if (miiphy_read(PHY_ANLPAR,&bmcr)) {
+ if (miiphy_read(0,PHY_ANLPAR,&bmcr)) {
printf("phy speed1 read failed \n");
miiphy_dump();
}
int speed = HALF; /* Assume HALF */
unsigned short bmcr = 0x0;
- if (miiphy_read(PHY_ANLPAR,&bmcr))
+ if (miiphy_read(0,PHY_ANLPAR,&bmcr))
{
printf("phy duplex read failed \n");
miiphy_dump();
#define CFG_CMD_FDC 0x04000000 /* Floppy Disk Support */
#define CFG_CMD_SCSI 0x08000000 /* SCSI Support */
#define CFG_CMD_AUTOSCRIPT 0x10000000 /* Autoscript Support */
-#define CFG_CMD_BSP 0x80000000 /* Board SPecific functions */
+#define CFG_CMD_MII 0x20000000 /* MII support */
+#define CFG_CMD_BSP 0x80000000 /* Board Specific functions */
#define CFG_CMD_ALL 0xFFFFFFFF /* ALL commands */
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ *
+ * 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
+ */
+
+/*
+ * MII Functions
+ */
+#ifndef _CMD_MII_H
+#define _CMD_MII_H
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+#define CMD_TBL_MII MK_CMD_TBL_ENTRY( \
+ "mii", 3, 5, 1, do_mii, \
+ "mii - MII utility commands\n", \
+ "\
+info <addr> - display MII PHY info\n\
+mii read <addr> <reg> - read MII PHY <addr> register <reg>\n\
+mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n" \
+),
+
+void do_mii (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+
+#else
+#define CMD_TBL_MII
+#endif /* CFG_CMD_MII */
+
+#endif /* _CMD_MII_H */
*****************************************************************************/
/* What is the oscillator's (UX2) frequency in Hz? */
-#define CONFIG_8260_CLKIN (33 * 1000 * 1000)
+#define CONFIG_8260_CLKIN (66 * 1000 * 1000)
/*-----------------------------------------------------------------------
* MODCK_H & MODCLK[1-3] - Ref: Section 9.2 in MPC8206 User Manual
* 0x6 0x1 66 133 266 Close Close Open
* 0x6 0x2 66 133 300 Close Open Close
*/
-#define CFG_SBC_MODCK_H 0x02
+#define CFG_SBC_MODCK_H 0x05
/* Define this if you want to boot from 0x00000100. If you don't define
* this, you will need to program the bootloader to 0xfff00000, and
#define CONFIG_ETHER_ON_FCC /* define if ethernet on FCC */
#undef CONFIG_ETHER_NONE /* define if ethernet on neither */
#define CONFIG_ETHER_INDEX 2 /* which SCC/FCC channel for ethernet */
+#define CONFIG_MII /* MII PHY management */
+#define CONFIG_BITBANGMII /* bit-bang MII PHY management */
+/*
+ * Port pins used for bit-banged MII communictions (if applicable).
+ */
+#define MDIO_PORT 2 /* Port C */
+#define MDIO_ACTIVE (iop->pdir |= 0x00400000)
+#define MDIO_TRISTATE (iop->pdir &= ~0x00400000)
+#define MDIO_READ ((iop->pdat & 0x00400000) != 0)
+
+#define MDIO(bit) if(bit) iop->pdat |= 0x00400000; \
+ else iop->pdat &= ~0x00400000
+
+#define MDC(bit) if(bit) iop->pdat |= 0x00200000; \
+ else iop->pdat &= ~0x00200000
+
+#define MIIDELAY udelay(1)
#endif /* CONFIG_ETHER_USE_FCC2 */
/* Define this to reserve an entire FLASH sector (256 KB) for
#define CFG_PROMPT "=> "
/* What ppcboot subsytems do you want enabled? */
-#define CONFIG_COMMANDS (((CONFIG_CMD_DFL & ~(CFG_CMD_KGDB))) | CFG_CMD_BEDBUG)
+#define CONFIG_COMMANDS (((CONFIG_CMD_DFL & ~(CFG_CMD_KGDB))) | \
+ CFG_CMD_BEDBUG | \
+ CFG_CMD_ASKENV | \
+ CFG_CMD_ECHO | \
+ CFG_CMD_I2C | \
+ CFG_CMD_REGINFO | \
+ CFG_CMD_IMMAP | \
+ CFG_CMD_MII | \
+ CFG_CMD_BSP)
+
/* Where do the internal registers live? */
#define CFG_IMMR 0xf0000000
+----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------+
|
-| File Name: dp83843.h
+| File Name: miiphy.h
|
-| Function: Include file for NS DP83843 PHY.
+| Function: Include file defining PHY registers.
|
| Author: Mark Wisner
|
| --------- --------------------- ---
| 04-May-99 Created MKW
| 07-Jul-99 Added full duplex support MKW
+| 08-Sep-01 Tweaks gvb
|
+----------------------------------------------------------------------------*/
#ifndef _miiphy_h_
#define _miiphy_h_
-int miiphy_read(unsigned char reg, unsigned short * value);
-int miiphy_write(unsigned char reg, unsigned short value);
-void miiphy_dump(void);
-int miiphy_speed(void);
-int miiphy_duplex(void);
+int miiphy_read(unsigned char addr, unsigned char reg, unsigned short * value);
+int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value);
+int miiphy_info(unsigned char addr, unsigned int *oui, unsigned char *model,
+ unsigned char *rev);
+int miiphy_reset(unsigned char addr);
+int miiphy_speed(unsigned char addr);
+int miiphy_duplex(unsigned char addr);
/* phy seed setup */
/* phy register offsets */
#define PHY_BMCR 0x00
#define PHY_BMSR 0x01
-#define PHY_PHY1DR1 0x02
+#define PHY_PHYIDR1 0x02
#define PHY_PHYIDR2 0x03
#define PHY_ANAR 0x04
#define PHY_ANLPAR 0x05