* Fixes for TQM8560 board:
[oweals/u-boot.git] / cpu / mpc85xx / tsec.c
index 0d858ed977bfb62505fbb460ca71fefb64e69632..d327a6decbc53438ab7d31f1d9a8f389ba3519a8 100644 (file)
 
 #define TX_BUF_CNT 2
 
-#undef TSEC_DEBUG
-#ifdef TSEC_DEBUG
-#define DBGPRINT(x,y) printf(x,y)
-#else
-#define DBGPRINT(x,y)
-#endif
-
 static uint rxIdx;     /* index of the current RX buffer */
 static uint txIdx;     /* index of the current TX buffer */
 
@@ -53,15 +46,15 @@ struct tsec_info_struct {
  * knowledge that all current implementations have 2 TSEC
  * devices, and one FEC.  The information needed is:
  *  phyaddr - The address of the PHY which is attached to
- *      the given device.
+ *     the given device.
  *
  *  gigabit - This variable indicates whether the device
- *      supports gigabit speed ethernet
+ *     supports gigabit speed ethernet
  *
  *  phyregidx - This variable specifies which ethernet device
- *      controls the MII Management registers which are connected
- *      to the PHY.  For 8540/8560, only TSEC1 (index 0) has
- *      access to the PHYs, so all of the entries have "0".
+ *     controls the MII Management registers which are connected
+ *     to the PHY.  For 8540/8560, only TSEC1 (index 0) has
+ *     access to the PHYs, so all of the entries have "0".
  *
  * The values specified in the table are taken from the board's
  * config file in include/configs/.  When implementing a new
@@ -78,12 +71,18 @@ struct tsec_info_struct {
 static struct tsec_info_struct tsec_info[] = {
 #ifdef CONFIG_MPC85XX_TSEC1
        {TSEC1_PHY_ADDR, 1, TSEC1_PHYIDX},
+#else
+       { 0, 0, 0},
 #endif
 #ifdef CONFIG_MPC85XX_TSEC2
        {TSEC2_PHY_ADDR, 1, TSEC2_PHYIDX},
+#else
+       { 0, 0, 0},
 #endif
 #ifdef CONFIG_MPC85XX_FEC
        {FEC_PHY_ADDR, 0, FEC_PHYIDX},
+#else
+       { 0, 0, 0},
 #endif
 };
 
@@ -142,7 +141,7 @@ int tsec_initialize(bd_t *bis, int index)
        priv->phyaddr = tsec_info[index].phyaddr;
        priv->gigabit = tsec_info[index].gigabit;
 
-       sprintf(dev->name, "MOTO ENET%d", index);
+       sprintf(dev->name, "ENET%d", index);
        dev->iobase = 0;
        dev->priv   = priv;
        dev->init   = tsec_init;
@@ -167,7 +166,7 @@ int tsec_initialize(bd_t *bis, int index)
 
 
 /* Initializes data structures and registers for the controller,
- * and brings the interface up.  Returns the link status, meaning
+ * and brings the interface up.         Returns the link status, meaning
  * that it returns success if the link is up, failure otherwise.
  * This allows u-boot to find the first active controller. */
 int tsec_init(struct eth_device* dev, bd_t * bd)
@@ -235,7 +234,7 @@ void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
 
 
 /* Reads register regnum on the device's PHY through the
- * registers specified in priv.  It lowers and raises the read
+ * registers specified in priv.         It lowers and raises the read
  * command, and waits for the data to become valid (miimind
  * notvalid bit cleared), and the bus to cease activity (miimind
  * busy bit cleared), and then returns the value
@@ -278,7 +277,21 @@ static int init_phy(struct eth_device *dev)
        struct phy_info *curphy;
 
        /* Assign a Physical address to the TBI */
-       priv->regs->tbipa=TBIPA_VALUE;
+
+       {
+               volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
+               regs->tbipa = TBIPA_VALUE;
+               regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
+               regs->tbipa = TBIPA_VALUE;
+               asm("msync");
+       }
+
+       /* Reset MII (due to new addresses) */
+       priv->phyregs->miimcfg = MIIMCFG_RESET;
+       asm("msync");
+       priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+       asm("msync");
+       while(priv->phyregs->miimind & MIIMIND_BUSY);
 
        if(0 == relocated)
                relocate_cmds();
@@ -550,9 +563,9 @@ static void startup_tsec(struct eth_device *dev)
        regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
 }
 
-/* This returns the status bits of the device.  The return value
+/* This returns the status bits of the device. The return value
  * is never checked, and this is what the 8260 driver did, so we
- * do the same.  Presumably, this would be zero if there were no
+ * do the same.         Presumably, this would be zero if there were no
  * errors */
 static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
 {
@@ -564,7 +577,7 @@ static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
        /* Find an empty buffer descriptor */
        for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
                if (i >= TOUT_LOOP) {
-                       DBGPRINT("%s: tsec: tx buffers full\n", dev->name);
+                       debug ("%s: tsec: tx buffers full\n", dev->name);
                        return result;
                }
        }
@@ -579,7 +592,7 @@ static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
        /* Wait for buffer to be transmitted */
        for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
                if (i >= TOUT_LOOP) {
-                       DBGPRINT("%s: tsec: tx error\n", dev->name);
+                       debug ("%s: tsec: tx error\n", dev->name);
                        return result;
                }
        }
