]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/eepro100.c
Apply SoC concept to arm926ejs CPUs, i.e. move the SoC specific timer and
[karo-tx-uboot.git] / drivers / eepro100.c
index a0bb76da4d1f40f3ed9b6d2e30727f1986138b8c..04c17f69f6e6d94a3b96a1519989a215c9cec1ba 100644 (file)
@@ -26,6 +26,7 @@
 #include <net.h>
 #include <asm/io.h>
 #include <pci.h>
+#include <miiphy.h>
 
 #undef DEBUG
 
 
        /* Ethernet chip registers.
         */
-#define SCBStatus              0       /* Rx/Command Unit Status *Word* */
-#define SCBIntAckByte          1       /* Rx/Command Unit STAT/ACK byte */
-#define SCBCmd                 2       /* Rx/Command Unit Command *Word* */
-#define SCBIntrCtlByte         3       /* Rx/Command Unit Intr.Control Byte */
-#define SCBPointer             4       /* General purpose pointer. */
-#define SCBPort                8       /* Misc. commands and operands. */
-#define SCBflash               12      /* Flash memory control. */
-#define SCBeeprom              14      /* EEPROM memory control. */
-#define SCBCtrlMDI             16      /* MDI interface control. */
-#define SCBEarlyRx             20      /* Early receive byte count. */
-#define SCBGenControl          28      /* 82559 General Control Register */
-#define SCBGenStatus           29      /* 82559 General Status register */
+#define SCBStatus              0       /* Rx/Command Unit Status *Word* */
+#define SCBIntAckByte          1       /* Rx/Command Unit STAT/ACK byte */
+#define SCBCmd                 2       /* Rx/Command Unit Command *Word* */
+#define SCBIntrCtlByte         3       /* Rx/Command Unit Intr.Control Byte */
+#define SCBPointer             4       /* General purpose pointer. */
+#define SCBPort                        8       /* Misc. commands and operands. */
+#define SCBflash               12      /* Flash memory control. */
+#define SCBeeprom              14      /* EEPROM memory control. */
+#define SCBCtrlMDI             16      /* MDI interface control. */
+#define SCBEarlyRx             20      /* Early receive byte count. */
+#define SCBGenControl          28      /* 82559 General Control Register */
+#define SCBGenStatus           29      /* 82559 General Status register */
 
        /* 82559 SCB status word defnitions
         */
-#define SCB_STATUS_CX          0x8000  /* CU finished command (transmit) */
-#define SCB_STATUS_FR          0x4000  /* frame received */
-#define SCB_STATUS_CNA         0x2000  /* CU left active state */
-#define SCB_STATUS_RNR         0x1000  /* receiver left ready state */
-#define SCB_STATUS_MDI         0x0800  /* MDI read/write cycle done */
-#define SCB_STATUS_SWI         0x0400  /* software generated interrupt */
-#define SCB_STATUS_FCP         0x0100  /* flow control pause interrupt */
+#define SCB_STATUS_CX          0x8000  /* CU finished command (transmit) */
+#define SCB_STATUS_FR          0x4000  /* frame received */
+#define SCB_STATUS_CNA         0x2000  /* CU left active state */
+#define SCB_STATUS_RNR         0x1000  /* receiver left ready state */
+#define SCB_STATUS_MDI         0x0800  /* MDI read/write cycle done */
+#define SCB_STATUS_SWI         0x0400  /* software generated interrupt */
+#define SCB_STATUS_FCP         0x0100  /* flow control pause interrupt */
 
-#define SCB_INTACK_MASK        0xFD00  /* all the above */
+#define SCB_INTACK_MASK                0xFD00  /* all the above */
 
-#define SCB_INTACK_TX          (SCB_STATUS_CX | SCB_STATUS_CNA)
-#define SCB_INTACK_RX          (SCB_STATUS_FR | SCB_STATUS_RNR)
+#define SCB_INTACK_TX          (SCB_STATUS_CX | SCB_STATUS_CNA)
+#define SCB_INTACK_RX          (SCB_STATUS_FR | SCB_STATUS_RNR)
 
        /* System control block commands
         */
 /* CU Commands */