@@ -676,6 +689,38 @@ struct phy_info phy_info_M88E1011S = {
        },
 };
 
+struct phy_info phy_info_M88E1111S = {
+       0x01410cc,
+       "Marvell 88E1111S",
+       4,
+       (struct phy_cmd[]) { /* config */
+         /* Reset and configure the PHY */
+               {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+               {0x1d, 0x1f, NULL},
+               {0x1e, 0x200c, NULL},
+               {0x1d, 0x5, NULL},
+               {0x1e, 0x0, NULL},
+               {0x1e, 0x100, NULL},
+               {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
+               {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
+               {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+               {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* startup */
+         /* Status is read once to clear old link state */
+               {MIIM_STATUS, miim_read, NULL},
+               /* Auto-negotiate */
+               {MIIM_STATUS, miim_read, &mii_parse_sr},
+               /* Read the status */
+               {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* shutdown */
+               {miim_end,}
+       },
+};
+
 struct phy_info phy_info_cis8204 = {
        0x3f11,
        "Cicada Cis8204",
@@ -762,19 +807,72 @@ struct phy_info phy_info_dm9161 = {
        },
 };
 
+uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
+{
+       unsigned int speed;
+       if (priv->link) {
+               speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
+
+               switch (speed) {
+               case MIIM_LXT971_SR2_10HDX:
+                       priv->speed = 10;
+                       priv->duplexity = 0;
+                       break;
+               case MIIM_LXT971_SR2_10FDX:
+                       priv->speed = 10;
+                       priv->duplexity = 1;
+                       break;
+               case MIIM_LXT971_SR2_100HDX:
+                       priv->speed = 100;
+                       priv->duplexity = 0;
+               default:
+                       priv->speed = 100;
+                       priv->duplexity = 1;
+                       break;
+               }
+       } else {
+               priv->speed = 0;
+               priv->duplexity = 0;
+       }
+
+       return 0;
+}
+
+static struct phy_info phy_info_lxt971 = {
+       0x0001378e,
+       "LXT971",
+       4,
+       (struct phy_cmd []) {  /* config */
+               { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
+               { miim_end, }
+       },
+       (struct phy_cmd []) {  /* startup - enable interrupts */
+               /* { 0x12, 0x00f2, NULL }, */
+               { MIIM_STATUS, miim_read, NULL },
+               { MIIM_STATUS, miim_read, &mii_parse_sr },
+               { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
+               { miim_end, }
+       },
+       (struct phy_cmd []) {  /* shutdown - disable interrupts */
+               { miim_end, }
+       },
+};
+
 struct phy_info *phy_info[] = {
 #if 0
        &phy_info_cis8201,
 #endif
        &phy_info_cis8204,
        &phy_info_M88E1011S,
+       &phy_info_M88E1111S,
        &phy_info_dm9161,
+       &phy_info_lxt971,
        NULL
 };
 
 
 /* Grab the identifier of the device's PHY, and search through
- * all of the known PHYs to see if one matches.  If so, return
+ * all of the known PHYs to see if one matches.         If so, return
  * it, if not, return NULL */
 struct phy_info * get_phy_info(struct eth_device *dev)
 {