-#define CU_NOP                 0x0000
-#define        CU_START                0x0010
-#define        CU_RESUME               0x0020
-#define        CU_STATSADDR            0x0040  /* Load Dump Statistics ctrs addr */
-#define        CU_SHOWSTATS            0x0050  /* Dump statistics counters. */
-#define        CU_ADDR_LOAD            0x0060  /* Base address to add to CU commands */
-#define        CU_DUMPSTATS            0x0070  /* Dump then reset stats counters. */
+#define CU_NOP                 0x0000
+#define CU_START               0x0010
+#define CU_RESUME              0x0020
+#define CU_STATSADDR           0x0040  /* Load Dump Statistics ctrs addr */
+#define CU_SHOWSTATS           0x0050  /* Dump statistics counters. */
+#define CU_ADDR_LOAD           0x0060  /* Base address to add to CU commands */
+#define CU_DUMPSTATS           0x0070  /* Dump then reset stats counters. */
 
 /* RUC Commands */
-#define RUC_NOP                0x0000
-#define        RUC_START               0x0001
-#define        RUC_RESUME              0x0002
-#define RUC_ABORT              0x0004
-#define        RUC_ADDR_LOAD           0x0006  /* (seems not to clear on acceptance) */
-#define RUC_RESUMENR           0x0007
-
-#define CU_CMD_MASK            0x00f0
-#define RU_CMD_MASK            0x0007
-
-#define SCB_M                  0x0100  /* 0 = enable interrupt, 1 = disable */
-#define SCB_SWI                0x0200  /* 1 - cause device to interrupt */
-
-#define CU_STATUS_MASK         0x00C0
-#define RU_STATUS_MASK         0x003C
-
-#define RU_STATUS_IDLE         (0<<2)
-#define RU_STATUS_SUS          (1<<2)
-#define RU_STATUS_NORES        (2<<2)
-#define RU_STATUS_READY        (4<<2)
-#define RU_STATUS_NO_RBDS_SUS   ((1<<2)|(8<<2))
+#define RUC_NOP                        0x0000
+#define RUC_START              0x0001
+#define RUC_RESUME             0x0002
+#define RUC_ABORT              0x0004
+#define RUC_ADDR_LOAD          0x0006  /* (seems not to clear on acceptance) */
+#define RUC_RESUMENR           0x0007
+
+#define CU_CMD_MASK            0x00f0
+#define RU_CMD_MASK            0x0007
+
+#define SCB_M                  0x0100  /* 0 = enable interrupt, 1 = disable */
+#define SCB_SWI                        0x0200  /* 1 - cause device to interrupt */
+
+#define CU_STATUS_MASK         0x00C0
+#define RU_STATUS_MASK         0x003C
+
+#define RU_STATUS_IDLE         (0<<2)
+#define RU_STATUS_SUS          (1<<2)
+#define RU_STATUS_NORES                (2<<2)
+#define RU_STATUS_READY                (4<<2)
+#define RU_STATUS_NO_RBDS_SUS  ((1<<2)|(8<<2))
 #define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2))
 #define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2))
 
@@ -138,27 +139,27 @@ struct RxFD {
 };
 
 #define RFD_STATUS_C           0x8000  /* completion of received frame */
-#define RFD_STATUS_OK          0x2000  /* frame received with no errors */
-
-#define RFD_CONTROL_EL         0x8000  /* 1=last RFD in RFA */
-#define RFD_CONTROL_S          0x4000  /* 1=suspend RU after receiving frame */
-#define RFD_CONTROL_H          0x0010  /* 1=RFD is a header RFD */
-#define RFD_CONTROL_SF         0x0008  /* 0=simplified, 1=flexible mode */
-
-#define RFD_COUNT_MASK         0x3fff
-#define RFD_COUNT_F            0x4000
-#define RFD_COUNT_EOF          0x8000
-
-#define RFD_RX_CRC             0x0800  /* crc error */
-#define RFD_RX_ALIGNMENT       0x0400  /* alignment error */
-#define RFD_RX_RESOURCE        0x0200  /* out of space, no resources */
-#define RFD_RX_DMA_OVER        0x0100  /* DMA overrun */
-#define RFD_RX_SHORT           0x0080  /* short frame error */
-#define RFD_RX_LENGTH          0x0020
-#define RFD_RX_ERROR           0x0010  /* receive error */
-#define RFD_RX_NO_ADR_MATCH    0x0004  /* no address match */
-#define RFD_RX_IA_MATCH        0x0002  /* individual address does not match */
-#define RFD_RX_TCO             0x0001  /* TCO indication */
+#define RFD_STATUS_OK          0x2000  /* frame received with no errors */
+
+#define RFD_CONTROL_EL         0x8000  /* 1=last RFD in RFA */
+#define RFD_CONTROL_S          0x4000  /* 1=suspend RU after receiving frame */
+#define RFD_CONTROL_H          0x0010  /* 1=RFD is a header RFD */
+#define RFD_CONTROL_SF         0x0008  /* 0=simplified, 1=flexible mode */
+
+#define RFD_COUNT_MASK         0x3fff
+#define RFD_COUNT_F            0x4000
+#define RFD_COUNT_EOF          0x8000
+
+#define RFD_RX_CRC             0x0800  /* crc error */
+#define RFD_RX_ALIGNMENT       0x0400  /* alignment error */
+#define RFD_RX_RESOURCE                0x0200  /* out of space, no resources */
+#define RFD_RX_DMA_OVER                0x0100  /* DMA overrun */
+#define RFD_RX_SHORT           0x0080  /* short frame error */
+#define RFD_RX_LENGTH          0x0020
+#define RFD_RX_ERROR           0x0010  /* receive error */
+#define RFD_RX_NO_ADR_MATCH    0x0004  /* no address match */
+#define RFD_RX_IA_MATCH                0x0002  /* individual address does not match */
+#define RFD_RX_TCO             0x0001  /* TCO indication */
 
        /* Transmit frame descriptors
         */
@@ -176,45 +177,45 @@ struct TxFD {                             /* Transmit frame descriptor set. */
 };
 
 #define TxCB_CMD_TRANSMIT      0x0004  /* transmit command */
-#define TxCB_CMD_SF            0x0008  /* 0=simplified, 1=flexible mode */
-#define TxCB_CMD_NC            0x0010  /* 0=CRC insert by controller */
-#define TxCB_CMD_I             0x2000  /* generate interrupt on completion */
-#define TxCB_CMD_S             0x4000  /* suspend on completion */
-#define TxCB_CMD_EL            0x8000  /* last command block in CBL */
+#define TxCB_CMD_SF            0x0008  /* 0=simplified, 1=flexible mode */
+#define TxCB_CMD_NC            0x0010  /* 0=CRC insert by controller */
+#define TxCB_CMD_I             0x2000  /* generate interrupt on completion */
+#define TxCB_CMD_S             0x4000  /* suspend on completion */
+#define TxCB_CMD_EL            0x8000  /* last command block in CBL */
 
-#define TxCB_COUNT_MASK        0x3fff
-#define TxCB_COUNT_EOF         0x8000
+#define TxCB_COUNT_MASK                0x3fff
+#define TxCB_COUNT_EOF         0x8000
 
        /* The Speedo3 Rx and Tx frame/buffer descriptors.
         */
 struct descriptor {                    /* A generic descriptor. */
        volatile u16 status;
        volatile u16 command;
-       volatile u32 link;              /* struct descriptor *  */
+       volatile u32 link;              /* struct descriptor *  */
 
        unsigned char params[0];
 };
 
-#define CFG_CMD_EL             0x8000
-#define CFG_CMD_SUSPEND        0x4000
-#define CFG_CMD_INT            0x2000
-#define CFG_CMD_IAS            0x0001  /* individual address setup */
-#define CFG_CMD_CONFIGURE      0x0002  /* configure */
+#define CFG_CMD_EL             0x8000
+#define CFG_CMD_SUSPEND                0x4000
+#define CFG_CMD_INT            0x2000
+#define CFG_CMD_IAS            0x0001  /* individual address setup */
+#define CFG_CMD_CONFIGURE      0x0002  /* configure */
 
-#define CFG_STATUS_C           0x8000
-#define CFG_STATUS_OK          0x2000
+#define CFG_STATUS_C           0x8000
+#define CFG_STATUS_OK          0x2000
 
        /* Misc.
         */
-#define NUM_RX_DESC            PKTBUFSRX
-#define NUM_TX_DESC            1       /* Number of TX descriptors   */
+#define NUM_RX_DESC            PKTBUFSRX
+#define NUM_TX_DESC            1       /* Number of TX descriptors   */
 
 #define TOUT_LOOP              1000000
 
 #define ETH_ALEN               6
 
-static struct RxFD rx_ring[NUM_RX_DESC];       /* RX descriptor ring         */
-static struct TxFD tx_ring[NUM_TX_DESC];       /* TX descriptor ring         */
+static struct RxFD rx_ring[NUM_RX_DESC];       /* RX descriptor ring         */
+static struct TxFD tx_ring[NUM_TX_DESC];       /* TX descriptor ring         */
 static int rx_next;                    /* RX descriptor ring pointer */
 static int tx_next;                    /* TX descriptor ring pointer */
 static int tx_threshold;
@@ -248,8 +249,13 @@ static int eepro100_send (struct eth_device *dev, volatile void *packet,
 static int eepro100_recv (struct eth_device *dev);
 static void eepro100_halt (struct eth_device *dev);
 
+#if defined(CONFIG_E500) || defined(CONFIG_DB64360) || defined(CONFIG_DB64460)
+#define bus_to_phys(a) (a)
+#define phys_to_bus(a) (a)
+#else
 #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a)
 #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
+#endif
 
 static inline int INW (struct eth_device *dev, u_long addr)
 {
@@ -266,8 +272,124 @@ static inline void OUTL (struct eth_device *dev, int command, u_long addr)
        *(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command);
 }
 
-       /* Wait for the chip get the command.
-        */
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+static inline int INL (struct eth_device *dev, u_long addr)
+{
+       return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase));
+}
+
+static int get_phyreg (struct eth_device *dev, unsigned char addr,
+               unsigned char reg, unsigned short *value)
+{
+       int cmd;
+       int timeout = 50;
+
+       /* read requested data */
+       cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16);
+       OUTL (dev, cmd, SCBCtrlMDI);
+
+       do {
+               udelay(1000);
+               cmd = INL (dev, SCBCtrlMDI);
+       } while (!(cmd & (1 << 28)) && (--timeout));
+
+       if (timeout == 0)
+               return -1;
+
+       *value = (unsigned short) (cmd & 0xffff);
+
+       return 0;
+}
+
+static int set_phyreg (struct eth_device *dev, unsigned char addr,
+               unsigned char reg, unsigned short value)
+{
+       int cmd;
+       int timeout = 50;
+
+       /* write requested data */
+       cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16);
+       OUTL (dev, cmd | value, SCBCtrlMDI);
+
+       while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout))
+               udelay(1000);
+
+       if (timeout == 0)
+               return -1;
+
+       return 0;
+}
+
+/* Check if given phyaddr is valid, i.e. there is a PHY connected.
+ * Do this by checking model value field from ID2 register.
+ */
+static struct eth_device* verify_phyaddr (char *devname, unsigned char addr)
+{
+       struct eth_device *dev;
+       unsigned short value;
+       unsigned char model;
+
+       dev = eth_get_dev_by_name(devname);
+       if (dev == NULL) {
+               printf("%s: no such device\n", devname);
+               return NULL;
+       }
+
+       /* read id2 register */
+       if (get_phyreg(dev, addr, PHY_PHYIDR2, &value) != 0) {
+               printf("%s: mii read timeout!\n", devname);
+               return NULL;
+       }
+
+       /* get model */
+       model = (unsigned char)((value >> 4) & 0x003f);
+
+       if (model == 0) {
+               printf("%s: no PHY at address %d\n", devname, addr);
+               return NULL;
+       }
+
+       return dev;
+}
+
+static int eepro100_miiphy_read (char *devname, unsigned char addr,
+               unsigned char reg, unsigned short *value)
+{
+       struct eth_device *dev;
+
+       dev = verify_phyaddr(devname, addr);
+       if (dev == NULL)
+               return -1;
+
+       if (get_phyreg(dev, addr, reg, value) != 0) {
+               printf("%s: mii read timeout!\n", devname);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int eepro100_miiphy_write (char *devname, unsigned char addr,
+               unsigned char reg, unsigned short value)
+{
+       struct eth_device *dev;
+
+       dev = verify_phyaddr(devname, addr);
+       if (dev == NULL)
+               return -1;
+
+       if (set_phyreg(dev, addr, reg, value) != 0) {
+               printf("%s: mii write timeout!\n", devname);
+               return -1;
+       }
+
+       return 0;
+}
+
+#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
+
+/* Wait for the chip get the command.
+*/
 static int wait_for_eepro100 (struct eth_device *dev)
 {
        int i;
@@ -340,6 +462,12 @@ int eepro100_initialize (bd_t * bis)
 
                eth_register (dev);
 
+#if defined (CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+               /* register mii command access routines */
+               miiphy_register(dev->name,
+                               eepro100_miiphy_read, eepro100_miiphy_write);
+#endif
+
                card_number++;
 
                /* Set the latency timer for value.
@@ -679,11 +807,11 @@ int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, u
     /* Shift the enable command bits out. */
     for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--)
     {
-        dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-        OUTW(dev, EE_ENB | dataval, SCBeeprom);
-        udelay(1);
-        OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom);
-        udelay(1);
+       dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+       OUTW(dev, EE_ENB | dataval, SCBeeprom);
+       udelay(1);
+       OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom);
+       udelay(1);
     }
 
     OUTW(dev, EE_ENB, SCBeeprom);
@@ -696,11 +824,11 @@ int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, u
     /* Shift the write command bits out. */
     for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--)
     {
-        dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-        OUTW(dev, EE_ENB | dataval, SCBeeprom);
-        udelay(1);
-        OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom);
-        udelay(1);
+       dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+       OUTW(dev, EE_ENB | dataval, SCBeeprom);
+       udelay(1);
+       OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom);
+       udelay(1);
     }
 
     /* Write the data */
@@ -718,29 +846,29 @@ int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, u
     OUTW(dev, EE_ENB | dataval, SCBeeprom);
     udelay(1);
 
-    datalong = datalong << 1; /* Adjust significant data bit*/
+    datalong = datalong << 1;  /* Adjust significant data bit*/
     }
 
     /* Finish up command  (toggle CS) */
     OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom);
-    udelay(1);                /* delay for more than 250 ns */
+    udelay(1);                 /* delay for more than 250 ns */
     OUTW(dev, EE_ENB, SCBeeprom);
 
     /* Wait for programming ready (D0 = 1) */
     tmplong = 10;
     do
     {
-        dataval = INW(dev, SCBeeprom);
-        if (dataval & EE_DATA_READ)
-            break;
-        udelay(10000);
+       dataval = INW(dev, SCBeeprom);
+       if (dataval & EE_DATA_READ)
+           break;
+       udelay(10000);
     }
     while (-- tmplong);
 
     if (tmplong == 0)
     {
-        printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n");
-        return -1;
+       printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n");
+       return -1;
     }
 
     /* Terminate the EEPROM access. */